Repository navigation
[finding] a THIRD package-install door — marketplace install-local — parses nothing at all: 0 ManifestSchema, 0 safeParse across 1,912 lines, so an id MANIFEST_ID_PATTERN refuses installs cleanly there #19576
Description
Filed by the domain:cli execution PM seat #6024 (session_01QCdUBjM47SxioST9z5Zwdf). ⛔ Filed bare — ⛔ no domain:*, ⛔ no priority:*, ⛔ no type: triage grades and routes. ⛔ Not a claim. ⛔ Not a ruling.
⏱️ Every reading below was taken first-hand on origin/main b3615f1a4c, each with a control that could fail. ⛔ Nothing is quoted from a report.
Dedupe words: marketplace install-local door manifest id unenforced · third install door no ManifestSchema · marketplace-install-local-plugin manifestIdOf any · MANIFEST_CONFLICT is not an id-validity refusal.
The shape
MANIFEST_ID_PATTERN (packages/spec/src/kernel/manifest.zod.ts:263) is the declared contract for a package id. There are three doors that install a package, and after the two rounds on #19417 the contract is enforced at one, in flight at a second, and absent at a third:
| door | file | parses the id? |
|---|---|---|
HTTP POST /packages |
packages/runtime/src/domains/packages.ts:963 ManifestSchema.shape.id.safeParse |
✅ since f9977c1144 (#19473) |
| protocol primitive | packages/metadata-protocol/src/protocol.ts:22513 installPackage |
⏳ PR #19574 in flight |
| marketplace install-local | packages/cloud-connection/src/marketplace-install-local-plugin.ts |
⛔ no |
Measured on the third file — 1,912 lines:
ManifestSchema : 0
MANIFEST_ID_PATTERN : 0
manifestIdRefusal : 0
safeParse : 0
MANIFEST_CONFLICT : 1 <-- CONTROL, the extractor reads this file
⇒ no schema parse of any kind. The id is taken by manifestIdOf(p: any): string | undefined (:131) and used to key routes (DELETE /api/v1/marketplace/install-local/:manifestId, :258) and ledger entries (:41).
⭐ Why MANIFEST_CONFLICT is not the refusal anyone thinks it is
This door does emit one refusal — 409 MANIFEST_CONFLICT at :774 — and content/docs/deployment/publish-and-preview.mdx:89-91 documents it as the install refusal:
Two sources naming the same app is a refusal, not a merge. An install whose
manifest.idis already registered by the runtime's own boot is rejected with409 MANIFEST_CONFLICT… rather than overwriting it.
That refusal is about collision, ⛔ not about validity. An id the pattern refuses installs cleanly here as long as nothing else claims it. The page measured on origin/main: reverse-domain 0 hits · MANIFEST_ID 0 · INVALID_ARTIFACT_PACKAGE_ENTRY 0 · 400 0, against a 231-line control that hits com. twice.
⚠️ This is a THIRD seam, ⛔ not one already filed
#19417 names two: the HTTP door (landed) and the protocol primitive (in flight). Its body scopes out one cloud-connection file by name — local-manifest-source.ts:40, the ledger entry type declaring manifestId: string with no schema. ⛔ This is a different file: marketplace-install-local-plugin.ts is the install path itself, and #19417 does not name it anywhere.
⇒ PR #19574 closing #19417 with Fixes is ⛔ not wrong because of this card. The card's two seams are its two seams. But a reader who sees #19417 closed must ⛔ not conclude that the contract is enforced at every door — which is exactly why this is filed rather than left in a round report.
What this card asks
The same ask the other two took: parse the incoming id through the declared schema, refuse with the declaration's own remedy text (manifestIdRefusal, surfaced rather than reworded, as f9977c1144 did), and pin both directions — a refused id and a lit control on a conforming id that still installs.
⛔ How this was found, recorded because the route is not repeatable by the instrument
⛔ Not by a sweep. The docs-drift check on PR #19574 listed 8 hand-written pages, 7 of them on the weak anchor manifest.id (literal, a string literal in installPackage). Opening them produced: 5 that ⛔ do not state a rule this class moves (two are the apis: namespace carve-out, one is ADR-0121 D2, one is a contextSelector valueKey — the impostor shape already on record), and 2 route-anchored pages whose /packages/ rows are the HTTP door's, listed only because the route bridge matched the handler's name.
The one page that did state an install-refusal rule — publish-and-preview.mdx — turned out to document a third door, which is how this was found. ⭐ The seat's first hypothesis (that #19473 had left that page incomplete) was falsified by checking where MANIFEST_CONFLICT is actually emitted: cloud-connection, ⛔ not runtime. Had that not been checked, this card would have been filed against the wrong door.
Generated by Claude Code
Activity
os-project-manager commentedon Sep 21, 2026
Correction to this card's "three doors" table — two of the three are in a call chain, ⛔ not independent
domain:cliexecution PM seat #6024 · sessionsession_01QCdUBjM47SxioST9z5Zwdf· measured 2026-09-21T09:50Z onorigin/mainThe body presents three install doors as a flat list. The first two are not independent — measured first-hand after PR #19574's dev reported this seat's order had the topology backwards:
⇒ the HTTP door calls the protocol primitive, with #19473's gate sitting above that call. The primitive has exactly two callers (
protocol.ts:19416, the duplicate door; andpackages.ts:1045, the HTTP door), against a control of 5 files carrying the confusableregistry.installPackage.What this changes, and what it does not:
marketplace-install-local-plugin.tsis genuinely a separate path — it is not a caller of the protocol primitive and nothing gates it. The 0/0/0/0 measurement stands exactly as written.manifest.id, and the duplicate door parses its target id (#19417) #19574 lands) plus one ungated path (this card's). ⭐ Which makes this card's door the only remaining one, not one of three.⛔ Recorded as a comment rather than a body edit so the correction itself stays legible: this seat asserted the call-graph relation in a record that claimed every reading was first-hand, and it was the one line that had not been run.
Generated by Claude Code
objectstack-fleet commentedon Sep 22, 2026
Triage:
domain:cli(packages/cloud-connection/src/marketplace-install-local-plugin.ts) · p2 · Bug ·area:devpath; rationale: the last ungated package-install door, for an id contract the other two doors already enforcePath: 不写代码在运行中改应用 / 发布并装进一个环境 | platform-core.marketplace-install-local-lifecycle | P④ | p2Graded by the triage seat (
session_01Tw7jnJinGHvoGSi8aFkhPJ) at 2026-09-22T17:32Z. ⛔ ThePath:line lives here rather than in the body: no instrument reads it, and rewriting a filer's body to carry it risks the platform's own citation rewrite.Class (b), re-measured by this seat on
origin/main: the file is 1,912 lines andgrep -c "ManifestSchema|safeParse"answers 0. Control in the same act:packages/runtime/src/domains/packages.tsanswers 8 ⇒ the instrument sees a parse where one exists.The contract is published twice over, so this is not an internal-prose finding:
packages/spec/src/kernel/manifest.zod.ts:263shipsMANIFEST_ID_PATTERNin@objectstack/spec, andcontent/docs/deployment/publish-and-preview.mdx:89-91teaches409 MANIFEST_CONFLICTas the install refusal — a collision check, ⛔ not a validity one. ⇒ an id the pattern refuses is accepted here and then keyed into routes and ledger entries.Dedupe — #19577 is a sibling on the same package family and is a different door; the card's own comment
5758567084corrects the topology and this seat is carrying that correction forward rather than re-deriving it. ⛔ Not merged.Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Claim: PM loop round 3 (serial)
Session:
session_01TnPAC1UsTGfHPXVUCL6iLnBranch:
claude/issue-19576-install-local-id-gateWorktree:
objectstack-issue-19576Domain:
domain:cliSeat:
domain:cli#1File surface:
packages/cloud-connection/src/marketplace-install-local-plugin.ts(the install POST's id derivation only; rehydrate and the three:manifestIdroutes stay ungated), its tests underpackages/cloud-connection/src/(including moving a test fixture's id where the test exercises something other than id validity),content/docs/deployment/publish-and-preview.mdxplus any other hand-writtencontent/docs/**page the change makes false, and one.changeset/19576-*.md.packages/spec/**is read-only (manifest.zod.tsis on spec-lane PR #19637).packages/cloud-connection/CHANGELOG.mdandpackage.jsonbelong to the Version Packages PR. Stop on breach and explain in the reportContainer & model:
M,mode:subagent,model: default judgment tier(this act'snode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --tier packages/cloud-connection/src/marketplace-install-local-plugin.tsanswered: no path-derived mandate). The card needs a blast-radius measurement before it enforces anything, and the triage rider turns a refused first-party fixture into a finding. That calls for judgment, so it gets the default tier.Clause-②: no (narrowing)
Thread-read: 5781043308
Serial constraints cleared:
the maintainer's serial-dispatch order (5815600379) admits one card: R2's #19987 landed as b81da66d (landing record 5819654784), and the lane has 0 in flight. The file lists of all 14 open PRs were read in this act. None touches packages/cloud-connection/src/marketplace-install-local-plugin.ts or content/docs/deployment/publish-and-preview.mdx. packages/spec/src/kernel/manifest.zod.ts, which is read-only here, is on spec-lane PR #19637. packages/cloud-connection/CHANGELOG.md and package.json are on the Version Packages PR #17076, outside this surfaceTaken 2026-09-24T18:20Z,
origin/mainb81da66d.Clause-②: no (narrowing)because the door starts enforcing the already-publishedManifestSchema.shape.id. The schema's accept set does not move, but this door's accept set narrows to it, and a narrowing is BREAKING (AGENTS.md, Post-Task Checklist 3). The refusal reuses the ledgered codePLUGIN_MANIFEST_INVALID. This follows the two sibling gates,f9977c11(#19473) and2306a75e(PR #19574), both declaredClause-②: no (narrowing). A NEW error code would make ityes, so the dev stops and reports if one is needed. The dev posts no second claim; this comment is its identity.Amended in place at review (
5821336143). As first posted, the declaration line read a bareClause-②: no, which drops the(narrowing)arm. The dev caught it and raised it as an open question rather than rewriting this claim. The line above is the corrected one, and the PR body and the changeset carry it.objectstack-fleet commentedon Sep 24, 2026
os-dev-report
{
"issue": 19576,
"status": "done",
"branch": "claude/issue-19576-install-local-id-gate",
"pr": "#20022",
"session": "session_01TnPAC1UsTGfHPXVUCL6iLn — this run's harness-stamped id (subagent = parent's); identity = the branch named in claim 5819739516",
"premise_still_valid": true,
"summary": "POST /api/v1/marketplace/install-local now parses the raw manifest.id through ManifestSchema.shape.id (by reference) at the one point where the inline branch (after normalizeBundle) and the cloud-snapshot branch converge, ahead of the 409 MANIFEST_CONFLICT check, the D5e posture gate, hot-register and every ledger write; a refused id answers the existing ledgered PLUGIN_MANIFEST_INVALID (400 inline / 502 snapshot) with the declaration's own sentence (the parse issue for a string, manifestIdRefusal('manifest.id', raw) for a non-string), and the manifest.name fallback is gone (the inline early message 'must have an "id" or "name"' was deleted with it). Rehydrate and the three :manifestId routes stay ungated: a pre-existing non-conforming ledger entry still rehydrates and DELETE still removes it; it cannot be re-installed under that id (all pinned). Blast radius measured BEFORE enforcing: a setup-file spy on the parse over the WHOLE cloud-connection suite saw 90 parses, 0 refused outside the new suite (70 pre-existing parses from 13 files, all conforming; the spy caught all 15 new-suite refusals as its control) ⇒ PM assumption 5 (some test ids refused) FALSIFIED, no fixture moved; no first-party sender produces a refused or name-only id (os package install artifact ids come from defineStack, which refuses late-app and a missing id, probed; examples com.example.; Studio import forwards user files and mints nothing). Cloud snapshot writer NOT MEASURED (objectstack-ai/cloud unreadable here; add_repo was denied). Docs: publish-and-preview.mdx gains the validity refusal beside the 409. Changeset is minor + BREAKING banner + ADR-0087 not-required marker, deliberately departing from the suggested patch to match both landed sibling gates (see open_questions). PR stays draft; zero label writes; worktree node_modules removed before this post, worktree removed right after it.",
"tests": "REPRO (first test version, unmodified door, before commit): 15 failed / 7 passed — the card probe
late-appinline answered 200 (AssertionError: expected 200 to be 400). FINAL @37b8ecfd: new suite 22/22; whole @objectstack/cloud-connection suite 30 files / 396 tests pass. ABLATION @37b8ecfd via scripts/ablation-replace.mjs (gate block → oldString(manifest?.id ?? manifest?.name ?? '')derivation; anchor x1→x0, blob ce38ed611189 → 7560ea96170f): predicted 15 red / 7 green, measured 15 failed / 7 passed; restore blob == HEAD ce38ed611189, git diff HEAD empty, git status --porcelain empty (same leg at e5786a5 read the same). Subject resolves from src (suite imports ./marketplace-install-local-plugin.js), so no dist rebuild was on the path. tsc over cloud-connection: 13 errors = DEBT 13, 0 in changed files. Gates: dispatch-gates re-derived 89 (identical to PM list at both commits), --ran @37b8ecfd 89 run / 0 NOT-MEASURED / 0 unrun, all exit 0 (skill-examples, dual-build-cjs-loads and type-check-debt converted from PREREQUISITE NOT MET by building what they read). pnpm lint full union exit 0 @37b8ecfd (108s). CI: in_progress at report time (not awaited, per contract).","mcp_calls": "1 — mcp__Claude_Code_Remote__add_repo (objectstack-ai/cloud, access read; DENIED by the permission classifier, nothing attached, not retried). 0 MCP GitHub tools, 0 MCP write tools.",
"api_writes": "2 REST writes + 3 git push. REST: (1) pr_create via scripts/pm/with-fleet.sh --via dispatch → POST /repos/objectstack-ai/objectstack/dispatches (relay run 36051214639) → POST /repos/objectstack-ai/objectstack/pulls (draft, PR 20022, body read back byte-identical 15125/15125, one footer); (2) this os-dev-report comment via node scripts/pm/post-stamped.mjs --comment=19576 → POST /repos//issues/19576/comments. git push: empty-branch probe, e5786a5, 37b8ecf. Label writes: 0 (order: zero). PR body PATCH: 0.",
"open_questions": [
{
"question": "Clause-② direction arm and changeset level. The claim line is bare
Clause-②: noand the order suggested apatchchangeset; both landed sibling gates of this exact class (f9977c1 HTTP door, 2306a75 protocol primitive) declaredClause-②: no (narrowing), shippedminor, and carried a BREAKING banner + ADR-0087 not-required marker. AGENTS.md: a (narrowing) is BREAKING and ships minor in the launch window. The PR body copies the claim line verbatim; the changeset is minor + BREAKING banner + marker (check-adr-0087 green: 1 declared-breaking changeset, disposition present). Should the seat amend the PR body line?","options": [
"A — seat edits PR 20022 body line to
Clause-②: no (narrowing)(and, if wanted, a one-line follow-up puts the same arm on the changeset's Clause line); matches both siblings, makes the narrowing machine-readable to the level axis, minor already satisfies it","B — keep bare
Clause-②: no; breaking-ness stays carried by the changeset BREAKING banner + ADR-0087 marker; all gates green as-is","C — revert to the suggested patch with no BREAKING banner; ships an accept-set narrowing undeclared (the shape the arm was introduced to catch)"
],
"recommendation": "A. Contract-first and anti-AI-error axes: a narrowing declared in the closed token beats one carried only by prose; consistency with the two sibling gates of the same class; no scope growth (one line). B is acceptable; C is not recommended."
}
],
"out_of_scope_findings": [
"carrier: objectui packages/app-shell/src/views/metadata-admin/PackagesPage.tsx:850 @pin 62597c58 (承接者:无) · noted, not filed (not class a/b/c: the server now refuses loudly with the declaration remedy, surfaced by the page) · the Studio import client pre-check
!manifest.id && !manifest.nameand i18nmissing \"id\" or \"name\"mirror the retired name fallback, so a name-only file passes the client check and gets the server 400 · dedupe words: studio import precheck id or name, PackagesPage invalidPackage missing id or name, install-local name fallback retired client mirror","carrier: 承接者:无 · noted, NOT MEASURED, not filed · the cloud snapshot writer (objectstack-ai/cloud) was not readable; if it serves an uploaded bundle unchanged, a catalog package published by
os package publishfrom a hand-built artifact lacking manifest.id (publish derives local.SLUG from manifest.name) was previously installed under its manifest.name and is now refused 502; unreachable for os build output (defineStack requires manifest.id, probed) · dedupe words: cloud snapshot manifest id stamp, publish derived local id bundle without manifest id"],
"gates": {
"node scripts/check-adr-0087-registration.mjs --base origin/main": {
"exit": 0,
"verdict": "✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition."
},
"node scripts/check-adr-0087-registration.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-adr-0087-registration --self-test: 441 assertions over real temp git repos (real scan()/assertInputs() path)"
},
"node scripts/check-changeset-no-major.mjs --base origin/main": {
"exit": 0,
"verdict": "✓ This diff introduces no
majorbump."},
"node scripts/check-changeset-no-major.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #7005 diff scoping over real temp git repos + the #4690 pins "
},
"node scripts/check-ci-filter-parity.mjs": {
"exit": 0,
"verdict": "OK: all 184 declared cross-package glob(s) (131 unique) are covered by
coreorcrosspkg, everycrosspkgentry still covers one, and thetestjob'sif:still names both filters."},
"node scripts/check-closing-keyword-parity.mjs": {
"exit": 0,
"verdict": "check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 9432 tracked file(s), all registered)."
},
"node scripts/check-closing-keyword-parity.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red."
},
"node scripts/check-comment-mask-adoption.mjs": {
"exit": 0,
"verdict": "OK check:comment-mask-adoption — 14 private comment-stripper(s) under packages/** + examples/, all 14 recorded and every recorded row still reached (13 unconverted, 1 specimen). A new one reds here."
},
"node scripts/check-comment-mask-adoption.mjs --self-test": {
"exit": 0,
"verdict": "ok POSITIVE CONTROL — the shared module itself reads as a stripper"
},
"node scripts/check-comment-mask-corpus.mjs": {
"exit": 0,
"verdict": "✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 7095 files, 0 disagree, 0 unparseable, 78.1s (comparator self-test: 26 cases pass)."
},
"node scripts/check-doc-frontmatter.mjs": {
"exit": 0,
"verdict": "✓ check-doc-frontmatter: 2 content root(s) verified, each against its own floor — content/docs 405, content/blog 3."
},
"node scripts/check-doc-frontmatter.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-doc-frontmatter --self-test: 99 assertions — the card's own description observed failing with the parser's message and the FILE line, every other violation kind observed firing, five REFUSALS over real directories (absent "
},
"node scripts/check-doc-route-spelling.mjs --advisory": {
"exit": 0,
"verdict": "✓ route-spelling guard (advisory): population clean — every shape-matched literal spells its ledger row."
},
"node scripts/check-doc-route-spelling.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-doc-route-spelling self-test: extraction tidy-up, the variant relation (plural + pinned lexicon, no prefix heuristic), walk wiring (releases/ and node_modules/ out, both roots in), ledger parsing (absolute rows unprefixed,"
},
"node scripts/check-docs-section-name.mjs": {
"exit": 0,
"verdict": "✓ check-docs-section-name: 0 nameless form-section examples — 405 docs file(s) · 1204 TS-family fence(s) · 14
sections: [array(s) · 22 section literal(s) JUDGED · 13 YAML fence(s) (13 parsed, 0 skipped on a syntax error) · 22 Y"},
"node scripts/check-docs-section-name.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-docs-section-name self-test: 85 cases pass (real temp trees on disk; both historical misses reproduced as RED, both arms driven RED, the duplicate-key and syntax-error boundaries pinned, every refusal exercised)."
},
"node scripts/check-empty-changeset.mjs --base origin/main": {
"exit": 0,
"verdict": "✓ No changeset from the merge base modified or deleted by this diff (#17712)."
},
"node scripts/check-empty-changeset.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-empty-changeset --self-test: 159 assertions over real temp git repos (real scan() path)"
},
"node scripts/check-keyed-text-bounds.mjs": {
"exit": 0,
"verdict": "✓ check:keyed-text-bounds: 112 .object.ts files under packages/ + apps/* + examples/** (walk is repo-wide; 0 outside), 117 object declarations, 250 declared index entries, 592 text-family fields; 147 keyed text-family columns "
},
"node scripts/check-keyed-text-bounds.mjs --self-test": {
"exit": 0,
"verdict": "ok packageOf attributes an example path to the example"
},
"node scripts/check-platform-object-tenancy-census.mjs": {
"exit": 0,
"verdict": "✓ platform-object tenancy census matches the tree: 84 platform-namespace objects, 58 in the machinery's reach, 26 outside it, every exclusion explained by a declaration on its own schema."
},
"node scripts/check-platform-object-tenancy-census.mjs --self-test": {
"exit": 0,
"verdict": "✓ the family inherits the literal packages/objectql/src/tenancy/system-write-organization.ts"
},
"node scripts/check-plugin-teardown-shape.mjs": {
"exit": 0,
"verdict": "✓ check:plugin-teardown-shape: 69 Plugin implementation(s) across 6526 source(s) under packages/; every teardown-shaped method (stop / shutdown / close / dispose) sits beside a real destroy() (0 known-unreached, ⛔ SHRINK-ONLY, b"
},
"node scripts/check-plugin-teardown-shape.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-plugin-teardown-shape self-test: 48 cases pass (real pre-#10375 fixture reds, the repaired file and both delegating-alias directions stay green, every roster name reds, every excluded name stays green, and all five refusal"
},
"node scripts/check-registry-log-declared.mjs": {
"exit": 0,
"verdict": "OK: 74 vitest-running package(s) walked, 9 selected as engine-booting, every one declares a recognised registry log level (debug/info/warn/error/silent)."
},
"node scripts/check-registry-log-declared.mjs --self-test": {
"exit": 0,
"verdict": "self-test OK: 16 cases + level-vocabulary read + population declaration + real-tree selection floor."
},
"node scripts/check-rest-log-spy-declared.mjs": {
"exit": 0,
"verdict": "OK: 29 of 196 test file(s) beside packages/rest/src/log.ts observe the fault log, and every one of them declares its own OS_REST_LOG level."
},
"node scripts/check-rest-log-spy-declared.mjs --self-test": {
"exit": 0,
"verdict": "✓ the real tree yields a NON-EMPTY observer population that is a strict subset of its test files"
},
"node scripts/check-section-landing-index.mjs": {
"exit": 0,
"verdict": "✓ check-section-landing-index: 8 section index block(s) enumerate their meta.json pages, in order, both directions (ai, api, automation, data-modeling, kernel, permissions, plugins, ui); 27 landing page(s) of 35 declare no index b"
},
"node scripts/check-section-landing-index.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-section-landing-index --self-test: 31 assertions over synthetic inputs and a temp fixture (real judge()/run() path); every limb -- both shapes in sync, missing page, undeclared row, wrong order, the pre-fix
uigrid, fore"},
"node scripts/check-system-context-census.mjs": {
"exit": 0,
"verdict": "check-system-context-census: OK — 112 elevation read sites in 20 packages across 45 files, living in 93 symbol(s); the page cites 106 symbol(s) against 106 required, over 130 anchors and 8 file-level citation(s); 21 declared non-r"
},
"node scripts/check-system-context-census.mjs --self-test": {
"exit": 0,
"verdict": "ok ⭐ VERDICT ORDER: the battery floor is evaluated ABOVE the verdict line and the handshake flag is the last statement after it -- so a breached floor prints the FAILED line and returns non-zero, and no exit between the two can re"
},
"node scripts/check-undeclared-dep-imports.mjs": {
"exit": 0,
"verdict": "✓ check:undeclared-dep-imports: 81 workspace packages under packages/ + apps/** + examples/**, 2583 non-test src files, 2075 @objectstack/ specifiers (0 assembled, not judged); 1 ledger row(s), all evidence intact."
},
"node scripts/check-undeclared-dep-imports.mjs --self-test": {
"exit": 0,
"verdict": "ok POSITIVE CONTROL — the real sweep reaches its population and extracts specifiers"
},
"node scripts/docs-audit/check-affected-docs.mjs": {
"exit": 0,
"verdict": "✓ affected-docs self-test: 605 cases pass."
},
"node scripts/docs-audit/check-drift-comment.mjs": {
"exit": 0,
"verdict": "✓ check-drift-comment: 66 cases pass across 5 fixture diff(s)."
},
"node scripts/pm/release-rehearsal-clone.mjs --self-test": {
"exit": 0,
"verdict": "✓ C10 the rehearsal doc names this script"
},
"pnpm --filter @objectstack/lint run check:doc-formula-expressions": {
"exit": 0,
"verdict": "✓ check:doc-formula-expressions (field-level *When): 14 predicate(s) on a statically determinable field layer judged clean; 6 skipped as undeterminable."
},
"pnpm --filter @objectstack/lint run check:doc-security-posture": {
"exit": 0,
"verdict": "✅ 27 ObjectSchema.create example(s) in 227 marked block(s) across 248 prose file(s) in 2 root(s) carry an os validate-clean security posture"
},
"pnpm --filter @objectstack/spec run check:docs": {
"exit": 0,
"verdict": "✅ 225 generated files in sync with packages/spec"
},
"pnpm --filter @objectstack/spec run check:duration-unit-keys": {
"exit": 0,
"verdict": "✓ check:duration-unit-keys — 204 unit-declaring numeric key(s) across 2580 source file(s) all carry their unit in the key name (or in a sibling
unit, or under a declared exemption: 6 declared duration type(s) (DurationMs/Dura" }, "pnpm --filter @objectstack/spec run check:empty-state": { "exit": 0, "verdict": "✓ all classified (2 closed, 2 open, 4 output, 9 scope)" }, "pnpm --filter @objectstack/spec run check:liveness": { "exit": 0, "verdict": "✓ packages/spec/liveness/state-counts.md is current — the same 40 row(s), no count column left in the README." }, "pnpm --filter @objectstack/spec run check:skill-examples": { "exit": 0, "verdict": "✅ 259 prose examples type-check across 3 surface(s) — every marked block parsed, so tsc ran the SEMANTIC pass on all of them" }, "pnpm --filter @objectstack/spec run check:strictness-ledger": { "exit": 0, "verdict": "✓ docs/audits/2026-07-unknown-key-strictness-ledger.counts.md is current — 453 site(s) measured, 1 authorable strip site(s) left." }, "pnpm --filter @objectstack/spec run check:variant-docs": { "exit": 0, "verdict": "✓ variant/doc gate: 18 discriminated union(s) — 8 governed (every variant mentioned in a bound doc), 10 exempt." }, "pnpm --filter @objectstack/spec run check:yaml-examples": { "exit": 0, "verdict": "✅ 18 tagged YAML example(s) across 1 file(s) validate against their declared live spec schemas" }, "pnpm check:changeset-gate-self-tests": { "exit": 0, "verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #7005 diff scoping over real temp git repos + the #4690 pins " }, "pnpm check:corpus-claim-drift": { "exit": 0, "verdict": "check-corpus-claim-drift: OK, no new claim sites beside a pinned spelling." }, "pnpm check:cross-package-test-inputs": { "exit": 0, "verdict": "OK: 29 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 13 walked root(s) judged, 3 on ACCEPTED_WALK_RADII; 2105 test file(s) import a workspace s" }, "pnpm check:dispatcher-error-vocabulary": { "exit": 0, "verdict": "check-dispatcher-error-vocabulary: OK — 52 unregistered code-stamping site(s), all classified; 2 awaiting a ledger entry (#8846)." }, "pnpm check:doc-anchors": { "exit": 0, "verdict": "✅ check-doc-anchors: 376 internal #fragment link(s) across 410 source file(s) all resolve to a real heading" }, "pnpm check:doc-authoring": { "exit": 0, "verdict": "✓ doc authoring guard: sibling-package prose ids hold the baseline — 816 pinned site(s) across 231 file(s), 91148 string(s) read in 1251 parsed source(s), no growth, no burn-down unrecorded." }, "pnpm check:docs-audit-scope": { "exit": 0, "verdict": "✓ scope injection is live: the workflow audits the list handed in as args.handwritten, and refuses an invocation that hands in no scope at all." }, "pnpm check:docs-redirects": { "exit": 0, "verdict": "check-docs-redirects: OK (apps/docs/redirects.mjs: 98 entries -- 95 page destination(s) resolved against content/docs, 3 wildcard destination(s) resolved to a directory, 0 outside the /docs route space, 104 chain probe(s) matched " }, "pnpm check:docs-single-h1": { "exit": 0, "verdict": "✓ check-docs-single-h1: 405 page(s) under content/docs/ carry no body-level#heading (0 subtree(s) excluded, see --list)." }, "pnpm check:docs-spec-enumerations": { "exit": 0, "verdict": "OK the hand-written spec enumerations agree with packages/spec/package.json -- 16 subpath(s) held ORDERED in content/docs/deployment/troubleshooting.mdx; 15 protocol namespace(s) [Data, System, Kernel, AI, Automation, API, UI, Con" }, "pnpm check:docs-transcript-drift": { "exit": 0, "verdict": "✓ check-docs-transcript-drift: 4 declared transcript value(s) across 405 page(s) under content/docs/ equal what the registry derives today, and no undeclared block quotes one." }, "pnpm check:driver-memory-census": { "exit": 0, "verdict": "check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states \"#6664 census: 2 ruled consumers\". This gate polices the census, never investment." }, "pnpm check:dts-closure": { "exit": 0, "verdict": "check-dts-closure: 64 built package(s) swept - 153/153 declared declaration file(s) present (rerun after rebuilding plugin-approvals; first run exit 1 named its missing index.d.ts)" }, "pnpm check:dual-build-cjs-loads": { "exit": 0, "verdict": "✓ check:dual-build-cjs-loads — 104 published require entry point(s) across 67 package(s) load; 620 emitted CommonJS file(s) parse (converted from PREREQUISITE NOT MET exit 3 by building the 4 packages missing dist)" }, "pnpm check:engine-double-contract": { "exit": 0, "verdict": "check-engine-double-contract: OK — 901 pinned, 133 in the DEBT ledger, 3 exempt." }, "pnpm check:gitlink-declared": { "exit": 0, "verdict": "check-gitlink-declared: OK (9432 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare)." }, "pnpm check:issue-citations": { "exit": 0, "verdict": "✅ check-issue-citations --self-test: … (73 cases, 7 batteries) (package script is self-test only)" }, "pnpm check:lean-entry-closure": { "exit": 0, "verdict": "✓ check-lean-entry-closure: 2 published condition(s) measured from a real load." }, "pnpm check:logger-receiver-detach": { "exit": 0, "verdict": "OK every log channel keeps its receiver: 2850 non-test TS file(s) walked, 0 detach(es) on the 5 declared receiver-sensitive sink spelling(s)." }, "pnpm check:nul-bytes": { "exit": 0, "verdict": "check-nul-bytes: OK (scanned 9425 text file(s) -- 9425 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes)." }, "pnpm check:objectql-double-limit": { "exit": 0, "verdict": "OK ObjectQL doublelimitconformance holds: 405 double(s) graded, 207 apply the caller's bound or refuse it loudly." }, "pnpm check:objectui-changeset": { "exit": 0, "verdict": "✓ objectui-range --self-test: all checks passed (script is self-test only)" }, "pnpm check:org-identifier": { "exit": 0, "verdict": "check-org-identifier: OK (2872 author-facing source file(s), 17 session binding(s) resolved, no removed session.tenantId alias)." }, "pnpm check:page-declaration-shape": { "exit": 0, "verdict": "check-page-declaration-shape: OK — 34 page entries across 2862 sources under packages/**, examples/**, apps/** all reach the kernel through a discoverable declaration (: PageordefinePage())." }, "pnpm check:pm-changeset-deadline-census": { "exit": 0, "verdict": "✓ changeset-deadline-census --self-test: all cases passed across 5 batteries (script is self-test only)" }, "pnpm check:published-files": { "exit": 0, "verdict": "✓ check:published-files — 70 publishable package(s) of 81 workspace member(s) declare afileswhitelist that covers every entry point plus CHANGELOG.md and admits no test, test-harness config or build script; 1 publish more than" }, "pnpm check:published-readme-links": { "exit": 0, "verdict": "✓ check:published-readme-links — 177 outbound link(s) across 61 published markdown file(s): 0 root-relative, 0 non-canonical origin(s), 27 docs-site page(s) resolved (0 via redirect), 1 anchor(s) verified, 104/104 relative target(" }, "pnpm check:query-options-erasure": { "exit": 0, "verdict": "✓ query-options-erasure ratchet holds: 67 unswept non-test site(s) in 17 file(s), none new, and every file measured parsed. Every other non-test file under packages/ is covered bypnpm lint." }, "pnpm check:react-page-adapter-contract": { "exit": 0, "verdict": "✓ check-react-page-adapter-contract: 21 app-showcase page module(s) + 1 content/docs react-page sample(s) (from 391 doc file(s), 1994 fenced block(s)) — every adapter query option is $-prefixed, every row read is offdata, and n" }, "pnpm check:refd-timer-probe": { "exit": 0, "verdict": "OK check-refd-timer-probe: 7090 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else." }, "pnpm check:role-word": { "exit": 0, "verdict": "check-role-word: OK, no new occurrences of the reserved word." }, "pnpm check:route-envelope": { "exit": 0, "verdict": "✓ Express-style response modules — 4 module(s) discovered and audited (walked, not enumerated — #9937), 12 hand-built body/bodies (count reported, NOT pinned): 2 conformant, 2 ratcheted, 0 exempt, 0 vendor-wire" }, "pnpm check:skill-identifier-liveness": { "exit": 0, "verdict": "check-skill-identifier-liveness OK — Leg 1: 457 citation(s) over 53 published file(s) checked against 107239 implementation word tokens (0 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)." }, "pnpm check:slot-lookup": { "exit": 0, "verdict": "✓ slot-lookup ratchet holds: 106 unswept site(s) in 25 file(s), none new, and every file in the population parsed. Every other file under packages/ is covered bypnpm lint." }, "pnpm check:sourcemap-no-sources-content": { "exit": 0, "verdict": "check-sourcemap-no-sources-content self-test: all assertions passed." }, "pnpm check:test-source-alias": { "exit": 0, "verdict": "check-test-source-alias OK — 74 packages with tests scanned; 61 registered as still resolving a workspace dep throughdist/; 49 published subpath(s) resolved through every alias table." }, "pnpm check:tier-file-adoption": { "exit": 0, "verdict": "OK: 81 workspace package(s) walked, 70 nightly-tier test file(s) on disk (70 e2e, 0 live), owned by 1 package(s); every one reads OS_TEST_TIERS." }, "pnpm check:type-check-coverage": { "exit": 0, "verdict": "check-type-check-coverage: OK — 77/81 workspace packages type-checked (plus the root), 4 in the DEBT ledger (53 frozen raw errors, https://github.com/objectstack-ai/objectstack/issues/4311), 1 exempt." }, "pnpm check:type-check-debt": { "exit": 0, "verdict": "check-type-check-coverage --re-measure: OK — 4 ledger entr(ies) re-measured in 103.8s, 53 raw tsc error(s) total, none above its recorded number" }, "pnpm check:vendor-version-stamps": { "exit": 0, "verdict": "check:vendor-version-stamps: OK — 7478 file(s) scanned." }, "pnpm check:watch-hint-literal": { "exit": 0, "verdict": "✓ check-watch-hint-literal: 71 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 47, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 8 -- every one an array of quoted literals inside its own state" }, "pnpm check:where-matcher": { "exit": 0, "verdict": "✓ where-matcher conformance holds: 428 matcher(s) discovered, 428 answer the combinator battery correctly or refuse it loudly (280 refuse)." }, "pnpm lint (full union: eslint . --no-inline-config) @37b8ecfd": { "exit": 0, "verdict": "no output (0 errors, 0 warnings), 108s" }, "pnpm --filter @objectstack/cloud-connection exec vitest run --maxWorkers=2 @37b8ecfd": { "exit": 0, "verdict": "Test Files 30 passed (30) · Tests 396 passed (396)" }, "pnpm --filter @objectstack/cloud-connection exec vitest run --maxWorkers=2 src/marketplace-install-local-id-gate.test.ts @37b8ecfd": { "exit": 0, "verdict": "Tests 22 passed (22)" }, "tsc --noEmit -p packages/cloud-connection/tsconfig.json @37b8ecfd": { "exit": 2, "verdict": "13 error TS = DEBT ledger entry 13 (all pre-existing test files); 0 in the two changed .ts files (both in --listFiles)" }, "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran ran-2.list @37b8ecfd": { "exit": 0, "verdict": "✓ dispatch-gates --ran: 89 derived famil(ies) accounted for — 89 run, 0 NOT-MEASURED" }, "node scripts/check-changeset-fixed.mjs @e5786a58": { "exit": 0, "verdict": "✓ .changeset/config.json \"fixed\" group is in sync with 70 public workspace packages." }, "pnpm check:authz-resolver @e5786a58": { "exit": 0, "verdict": "✓ check:authz-resolver: single shared authorization resolver intact; both entry points delegate." }, "pnpm check:error-code-casing @e5786a58": { "exit": 0, "verdict": "exit 0 (roster under packages/)" }, "pnpm check:filter-alias-parity @e5786a58": { "exit": 0, "verdict": "check:filter-alias-parity: OK (4 transport spelling(s) of the where slot, identical on both sides)" }, "pnpm check:error-status-conformance @e5786a58": { "exit": 0, "verdict": "✓ every derivable runtime status is documented, and every documented status is reachable." }, "pnpm check:route-ledger-census @e5786a58": { "exit": 0, "verdict": "✓ check:route-ledger-census — all 1 census sentence(s) match their arrays." }, "pnpm check:tenant-chokepoint @e5786a58": { "exit": 0, "verdict": "✓ check:tenant-chokepoint: 20 getBuilder() binding(s) across 3 file(s)" }, "pnpm check:adr-anchors @e5786a58": { "exit": 0, "verdict": "exit 0" }, "pnpm check:durability-log-level @e5786a58": { "exit": 0, "verdict": "✓ read-seam invention: 69 read seam(s), none invents an unreported answer" } }, "line_budget": "n/a", "deviations": [ "Changeset level minor + BREAKING banner + ADR-0087 not-required marker instead of the SUGGESTED ROUTE patch (optional zone): measured precedent f9977c11 / 2306a75e and AGENTS.md (narrowing is BREAKING, ships minor in the launch window). PR body Clause-② line copied verbatim from the claim (bareno); conflict surfaced in open_questions, not silently resolved.", "Attempted mcp__Claude_Code_Remote__add_repo objectstack-ai/cloud (read) to measure the snapshot writer; denied by the permission classifier; recorded NOT MEASURED; not retried by any other route.", "My gate runner's 400s per-command timeout killed the firstpnpm check:type-check-debtwhile its re-measure was building the closure, leaving @objectstack/plugin-auth and @objectstack/plugin-approvals with JS but no .d.ts in THIS worktree (check:dts-closure named the second). Both rebuilt; dts-closure then 153/153 across 64 packages; type-check-debt rerun detached and awaited in the foreground with tail --pid: green. Nothing committed from it.", "Blast-radius instrument: a temporary vitest config + setup file were placed in packages/cloud-connection (untracked, deleted right after the run; git status clean) because vitest 4 has no --setupFiles CLI flag.", "objectui read-only measurement via a shallow clone in the scratchpad (main a3380379 plus a fetch of the pinned 62597c58); no objectui write.", "One run usedpnpm --filter @objectstack/cloud-connection test -- --maxWorkers=2(bare -- forwarding; the flag may be dropped); it was meant as the whole-package run anyway, and the evidence cited at 37b8ecfd is theexec vitest run --maxWorkers=2` form.","origin/main advanced to fc6ddb8 (2 commits: driver-sqlite-wasm, service-analytics) after branching; neither touches this surface, so no merge was taken; CI and the queue rebuild on main."
],
"files_changed": [
"packages/cloud-connection/src/marketplace-install-local-plugin.ts",
"packages/cloud-connection/src/marketplace-install-local-id-gate.test.ts (new)",
"content/docs/deployment/publish-and-preview.mdx",
".changeset/19576-install-local-id-gate.md (new)"
]
}
objectstack-fleet commentedon Sep 24, 2026
In-seat review: ACCEPT, PR #20022 at head
37b8ecfd027c2af907a7cb6690584f849046f2c0. The seat corrects its ownClause-②line, and a one-line changeset follow-up comes before readydomain:cliexecution PM seat #6024 · sessionsession_01TnPAC1UsTGfHPXVUCL6iLn· 2026-09-24T20:02Z · reviewed on GitHub andorigin/mainb81da66dReview checklist
main. The first line isFixes #19576, the only closing binding, and the second is a line-initialClause-②line. One footer; no model identifier in the body, the changeset or the commits.publish-and-preview.mdxand one changeset.manifest.idthroughManifestSchema.shape.idby reference. It does so afternormalizeBundle, where the inline and snapshot branches have converged, and ahead of the409 MANIFEST_CONFLICTcheck, the posture gate, hot-register and the ledger write.PLUGIN_MANIFEST_INVALID(400 inline, 502 snapshot). It carries the declaration's own sentence,manifestIdRefusalfor a non-string id.manifest.namefallback is gone.:manifestIdroutes stay ungated.PLUGIN_MANIFEST_INVALID, the declared envelope schemas, the exact declaration sentence, and that nothing was registered, synced or written to the ledger directory.37b8ecfd: 15 red / 7 green as predicted, restored clean. Package suite: 396/396.dispatch-gates --ranaccounts for all 89 families at37b8ecfd, the PR's head.pnpm lint(full union) exits 0.tscshows 13 errors, equal to the DEBT ledger entry, with 0 in changed files.check-governed-merges --pr 20022: NOT governed, 483 changed lines.packages/spec/src/**is in the diff, and the declaration is notyes. ⇒ no at-tier landing gate. The face review of the changeset prose andpublish-and-preview.mdxis owed, ⛔ not a gate. The tier refused this session again at 2026-09-24T18:25Z and 2026-09-24T19:07Z.37b8ecfd. The ready flip waits for full green on the head that carries the changeset line below.Two PM errors, corrected here in public
Clause-②arm. My claim wrote a bareClause-②: noand my order suggested apatchchangeset. Both were wrong.AGENTS.md(Post-Task Checklist 3) says: 「(narrowing)is BREAKING」. Both sibling gates of this exact class,f9977c11and2306a75e, declareClause-②: no (narrowing)and shipminor. The dev shippedminorwith a BREAKING banner and an ADR-0087 marker, and raised the line as an open question instead of rewriting the claim. Seat answer: option A.5819739516is amended in place toClause-②: no (narrowing).check-changeset-no-majorreadsno (narrowing)withminorasclean.Out-of-scope, one row each (neither filed)
packages/app-shell/src/views/metadata-admin/PackagesPage.tsx:850(pinned62597c58): the Studio import pre-check!manifest.id && !manifest.namestill mirrors the retired fallback. A name-only file now passes the client check and gets the server's 400 with the declaration's remedy. The refusal is loud and carries its fix, so this is not class a/b/c.objectstack-ai/cloud) was not readable from this session. Residual: a catalog package published from a hand-built artifact with nomanifest.idused to install under itsnameand is now refused 502.os buildoutput always carries a conforming id, becausedefineStackrefuses anything else. This is put to the maintainer, ⛔ not assumed away.Report hygiene: the dev tried to attach
objectstack-ai/cloudfor that measurement. The session's permission classifier denied it, and the dev did not retry by another route. It is recorded as a deviation.objectstack-fleet commentedon Sep 24, 2026
os-dev-report
{
"issue": 19576,
"status": "done",
"round": "patch — review record 5821336143 (option A)",
"branch": "claude/issue-19576-install-local-id-gate",
"pr": "#20022",
"head": "ca79edd22437c0b94df24274be25f90cbfb1e498",
"session": "session_01TnPAC1UsTGfHPXVUCL6iLn — this run's harness-stamped id (subagent = parent's); identity = the branch named in claim 5819739516",
"premise_still_valid": true,
"summary": "The changeset now carries the amended claim's line. In .changeset/19576-install-local-id-gate.md,
Clause-②: nowas changed toClause-②: no (narrowing), copied from claim 5819739516 as amended (read back: updated 2026-09-24T20:03:37Z). No other change in any file. Commit ca79edd sits on 37b8ecf with no merge, no rebase and no force. Diff vs 37b8ecf: 1 file changed, 1 insertion(+), 1 deletion(-). Whole PR vs merge base b81da66: 4 files, +477 / -6. check-adr-0087 now reads the changeset as [BREAKING+clause-②-narrowing] with its disposition present. The level axis, driven offline with PR 20022's current body as the event, readsno (narrowing)and is satisfied by the minor grade. The PR is still draft and nothing else was touched. The worktree was re-created on the existing branch, and pnpm install was needed because 4 of the gates imported dependencies. Its node_modules was removed before this post, and the worktree is removed right after it.","tests": "No code changed this round. Every gate below was run on ca79edd with its exit code captured before any pipe.",
"mcp_calls": "0",
"api_writes": "1 REST write + 1 git push. git push: 37b8ecf..ca79edd. REST: this os-dev-report comment via node scripts/pm/post-stamped.mjs --comment=19576, which goes out as POST /repos//issues/19576/comments over the fleet relay. PR body edits: 0. Label writes: 0. Ready flips: 0. Auto-merge: 0.",
"open_questions": [],
"out_of_scope_findings": [],
"gates": {
"node scripts/check-adr-0087-registration.mjs --base origin/main": {
"exit": 0,
"verdict": "✓ check-adr-0087-registration: 1 declared-breaking changeset(s), each carrying an ADR-0087 disposition. — .changeset/19576-install-local-id-gate.md [BREAKING+clause-②-narrowing] not-required (no-migration-prescription)"
},
"node scripts/check-changeset-no-major.mjs --base origin/main": {
"exit": 0,
"verdict": "✓ This diff introduces no
majorbump."},
"node scripts/check-changeset-no-major.mjs --base origin/main --event (PR 20022 body as pull_request payload)": {
"exit": 0,
"verdict": "✓ LEVEL AXIS: this PR declares clause-②
no (narrowing), and no package whosepackages/**/src/**it moves is gradedpatch."},
"node scripts/check-empty-changeset.mjs --base origin/main": {
"exit": 0,
"verdict": "✓ No empty-frontmatter changeset introduced by this diff (1 declaring changeset(s) added)."
},
"node scripts/check-adr-0087-registration.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-adr-0087-registration --self-test: 441 assertions over real temp git repos (real scan()/assertInputs() path)"
},
"node scripts/check-changeset-no-major.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #7005 diff scoping over real temp git repos + the #"
},
"node scripts/check-closing-keyword-parity.mjs": {
"exit": 0,
"verdict": "check-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 9432 tracked file(s), all registered). (first run exit 3 PREREQUISITE NOT MET: dependency not installed in the fresh worktree; rerun after pnpm install)"
},
"node scripts/check-closing-keyword-parity.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-closing-keyword-parity --self-test: 40 assertions, 5 mutations of the shipped parsers each driven to red. (first run exit 3 PREREQUISITE NOT MET: dependency not installed in the fresh worktree; rerun after pnpm install)"
},
"node scripts/check-comment-mask-corpus.mjs": {
"exit": 0,
"verdict": "✓ comment-mask corpus sweep [scripts/js-comment-mask.mjs]: 7095 files, 0 disagree, 0 unparseable, 77.8s (comparator self-test: 26 cases pass). (first run exit 3 PREREQUISITE NOT MET: dependency not installed in the fresh worktree; rerun after pnpm install)"
},
"node scripts/check-empty-changeset.mjs --self-test": {
"exit": 0,
"verdict": "✓ check-empty-changeset --self-test: 159 assertions over real temp git repos (real scan() path)"
},
"node scripts/pm/release-rehearsal-clone.mjs --self-test": {
"exit": 0,
"verdict": "✓ self-test passed"
},
"pnpm check:changeset-gate-self-tests": {
"exit": 0,
"verdict": "✓ check-changeset-no-major --self-test: 339 assertions (frontmatter dialects measured against @changesets/parse + the pre/exit exemption switch in both directions + the #7005 diff scoping over real temp git repos + the #"
},
"pnpm check:driver-memory-census": {
"exit": 0,
"verdict": "check-driver-memory-census: OK — every declaration is ledgered, every ledger entry is live, and every ruled file states "#6664 census: 2 ruled consumers". This gate polices the census, never investment. (first run exit 3 PREREQUISITE NOT MET: dependency not installed in the fresh worktree; rerun after pnpm install)"
},
"pnpm check:gitlink-declared": {
"exit": 0,
"verdict": "check-gitlink-declared: OK (9432 index entries -- 0 gitlink(s) at mode 160000; no .gitmodules in the index, so nothing is declared; nothing to declare)."
},
"pnpm check:nul-bytes": {
"exit": 0,
"verdict": "check-nul-bytes: OK (scanned 9425 text file(s) -- 9425 tracked, 0 untracked-not-ignored; skipped 7 binary; no raw ASCII control bytes)."
},
"pnpm check:objectui-changeset": {
"exit": 0,
"verdict": "✓ objectui-range --self-test: all checks passed"
},
"pnpm check:pm-changeset-deadline-census": {
"exit": 0,
"verdict": "✓ changeset-deadline-census --self-test: all cases passed across 5 batteries (what counts as a named target, the controls that make a zero a reading, the verdict truth table including the inconclusive refusal, the bucket"
},
"pnpm check:published-files": {
"exit": 0,
"verdict": "✓ check:published-files — 70 publishable package(s) of 81 workspace member(s) declare a
fileswhitelist that covers every entry point plus CHANGELOG.md and admits no test, test-harness config or build script; 1 publish"},
"pnpm check:refd-timer-probe": {
"exit": 0,
"verdict": "OK check-refd-timer-probe: 7090 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else."
},
"pnpm check:watch-hint-literal": {
"exit": 0,
"verdict": "✓ check-watch-hint-literal: 71 declaration(s) across 4 rostered name(s) -- ROOT_DIR_WATCH_HINTS 47, ROOT_FILE_WATCH_HINTS 13, ROOT_WATCH_HINTS 3, DECLARED_WATCH_HINTS 8 -- every one an array of quoted literals inside its"
},
"node scripts/check-changeset-fixed.mjs": {
"exit": 0,
"verdict": "✓ .changeset/config.json "fixed" group is in sync with 70 public workspace packages."
},
"node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack": {
"exit": 0,
"verdict": "89 command(s), identical set to the 37b8ecf derivation; the .changeset path alone places 19 (8 whole-tree + 11 by path), all run above"
}
},
"line_budget": "n/a",
"deviations": [
"pnpm install was run in the re-created worktree. The patch order allowed it only if a script refused without it, and 4 did: check-closing-keyword-parity (both legs,
yaml), check-comment-mask-corpus (@typescript-eslint/parser) and check:driver-memory-census (typescript). Each exited 3 PREREQUISITE NOT MET and went green on rerun. The install left git status clean.","Beyond the three named gates, the level axis was also run offline (check-changeset-no-major --event with PR 20022's current body). It writes nothing, and it confirms the narrowing arm on the PR is satisfied by the minor grade.",
"node scripts/check-changeset-fixed.mjs was also run, because its roster lives under .changeset: exit 0."
],
"files_changed": [
".changeset/19576-install-local-id-gate.md (one line:
Clause-②: nochanged toClause-②: no (narrowing))"]
}
objectstack-fleet commentedon Sep 24, 2026
⛔ Landing STOPPED: the ready flip of PR #20022 was denied by the session's permission classifier. Surfaced to the maintainer; no other route tried
domain:cliexecution PM seat #6024 · sessionsession_01TnPAC1UsTGfHPXVUCL6iLn· 2026-09-24T20:30ZRecorded per
references/landing-operations.md§B (as ofcc4ee775): 「落地中遭分类器拒 ⇒ 停手、报维护者、卡上记命令与拒因;⛔ 不换拼法或改走中继绕过」 (a classifier denial during landing: stop, report to the maintainer, record the command and the denial reason on the card; never respell the command or switch to the relay to get around it)..claude/settings.json):curl -sS -X POST https://api.github.com/repos/objectstack-ai/objectstack/pulls/20022/ccr/ready_for_review -d '{}'[Auto-Mode Bypass](the Claude Code auto-mode classifier).pr_ready/automerge_enable. The relay landed R1 and R2 on this seat beforecc4ee775reached this checkout. Under the rule now in force it is a bypass, so it is ⛔ not used.State the PR is left in (read at head
ca79edd22437c0b94df24274be25f90cbfb1e498):5821336143), and the one-line changeset patch was verified at source.Console Pin Gate,Packed-tarball smoke (opt-in)), with 0 pending and 0 failed.Lint & Repo Gates,TypeScript Type CheckandCheck Changesetare eachsuccessonca79edd2.check-governed-merges --pr 20022: NOT governed, 483 changed lines. There is noos-regenpath in the diff. No Clause-② limb hits (no (narrowing), and nopackages/spec/src/**).What unblocks it, the maintainer's call: flip it ready and arm auto-merge yourself, or allow the seat to run the ccr pair in this session. The card keeps
pm:dispatcheduntil MERGED, and the serial lane admits no next card until then.objectstack-fleet commentedon Sep 24, 2026
LANDED —
d58b8b633bb639a1cbbd181203c294c653de7fe3(PR #20022), verified by CONTENT onorigin/maindomain:cliexecution PM seat #6024 · sessionsession_01TnPAC1UsTGfHPXVUCL6iLn· 2026-09-24T23:33Z5581d300)origin/mainManifestSchema.shape.id.safeParseinmarketplace-install-local-plugin.tsmanifestIdRefusalin the same filecode: 'MANIFEST_CONFLICT'in the same filemarketplace-install-local-id-gate.test.tsin the tree (git ls-tree origin/main).changeset/19576-install-local-id-gate.md, carryingClause-②: no (narrowing)publish-and-preview.mdx: "A collision is the second refusal"ca79edd2is ⛔ not an ancestor (exit 1); the control leg5581d300is an ancestor (exit 0). The commit carries the enqueue instant 2026-09-24T23:17:25Z.POST /api/v1/marketplace/install-localparsesmanifest.idthroughManifestSchema.shape.idbefore the collision check, the posture gate, the hot-register and the ledger write. An id the declaration refuses answersPLUGIN_MANIFEST_INVALID:400for an inline manifest,502for a cloud snapshot. The message is the declaration's own sentence.manifest.nameis no longer read as an id. Rehydrate and the three:manifestIdroutes stay ungated, so an entry installed earlier under a refused id still boots and can still be deleted.[Auto-Mode Bypass], record5821758726). The maintainer readied, armed and enqueued the PR by hand, asos-steve, at 2026-09-24T23:15Z–2026-09-24T23:17Z. That denial is the maintainer-ordered skills card pm-dispatch: the allow-listed ccr ready flip was denied[Auto-Mode Bypass]in a session whose checkout carried the allow rows from its first HEAD — and since #19997 a denied ccr call leaves a session seat no landing route #20048.Fixes #19576. In the same stroke as this comment,pm:dispatchedis stripped and the assignee cleared.objectstack-ai/cloud). A catalog package published from a hand-built artifact with nomanifest.idis now refused502.os package publishuploads the artifact unchanged (bundle: artifact,packages/cli/src/commands/package/publish.ts:660), and the derivedlocal.id goes only into the catalog'smanifest_idcolumn. So whether such a snapshot carries an id depends on the cloud side.os buildoutput always carries a conforming id.namefallback.publish-and-preview.mdx. The tier has been unavailable to this session since 2026-09-24T14:14Z; the review is listed on the seat post.fix(metadata-protocol): duplicatePackage parses an explicit targetNam…
fix(cloud-connection): POST /api/v1/marketplace/install-local parses …