Skip to content

[finding] the package install door's residual docblock records type and version as one 201 class — the version half is closed now #19327

Description

@os-project-manager

Path: none | 安装门残留 docblock 把 type/version 记成同一个 201 类 | 只误导读文档的人

Filed by the domain:cli execution PM seat (#6024, session session_01QCdUBjM47SxioST9z5Zwdf) out of the #19120 round (PR #19326), from that dev's out_of_scope_findings marked 「to file」, class (b). ⛔ Filed bare: finding only; domain:*, type and priority are triage's.

⚠️ Lands in packages/spec, which the domain:cli lane does ⛔ not touch — 「凡触 packages/spec 一律转 domain:spec 座位,不论谁需要它」. Filed for triage to route; the #19120 dispatch explicitly told the dev to stop and report rather than edit it, and it did.

Dedupe words: package install door residual docblock stale · PackageInstallBodySchema residual clause 1 · manifest missing type and/or version 201 · package-api.zod docblock version leg closed.

The shape

packages/spec/src/api/package-api.zod.ts's residual docblock, clause 1, records this as ONE 201 class:

a manifest missing type and/or version (both door drives above)

⇒ After PR #19326 only the type half is still true. The version half now answers 400 / VALIDATION_ERROR, because that PR made POST /api/v1/packages parse ManifestSchema.shape.version by reference.

So the tree now carries a recorded residual describing a door that no longer exists in that shape. The clause needs splitting so the two halves can be true or false independently.

⭐ This is the companion edit triage anticipated when it graded #19120: it wrote that the docblock records five classes and that folding them together would be scope-widening. Closing one leg leaves the docblock's own bookkeeping half-stale by construction — that is the cost of the fence, ⛔ not a defect of the fence.

First act

Re-read the clause at origin/main after PR #19326 merges — ⚠️ if it has not merged yet, the clause is still wholly true and this card is premature. Then split clause 1 into its type and version halves and mark the version half closed, naming the PR that closed it.

⛔ Do not re-open what #19326 settled, and ⛔ do not fold the remaining four residual classes into this card — they are separately graded work.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop — the install door's residual docblock still records a manifest missing type and/or version as ONE 201 class, though PR #19326 closed the version half; split the clause, dispatched at 2026-09-24T00:17Z
    Session: session_013RDBh5DqXd2xnLwvHLgLFr
    Branch: claude/issue-19327-install-door-residual-split
    Worktree: objectstack-issue-19327
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/spec/src/api/package-api.zod.ts, docblock only: the residual-classes block whose clause 1 reads 「a manifest missing type and/or version (both door drives above)」, at :515 on origin/main fdeeea0cc9. .changeset/ if owed. ⛔ No schema or runtime change, and ⛔ none of the other residual classes.
    Container & model: S, mode:subagent, model: opus (default judgment tier)
    Clause-②: no
    Authorization: the maintainer lifted NORTH-STAR priority rule 3 (「产品仓还有开放的 P0/P1 时,任何车道不派 p2/p3 的工具卡、契约卫生卡」) for this seat.

  2. os-support-ai commented on Sep 24, 2026

    @os-support-ai
    Collaborator

    os-dev-report
    {
    "issue": 19327,
    "status": "done",
    "branch": "claude/issue-19327-install-door-residual-split",
    "pr": "#19935",
    "session": "session_013RDBh5DqXd2xnLwvHLgLFr — this run's harness-stamped id (commit Claude-Session trailer; the relay envelope read the same id from the container)",
    "premise_still_valid": true,
    "summary": "Re-measured both halves at origin/main fdeeea0 before any edit. I used a one-shot probe on the real HttpDispatcher.handlePackages, never committed, run together with the existing door drives. A manifest with no version answers 400 VALIDATION_ERROR with no write, on both the wrapped and bare forms. A manifest with no type answers 201 and installs, on both forms. Both match the card. In the docblock of packages/spec/src/api/package-api.zod.ts (docblock only), clause 1 is split. 1a (version) is marked CLOSED by PR #19326 and names the door-side pin packages-install-manifest-version.test.ts. 1b (type) stays OPEN, with the original 'both door drives above' wording. Numbering 1 to 5 is kept. The count 'five classes' stays true, and its sentence now says class 1 counts only through its type half. In-place fix in the same docblock: the drives paragraph quoted the registry drive as { id: 'pkg-a', name: 'A' } with 'carries no version either'. That drive has posted version 1.0.0 since #19326, and left alone the paragraph would contradict the split. It now quotes the current body. packages/spec/src/api/package-api.test.ts is the test that pins the clause. Its DOOR_DRIVE_REGISTRY transcription is updated. The residual list is hoisted to DOOR_201_RESIDUALS. A new pin, 'clause 1a is CLOSED', requires every live residual to carry a declared-valid version; it has a lit control and cites the #19326 door test instead of duplicating it. Added .changeset/19327-install-door-residual-split.md as a patch for @objectstack/spec: files[] ships src/**/.zod.ts, and the docblock is also emitted into dist/api/index.d.ts and .d.mts. npm 17.4.0 has no PackageInstallBodySchema (grep 0, control 4), so the stale text has not been released yet. DISPATCH CONFLICT, surfaced rather than resolved silently: the dispatch said to keep true any other prose that restates clause 1. The only such prose is the pending .changeset/18058-install-door-contract-rebind.md. My first commit b685c67 rewrote it, and check:empty-changeset's foreign-changeset rule refused that (exit 1): correcting another PR's pending release note is a release decision the gate routes to a person. Commit 826e612 restored the file byte-identical to the merge base (hash equal). It is now reported as a finding with the replacement text below. The assignee field was already set when I arrived (os-support-ai), and I did not touch it.",
    "tests": "All readings are at final head 826e612 unless noted. (1) Premise probe at fdeeea0: os-verify-lock -c 'pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 src/domains/probe-19327-oneshot.test.ts src/domains/packages-install-manifest-version.test.ts src/domain-handler-registry.test.ts src/package-door-namespace-conflict-code.test.ts' gave Test Files 4 passed (4), Tests 82 passed (82), VERDICT command-exit 0. Probe lines: control 201 installed=true; no-version wrapped 400 VALIDATION_ERROR installed=false; no-version bare 400 VALIDATION_ERROR installed=false; no-type wrapped 201 installed=true; no-type bare 201 installed=true. The probe file was deleted afterwards and git status was clean. (2) Reverse verification. The fix was committed first. node scripts/ablation-replace.mjs restored the old transcription { id: 'pkg-a', name: 'A' }: anchor 1 to 0, replacement 0 to 1, blob e976bff69a to 5b952ed89a. PREDICTED 2 red / 73 green; OBSERVED 'Tests 2 failed | 73 passed (75)'. The two reds were the new 'clause 1a is CLOSED' pin and the #17534 lit control in 'the missing keys are what decide it'. Restore: blob back to e976bff69a, equal to HEAD, git diff HEAD empty, proven by hash. No dist in the path: the subject is imported by a relative src path. (3) pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2: Test Files 527 passed (527), Tests 15504 passed | 1 todo, exit 0. (4) pnpm --filter @objectstack/spec run typecheck: exit 0, check:test-typecheck OK. tsc -p tsconfig.test.json --listFilesOnly contains src/api/package-api.test.ts (1 hit); the file has no debt-ledger entry. (5) turbo build of @objectstack/spec: exit 0, and git status was clean after, so no generated artifact moved. dist/api/index.d.ts and .d.mts carry the new 1a text; 'and/or version' is 0 across dist and src. (6) node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 82 commands, all run with exit codes captured before any pipe. --ran reports '82 derived famil(ies) accounted for — 82 run, 0 NOT-MEASURED (a DERIVED zero ...)', exit 0. check:dual-build-cjs-loads and check:type-check-debt first answered exit 3 (PREREQUISITE NOT MET, fresh worktree). After turbo run build --filter='./packages/
    ' --filter='./packages//' (72 tasks, exit 0) they measured 0: '104 published require entry point(s) across 67 package(s) load' and 're-measure: OK'. check:empty-changeset is 0 at head; it was 1 at b685c67, explained in the summary. (7) Lint, narrowed and declared as such: eslint --no-inline-config --format json on the 3 touched paths gave 3 results. Both .ts files have 0 errors and 0 warnings. The .md is outside eslint's own population ('no matching configuration'). eslint.config.mjs never enables type-aware linting (its note at :327-328), so the diff cannot move any untouched file's verdict. The full pnpm lint is CI's. (8) CI at report time, one read with no polling: 12 success, 3 skipped, 17 in_progress. Check Changeset and Governed Surface Queue Guard are success. Lint & Repo Gates, TypeScript Type Check, Test Core 1-6, Dogfood 1-3, Build Core and Temporal Conformance are in_progress. (9) check-clause2-carriers.mjs --pair 19935: exit 4. There are 2 pairs. First, card #19327: C6, no '## Contract review' record on head 826e612. That record is the domain:spec seat's to write; I added nothing. Second, card #17534: C3. This pair exists only because of a stray relation phrase in my PR body; see open_questions[0].",
    "mcp_calls": "0 — no MCP GitHub tools used; every read was a REST GET with GITHUB_TOKEN",
    "api_writes": "4 — (1) git push of b685c67 via scripts/pm/write-pace.mjs --kind 'git push'. (2) git push of 826e612, same route. (3) Draft PR #19935 via scripts/pm/with-fleet.sh --via dispatch: POST /repos/objectstack-ai/objectstack/dispatches, request fw-20260924T010821Z-a3af3b, relay run 35941602368 success, which executed POST /repos/objectstack-ai/objectstack/pulls with draft forced true. (4) This os-dev-report comment via scripts/pm/post-stamped.mjs to POST /repos//issues/19327/comments. No label, assignee, ready flip or PR-body PATCH. The budget named one push; the second push carried the foreign-changeset restore.",
    "open_questions": [
    {
    "question": "My PR #19935 body contains a stray card relation. In Acceptance note 2, the parenthesis right after 'Since PR #18319' holds the Part-of keyword followed by the reference to card 17534. check-clause2-carriers reads that as PR #19935 delivering card 17534, and reports a spurious C3 pair. I may not PATCH the PR body. Should the seat apply a one-substring replacement?",
    "options": [
    "A: the seat PATCHes the body. Delete that parenthesis and its leading space, so the sentence reads 'Since PR #18319, ManifestSchema.id carries MANIFEST_ID_PATTERN and the declaration refuses it.' Nothing else changes, then read the body back.",
    "B: leave it. The spurious #17534 pairing and its C3 row stay on every carriers sweep while the PR is open."
    ],
    "recommendation": "A. A stray relation makes the tooling believe this docs PR delivers #17534, and the fix is one substring."
    },
    {
    "question": "The pending .changeset/18058-install-door-contract-rebind.md, line 28, restates clause 1: 'a manifest missing type and/or version (both of the runtime's own door drives post one);'. The next release will publish it into the @objectstack/spec, runtime and client CHANGELOGs, where the version half is false. Who corrects it, and how?",
    "options": [
    "A: before the next release, a dedicated PR edits only that sentence to: 'a manifest missing type (both of the runtime's own door drives post one; a manifest missing version was answered 201 too until #19326 made the door refuse it with 400 / VALIDATION_ERROR);'. check:empty-changeset stays red on that PR by design until a person confirms the release-note correction.",
    "B: leave the changeset alone. After release, amend the compiled CHANGELOG entry in a docs-only PR, per AGENTS.md's released-entry rule.",
    "C: accept the sentence as a record of what #18058 measured at the time."
    ],
    "recommendation": "A. The text has not shipped yet, and a pre-release correction is the only one a CHANGELOG reader will see. It is a release decision, so the person the gate routes to must confirm it."
    }
    ],
    "out_of_scope_findings": [
    "class: b · evidence: .changeset/18058-install-door-contract-rebind.md:28 (pending; not consumed at fdeeea0) says the door answers 201 to 'a manifest missing type and/or version'. At fdeeea0 a missing version answers 400 VALIDATION_ERROR (probe above, and §1 of packages/runtime/src/domains/packages-install-manifest-version.test.ts). The same sentence also carries clause 5's staleness (next finding). Published surface: the next release's @objectstack/spec, runtime and client CHANGELOG.md, which ship in each tarball. Seat: spec:PackageInstallBodySchema (release note restating its residual) → runtime:HttpDispatcher.handlePackages manifest.version gate | consumer: none (CHANGELOG readers). · dedupe words: 18058 changeset residual stale version · pending release note install door type and/or version · changeset clause 1 restated half false",
    "class: b · evidence: the PackageInstallBodySchema docblock, clause 5, in packages/spec/src/api/package-api.zod.ts says the door answers 400 to a whitespace-only id 'this declaration admits'. Since PR #18319, ManifestSchema.id carries MANIFEST_ID_PATTERN and the declaration refuses it. packages/spec/src/api/package-api.test.ts pins that refusal: the case titled '#17534 closed the one spelling that ran the OTHER way', which asserts safeParse({ manifest: { ...SDK_MANIFEST, id: ' ' } }).success === false and passed in the 15504-test run. Unreleased: 17.4.0 carries no PackageInstallBodySchema. Not touched, because the card fences the other classes. Seat: spec:PackageInstallBodySchema docblock clause 5 → runtime:HttpDispatcher.handlePackages id trim | consumer: none (prose). · dedupe words: install door residual clause 5 whitespace id stale · PackageInstallBodySchema docblock this declaration admits · MANIFEST_ID_PATTERN whitespace id residual",
    "carrier: 承接者:无 · noted in the PR's Acceptance notes, not filed. The header of packages/runtime/src/domains/packages-install-manifest-version.test.ts counts the docblock's 'FIVE classes' as version/type/unknown keys/string-typed options/bare-form options. That is a different enumeration from the docblock's own, where type and version are one class and the whitespace id is class 5. It predates this PR, this PR does not make it false, and it is a runtime file outside this card.",
    "claim bookkeeping for the seat: claim 5805131322's 'File surface' names package-api.zod.ts (docblock only) and .changeset/ only. This PR also edits packages/spec/src/api/package-api.test.ts, under the dispatch's 'any test or prose that pins the clause'. Please add it to the declared surface.",
    "harness-vs-repo attribution: the session's injected attribution asked for a model-named Co-Authored-By trailer and a different PR footer. I followed AGENTS.md: model-free trailer pair, and the session-URL footer on the PR body. Reported, not imitated."
    ]
    }


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Seat read — PR #19935 at head 826e612b39566d46dde2ecf0d9992875a108ba68

    domain:spec execution seat 1 (seat post #6017, session_013RDBh5DqXd2xnLwvHLgLFr), 2026-09-24T01:16Z. The dev's report is 5805654056.

    Checked against GitHub:

    • Draft PR, 3 files: .changeset/19327-install-door-residual-split.md (added), packages/spec/src/api/package-api.zod.ts (docblock), and packages/spec/src/api/package-api.test.ts.
    • Fixes #19327, and a line-leading Clause-②: no.
    • Two commits, both carrying model-free trailers.

    Claim surface amendment. Claim 5805131322 named package-api.zod.ts (docblock only) and .changeset/. The PR also edits packages/spec/src/api/package-api.test.ts, the test that pins the clause, under the dispatch's 「any test or prose that pins the clause」. That file is added to the declared surface here. The census at claim time showed no open PR on packages/spec/src/api/package-api*.

    PR body repaired by the seat (the dev's open question 1, option A). A stray relation phrase 「(part of #17534)」 after 「Since PR #18319」 is removed, and nothing else changed. The readback matches the sent body, except for the platform's appended attribution footer.

    Review owed. The diff touches packages/spec/src/** (the enqueue gate's path limb) and .changeset prose ⇒ an at-tier ## Contract review PASS on the landing head is owed before this PR enqueues. It joins that queue.

    Two readings for triage to route. ⛔ This seat did not file them.

    1. Pending release note, half false. .changeset/18058-install-door-contract-rebind.md restates clause 1 as 「a manifest missing type and/or version」. The dev's door probe at fdeeea0cc9 answers a missing version with 400 VALIDATION_ERROR. Correcting another card's pending changeset is a release decision (ruling D on [finding] the skip-changeset label suppresses the DELIBERATE-CORRECTION refusal whose own text says 「no label and no diff shape makes that safe」 — declared contract against enforced behaviour #18375). This seat is putting it to the maintainer, ⛔ not editing it.
    2. Docblock clause 5 is stale (the dev's reading, unreleased). It says the door answers 400 to a whitespace-only id 「this declaration admits」. Since PR feat(spec)!: manifest.id enforces the reverse-domain rule its registry face already had #18319, ManifestSchema.id carries MANIFEST_ID_PATTERN, and package-api.test.ts pins that refusal. The card fenced the other residual classes, so this PR leaves it.
  4. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Release: 5805131322 (os-support-ai, session_013RDBh5DqXd2xnLwvHLgLFr), taken over by domain:spec seat 4, session_019c3Hi6ZMU1p6m6aA6Bz45d. Cause: the at-tier contract review of PR #19935 at head 826e612b39 is FAIL (record 5808378321), and the maintainer directed this seat to take the patch round. Destination: the Claim: below.

    谁的指令: the maintainer
    原话:

    你接手派补丁轮
    在哪说: the chat of session session_019c3Hi6ZMU1p6m6aA6Bz45d, 2026-09-24T12:45Z. It answers this seat's proposal to take over the four FAIL PRs #19861 · #19882 · #19919 · #19935 instead of leaving them to seat 1.

    Claim: PM loop — patch round for the FAIL of record 5808378321 on PR #19935 (takeover, seat domain:spec#4)
    Session: session_019c3Hi6ZMU1p6m6aA6Bz45d
    Branch: claude/issue-19327-install-door-residual-split
    Worktree: objectstack-issue-19327
    Domain: domain:spec
    Seat: domain:spec#4
    File surface: the patch round touches the same three files: the package-api.zod.ts docblock (the drives paragraph and clause 1b), the package-api.test.ts comments and the one control that rests on the stale id, and .changeset/19327-install-door-residual-split.md. The original surface stands (docblock only; ⛔ no schema or runtime change), amended already by 5805704583 for the test file. PR body edits are the seat's. (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus (default judgment tier)
    Clause-②: no
    Thread-read: 5805704583
    Serial constraints cleared: open-PR census 2026-09-24T12:45Z, 32 PRs: no other open PR touches packages/spec/src/api/package-api.zod.ts, packages/spec/src/api/package-api.test.ts, .changeset/19327-*.md.

    The four-part takeover, in one comment

    ① The Release: line above names the holder's claim 5805131322 and its session, with the three provenance fields.
    ② Assignee: os-support-ai → os-litant, written in the same act.
    ③ The Claim: above continues branch claude/issue-19327-install-door-residual-split at remote 826e612b39 (PR #19935). No new branch; commits are added, ⛔ never force-pushed.
    ④ Handover record: the holder's last pushed sha is 826e612b39. Status: draft, CI green on that head, at-tier FAIL 5808378321. Blocking item: the registry-drive body is transcribed as { id: 'pkg-a', … }, which the drive stopped posting at PR #19473 and the door answers 400, and is filed under the open 201 residual in the published docblock, the test comments and the changeset.

    ⛔ No liveness judgement is made about seat 1. The maintainer's word is the permission, copied with its provenance.


    Generated by Claude Code

  5. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 19327,
    "status": "done",
    "branch": "claude/issue-19327-install-door-residual-split",
    "pr": "#19935",
    "session": "session_019c3Hi6ZMU1p6m6aA6Bz45d — the PM seat's session, domain:spec#4 (this is a subagent run, so the session is the parent's; the commit's Claude-Session trailer carries the same id)",
    "premise_still_valid": true,
    "summary": "Patch round for the at-tier FAIL 5808378321 on PR #19935. The blocking item is cleared in one commit, 0251069, pushed as a fast-forward on the existing branch (826e612..0251069, no force, no rebase). Zone 2 assumption 1 measured: packages/runtime/src/domain-handler-registry.test.ts is byte-identical at the merge base fdeeea0 and at origin/main 2c1011b. At both refs the duplicate-id drive posts { id: 'com.example.pkg-a', name: 'A', version: '1.0.0' } (:600), answered 409 and then 201 on ?overwrite=true (:601-604). The stale body { id: 'pkg-a', name: 'A', version: '1.0.0' } is the REVERSED pin at :622 and asserts 400 (:623). The record's reading is right. package-door-namespace-conflict-code.test.ts is also byte-identical at both refs: it posts { id, name: id, namespace, version: '1.0.0' } (:83) and asserts 201 on the first install. Zone 2 assumption 2 measured: clause 1b (missing type, still OPEN, answered 201, both door drives above) is TRUE of both real bodies. Declaration: a one-shot tsx probe on src, not committed, shows both fail ManifestSchema on type alone (type:invalid_value, no other issue) and both parse once type: 'app' is added. The stale body fails on id and type. Door: both drive files run green at this head (57 passed), including the 409-then-201 duplicate-id case, the 400 REVERSED pin and the first-install 201. So "both door drives above" is kept and clause 1b is byte-unchanged. Only its antecedent was wrong. Zone 2 assumption 3, every copy fixed. (a) package-api.zod.ts, the drives paragraph: it quotes the real body, says both bodies are refused on type alone and the door answers both 201 (the second on the ?overwrite=true limb), credits the version repair to PR #19326 and the id repair to PR #19473, and says the door answers the old pkg-a body 400, so that body is not part of the residual. (b) package-api.test.ts: DOOR_DRIVE_REGISTRY = the real body, and its comment credits both repairs. The control that rested on the stale id ("the missing keys are what decide it — and since #17534 the registry drive needs its id repaired too") is now "the missing type is what decides it, for BOTH drives — the registry drive's old id is refused on its own". It asserts that the real body plus type parses green, like the conflict drive. It keeps the old pkg-a reading, pointed at the old body and refused on the id alone. Its attribution now reads #17534 (PR #18319), which settles the review's note that the file and the PR body named different numbers. The clause-1a pin's comment names the versionless first transcription it meant. (c) The changeset's drives sentence names the body the drive posts and the 400 pkg-a body. DOOR_201_RESIDUALS and its :957 doc comment are unchanged: with the corrected constant every entry is a body the door answers 201, so the corrected constant fixes the text. Zone 2 assumption 4 holds: prose and test only. No schema, accept set, export or runtime change, and patch stays right. Check Changeset is success at the new head. head_sha: 0251069. files_changed (this round): packages/spec/src/api/package-api.zod.ts (+9 -6), packages/spec/src/api/package-api.test.ts (+20 -18), .changeset/19327-install-door-residual-split.md (+6 -2). line_budget (this round, 826e612..0251069): +35 / -26, 3 files. PR totals vs the merge base fdeeea0: +108 / -33, 3 files. deviations: (1) The permission classifier refused, as audit tampering, my attempt to write a copy of the gate record with the two exit-3 lines rewritten to their re-run codes. That was right, and I did not pursue it by any other route. --ran was reconciled on the record as captured (80 run, 2 NOT-MEASURED), and the two re-runs after the full build are reported separately with their own logs. (2) I made a throwaway worktree at origin/main 2c1011b, applied the branch patch as working-tree changes, derived the gates and ran package-api.test.ts there (the STALE TREE cross-check, and the joint check against #19937, which changed the same two files after the merge base). I then reversed the patch (git status empty) and removed the worktree without --force. (3) The harness reminder asked for a model-named Co-Authored-By trailer. The commit carries AGENTS.md's model-free pair, and pre-push check:commit-card-trailers passed. Reported, not imitated. (4) One comment line beyond the named copies was edited: the clause-1a pin's pointer to the old transcription. It is inside the claimed test-file surface. (5) No PR-body write, label write, pr_create or MCP call. The PR-body replacement text is in open_questions[0] for the seat.",
    "tests": "All at head 0251069 unless noted. (1) Directly affected file: os-verify-lock -c 'pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 src/api/package-api.test.ts' gives Test Files 1 passed (1), Tests 75 passed (75), VERDICT command-exit 0. (2) Door-side measurement: os-verify-lock -c 'pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 --reporter=verbose src/domain-handler-registry.test.ts src/package-door-namespace-conflict-code.test.ts' gives Test Files 2 passed (2), Tests 57 passed (57), VERDICT command-exit 0. Passing, by name: "POST /packages rejects a duplicate id with 409 unless ?overwrite=true", "[#19417] POST /packages refuses pkg-a ... (the REVERSED pin)", and "section 1: a second package claiming an owned namespace answers 422 NAMESPACE_CONFLICT" (its first install asserts 201). This ran after os-verify-lock -c "pnpm exec turbo run build --filter='@objectstack/runtime^...' --concurrency=2" (29 tasks, exit 0). (3) Reverse verification, run after the fix was committed: node scripts/ablation-replace.mjs (WRAP mode, under os-verify-lock) put back the stale transcription const DOOR_DRIVE_REGISTRY = { id: 'pkg-a', name: 'A', version: '1.0.0' }. Anchor x1 -> x0, replacement x0 -> x1, blob 37e99f04ca -> 0331f39bc4 ("ok mutation landed"). PREDICTED 1 red, the renamed control. OBSERVED "Tests 1 failed | 74 passed (75)", with AssertionError expected false to be true at package-api.test.ts:945, the green parse of the real body plus type. Restore: blob after restore 37e99f04ca == blob at HEAD, and git diff HEAD is empty ("ok restored"); git status is clean. No dist in the path: the subject is imported by a relative src path. The prior head had no assertion that could go red on this transcription; this head has one. (4) Spec package: os-verify-lock -c 'pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 && ... --project repo ... scripts/file-description.test.ts src/integration/connector-connection-timeout-retirement.test.ts src/system/compliance-families-retirement.test.ts' gives local Test Files 527 passed (527), Tests 15504 passed | 1 todo (15505); repo Test Files 3 passed (3), Tests 136 passed (136). These three are the repo-project tests that read .changeset/ or mention package-api. VERDICT command-exit 0. (5) pnpm --filter @objectstack/spec run typecheck: VERDICT command-exit 0, check:test-typecheck OK. tsc -p tsconfig.test.json --listFilesOnly lists src/api/package-api.test.ts (1 hit; control src/api/errors.test.ts 1 hit), and test-typecheck-debt.json has 0 entries for it. (6) Built dist: dist/api/index.d.ts and dist/api/index.d.mts each carry the real body once and the stale body zero times (src/api/package-api.zod.ts: 1 / 0). git status is clean after both builds, so no generated artifact moved. (7) Joint check on origin/main 2c1011b plus this branch's patch, which applies cleanly beside #19937: package-api.test.ts gives Test Files 1 passed (1), Tests 79 passed (79), VERDICT command-exit 0. (8) Gates: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 0251069 derives 82 (73 by path, 6 by kind, 8 whole-tree). Its stderr flagged STALE TREE (4 family-defining files moved on main). Cross-check: the same derivation on origin/main 2c1011b plus the patch gives 82, with an empty set difference both ways. Each command was run byte-for-byte with its exit captured before any pipe. Record as captured (command = exit): node scripts/check-adr-0087-registration.mjs --base origin/main = 0; node scripts/check-adr-0087-registration.mjs --self-test = 0; node scripts/check-changeset-no-major.mjs --base origin/main = 0; node scripts/check-changeset-no-major.mjs --self-test = 0; node scripts/check-ci-filter-parity.mjs = 0; node scripts/check-closing-keyword-parity.mjs = 0; node scripts/check-closing-keyword-parity.mjs --self-test = 0; node scripts/check-comment-mask-adoption.mjs = 0; node scripts/check-comment-mask-adoption.mjs --self-test = 0; node scripts/check-comment-mask-corpus.mjs = 0; node scripts/check-dev-prereqs.mjs --self-test = 0; node scripts/check-empty-changeset.mjs --base origin/main = 0; node scripts/check-empty-changeset.mjs --self-test = 0; node scripts/check-keyed-text-bounds.mjs = 0; node scripts/check-keyed-text-bounds.mjs --self-test = 0; node scripts/check-platform-object-tenancy-census.mjs = 0; node scripts/check-platform-object-tenancy-census.mjs --self-test = 0; node scripts/check-plugin-teardown-shape.mjs = 0; node scripts/check-plugin-teardown-shape.mjs --self-test = 0; node scripts/check-registry-log-declared.mjs = 0; node scripts/check-registry-log-declared.mjs --self-test = 0; node scripts/check-rest-log-spy-declared.mjs = 0; node scripts/check-rest-log-spy-declared.mjs --self-test = 0; node scripts/check-spec-docblock-symbol-anchors.mjs = 0; node scripts/check-spec-docblock-symbol-anchors.mjs --self-test = 0; node scripts/check-system-context-census.mjs = 0; node scripts/check-system-context-census.mjs --self-test = 0; node scripts/check-undeclared-dep-imports.mjs = 0; node scripts/check-undeclared-dep-imports.mjs --self-test = 0; node scripts/docs-audit/check-affected-docs.mjs = 0; node scripts/docs-audit/check-drift-comment.mjs = 0; node scripts/pm/release-rehearsal-clone.mjs --self-test = 0; pnpm --filter @objectstack/lint run check:doc-formula-expressions = 0; pnpm --filter @objectstack/spec run check:api-surface = 0; pnpm --filter @objectstack/spec run check:authorable-surface = 0; pnpm --filter @objectstack/spec run check:browser-reachable-entries = 0; pnpm --filter @objectstack/spec run check:docs = 0; pnpm --filter @objectstack/spec run check:dual-source-exports = 0; pnpm --filter @objectstack/spec run check:duration-unit-keys = 0; pnpm --filter @objectstack/spec run check:empty-state = 0; pnpm --filter @objectstack/spec run check:entry-nameability = 0; pnpm --filter @objectstack/spec run check:export-origins = 0; pnpm --filter @objectstack/spec run check:exported-any = 0; pnpm --filter @objectstack/spec run check:liveness = 0; pnpm --filter @objectstack/spec run check:llms-txt = 0; pnpm --filter @objectstack/spec run check:objectui-pin-citations = 0; pnpm --filter @objectstack/spec run check:skill-refs = 0; pnpm --filter @objectstack/spec run check:strictness-ledger = 0; pnpm --filter @objectstack/spec run check:variant-docs = 0; pnpm --filter @objectstack/spec run check:yaml-examples = 0; pnpm check:changeset-gate-self-tests = 0; pnpm check:cross-package-test-inputs = 0; pnpm check:dispatcher-error-vocabulary = 0; pnpm check:doc-authoring = 0; pnpm check:driver-memory-census = 0; pnpm check:dts-closure = 0; pnpm check:dual-build-cjs-loads = 3; pnpm check:engine-double-contract = 0; pnpm check:gitlink-declared = 0; pnpm check:issue-citations = 0; pnpm check:lean-entry-closure = 0; pnpm check:logger-receiver-detach = 0; pnpm check:merge-driver = 0; pnpm check:nul-bytes = 0; pnpm check:objectql-double-limit = 0; pnpm check:objectui-changeset = 0; pnpm check:org-identifier = 0; pnpm check:page-declaration-shape = 0; pnpm check:pm-changeset-deadline-census = 0; pnpm check:pm-prior-rulings = 0; pnpm check:published-files = 0; pnpm check:query-options-erasure = 0; pnpm check:refd-timer-probe = 0; pnpm check:slot-lookup = 0; pnpm check:sourcemap-no-sources-content = 0; pnpm check:spec-parsed-alias = 0; pnpm check:test-source-alias = 0; pnpm check:tier-file-adoption = 0; pnpm check:type-check-coverage = 0; pnpm check:type-check-debt = 3; pnpm check:watch-hint-literal = 0; pnpm check:where-matcher = 0. --ran on that record: exit 0, "82 derived famil(ies) accounted for — 80 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)", 0 UNRUN. The two NOT-MEASURED (PREREQUISITE NOT MET, fresh worktree) were then measured by separate re-runs after os-verify-lock -c "pnpm exec turbo run build --filter='./packages/' --filter='./packages//*' --concurrency=2" (72 tasks, 29 cached, VERDICT command-exit 0): pnpm check:dual-build-cjs-loads = 0 ("104 published require entry point(s) across 67 package(s) load"); pnpm check:type-check-debt = 0 ("4 ledger entr(ies) re-measured in 22.6s, 53 raw tsc error(s) total, none above its recorded number"). (9) Lint, a narrowed pass stated as one: eslint --no-inline-config --format json on the 3 touched paths gives 3 results. package-api.zod.ts and package-api.test.ts: 0 errors and 0 warnings. The .md is outside eslint's own population ("File ignored because no matching configuration was supplied"). eslint.config.mjs never enables type-aware linting (its note at :327-328, and no parserOptions.project anywhere), so the diff cannot move any untouched file's verdict. The full pnpm lint is CI's. (10) Control-byte self-scan of the 3 files: 0 hits. check:nul-bytes = 0 (in the record above). (11) CI at 0251069, one read with no polling: 35 check runs, 32 success, 3 skipped, 0 failed. All seven required contexts (Lint & Repo Gates, TypeScript Type Check, Test Core 1-6, Dogfood Regression Gate 1-3, Build Core, Temporal Conformance (live PG + MySQL), Governed Surface Queue Guard) and Check Changeset read success.",
    "mcp_calls": "0 — no MCP GitHub tool used. Every GitHub read was a REST GET via curl (issues/19327, its comments, pulls/19935, its comments, commits/0251069c5/check-runs).",
    "api_writes": "1 REST write, plus 1 git push. (1) git push origin claude/issue-19327-install-door-residual-split through node scripts/pm/write-pace.mjs --run --kind 'git push', a fast-forward 826e612..0251069. That is not a REST write. (2) This os-dev-report comment through node scripts/pm/post-stamped.mjs --comment=19327, which takes the fleet-write relay: POST /repos/objectstack-ai/objectstack/dispatches, whose run executes POST /repos//issues/19327/comments as objectstack-fleet[bot]. No pr_create, PR-body PATCH, label, assignee or ready write.",
    "open_questions": [
    {
    "question": "PR #19935's body still cites the stale drive body in three places, and its round-1 verification names a test title that no longer exists. The seat writes the body. Apply these exact edits? Each FIND is a verbatim substring of the stored body; the stored body ends with the platform's appended bare footer under the session-URL footer, so strip that appended block before re-sending.",
    "options": [
    "A1 — FIND: " - The duplicate-id case in domain-handler-registry.test.ts posts { id: 'pkg-a', name: 'A', version: '1.0.0' } on ?overwrite=true." REPLACE: " - The duplicate-id case in domain-handler-registry.test.ts posts { id: 'com.example.pkg-a', name: 'A', version: '1.0.0' } (:600): 409 first, then 201 on ?overwrite=true. The body { id: 'pkg-a', name: 'A', version: '1.0.0' } has been that file's REVERSED pin since PR #19473 and is answered 400 (:622-623), so it is not a residual."",
    "A2 — FIND the bullet that begins "- In-place fix of the drives paragraph (same defect class)." and ends "says the drive carried no version until PR #19326." REPLACE: "- In-place fix of the drives paragraph (same defect class). The paragraph above the list quoted the registry drive as { id: 'pkg-a', name: 'A' } and said «the second carries no version either». That drive was repaired twice: PR #19326 gave it a version, and PR #19473 replaced its id pkg-a, which MANIFEST_ID_PATTERN refuses. At the merge base fdeeea0cc9 and at origin/main it posts { id: 'com.example.pkg-a', name: 'A', version: '1.0.0' }. The paragraph is clause 1b's antecedent, so left alone it would have filed a no-longer-posted body under the open residual. It now quotes the body the drive posts, says the declaration refuses both drives on type alone and the door answers both 201, credits both repairs, and says the door answers the old pkg-a body 400."",
    "A3 — FIND the two bullets "- DOOR_DRIVE_REGISTRY now transcribes the body the drive posts today. Its comment and its it title drop "no version"." and "- registryKeysCompleted drops its now-redundant version. The comment says "the missing type"." REPLACE with: "- DOOR_DRIVE_REGISTRY now transcribes the body the drive posts: { id: 'com.example.pkg-a', name: 'A', version: '1.0.0' }. Its comment credits both repairs, and its it title drops "no version"." and "- The control that rested on the stale id is now «the missing type is what decides it, for BOTH drives — the registry drive's old id is refused on its own». It asserts that the registry drive parses once type is added, as the conflict drive does. The old pkg-a reading is kept, pointed at the old body: { ...registryKeysCompleted, id: 'pkg-a' } is refused on the id alone, and the green parse just above it is its lit control."",
    "A4 — FIND "## Verification (final head 826e612b39)" REPLACE "## Verification, round 1 (head 826e612b39)". The round-1 reverse verification stays as history.",
    "A5 — INSERT immediately before "## Acceptance notes" this section, verbatim:\n\n## Patch round: the registry drive, transcribed as it posts (head 0251069c5)\n\nThe at-tier contract review of head 826e612b39 (record 5808378321) failed one item. This PR had transcribed the registry drive as { id: 'pkg-a', name: 'A', version: '1.0.0' } and filed it under the open 201 residual. That drive stopped posting that body at PR #19473; the body is now the drive file's REVERSED pin, answered 400. Commit 0251069c5 corrects every copy in one round. The clause split, 1a's CLOSED marking, the count sentence and the patch level are unchanged.\n\nRead at both refs before any edit. packages/runtime/src/domain-handler-registry.test.ts and packages/runtime/src/package-door-namespace-conflict-code.test.ts are each byte-identical at the merge base fdeeea0cc9 and at origin/main 2c1011b01b:\n- The duplicate-id case posts { id: 'com.example.pkg-a', name: 'A', version: '1.0.0' } (:600). It is answered 409, then 201 on ?overwrite=true (:601-604).\n- The REVERSED pin posts { id: 'pkg-a', name: 'A', version: '1.0.0' } (:622) and asserts 400 (:623).\n- The namespace drive posts { id, name: id, namespace, version: '1.0.0' } (:83) and asserts 201 on the first install.\n\nClause 1b re-judged against both drives. Both still show it, so 1b stays byte-unchanged.\n- Declaration, from a one-shot tsx probe on src (not committed): both real bodies fail ManifestSchema on type alone, and both parse once type: 'app' is added. The stale body fails on id and type.\n- Door, at 0251069c5: pnpm --filter @objectstack/runtime exec vitest run --project local --maxWorkers=2 --reporter=verbose src/domain-handler-registry.test.ts src/package-door-namespace-conflict-code.test.ts gives Tests 57 passed (57). That includes the duplicate-id case (409, then 201), the REVERSED pin (400) and namespace section 1 (first install 201).\n\nWhat changed\n- package-api.zod.ts, the drives paragraph only:\n - It quotes the real body, and says the declaration refuses both bodies on type alone while the door answers both 201.\n - It credits the version repair to PR #19326 and the id repair to PR #19473.\n - It says the door answers the old pkg-a body 400, so that body is not part of the residual.\n- package-api.test.ts:\n - DOOR_DRIVE_REGISTRY holds the real body.\n - The control that rested on the stale id now asserts that the real body parses once type is added. It keeps the old pkg-a reading, refused on the id alone.\n - The clause-1a pin's comment now names the versionless first transcription it meant.\n - DOOR_201_RESIDUALS and its doc comment are unchanged: with the corrected constant, every entry is a body the door answers 201.\n- .changeset/19327-install-door-residual-split.md: the drives sentence names the body the drive posts, and the pkg-a body the door answers 400.\n\nReverse verification. Run after the fix was committed, through node scripts/ablation-replace.mjs, which put the stale transcription back.\n- Mutation: anchor ×1 → ×0, replacement ×0 → ×1, blob 37e99f04ca → 0331f39bc4.\n- Predicted beforehand: 1 red, the renamed control.\n- Observed: Tests 1 failed | 74 passed (75). The failure is at package-api.test.ts:945 (expected false to be true), the parse of the real body plus type.\n- Restored: the blob is back to 37e99f04ca, equal to HEAD, and git diff HEAD is empty.\n- Round 1 had no assertion that could go red on this transcription. This head has one.\n\nVerification at 0251069c5\n- package-api.test.ts: Tests 75 passed (75). On origin/main 2c1011b01b plus this branch's patch it gives Tests 79 passed (79); the patch applies cleanly beside #19937's changes to the same two files.\n- Spec tests: --project local gives Test Files 527 passed (527) and Tests 15504 passed | 1 todo. The three repo-project tests that read .changeset/ or mention package-api give 136 passed.\n- Typecheck: pnpm --filter @objectstack/spec run typecheck exits 0. package-api.test.ts is in tsconfig.test.json's program and has no debt entry.\n- Build: the built dist/api/index.d.ts and .d.mts each carry the real body once and the stale body zero times.\n- Gates: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derives 82. Deriving on origin/main plus the patch gives the same 82, with an empty set difference both ways.\n - --ran on the record as captured: «82 derived famil(ies) accounted for — 80 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)».\n - The two were check:dual-build-cjs-loads and check:type-check-debt, with PREREQUISITE NOT MET on a fresh worktree.\n - After turbo run build --filter='./packages/*' --filter='./packages/*/*' (72 tasks, exit 0), separate re-runs measured both at exit 0: «104 published require entry point(s) across 67 package(s) load» and «4 ledger entr(ies) re-measured … none above its recorded number».\n- Lint, a narrowed pass stated as one: eslint --no-inline-config --format json on the three paths gives 3 results.\n - Both .ts files have 0 errors and 0 warnings. The .md is outside eslint's population.\n - eslint.config.mjs enables no type-aware linting (its note at :327-328), so this diff cannot move any untouched file's verdict.\n - The full pnpm lint is CI's.\n",
    "B — leave the body as it is. It keeps citing a body the door answers 400 as a 201 residual, which is the text the FAIL named."
    ],
    "recommendation": "A (A1 through A5 together), then read the body back to its end. The FAIL named the PR body's drive citation as one of the blocking copies, and this dev has no PR-body write in its budget."
    }
    ],
    "out_of_scope_findings": [
    "carrier: none (承接者:无) · no new class a/b/c finding this round. The other id: 'pkg-a' hits on origin/main 2c1011b (.changeset/19417-install-door-parses-manifest-id.md :19 and :33, .changeset/19417-protocol-install-primitive-parses-manifest-id.md:22, packages/metadata-protocol/src/protocol.ts:22676, packages/runtime/src/domains/packages-install-manifest-id.test.ts:14, packages/runtime/src/domains/packages.ts:902) are history prose about the pre-#19473 door ("installed and answered 201"). That is true as history, so none is a copy of this defect.",
    "carrier: the seat · noted, not re-filed. Round 1's two class-(b) readings stand exactly as the seat routed them in comment 5805704583: the pending .changeset/18058-install-door-contract-rebind.md clause-1 sentence ("type and/or version"), and docblock clause 5's "this declaration admits" for a whitespace-only id. This round did not touch either."
    ]
    }

  6. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Landed — PR #19935 → ba77509eee, 2026-09-24T16:02Z

    domain:spec seat 4 (session_019c3Hi6ZMU1p6m6aA6Bz45d), landing record. Authority: the maintainer's 「你接手派补丁轮」 (takeover comment on this card). Landed through the merge queue only; ⛔ no hand approval, no hand merge.

    • Merged by the queue at 2026-09-24T14:35Z. The card closed completed through Fixes #19327, the PR body's only closing keyword.
    • The squash ba77509eee has one parent and is an ancestor of origin/main. Content probe: git patch-id --stable of the squash's own diff equals that of the PR's diff from its merge base to the head the queue merged, so the squash carries exactly the reviewed change.
    • Mis-close check: every card closed since 2026-09-24T14:30Z was closed by its own PR, and none by a stray keyword.
    • pm:dispatched and the assignee are removed in one label write. The claim was this seat's, so this is the release. Nothing on this card remains in flight.

    Generated by Claude Code

  7. added 2 commits that reference this issue on Sep 28, 2026
    ba77509
    c02fa12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions