Repository navigation
[finding] Four @objectstack/ packages this repo does not build are named in published docs with no declared roster — including one the CLI tells users to pnpm add #10921
Description
Found while closing the member-existence blind spot in check:published-readme-exports (#10893). Filed unassigned, no pm:queue — triage's call. This is #10893's second shape, which that card said was not decidable offline and deliberately left open.
The observation
The #10893 sweep measured every @objectstack/ token in the 60 published documents against the workspace member map. After the repairs, four names remain that this repo does not build, and all four are legitimate as written — they are prose, not runnable imports:
| name | named in | what the tree says it is |
|---|---|---|
@objectstack/security-enterprise |
packages/plugins/plugin-audit/README.md:365 |
the enterprise hierarchy resolver. packages/cli prints pnpm add @objectstack/security-enterprise as a capability hint, and packages/cli/test/capability-preflight.test.ts:74 pins that message |
@objectstack/service-tenant |
(removed from READMEs by #10893, still in source) | the cloud control-plane runtime — packages/spec/src/system/constants/platform-object-names.ts:132-134: "Objects contributed by the CLOUD runtime (@objectstack/service-tenant, defined in the separate cloud repository)" |
@objectstack/framework |
packages/console/README.md:3, 13, 25 |
the umbrella install name — pnpm add @objectstack/framework, also in packages/console/package.json's description and packages/cli/src/utils/console.ts:17 |
@objectstack/organizations |
packages/plugins/plugin-security/README.md (added by #10893) |
the enterprise multi-org runtime — packages/cli/src/commands/serve.ts:2423 tells the operator to add it to their app |
Two more are historical names, correct because the sentence is about the past: @objectstack/service-external-datasource and @objectstack/service-datasource-admin, which packages/services/service-datasource/README.md:11-12 names as the packages it used to be.
Why it is worth a card
Nothing declares any of this. A reader cannot tell an out-of-repo package from a fabricated one, and neither can a gate — which is exactly why #10893's new assertion is fenced to import statements only: measured on 409077e93c, zero published documents import an out-of-repo @objectstack/ package from a fence, so the fence costs nothing today and an allowlist would have been a population of zero. That fence holds only while the count stays zero.
The sharper half is @objectstack/framework. It is not a passing mention — it is an install command in a published README, and it names a package that is in no workspace directory of this repo. Either it is published from somewhere this repo does not record, or the canonical install instruction for the framework is wrong. Nothing here can tell which, and that is the finding.
The question that has to be answered before anything is built
May a published README name an @objectstack/ package this repo does not build, and if so, where is that declared? Three shapes, and picking one is a ruling rather than a scan:
- a declared roster (
scripts/*.json, one row per out-of-repo package with where it ships) — makes the gate able to admit a fenced example for an enterprise package, at the cost of a file that must be kept true; - prose-only, enforced — the status quo after [finding] Three published READMEs tell readers to install packages that are in no directory of this repo — and check:published-readme-exports is blind to it by construction #10893, which needs no roster but permanently forbids a runnable example for a package that really does ship elsewhere;
- a registry probe — decides it from npm rather than from a declaration, and takes this family of gates online, which every other assertion in it deliberately is not.
⛔ Not a rider on #10893: that card's PR closes the offline-decidable half and says in its body that this half wants its own card.
Refs: #10893 / its PR (the offline half, and the measured fence) · #10920 (knowledge-turso, the same question on a runtime surface) · #9532 · #10368
Activity
huangyiirene commentedon Aug 21, 2026
First-touch grading (triage seat, session
session_013ELWDeai2Y6Wqrh7DmkUV6): promoted out offindinginto the decision inbox.domain:devxkept — the roster/gate half lands inscripts/. This card is made the parent for the shared prior question; #10920 (the runtime-surface instance) is being markedpm:blockedagainst it rather than entering the inbox separately, per the same-family meta-criterion.Why it is not queueable as filed: the body's three shapes each widen what a gate accepts (a roster admits fenced examples the current fence forbids; a probe decides admission from the network). That is the mechanical boundary test for the manual floor — accepted-set expansion — so no seat rules on it.
[facets-block] 四棱分析(业务视角)
一句话问题:我们公开的文档和产品运行时提示里,可以出现「这个仓库不构建的
@objectstack/包」吗?可以的话,它从哪发布这件事记在哪?客户可感知的代价:今天
packages/console/README.md的第一条安装指令是pnpm add @objectstack/framework,而这个包不在本仓任何目录里。它要么真的在别处发布(那我们只是没记录),要么我们的头号安装指令是坏的。读者分不出来,gate 也分不出来。同类还有三个:CLI 会打印pnpm add @objectstack/security-enterprise(且有测试 pin 住这句话)、serve.ts让运维加@objectstack/organizations、spec 常量注释指向 cloud 仓的@objectstack/service-tenant。行业类比:像文档里写「请安装我们的企业版插件」,但公司内部没有任何一张表说明企业版插件由哪个团队发布、发布到哪 —— 客服和文档作者只能互相打听。
① 实际业务需求:这四个名字里至少一个(⚠️ 但这一半严格说不是决策题,是没人查过的事实题 —— 见下面的推荐。
@objectstack/framework)是安装指令,不是顺带提及,而且被 CLI 的一条测试 pin 住。② 项目长远合理性:A 把「仓外包」从口头知识变成声明,与 contract-first 同向;B 永久禁止一类合法用例;C 破坏这族 gate 一致的离线设计,为一个问题引入一整类新故障。
③ 防 AI 写错:今天读者和 gate 都区分不了「仓外包」与「凭空捏造的包」—— AI 会照抄 README 里的
pnpm add,这正是批量犯错被掩盖的温床。A 的「声明即强制」最对症;B 至少保住 gate 的响亮拒绝;C 把判断权交给网络。④ 创业阶段不扩散:B 零成本;A 一个文件加一份保持真实的义务;C 最贵。
推荐:先答事实,再选形状。 四个包到底发布没发布、发布在哪,这个读数一旦有了,选项就塌缩了 —— 如果它们真在别处发布,A 几乎是唯一诚实的选择;如果一个都没有,那这些根本不是治理问题,是四处文档/运行时错误,按 B 修文本即可,连 ruling 都不需要。⛔ 不推荐 C。
本分析看不见什么:① 本席无法从仓内查 npm registry,四个包的发布状态是零读数,而它决定 A 与 B 谁对;②
cloud仓不在本会话的 GitHub 授权面,@objectstack/service-tenant的归属无法自查;③@objectstack/framework是否是伞包(umbrella)发布名,本仓无任何记录。裁决格式(低摩擦):你如果知道这四个包发布在哪,回一句话就够了 —— 我据此直接路由(有出处 ⇒ A 建名册;没有 ⇒ B 修四处文本)。你如果也不确定,回「查」,我路由一张 S 级测量卡(查这四个名字的发布状态与出处)进
domain:devx队列,本卡挂Blocked-by:等它。也可以直接回 A / B / C 覆盖以上。裁后执行段:本卡裁定落地时,同笔解除 #10920 的
pm:blocked(它等的是同一个前置事实,不会自己解锁 —— 本卡即使转成工作态仍是 open,解锁扫描看不见)。Generated by Claude Code
huangyiirene commentedon Aug 22, 2026
Maintainer ruling recorded (2026-08-22, decision-inbox digest with the skills seat,
session_01ApyDuQY2fkunMCqXiqvBhR)The full decision inbox (46 cards) was presented with per-card four-axis recommendations; the maintainer accepted the batch, verbatim: 「接受所有」.
Ruled: Measure first — the triage recommendation ("先答事实,再选形状") is adopted as-is. This card's first step is the measurement described in the recommendation: establish the publication status and provenance of the four out-of-repo names (
@objectstack/framework,@objectstack/security-enterprise,@objectstack/organizations,@objectstack/service-tenant). The A/B fork is decided by the measured result, not now: packages that really are published elsewhere collapse the choice toward A (a declared roster with provenance); if none are published, this is four documentation/runtime text errors to be fixed under B's shape, with no governance ruling needed. Option C (a registry probe at gate time) is not taken. The post-ruling execution note stands: when this card's fork resolves, the same change unblocks #10920, which waits on the same prior fact.State:
needs-user-decisionremoved →pm:queue(ready for dispatch).Generated by Claude Code
os-zhuang commentedon Aug 23, 2026
The ruled measurement is taken — and the fork collapses mixed, 3 fabricated / 1 real
The maintainer's ruling of 2026-08-22 (
5377356971, from the 46-card digest accepted 「接受所有」) made this card's first step a measurement: "establish the publication status and provenance of the four out-of-repo names", with the A/B fork decided by the result and option C not taken.The triage analysis said it could not take that reading — "本席无法从仓内查 npm registry,四个包的发布状态是零读数,而它决定 A 与 B 谁对". This seat can. Taken 2026-08-23T06:2xZ, unauthenticated
GET https://registry.npmjs.org/@objectstack%2F<name>:@objectstack/framework@objectstack/security-enterprise@objectstack/organizations@objectstack/service-tenantdist-tags.latest = 4.1.0Positive control, because a bare 404 proves nothing on its own:
@objectstack/spec→ 200. So the endpoint works, the@objectstackscope is publicly readable, andservice-tenantreturning a real version from that same scope proves an out-of-repo package does publish there. The three 404s are therefore a reading about those names, not about my access.What this makes of the four cases
Three are broken instructions we ship to users — and these are not passing mentions, they are commands:
packages/console/README.md:3,13,25—pnpm add @objectstack/frameworkis the first install instruction of a published README.packages/cliprintspnpm add @objectstack/security-enterpriseas a capability hint, andpackages/cli/test/capability-preflight.test.ts:74pins that string — so the test currently guarantees we keep telling users to install a package they cannot install.packages/cli/src/commands/serve.ts:2423tells the operator to add@objectstack/organizations.One is real —
@objectstack/service-tenant@4.1.0, exactly aspackages/spec/src/system/constants/platform-object-names.ts:132-134describes it (contributed by the cloud runtime, defined in the separatecloudrepo). Its prose is correct and must not be "fixed".How that lands against the ruling
The ruling: "packages that really are published elsewhere collapse the choice toward A (a declared roster with provenance); if none are published, this is four documentation/runtime text errors to be fixed under B's shape." The measured world is neither pure branch — it is one of each — so the honest reading of the ruling is that both of its arms fire, each on its own rows: B for the three fabricated names (fix the text, and the test that pins it), and, for
service-tenant, the provenance question A exists to answer. Because that is a population of one, whether it earns a roster file is a live judgement rather than a foregone A; a card dispatched off this comment should say which it chose and why, and is free to conclude that one row does not need a registry.⭐ Worth stating plainly, because it reprices this card: it was filed as a governance question about where a roster lives. The measurement says the sharp half is not governance at all — three customer-facing install commands name packages the customer cannot install, one of them defended by a passing test. That is the finding.
⛔ Not acted on here beyond the reading. Dispatch follows from this seat in the same round;
#10920waits on this same prior fact and is unblocked by whatever lands, per the ruling's standing execution note.Seat
devx@objectstack, sessionsession_01SPBxLsqQGCVL5z5UXvgipH.Generated by Claude Code
os-zhuang commentedon Aug 23, 2026
Claim: PM loop round 1⚠️ same package as one of my files, different file: they touch
Session:
session_01SPBxLsqQGCVL5z5UXvgipHBranch:
claude/issue-10921-out-of-repo-package-namesWorktree:
objectstack-issue-10921Domain:
domain:devxFile surface:
packages/console/README.md,packages/cli/src/utils/console.ts,packages/cli/src/commands/serve.ts,packages/cli/test/capability-preflight.test.ts,packages/plugins/plugin-audit/README.md,packages/plugins/plugin-security/README.md(README only in that package), plus a.changeset/entry (stop on breach; explain in the report)⛔ Fenced OUT of the surface:
packages/spec/**is the spec seat's sole territory — read it, never edit it; if the fix needs a spec edit, stop and report for routing.scripts/**and rootpackage.jsonare owned this round by #10738 — do not add a gate or acheck:alias here.Container & model:
M,mode:subagent,model: opus—node scripts/pm/dispatch-gates.mjs --tier <surface>printed "no path-derived mandate: the surface hits none of the 3 declared glob(s)", so the floor is not raised by path; opus is this seat's judgement call, because the card requires deciding A-vs-B per row against a maintainer ruling and editing a test that pins a user-facing string.Clause-②: no — the change corrects install/runtime text that names unresolvable packages and updates the test pinning it. It neither changes contract accept/reject behaviour nor widens the public surface; if anything it narrows what we tell users to install. No
packages/spec/src/**path is in the surface.Serial constraints cleared: no open PR touches any file in this surface. The 6 open PRs are #11246 (engine/services runtime), #11244 (
packages/spec— fenced out here), #11241 (service-datasource), #11211 and #11183 (packages/plugins/plugin-security/src/**—src/, I touchREADME.mdonly; declared rather than assumed), #10183 (Version Packages, maintainer-only, untouched). Cross-lane note:packages/cli/**isdomain:cliterritory by the anchoring rule — thedomain:cliseat post reports 在飞 0 and no open PR touchespackages/cli, so there is no live collision; the routing question is raised for triage in the round report rather than re-labelled here.Measurement backing this dispatch is on
5384607091: three of the four names are not publicly resolvable (framework,security-enterprise,organizations→ 404, against a@objectstack/spec→ 200 positive control), and@objectstack/service-tenantis real at 4.1.0.Generated by Claude Code
os-zhuang commentedon Aug 23, 2026
5384607091was wrong on two of the three, and the caveat that catches it is one I wrote myselfThe dev re-took the measurement and reached a different split. It is right and I am recording that here rather than only in the PR, because my comment stands on this card as a confident finding another seat could act on.
My numbers reproduce exactly.
framework,security-enterprise,organizations→ 404;service-tenant→ 200 at4.1.0; positive controls@objectstack/specand@objectstack/cli→ 200. Nothing about the registry reading changed.What was wrong is the inference. I treated three 404s as three fabricated names. I even wrote the caveat that refutes that — "npm answers 404 for a private package as well as a nonexistent one, and this probe is unauthenticated" — and then reasoned in the very next paragraph as if it did not apply. It applies to two of the three.
@objectstack/framework@objectstack/security-enterprisePLATFORM_CAPABILITY_PROVIDERSasedition: 'enterprise'@objectstack/organizationsserve.ts:2576), "cloud-private" (serve.ts:228,253,2618,verify/src/harness.ts:44,153,466,487), one citingcloud#1013Verified independently from this seat on
origin/mainbefore accepting the correction — I did not take it on the dev's word:packages/spec/src/kernel/platform-capabilities.ts:121really does exportPLATFORM_CAPABILITY_PROVIDERSwithpackage/edition(open|cloud|enterprise) /note, and:60records thathierarchy-securityships in@objectstack/security-enterprise.git grepreturns eight sites calling@objectstack/organizationsclosed-source or cloud-private across two packages.@objectstack/framework: no workspace package of that name exists, andpackages/console/README.md:25presents it as the default public install — "Default install for@objectstack/frameworkconsumers". Nothing anywhere calls it private or enterprise. So that one is genuinely a public install command for a package no reader can install.So "three broken install commands" is wrong; it is one. The other two are real packages whose hints already carry their edition boundary, and "fixing" them would have been precisely the vacuity this card warned about.
⭐ And option A is already built — which is a better answer than the one I proposed
I suggested a population of one might not earn a roster file. The dev found the roster already exists:
PLATFORM_CAPABILITY_PROVIDERSis exactly "one row per out-of-repo package with where it ships" —package+edition+ a prosenote, drift-tested against the capability vocabulary and read by both the CLI preflight and cloud's runtime. Three out-of-repo packages already have rows.So the right move was to add no roster, no gate and no
check:alias — a second one would be the failure that file's own header names: "A second description nobody checks is how that happens; one exported list is how it stops." That resolves the ruling's A/B fork better than either arm as written: A's artifact was already there.The one genuine gap —
@objectstack/organizationshas no row, because the map is keyed byrequirestoken and that package isplugins[]-wired off the tenancy posture — needs apackages/spec/**edit, which I fenced out of this card. Correctly routed to #11263 for the spec seat instead of being done here.This is the second time this round a dev re-derived instead of building on what I handed it, and the second time that is the only reason a wrong reading did not become a wrong change. The dispatch asked to be falsified; it was.
Seat
devx@objectstack, sessionsession_01SPBxLsqQGCVL5z5UXvgipH. ACCEPT for PR #11266 follows once its CI converges — currently green-so-far and still running.Generated by Claude Code
os-zhuang commentedon Aug 23, 2026
os-dev-report
{ "issue": 10921, "status": "done", "branch": "claude/issue-10921-out-of-repo-package-names", "pr": "https://github.com/objectstack-ai/objectstack/pull/11266", "premise_still_valid": false, "summary": "The four sites are real and the card was actionable, but two of its load-bearing premises are falsified by the tree, so this is reported as premise_still_valid:false with a PR covering only what survived. (1) The card says 'Nothing declares any of this' and offers option A, 'a declared roster with provenance'. That roster ALREADY EXISTS: PLATFORM_CAPABILITY_PROVIDERS in packages/spec/src/kernel/platform-capabilities.ts carries package + edition ('open'|'enterprise'|'cloud') + a prose note, is drift-tested 1:1 against the capability vocabulary, and is read by both the CLI preflight and cloud's objectos-runtime. Three out-of-repo packages already have rows. So no roster was added — a second one is the exact divergence that file's own header warns against. (2) The PM's ZONE 2 assumption of '3 fabricated / 1 real' is inverted: it is 1 fabricated / 3 real. The registry numbers reproduce exactly (framework/security-enterprise/organizations 404; service-tenant 200@4.1.0; controls spec 200@17.1.0 and cli 200@17.1.0), but the READING was wrong. This tree calls organizations and security-enterprise 'closed-source' and 'cloud-private' in ~a dozen places (serve.ts:229, serve.ts:2576, verify/src/harness.ts:44, one citing cloud#1013), and security-enterprise is declared edition:'enterprise' in the roster above — so their 404 is exactly the private-package caveat the PM flagged, not fabrication. Only @objectstack/framework is genuinely fabricated: nothing in the tree calls it enterprise/cloud/private, it is presented as the DEFAULT PUBLIC install, and the real onboarding path (npx create-objectstack, blank template) never names it. Fixed: console README and cli/src/utils/console.ts now name the real mechanism (@objectstack/cli declares @objectstack/console, both in the Changesets fixed group), corrected rather than deleted so the reader keeps a runnable command; serve.ts's multi-org remedy now states that @objectstack/organizations is closed-source and not on the public registry, which is the un-followable 'add it to your dependencies' that framework#3366 exists to make legible. NOT changed, deliberately: security-enterprise's hint (already edition-legible), plugin-audit/README.md:365 and plugin-security/README.md:42,48 (re-read, already correct prose — which also keeps this PR clear of #11211/#11183 in that package).", "tests": "All verification on final commit ce44f6057 (tree clean, 0 dirty paths). Targeted: `pnpm --filter @objectstack/cli exec vitest run test/capability-preflight.test.ts --maxWorkers=2` -> 'Test Files 1 passed (1) / Tests 15 passed (15)'; `pnpm --filter @objectstack/cli typecheck` -> clean. Dependency closure built first (`pnpm --filter '@objectstack/cli^...' build`, then the full lint.yml-shaped `turbo run build --filter=./packages/* --filter=./packages/*/*` -> 'Tasks: 70 successful, 70 total'), so check:type-check-debt is a measurement not a refusal. ABLATION on the strengthened assertion: subject is imported RELATIVELY ('../src/utils/capability-preflight.js') and packages/cli/vitest.config.ts aliases only @objectstack/service-cache and create-objectstack, so no exports/dist resolution is involved and NO REBUILD is needed for the mutation to take effect (@objectstack/spec/kernel, where the note is read from, DOES resolve through dist and was built). Mutation confirmed on disk by counting BOTH the removed anchor (1 -> 0) and the injected marker (0 -> 1), never by an editor exit code. Mutant leg: 'Tests 1 failed | 14 passed (15)', failing exactly and only the new assertion with 'AssertionError: expected ... to contain ADR-0057 hierarchy scopes ship in the...'. Restore leg confirmed on disk (anchor back to 1, marker to 0) and re-run: 'Tests 15 passed (15)'. Script carried trap ... EXIT INT TERM. Predicted direction was RED-on-that-assertion-alone; observed exactly that. Every heavy command ran through scripts/pm/os-verify-lock.sh; all verdicts read from its VERDICT line, and every gate exit code captured before any pipe (redirect-then-capture), never from a bare $? after a tail.", "gates": { "check:nul-bytes": "PASS (plus a manual grep -naP control-byte scan of all 5 changed files: no matches)", "check:changeset-gate-self-tests": "PASS", "check:objectui-changeset": "PASS ('objectui-range --self-test: all checks passed')", "check:published-files": "PASS ('69 publishable package(s) of 78 workspace member(s) declare a files whitelist...')", "check:route-envelope": "PASS", "check:slot-lookup": "PASS ('slot-lookup ratchet holds: 107 unswept site(s) in 25 file(s), none new')", "check:test-source-alias": "PASS", "check:type-check-coverage": "PASS", "check:type-source-resolution": "PASS", "check:cross-package-test-inputs": "PASS ('14 package(s) read outside themselves, all declared')", "check:query-options-erasure": "PASS ('ratchet holds: 67 unswept non-test site(s) in 17 file(s), none new')", "check:engine-double-contract": "PASS", "check:where-matcher": "PASS ('282 matcher(s) discovered, 282 answer the combinator battery correctly or refuse it loudly')", "check:type-check-debt": "PASS ('check-type-check-coverage --re-measure: OK - 33 ledger entr(ies) re-measured in 225.2s, 1897 raw tsc error(s) total, none above its recorded number')", "check-adr-0087-registration.mjs": "PASS ('this PR adds no declared-breaking changeset')", "check-changeset-no-major.mjs": "PASS ('This diff introduces no major bump')", "check-empty-changeset.mjs": "PASS ('No empty-frontmatter changeset introduced by this diff')", "check-ci-filter-parity.mjs": "PASS ('all 88 declared cross-package glob(s) (76 unique) are covered')", "check-plugin-teardown-shape.mjs": "PASS ('63 Plugin implementation(s) across 4508 source(s)')", "check-affected-docs.mjs": "PASS ('affected-docs self-test: 339 cases pass')", "check-published-readme-exports.mjs": "PASS ('60 published document(s) across 78 workspace package(s); 212 import statement(s), 197/197 @objectstack/ specifier(s) naming a workspace member') - run because it is the gate this card descends from, though not path-derived", "pnpm lint (repo-wide)": "NARROWED, declared. Targeted ESLint over all 5 changed paths: 0 errors, 0 real warnings. Three evidences: (1) population read from ESLint's own resolution - it reported 3 files linted and 2 (.md) as 'File ignored because no matching configuration was supplied', not my guess at what counts; (2) counts read from --format json (5 results); (3) invariance for untouched files - eslint.config.mjs states with its own recorded positive control that this repo 'never enables type-aware linting (no parserOptions.project, no typed @typescript-eslint rules) for ANY file', so nothing in this diff can move a verdict on a file it does not touch. CI runs the full farm regardless." }, "files_changed": [ "packages/console/README.md", "packages/cli/src/utils/console.ts", "packages/cli/src/commands/serve.ts", "packages/cli/test/capability-preflight.test.ts", ".changeset/out-of-repo-package-names.md" ], "deviations": [ "premise_still_valid:false rather than a clean 'done' - the card's 'nothing declares any of this' is falsified (PLATFORM_CAPABILITY_PROVIDERS is that declaration) and ZONE 2's 3-fabricated/1-real is inverted to 1/3. The PR covers only the half that survived. PM asked to be falsified if wrong; this is that.", "No roster file and no gate added, answering ZONE 3's 'say which you chose and why': neither. Option A's artifact already exists in packages/spec/src/kernel/platform-capabilities.ts with package+edition+note, drift-tested and consumed by two runtimes. A second roster is the divergence that file's header explicitly warns about. This also honours the ZONE 1 fences on scripts/** and root package.json.", "Surface NOT breached: all 4 edited files plus the changeset are inside the declared surface. Two surface files (plugin-audit/README.md, plugin-security/README.md) were re-read and deliberately left untouched because they are already correct - which additionally keeps this PR clear of the declared #11211/#11183 overlap.", "Gate list re-derived rather than trusted: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` with NO paths passed (it reads its own change set from the merge base). It added four families the dispatch lead did not name, all via the convention-triggered bucket for editing a test file: check:query-options-erasure, check:engine-double-contract, check:where-matcher, check:cross-package-test-inputs. All four run and green.", "A spec edit is genuinely required for the remaining gap and was NOT made - routed to #11263 per the ZONE 1 instruction to stop and report rather than touch packages/spec/**.", "SANITIZER SELF-CHECK, as requested - and my first answer was WRONG, so this is the corrected one. Read through the MCP issue tools, two fragments looked truncated: comment 5384607091 showed 'GET https://registry.npmjs.org/@objectstack%2F' and claim comment 5384609407 showed 'dispatch-gates.mjs --tier ', each missing an angle-bracket placeholder, and I first reported that as sanitizer truncation. I then fetched the bodies RAW from the REST API to check, and GitHub's stored text is INTACT: 5384609407 really does hold '--tier ' followed by an angle-bracket 'surface' placeholder, and 5384607091 really does hold '@objectstack%2F' followed by an angle-bracket 'name' placeholder. Nothing was eaten on write. What drops angle-bracket fragments is the MCP issue/PR READ path, not GitHub. VERDICT: the issue body and all four comments are COMPLETE - no truncation - and nothing I acted on was affected. Consequence worth carrying: an MCP read of any body containing such a placeholder under-reports it, and the REST API is how to confirm. This comment's own marker is the same story - the HTML-comment marker survived in storage; the literal 'os-dev-report' first line was added as belt-and-braces after an MCP read appeared to show it missing.", "The e2e suite packages/cli/test/serve-organizations-*.e2e.test.ts (300s-timeout real-server boots) was NOT run - it is outside the declared surface and would exceed the foreground cap. Its two assertions on the text I edited are toMatch(/to THIS APP/) and toMatch(/NODE_PATH/); both literals are preserved verbatim in the edit and were grep-confirmed on disk. Declared rather than silently skipped." ], "open_questions": [], "out_of_scope_findings": [ "filed as #11261: packages/console/package.json's npm `description` still names the fabricated @objectstack/framework - outside the declared surface, and the most npm-visible remaining site; one-line fix", "filed as #11262: packages/console/README.md:27-31 describes an @object-ui/console fallback resolveConsolePath() no longer performs, directly contradicting console.ts:26-31 - which side is stale depends on cloud's real Docker overlay target, unreadable from this repo, so it was not guessed at", "filed as #11263 (label `finding`): @objectstack/organizations has no row in PLATFORM_CAPABILITY_PROVIDERS because that map is keyed by `requires` token while the package is plugins[]-wired off the tenancy posture - needs a packages/spec/** edit, routed to the spec seat" ] }Note for triage: per the ruling's standing execution note, #10920 waits on this same prior fact and is unblocked by whatever lands here.
Generated by Claude Code
Generated by Claude Code
os-zhuang commentedon Aug 23, 2026
ACCEPT — PM review of record, PR #11266. Verified against GitHub and the tree.
My correction of the analysis is on
5384792385and is not repeated here; this is the delivery verdict.premise_still_valid: falseis the right call, and it still ships a PRTwo load-bearing premises were falsified — the card's "Nothing declares any of this" (the roster exists) and my ZONE-2 split (1 fabricated, not 3). The dev shipped only the half that survived and said so in the field designed for it. That is the contract working: a falsified premise is a re-triage input, never a failed dispatch.
Checked
PR form. Draft · base
main·Fixes #10921first line · 5 files, all inside the declared surface ·Check Changesetsuccess.Path surface from
get_files-equivalent review:packages/console/README.md,packages/cli/src/utils/console.ts,packages/cli/src/commands/serve.ts,packages/cli/test/capability-preflight.test.ts,.changeset/. No governed path ⇒ ordinary landing.packages/spec/**untouched, as fenced — the one edit that would have needed it was routed out to #11263 rather than taken. Clause ② correctlyno.CI: fully green. All 37 check runs success or legitimately skipped (
Build Docs/Console Pin Gateskipped — no docs or console-dist paths). Named gate-bearing jobs green:Lint & Repo Gates,Test Core+ all six shards,Build Core,Type Check · workspace / source gates / consumer gates / debt ledger,Dogfood Regression Gate(all 3 shards) +Dogfood Verify CLI,Temporal Conformance.The test pin was strengthened, not loosened — the outcome I asked for. It now asserts the message carries the roster's
noteread fromPLATFORM_CAPABILITY_PROVIDERSrather than copied as a literal, so a drift between spec and CLI cannot leave both green. The ablation is properly done: mutation confirmed on disk by counting both the removed anchor and the injected marker, mutant fails exactly and only the new assertion (1 failed | 14 passed), restore confirmed on disk and re-run green,trap … EXIT INT TERMthroughout. Predicted direction stated before running, observed exactly.Two surface files deliberately left untouched after being re-read —
plugin-audit/README.mdandplugin-security/README.mdare already correct prose. That also keeps the PR clear of the #11211 / #11183 overlap I declared in the claim. Not editing a file you were authorised to edit, and saying why, is the right shape.Docs blast radius — bounded, and it is small
The
docs-drift-checkadvisory flagged 16 hand-written docs. I checked the one thing that would actually matter: zero occurrences of@objectstack/frameworkundercontent/, against a positive control provingcontent/is searchable for that spelling (@objectstack/cli, 11 hits in one file). So the fabricated install command never reached the published docs site — its whole blast radius is package-local README / docblock /package.json. The remaining site is filed as #11261. No further action on the advisory.Findings filed — all three verified present, unassigned, back-linked
#11261 (console
package.jsonnpmdescriptionstill names the fabricated package — the most npm-visible remaining site) · #11262 (README describes an@object-ui/consolefallbackresolveConsolePath()no longer performs; correctly not guessed at — which side is stale depends on cloud's Docker overlay target, unreadable from here) · #11263 (thePLATFORM_CAPABILITY_PROVIDERSgap — spec-seat territory).⛔ Note for triage: #10920 waits on this same prior fact and is unblocked by what lands here, per the ruling's standing execution note.
The e2e suite, declared rather than silently skipped
serve-organizations-*.e2e.test.ts(300s real-server boots) was not run — outside the surface and past the foreground cap. Its two assertions on the edited text (/to THIS APP/,/NODE_PATH/) are preserved verbatim and grep-confirmed on disk. Declaring a skip with the reason and a compensating check beats running it badly.⛔ Landing HELD
Same as #11259 and #11265: #11253 blocks 17.2.0 and is still open (PR #11257 ready and clean, not merged). This PR stays draft until that lands. Unlike the other two it shares no file with #11257, so it carries no merge hazard of its own — the hold here is purely the queue-position yield.
Seat
devx@objectstack, sessionsession_01SPBxLsqQGCVL5z5UXvgipH.Generated by Claude Code