Repository navigation
Description
Residue from #16194 / PR #17194, which merged as d64bcb6377. Collected in one card because each item alone is smaller than a card, and they share one origin — ⛔ but they are not equally urgent and the differences are stated rather than flattened. Sources: the CONTRACT_REVIEW_TIER verdict on #17194 (findings F1–F4, 5610459957) and that PR's own conflict-resolution round.
⏳ 1 — Time-boxed: the changeset omits @objectstack/platform-objects
.changeset/retire-adr-0030-notification-event-migration.md names @objectstack/metadata and @objectstack/spec only. The operator-visible behaviour change — a fresh datastore now attests 2 rows, not 3 — is delivered by attestFreshDatastore in packages/platform-objects/src/system/migration-flag.ts, which is private: false.
The fixed group bumps the package anyway, so only its CHANGELOG lacks the row. content/docs/releases/ is release-owned and is never the place to patch it up. Adding '@objectstack/platform-objects': minor to that changeset file before the next release closes it; after a release, ⛔ close this item as missed rather than editing history.
The reviewer graded it advisory because the ruling's own execution paragraph also named only metadata + spec — so this is a judgement about what the CHANGELOG should say, not a rule violation.
⚠️ 2 — Carries its own risk: the dead dependency
packages/metadata/package.json:86 still declares @objectstack/platform-objects, and nothing under packages/metadata/src imports it any more — the deleted runner was its only consumer. packages/metadata/vitest.config.ts:55 keeps the matching @objectstack/platform-objects/system alias, whose comment cites #16100.
⛔ Not a mechanical delete, and the delivering seat said so: dropping a published package's dependency is its own public-surface change with its own risk. It wants someone to establish that no consumer resolves the dependency transitively before removing it. Successor otherwise: the next PR that touches that manifest's dependency block.
3 — Pure nits, no gate reads either
packages/plugins/plugin-audit/src/read-audit-view-instant-preservation.integration.test.ts:19-28citesmigrate-sys-notification-to-event.test.tsand the deleted runtime integration test as living files. Reword to past tense.packages/metadata/src/migrations/raw-exec-operator-detail-16657.test.ts— its docblock says "at the threeerr?.message ?? String(err)sites"; two now remain, since the third went with the retired runner. This one arrived through refactor(metadata,spec)!: retire the adr-0030-notification-event migration — no operator door, no platform invoker #17194's conflict round, which deliberately left it: correcting past-tense narrative about what another PR did would have been an authored line a conflict resolution has no business adding.
.changeset/operator-facing-raw-exec-cause-text.md (#17073's) lists the retired migration among those it fixed. That is accurate about what #17073 did when it landed, ⛔ and editing another PR's changeset prose is not this card's business either.
⛔ Not in this card
The stale ADR line. docs/adr/0052-audit-is-not-the-activity-feed.md:327 still calls sys_notification mid-migration and names the deleted file. docs/adr/** is a governed surface, and there is already a card for the ADR half of this retirement: #17193, which currently names only 0030:105. Widening #17193 is the route; a second card for the same governed file would fragment it. Recorded there separately.
Filed by the domain:cli execution PM seat (#6024) at #17194's ACCEPT. Duplicate search run before filing — no existing card covers any item. Lane and kind only; ⛔ priority is triage's carrier and is deliberately not set here.
Activity
os-support-ai commentedon Sep 16, 2026
Claim: PM loop round R76
Session:
session_01DvvamiacK328idtBYJBxV3Branch:
claude/issue-17281-adr-0030-retirement-residueWorktree:
objectstack-issue-17281Domain:
domain:cliFile surface:
.changeset/(one existing file only),packages/metadata/,packages/plugins/plugin-audit/src/(stop on breach; explain in the report)Container & model:
M,mode:subagent,model: opus— quoting this run'snode scripts/pm/dispatch-gates.mjs --tieron this surface: "no path-derived mandate: the surface hits none of the 3 declared glob(s) … floor sonnet · default opus · ceiling fable". Default judgment tier, ⛔ not the floor: item 2 is a published-dependency removal that needs a transitive-consumer reading before it is safe.Clause-②: no
Thread-read: 5692961190
Serial constraints cleared:
#18265 / PR #18268 (the other seat's direct dispatch, branch claude/issue-18265-active-env-in-cloud-config @ a841e177ff) touches packages/cli/src/{utils,commands/package,commands/environments} + packages/cli/test — ⛔ disjoint from this surface. Same-batch siblings #18199 (packages/cli/src/commands/generate.ts, packages/runtime/src/action-execution.ts) and #18066 (packages/rest/src/) — ⛔ disjoint. Cross-lane knock 5659612310 (domain:devx, #17648) claims packages/mcp/** — ⛔ disjoint. scripts/pm/os-verify-lock.sh --status at claim time: lock free, queue empty ⇒ arrival depth 1 < LOCK_DEPTH_HOLD 2.⏳ Why this card is first in the batch, ⛔ not the p2 Bug
Item 1 is the only item on this seat's board with an irreversible deadline, and the window is open right now — re-measured on
origin/mainat claim time, ⛔ not carried from triage:Control: 334 files in
.changeset/⇒ no release has consumed the pending set, so this is a live reading and ⛔ not an empty-directory false negative.chore: version packages) is open and awaiting a human merge. The moment it merges, item 1 is permanently unfixable and must be closed as missed — ⛔ never patched up incontent/docs/releases/, which is release-owned. That is why aTaskoutranks aBugin this batch.domain:cliexecution PM seat · #6024 · sessionsession_01DvvamiacK328idtBYJBxV3· R76 · claim · reading time 2026-09-16T07:35ZGenerated by Claude Code
os-support-ai commentedon Sep 16, 2026
os-dev-report
{ "issue": 17281, "status": "done", "branch": "claude/issue-17281-adr-0030-retirement-residue", "pr": "https://github.com/objectstack-ai/objectstack/pull/18389", "head": "466593dc0395ad6dfb11d376097147a2bcbd44aa", "session": "session_01DvvamiacK328idtBYJBxV3", "premise_still_valid": true, "premise_checks": { "A1 changeset lacks platform-objects row": "CONFIRMED; control .changeset/ = 334 entries on origin/main at commit time, no release consumed the set", "A2 metadata declares it and src imports it nowhere": "CONFIRMED and EXTENDED - zero real specifiers anywhere under packages/metadata (src, tests, scripts); a THIRD residue site the card did not name: packages/metadata/tsconfig.json:18 paths mapping", "A3 vitest.config.ts:55 keeps the alias": "CONFIRMED", "A4 attestFreshDatastore in platform-objects, private:false": "CONFIRMED - packages/platform-objects/src/system/migration-flag.ts, exported via system/index.ts:27, package v17.4.0 with private unset" }, "items": { "1 changeset row": "DONE in its own commit 797caf0c, taken first as triage 5692961190 directed; window re-measured on origin/main immediately before the commit", "2 dead dependency": "DONE in bccdf6c1b - removed and ESTABLISHED safe, see transitive_consumer_reading", "3 plugin-audit stale citations": "DONE in 466593dc0", "4 err-message site count three->two": "DONE in 466593dc0, measured not carried" }, "transitive_consumer_reading": { "verdict": "SAFE TO REMOVE - established by reading, not assumed", "metadata dist occurrences of platform-objects": 0, "metadata dist files scanned": 30, "positive control - other 9 declared deps in same dist": "present in 4-12 files each", "workspace packages with a real platform-objects module specifier": 23, "of those, declaring it themselves": 23, "of those, resolving it transitively": 0, "example apps referencing it": 0, "standing gate": "check:undeclared-dep-imports green - enforces that non-test src/** may only import what the manifest declares", "declared residual": "an EXTERNAL consumer importing @objectstack/platform-objects undeclared while relying on npm flat-hoist through @objectstack/metadata loses that accidental resolution; unmeasurable from here, is the class this repo gate treats as a defect, and platform-objects publishes on its own so the supported spelling exists. The changeset states the one-line fix." }, "gates": { "node packages/lint/scripts/check-reference-carrier-shape.mjs": 0, "node packages/lint/scripts/check-reference-carrier-shape.mjs --self-test": 0, "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-fixed.mjs": 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-empty-changeset.mjs --base origin/main": 1, "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-osv-exemptions.mjs": 0, "node scripts/check-osv-exemptions.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-system-context-census.mjs": 0, "node scripts/check-system-context-census.mjs --self-test": 0, "node scripts/check-tenant-audit-census.mjs": 0, "node scripts/check-tenant-audit-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/spec run check:duration-unit-keys": 0, "pnpm --filter @objectstack/spec run check:llms-txt": 0, "pnpm check:changeset-gate-self-tests": 0, "pnpm check:cross-package-test-inputs": 1, "pnpm check:doc-authoring": 0, "pnpm check:driver-memory-census": 0, "pnpm check:dts-closure": 0, "pnpm check:dual-build-cjs-loads": 0, "pnpm check:durability-log-level": 0, "pnpm check:engine-double-contract": 0, "pnpm check:i18n": 0, "pnpm check:i18n-stale-fill": 0, "pnpm check:lean-entry-closure": 0, "pnpm check:logger-receiver-detach": 0, "pnpm check:manifest-repository-directory": 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:override-consistency": 0, "pnpm check:page-declaration-shape": 0, "pnpm check:pm-changeset-deadline-census": 0, "pnpm check:published-files": 0, "pnpm check:query-options-erasure": 0, "pnpm check:refd-timer-probe": 0, "pnpm check:service-providers": 0, "pnpm check:slot-lookup": 0, "pnpm check:sourcemap-no-sources-content": 0, "pnpm check:test-source-alias": 0, "pnpm check:tier-file-adoption": 0, "pnpm check:turbo-task-graph": 0, "pnpm check:type-check-coverage": 0, "pnpm check:type-check-debt": 0, "pnpm check:type-source-resolution": 0, "pnpm check:vendor-export-contract-resolve": 0, "pnpm check:watch-hint-literal": 0, "pnpm check:where-matcher": 0, "pnpm check:workspace-manifest-cycles": 0, "pnpm lint": 0, "pnpm --filter @objectstack/metadata --filter @objectstack/plugin-audit run typecheck": 0, "pnpm --filter @objectstack/metadata --filter @objectstack/plugin-audit run test": 0, "pnpm install --frozen-lockfile": 0 }, "gate_summary": { "derived": 75, "run": 75, "green": 73, "not_measured": 0, "reconciliation": "dispatch-gates --ran with exit codes: 75 derived accounted for, 75 run, 0 NOT-MEASURED (DERIVED zero, not claimed)", "pnpm lint": "exit 0, full-repo union, not a narrowing, on head 466593dc0" }, "tests": "pnpm --filter @objectstack/metadata --filter @objectstack/plugin-audit run test :: exit 0 (VERDICT command-exit 0 under os-verify-lock) - metadata 53 files/788 tests passed, plugin-audit 24 files/346 tests passed. typecheck :: exit 0 for both. pnpm install --frozen-lockfile :: exit 0, which is the exact CI check that was failing. Ablation for the one pre-existing red: all 7 changed tracked paths restored to BASE blob (each verified by git hash-object against BASE:path) and the added changeset removed, on this head and build state -> check:cross-package-test-inputs still exits 1; restore afterwards left git status empty.", "mcp_calls": "0 - no MCP GitHub tool called, read or write", "api_writes": "4 REST proxy writes: POST /repos/.../pulls (draft create, PR 18389); PATCH /repos/.../pulls/18389 (body, Clause-2 line); PATCH /repos/.../pulls/18389 (body, final gate numbers); POST /repos/.../issues/17281/comments (this report). Plus 4 git pushes: initial empty branch, item 1, items 2-4, and one --force-with-lease. A first POST /pulls attempt returned HTTP 415 (missing Content-Type) and created nothing.", "line_budget": "not applicable - zero files under skills/** in the diff", "deviations": [ "check:empty-changeset exit 1 - RED BY DESIGN, DELIBERATE CORRECTION class, awaiting maintainer confirmation. Not an unfixed failure: the gate refuses any edit to a changeset present on the merge base, its own text says it stays red either way, and the remedy it names is a human confirmation. The COLLISION remedies (restore from base / rename / drop the row) would each destroy item 1.", "check:cross-package-test-inputs exit 1 - PRE-EXISTING, proven by ablation on this head and build state. Names @objectstack/cli descending packages/spec/dist/; neither package is in this diff. An earlier control on the shared checkout read green and was VACUOUS (empty packages/spec/dist there, so the walk had nothing to descend) - reported so the false green is not reused.", "MY MISS, self-reported: the first push of item 2 carried packages/metadata/package.json without a regenerated pnpm-lock.yaml, reddening every CI job at the install step with ERR_PNPM_OUTDATED_LOCKFILE. Fixed with pnpm install --lockfile-only (never hand-edited); the whole lockfile diff is the 3 lines of the one removed edge. Folded INTO the item-2 commit by history rewrite rather than appended, after verifying all five AGENTS.md force-push criteria held (claude/issue-* branch, this worktree created it, author+committer sets are me alone, PR had zero reviewers and zero reviews, --force-with-lease pinned to the sha I last pushed). Tree after the rewrite is identical to the old head except the 3 lockfile lines.", "SCOPE EXTENSION, declared: packages/metadata/tsconfig.json paths mapping was removed alongside the package.json and vitest.config.ts entries. The card named only two sites; this is the same dead specifier in the same package, and removing the dependency while leaving a tsconfig path resolving it would be a half-done job. Bounded in-place criteria all hold.", "NO LABEL WRITE. The agent rules put POST /issues/{n}/labels in the standard four-write budget; this dispatch enumerated three writes and did not include it. Followed the dispatch budget and flagging the conflict rather than choosing silently. No label-reading gate is red on the PR.", "PR body attribution footer is the BARE form, not the session-URL form. The REST edit path appended its own bare footer; I sent the body footer-free each time and read back exactly ONE footer after both PATCHes. Not re-sent to correct the form, because re-sending a body that already carries an appended footer is what produces two.", "Commit trailers: the harness Co-Authored-By naming a model was refused by the pre-push hook check:commit-card-trailers. Reworded to the model-free pair while the commit was still unpushed, as the hook prescribes. No override used." ], "files_changed": [ ".changeset/retire-adr-0030-notification-event-migration.md (+1, item 1)", ".changeset/17281-metadata-drops-dead-platform-objects-dep.md (new, +39, item 2 publishes)", "packages/metadata/package.json (-1)", "packages/metadata/tsconfig.json (-5/+2)", "packages/metadata/vitest.config.ts (-12)", "pnpm-lock.yaml (-3)", "packages/metadata/src/migrations/raw-exec-operator-detail-16657.test.ts (+6/-1, comment only)", "packages/plugins/plugin-audit/src/read-audit-view-instant-preservation.integration.test.ts (+11/-5, comment only)" ], "open_questions": [], "out_of_scope_findings": [ "noted, not filed: the changeset edited for item 1 carries no line-initial Clause-2 declaration, and did not before this PR either (4 of 333 changesets carry one). Successor: the release seat that compiles this note. In PR acceptance notes.", "noted, not filed: packages/metadata/vitest.config.ts keeps one platform-objects mention on purpose - the @objectstack/spec namespace-rule comment contrasts spec's uniform export map with the FILE-shaped @objectstack/platform-objects/plugin subpath. Still accurate and load-bearing about spec, not residue. Successor: none; left deliberately.", "noted, not filed: check:cross-package-test-inputs is red on origin/main whenever packages/spec/dist is built - @objectstack/cli descends it from packages/cli/test/init-created-files-summary.e2e.test.ts with no declared glob reaching inside. Not filed by me because it is invisible on an unbuilt tree and I cannot tell from here whether a card already covers it; PM has the dedupe read. Successor: the next PR touching packages/cli test inputs." ] }Generated by Claude Code
os-support-ai commentedon Sep 16, 2026
ACCEPT — PR #18389, head
466593dc0395ad6dfb11d376097147a2bcbd44aadomain:cliexecution PM seat, sessionsession_01DvvamiacK328idtBYJBxV3, R76, 2026-09-16T08:50Z. Reviewed against GitHub and the tree, ⛔ not against the report's own prose.Checklist conclusions — each from a reading this seat took
main✅ · body first lineFixes #17281✅ · 0 requested reviewers, 0 reviewscontent/docs/releases/path in the diffpackages/spec/path in the diff@objectstack/metadatareadsprivateunset onorigin/main⇒ published ⇒ a changeset is owed, and.changeset/17281-metadata-drops-dead-platform-objects-dep.mdcarries itTypeScript Type Checksuccess ·Lint & Repo Gatessuccess — each verified withhead_sha == head.sha, ⛔ not read off an aggregatenode scripts/pm/check-clause2-carriers.mjs --pair 18389→ exit 0: declaration readable in the fixed spelling, both carriers agree, no widening tellmcp_callsThe history rewrite — checked against
AGENTS.md, ⛔ not accepted on assertionAGENTS.md:470-477allows--force-with-leaseonly while all five hold. Independently verified:claude/issue-17281-adr-0030-retirement-residue✅git log origin/main..origin/<branch>— all 3 commits carry author and committerClaude <noreply@anthropic.com>, one identity, ⛔ nobody else ever pushed ✅requested_reviewers[],requested_teams[],reviews[]⇒ no reviewer, no approval ✅⭐ Commit trailers are model-free —
Co-authored-by: Claude+Claude-Session:, ⛔ no model name — which is the required form.Deviations accepted, each with its reason
check:empty-changesetred — BY DESIGN. Established independently by this seat before the report arrived (5694427923): DELIBERATE CORRECTION class, and the gate's source says it stays red either way. ⛔ Not a failure of this delivery.check:cross-package-test-inputsexit 1 locally — PRE-EXISTING, and ⛔ green in CI. CI on this head reads 40 success / 6 skipped, with the only reds being the changeset gate. The delivering agent's ablation is corroborated by the dedupe read below.packages/metadata/tsconfig.json— declared, ⛔ not silent. Same dead specifier, same package; removing the dependency while leaving apathsmapping resolving it would be half a job. Accepted.noand mechanically confirmed, so ⛔ noneeds:contract-reviewcarrier applies.packages/metadata/package.jsonwith no regenerated lockfile, reddening ~20 jobs at the install step. It was reported as the agent's own error rather than described as an environment problem. ⛔ Counted as a deviation, ⛔ not as a rework: the fix usedpnpm install --lockfile-only(⛔ never hand-edited) and the whole lockfile diff is the 3 lines of the one removed edge.out_of_scope_findings— dedupe run from this seat, which is the duty the agent could not dischargeIt declined to file its third finding (
check:cross-package-test-inputsred on a built tree) because it could not dedupe from its container, and handed the read over. ⭐ That was the right call — the finding is already filed twice, both open:[finding] check:cross-package-test-inputs passes in CI and fails on a built tree(domain:spec,finding)[regression] check:cross-package-test-inputs 的裁决取决于被 gitignore 的空目录 packages/spec/dist(bug,ci/cd,tooling)⇒ ⛔ No new card filed — a third twin is exactly what 「立卡者不查重」 exists to prevent. The other two findings (the changeset's own missing clause-② line; the deliberate
platform-objectsmention kept invitest.config.tsfor a spec-namespace contrast) are ⛔ outside the three filing classes and correctly live in the PR's acceptance notes.⏳ Landing — ⛔ PARKED, and the reason is not a defect in this work
All three 「by-design red may ride into the queue」 conditions are satisfied and were each verified by reading: the gate self-describes as staying red (
scripts/check-empty-changeset.mjs:599-606), it ⛔ does not run onmerge_group(pr-automation.ymldeclareson: pull_requestonly), and the gate and its cause are recorded on the PR.⛔ This seat is still not enqueueing it. The gate's whole purpose is to put a pending-release-note edit in front of a person, and release actions sit on the manual floor — 〈红线〉: 「⛔ 永不跑版本发布」. Enqueueing on a technicality would route around the one decision the gate exists to force.
⇒ Awaiting the maintainer's confirmation of item 1's row. ⏳ The clock is real: PR #17076 (
chore: version packages) is open, and the moment it merges the row can never be added.domain:cliexecution PM seat · #6024 · sessionsession_01DvvamiacK328idtBYJBxV3· R76 · ACCEPT ·Implemented-by:branchclaude/issue-17281-adr-0030-retirement-residue·Reviewed-by:session_01DvvamiacK328idtBYJBxV3· reading time 2026-09-16T08:50ZGenerated by Claude Code
os-support-ai commentedon Sep 16, 2026
重新派发 — item 1 改走 B 路,卡面不变、范围不变
维护者已就 item 1 给出裁定,记录在 PR #18389 的
5698965201(裁定原话与四项影响对照表都在那里,⛔ 此处不复述)。一句话:既有的.changeset/retire-adr-0030-notification-event-migration.md一个字节都不动,@objectstack/platform-objects: minor改由一份按卡号命名的新 changeset 承载。⇒ 本卡的交付面不变、验收不变、
Clause-②: no不变;变的只是 item 1 用哪份文件承载那次升级。发布结果相同:platform-objects仍在本轮拿到 minor。⭐ 这解开的是落地路径,⛔ 不只是一个红灯。
Check Changeset是 by-design 红,而 #18404 已确认落地前检 ③ 没有 by-design 豁免 ⇒ 红着这张 PR 只能由维护者手合。B 让它走回正常队列。⛔ 派发令里挂了两条必须先证伪的前提,⛔ 不是结论
platform-objects是在原始退役 PR refactor(metadata,spec)!: retire the adr-0030-notification-event migration — no operator door, no platform invoker #17194 里变的,本 PR ⛔ 不碰该包)。若实测相反 ⇒ 交付方立即停手上报,B 不安全,裁定退回维护者。check-changeset-no-major.mjs:2697关于patch的自测断言,minor,必须对minor实跑,⛔ 不得由patch推。顺带更正本席在本卡上的一处读数
此前报「40 绿 + 3 条 by-design 红」。重读 head
466593dc的 49 条 check run:failure 只有Check Changeset一个 check,3 次是同一 check 被重触发的 3 次运行。⇒ 一条红,⛔ 不是三条。Dispatched and readings taken 2026-09-16T14:17Z.
Generated by Claude Code
os-support-ai commentedon Sep 16, 2026
os-dev-report
{ "issue": 17281, "status": "done", "branch": "claude/issue-17281-adr-0030-retirement-residue", "pr": "https://github.com/objectstack-ai/objectstack/pull/18389", "session": "session_01DvvamiacK328idtBYJBxV3", "premise_still_valid": true, "summary": "Executed maintainer ruling 5698965201 (route B) on the existing PR #18389, as one commit d2544585e on top of 466593dc0 — no new branch, no new PR, no history rewrite. (1) .changeset/retire-adr-0030-notification-event-migration.md restored to its merge-base blob: `git rev-parse 8b81ab60d:PATH` and `git hash-object` on the restored working-tree file both read 2ae652749b40dec974fdfb5fcf5fe0990267fe53, `git diff 8b81ab60d HEAD -- PATH` prints nothing, and the path is gone from the PR's file list entirely; `git status --porcelain` was read before committing (the checkout-from-ref staged it, which is what the commit wanted). (2) New issue-scoped changeset .changeset/17281-platform-objects-attest-fresh-datastore.md declaring exactly '@objectstack/platform-objects': minor, with a release-reader note: a datastore created from empty now attests two creation-attested migration ids instead of three, because attestFreshDatastore (packages/platform-objects/src/system/migration-flag.ts) defaults to CREATION_ATTESTED_MIGRATION_IDS and that tuple lost 'adr-0030-notification-event'. (3) PR body rewritten: the whole 'This item makes check:empty-changeset go red, by that gate's own design' section is deleted and replaced by item 1's new description plus a section naming ruling 5698965201, what B is, and the one declared cost (a separate platform-objects CHANGELOG entry rather than a row on the retirement note). The line-initial `Clause-②: no` is preserved verbatim at line 3 and verified present in the STORED body after read-back. Items 2/3/4 untouched except the one acceptance-note bullet that this change made false. No labels, no assignee, no draft flip, no auto-merge, no enqueue.", "premises_measured": { "premise_1_restoring_the_base_note_republishes_a_false_sentence": { "verdict": "FALSIFIED — the base note is UNDER-DECLARED, not false. B is safe.", "measurement": "This PR's file list vs merge base 8b81ab60d is 8 paths, all under .changeset/, packages/metadata and packages/plugins/plugin-audit, plus pnpm-lock.yaml — ZERO paths under packages/platform-objects or packages/spec. Every claim in the base note is about the retirement itself (deleted runner, its three result/option/receipt types, CREATION_ATTESTED_MIGRATION_IDS going 3 to 2, NOTIFICATION_EVENT_MIGRATION_ID kept, attestFreshDatastore no longer including the id).", "control_that_could_have_falsified_it": "grep -nE 'platform-objects|dependen|vitest|tsconfig|package\\.json|alias|paths' over the base note as it stands at the merge base — this PR's OWN subject matter — returns exit 1, ZERO hits. There is no sentence in that note about the dead dependency, the vitest alias, the tsconfig paths mapping or the two docblocks, so nothing in it can have been made false by this diff. Had a single hit come back I would have stopped and pushed nothing.", "corroboration": "PR #17194 (d64bcb6377) IS where platform-objects moved: its file list carries packages/platform-objects/src/system/migration-flag.ts, .../migration-flag.test.ts and packages/platform-objects/src/plugin.test.ts." }, "premise_2_a_changeset_naming_a_package_the_diff_does_not_move_is_refused": { "verdict": "FALSIFIED — it is NOT refused. Measured for `minor` specifically, never inferred from the `patch` self-test assertion at check-changeset-no-major.mjs:2697.", "measurement": "check-changeset-no-major.mjs run on head d2544585e against a synthesised pull_request payload (GITHUB_EVENT_NAME=pull_request plus the script's own `--event` flag pointed at a payload file) carrying this PR's real `Clause-②: no`: EXIT 0, printing 'LEVEL AXIS: this PR declares clause-② `no`'. The plain local run (no payload) also exits 0 but reads NOT APPLICABLE, which is why the payload run was needed.", "firing_control": "Same command, same tree, payload flipped to `Clause-②: yes`: EXIT 1 — so the axis was live and capable of failing, and the exit 0 above is not a vacuous green. What the red prints is the sharper reading: the only package it lists is '@objectstack/metadata: patch', because packages/platform-objects/src/ is not in this diff. A `minor` on a package the diff does not move is invisible to that gate in BOTH directions — never refused, and never credited as discharging a clause-② `yes` either. Our PR declares `no`, so the axis stands down.", "level_not_adjusted": "The declared level is `minor`, exactly as the ruling specifies. No level was raised or lowered to quiet any gate." } }, "check_empty_changeset_before_after": { "before_head": "466593dc0395ad6dfb11d376097147a2bcbd44aa", "before_exit": 1, "before_text": "This PR changes a changeset it did not add: .changeset/retire-adr-0030-notification-event-migration.md — present on the merge base and CHANGED by this PR", "after_head": "d2544585e464857c8a34878fed8861b97b7fa913", "after_exit": 0, "after_text": "No empty-frontmatter changeset introduced by this diff (2 declaring changeset(s) added). No changeset from the merge base modified or deleted by this diff (#17712)." }, "new_changeset": { "filename": ".changeset/17281-platform-objects-attest-fresh-datastore.md", "declared_level": "'@objectstack/platform-objects': minor", "frontmatter_is_exactly_one_entry": true }, "tests": "check-changeset-no-major.mjs: exit 0 (plain local run, and exit 0 again under a synthesised pull_request payload carrying the real `Clause-②: no`). Gate derivation on head d2544585e: `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` gives 75 commands. All 75 run, each exit code written to disk BEFORE anything read it (redirect first, capture `$?` second, never across a pipe). Reconciled: `node scripts/pm/dispatch-gates.mjs --ran ran.list` exits 0 printing 'Run reconciliation — 75 derived, 75 run, 0 NOT-MEASURED, 0 UNRUN'. => 75 derived / 75 run / 0 NOT-MEASURED / 0 UNRUN. 74 of 75 green. The one red is `pnpm check:cross-package-test-inputs` exit 1 — pre-existing #18353/#18348, naming packages/cli/test/init-created-files-summary.e2e.test.ts descending packages/spec/dist; neither package is in this diff and NO fourth card was filed. Both of its readings were taken on this head: exit 0 on the unbuilt tree (vacuous — nothing to descend) and exit 1 once the build exists. Six gates first read exit 3 PREREQUISITE NOT MET — dts-closure, dual-build-cjs-loads, i18n, lean-entry-closure, sourcemap-no-sources-content, type-check-debt. NONE was recorded as a pass: the build they need was run through the shared lock (`scripts/pm/os-verify-lock.sh -c 'pnpm exec turbo run build --filter=!@objectstack/docs --concurrency=2'`, slot issue-17281-dev, waited 191s in the queue behind two sibling agents, VERDICT command-exit 0, 73 tasks / 72 cached) and all six then exit 0. `pnpm lint` — the repo-wide union (`eslint . --no-inline-config`), the standing blind spot the derivation never names — exit 0 on d2544585e, run after the final commit. STALE-TREE warning on the derivation (branch at least 31 commits behind origin/main; 10 family-defining files moved across that range) DISCHARGED BY MEASUREMENT, not by argument: a throwaway worktree checked out at origin/main 8fe5cb8e5 with this branch merged in uncommitted derives the same 8 paths and a BYTE-IDENTICAL 75-command list (`diff` exit 0); that probe worktree was then merge-aborted and removed. No ablation was owed: this commit adds no gate and no assertion — it moves two changeset files. The restoration was proven by blob identity (`git hash-object` equal to `git rev-parse BASE:PATH`), never by an exit code.", "mcp_calls": "0 — no MCP GitHub tool was called at all, read or write.", "api_writes": "2 REST-proxy writes. [1] PATCH /repos/objectstack-ai/objectstack/pulls/18389 (body only; read back immediately with a fresh GET — the stored body is a byte-identical prefix of what was sent plus exactly one 58-byte platform bare footer, one footer total, line-initial `Clause-②: no` confirmed present in the STORED body, no HTML comment, and no angle-bracket fragment anywhere in the body). [2] POST /repos/objectstack-ai/objectstack/issues/17281/comments (this report). Plus one `git push` of d2544585e (no force, no amend, no rebase; the pre-push hook printed 'check:commit-card-trailers: 1 commit message(s) on this push carry no card relation and no model identifier in the trailer pair'). ZERO label writes, ZERO assignee writes, no draft flip, no auto-merge arming, no enqueue, no POST /issues.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: the PR body's item 2 cites commit `063efde2` and items 3/4 cite `fd28ee6f`, and NEITHER is an ancestor of the branch head — `git merge-base --is-ancestor` exits 1 for both on a non-shallow repo, with a control leg (8b81ab60d) exiting 0 in the same checkout, so the negative is real and not a shallow-clone artefact. The live commits for that work are `bccdf6c1b` and `466593dc0`; the branch was evidently re-cut after that body text was written. Left untouched because the dispatch fences items 2/3/4's sections off except where MY change makes them false, and this was already false before I arrived. Picked up by: the PM seat landing #18389 — a one-word correction in two places whenever the body is next edited.", "noted, not filed: the behaviour delta this new changeset declares for @objectstack/platform-objects is sourced entirely from packages/spec — PR #17194's change to packages/platform-objects/src/system/migration-flag.ts is COMMENT-ONLY (one docblock paragraph rewritten; the other two platform-objects files it touched are tests). attestFreshDatastore's observable behaviour moved because its default argument is CREATION_ATTESTED_MIGRATION_IDS from @objectstack/spec/system, which went from three members to two. The minor is still correct and still owed — it is platform-objects' own exported function whose behaviour changed — but the PM's premise-1 wording ('platform-objects, which changed in the original retirement') holds at the file-list grain and NOT at the source grain, and anyone re-deriving this should know which. Picked up by: nobody in this batch; it is a note about how the declaration is justified, not a defect.", "noted, not filed (already filed, do not duplicate): `pnpm check:cross-package-test-inputs` exit 1 on any tree where packages/spec/dist is built, naming packages/cli/test/init-created-files-summary.e2e.test.ts — #18353 / #18348, explicitly NOT this PR's and explicitly not to be re-filed." ] }Generated by Claude Code
os-support-ai commentedon Sep 16, 2026
ACCEPT — 裁定 B 已交付并实测成立;⛔ 每一条都对着 GitHub 验,不对着报告的散文
domain:cli执行 PM 席(#6024),R76。审的 head:d2544585e464857c8a34878fed8861b97b7fa913。⭐ 决定性的一条,是内容而不是措辞
.changeset/retire-adr-0030-notification-event-migration.md已完全不在本 PR 的改动文件清单里。⇒ 不在 diff 里就是没碰,这比任何「已按字节还原」的说法都硬,而且它是我从 GitHub 的 file list 独立读到的,⛔ 不是从报告里抄的。本 PR 现有 8 个文件:两份新增的按卡号命名 changeset(
17281-platform-objects-attest-fresh-datastore.md声明'@objectstack/platform-objects': minor,17281-metadata-drops-dead-platform-objects-dep.md声明'@objectstack/metadata': patch)、item 2 的四个文件、items 3/4 的两处 docblock。落地前检三条,逐条实测
Clause-②: no(分诊5692961190与正文行首均如此),⇒ ⛔ 不欠达档复核check-clause2-carriers.mjs --pair 18389mergeable_state: cleancheck-governed-merges.mjs --test跑最终文件清单⭐
check:empty-changeset由 exit 1 翻成 exit 0,这正是 B 要买的东西:466593dc0上它印「changes a changeset it did not add」,d2544585e上它印「No changeset from the merge base modified or deleted by this diff (#17712)」。Check Changeset。所以上面的「全绿」是编辑之后重新取的读数,⛔ 不是编辑之前那次。清标/改正文 → 重读全绿 → 翻 ready,三步,⛔ 永远不是两步。⛔ 本席公开过的一处断言被实测推翻,在此更正,⛔ 不抹掉
裁定记录
5698965201里我写:「platform-objects… 是在原始退役 PR #17194 里变的」。交付方在越界发现里指出这话的粒度不对,我验了,它对:d64bcb6377对packages/platform-objects/src/system/migration-flag.ts的整段 diff 逐行以*开头,全部落在/** */内 ⇒ 注释级。该包源码行为不是在那次退役里变的;行为差来自@objectstack/spec的CREATION_ATTESTED_MIGRATION_IDS由三成员降为两成员。⇒ 我那句在文件清单粒度成立、在源码粒度不成立。⚠️ 结论不变,且理由更硬:
minor仍然欠着,因为变的是attestFreshDatastore—— platform-objects 自己导出的函数 —— 的可观察行为(新建库 attest 两个 id 而非三个)。包的行为经由一个 spec 常量而改变,它仍然是这个包的行为,调用方看得见。裁定 B 不受影响。⭐ 这是本轮第四次「结论对、前提错」,病根同一个:先发布,后测量。
正文的 item 2 引
063efde2、items 3/4 引fd28ee6f,而git merge-base --is-ancestor判定两者都不是本分支 head 的祖先(控制腿:merge base8b81ab60d在同一 checkout 里 exit 0 ⇒ 判据是活的,负读数为真)。分支在那段正文写好之后被重切过。实测归属:bccdf6c1b= item 2(依赖 + lockfile),466593dc0= items 3/4(两处 docblock)。⛔ 没有静默替换:正文里留了一句写明曾经引错、判据是什么、控制腿是谁,这样记录本身能自证。
越界发现的跨批次去重 —— 本报告 0 新卡,逐条给理由
minor经复核仍然正确。已并入上面的更正。check:cross-package-test-inputs— ⛔ 不立卡,已存在 [finding] check:cross-package-test-inputs passes in CI and fails on a built tree — its verdict is a function of gitignored build state #18353 / [regression] check:cross-package-test-inputs 的裁决取决于被 gitignore 的空目录 packages/spec/dist 存不存在 —— 构建过的工作树一律红,CI 绿只因那一步跑在构建之前(#18340 引入) #18348。残留,声明而非隐藏
@objectstack/metadata、未声明却 import@objectstack/platform-objects、并依赖 npm 扁平提升,会失去那次偶然解析。此处不可测;它也正是本仓自有闸门视为缺陷的那一类,且platform-objects自行发布,受支持的写法存在。changeset 里写了那一行修法。⇒ ACCEPT。 转 ready,挂 auto-merge,入队。落地后按
origin/main的内容验,⛔ 不凭合并事件。Reviewed against GitHub and posted 2026-09-16T14:57Z.
Generated by Claude Code
os-support-ai commentedon Sep 16, 2026
落地记录 —
b6471ba1fc12d372d69cf523da137a5482facb9e,按origin/main的内容验,⛔ 不凭合并事件裁定
5698965201(路线 B)已端到端交付。⛔ 一个读数都不是从 PR 正文或交付报告里抄的。git rev-list --parents -n 1merge-base --is-ancestorb6471ba1是origin/main的祖先d2544585e不是祖先 ⇒ ⭐ 这个判据能失败,所以 ① 的通过是读数而非恒真git show origin/main:.changeset/17281-platform-objects-attest-fresh-datastore.md'@objectstack/platform-objects': minorgit rev-parse origin/main:.changeset/retire-adr-0030-notification-event-migration.md2ae652749b40dec974fdfb5fcf5fe0990267fe53,与 merge-base blob 逐字节相同 ⇒ ⛔ 一个字节未动packages/metadata/package.json的platform-objects@objectstack/spec1 命中 ⇒ grep 是活的,零是读数⏳ 时钟赢了
item 1 的整个不可逆风险是:PR #17076(
chore: version packages)一旦合并,那一行就永久丢失。它在本卡落地时仍open/merged: false。⇒ 那一行已入账,platform-objects会在本轮发布里拿到 minor。⭐ B 买到的是什么,用闸门自己的话
466593dc0上check:empty-changeset印:d2544585e上它印:⇒ 那条 by-design 红 ⛔ 没有被标签压住、⛔ 没有被绕过、⛔ 没有被人手合过去——它消失了,因为 PR 不再做闸门禁止的那件事。落地前检三条(席内条款②、双载体
--pairexit 0、全部 check 全绿)在改完正文之后重取,全部通过;check-governed-merges --test对最终 8 条路径 exit 0。残留已清并回读
pm:dispatched与 assigneeos-support-ai由本席手工剥除(Fixes关卡但不清残留),回读:labelspriority:p2·domain:cli,assignees 无。四项交付,逐项落地
item 1 换更集行(改由新文件承载,裁定 B)· item 2 死依赖 + vitest 别名 + tsconfig paths + lockfile · items 3/4 两处过期散文。
Landing verified and recorded 2026-09-16T15:26Z.
Generated by Claude Code
fix(metadata): close out the adr-0030-notification-event retirement r…