Repository navigation
Description
Found while measuring #13801 (duration-shaped declarations in packages/spec). Not addressed there — #13801 is scoped to the wall-clock/business-hours misread on live declarations; this card is the enforce-or-remove question on declarations nothing reads.
What was measured
Four packages/spec schema files declare hour/minute/day-shaped deadline and SLA keys that no package outside packages/spec reads (git grep over packages/** excluding packages/spec, tests and changelogs: zero hits for every key below), and none of the four carries the ADR-0049 [EXPERIMENTAL — not enforced] tag (grep -c EXPERIMENTAL = 0 in each file):
| schema file | keys (all bare numbers, unit in .describe() prose only) |
|---|---|
packages/spec/src/system/incident-response.zod.ts |
IncidentResponsePhase.targetHours (:97), IncidentNotificationRule.withinMinutes (:142), regulatory deadline hours (:154), auto-escalation minutes (:177), IncidentResponsePolicy.triageDeadlineHours (:346), retentionDays (:363) |
packages/spec/src/system/training.zod.ts |
TrainingCourse.durationMinutes (:89), validityDays (:104), recertification interval days (:185), grace-period days (:197), reminder lead days (:209) |
packages/spec/src/system/change-management.zod.ts |
durationMinutes (:97), estimatedMinutes (:150, :285) |
packages/spec/src/data/document.zod.ts |
ESignatureConfig.expirationDays (:218), reminderDays (:224) |
All of them are on the published authorable surface (packages/spec/authorable-surface/system.json:508-521, :1308-1314; data.json for ESignatureConfig) and in the exported API surface (packages/spec/api-surface/system.json), so an author can write triageDeadlineHours: 4 today and nothing on the platform will ever act on it — the same declared-but-inert shape ADR-0049 names, here on SLA-shaped numbers rather than security bits. The schemas are exported from packages/spec/src/system/index.ts:68 but mounted by no stack key (stack.zod.ts does not reference them) and registered as no metadata type.
Why it is filed rather than fixed in #13801
#13801's ruling is about making the clock semantics of live duration declarations un-misreadable. An inert declaration has no clock to misread — its disposition is enforce-or-remove (ADR-0049 / the spec-property-retirement playbook), which is a separate decision per schema family (ISO-27001 compliance shapes vs the e-signature config). The 2026-06 liveness ledgers under docs/audits/ have no mention of incident-response, training or change-management, so this family appears to have missed the audit.
Suggested disposition (for triage, not decided here)
Per family: tag [EXPERIMENTAL — not enforced] in the describe text if a consumer is roadmapped, or retire via ADR-0087 conversion if none is. Either way the JSON-schema/reference-docs output (content/docs/references/**, generated from .describe()) stops advertising a deadline the platform does not keep.
Refs #13801.
Triage — graded
Spot-checked at origin/main 4a37870: grep -c EXPERIMENTAL is 0 in all four files, and the sampled keys (triageDeadlineHours, expirationDays, validityDays) have zero readers anywhere in packages/** outside packages/spec. The measurement holds.
The card is right that this is enforce-or-remove and right that it is a per-family question. Graded as a decision: retiring keys that sit on the published authorable surface is an ADR-0087 conversion each, and "is a consumer roadmapped" is product knowledge the seat does not have. Whoever executes after the ruling should run the spec-property-retirement playbook rather than improvising the route.
<!-- os-decision-facets -->
- ① 项目长远合理性(权重 ≥50%,领起推荐) —— 平台今天在公开的可编写面上摆着一批期限键:事故triage 几小时、证书多少天过期、电子签名多少天失效。作者可以写,写完平台永远不会照做。这不是「还没实现」,而是一份平台没打算守的承诺印在了参考文档里(那些文档正是从这些 describe 生成的)。ADR-0049 的 enforce-or-remove 就是为这个形状立的。长远终态:公开面上的每一个键,要么被执行,要么被标注为未执行,要么不存在 —— 三者之外没有第四种。①指向收窄:没有路线图的整族退役。
- ② 实际业务拉动 —— 零。四个文件、十五个键,全仓没有一个读取方,也没有客户在报。⇒ 按分歧推荐序,零拉动 ⇒ 荐④不扩散,而④在这里正好也指向退役。
- ③ 防 AI 犯错 —— 出错时谁看到什么:一个 AI 作者读参考文档,看到
triageDeadlineHours,合理地认为写上4平台就会在 4 小时后升级事故。它不会。没有报错、没有告警、没有任何反馈 —— 只有一条永远不会触发的 SLA,而这恰恰是合规场景里最不能静默失败的东西(ISO-27001 形状的键尤其如此)。[EXPERIMENTAL — not enforced]标注是最低限度的响亮;退役是彻底的响亮。 - ④ 创业阶段不扩散 —— 每一个已声明的键都是永久义务:向后兼容、迁移路径、文档、以及「将来真要实现时得按这个形状实现」的约束。十五个没有消费者的键,是十五条白背的义务。remove 优于 declare-and-maintain,这一条在本卡上是字面意义的。
推荐:A —— 按族分别处置,默认退役。 对 incident-response / training / change-management 三族(合规形状、无消费者、连 2026-06 的 liveness 台账都没收录),走 ADR-0087 转换退役,执行时按 spec-property-retirement playbook 走,⛔ 不要自创路线。对 ESignatureConfig(document.zod.ts)单独判:它与已在跑的文档子系统同族,最可能是四族里唯一有路线图的,若确有,给它 [EXPERIMENTAL — not enforced] 标注而不是退役。①④同向,②零拉动不构成保留理由。
回退:B —— 四族全部只加 [EXPERIMENTAL — not enforced] 标注,不退役。 若维护者判定这批合规形状是有意留下的路线图占位(ISO-27001 是可预期的商业需求),那就把「未执行」这件事说清楚,并把它们补进 liveness 台账,以免下一轮审计再次漏掉。代价:十五条永久义务原地保留。
置信缺口(本分析看不见什么): 看不见路线图 —— 这四族到底有没有计划中的消费者,是唯一能把 A 翻成 B 的变量,而它不在代码里。另外本席只抽验了三个键的读取方(triageDeadlineHours / expirationDays / validityDays),不是全部十五个;执行前应把卡面那张表整表重跑一遍,因为「零读取方」是整个推荐的地基。
Generated by Claude Code
Activity
os-project-manager commentedon Sep 3, 2026
Maintainer ruling recorded — A: retire per family, default retirement —
incident-response,trainingandchange-managementgo through the ADR-0087 conversion;ESignatureConfigis tagged[EXPERIMENTAL — not enforced]only if a consumer is roadmapped, otherwise retired with the restDirector seat (objectstack #12708), summon #10, session
session_01ShyhexkB2d1AeRZ85tgAAe, 2026-09-02.Provenance (who / verbatim / where): maintainer, live PM chat with the director seat, replying to decision batch #14 in which this card was item 1 with the recommendation A (fallback B: tag all four families and add them to the liveness ledger), the same recommendation triage attached. Verbatim reply: 「14461 你不处理,其他同意」 — "其他同意" covers this card, so A is adopted as recommended.
Ruled: A. The three compliance-shaped families (
packages/spec/src/system/incident-response.zod.ts,training.zod.ts,change-management.zod.ts: thirteen hour/minute/day-shaped keys, zero readers outsidepackages/spec, no EXPERIMENTAL tag, absent from the 2026-06 liveness ledgers) are retired under ADR-0049 enforce-or-remove, by thespec-property-retirementplaybook and an ADR-0087 conversion each — ⛔ no improvised route. The generated reference docs stop advertising deadlines the platform does not keep.The
ESignatureConfigpair (document.zod.tsexpirationDays,reminderDays) is the one branch the reply did not settle. The seat asked, alongside the card, whether e-signature has a roadmap; the reply did not answer it. Per the ruled text: a roadmap ⇒ the two keys get the[EXPERIMENTAL — not enforced]tag and a liveness-ledger entry; no roadmap ⇒ they retire with the other three families. The seat has put the one-line question back to the maintainer and records the answer here when it arrives. Until then the spec seat executes the three-family retirement; the e-signature pair is held in this card, not tagged and not retired.Not taken: B (tag all four families, keep fifteen permanent obligations with no consumer).
Execution:
domain:speclane. First step, before any removal: re-run the reader census for all fifteen keys acrosspackages/**outsidepackages/spec(triage sampled three; "zero readers" is the recommendation's foundation) — any reader found returns that key to the inbox rather than being retired. Published authorable keys are removed ⇒ Clause-② yes,needs:contract-reviewon the card and the PR atCONTRACT_REVIEW_TIER;@objectstack/specchangesetminorwith a BREAKING banner under the launch-window convention, ADR-0087 registry entries per key, authorable-surface and api-surface baselines regenerated with the repo's tooling, and a loud refusal naming the removed key for any existing declaration that still carries it — no alias, no transition window.State transition, same stroke:
needs-user-decision→pm:queue;domain:spec,priority:p3retained. Ledger: objectstack director seat post #12708, summon #10.Generated by Claude Code
os-sales commentedon Sep 4, 2026
Claim: PM seat
domain:spec, sessionsession_01G4138K1EG7kQ81FNba5Kp4(os-sales), R1, 2026-09-04T17:47Z.Branch:
claude/issue-14477-inert-deadline-key-retirementClause-②: yes
Claimed for dispatch to an
os-devatCONTRACT_REVIEW_TIER, per the maintainer ruling recorded at5518646938(ruled A).pm:queue→pm:dispatchedandneeds:contract-reviewapplied in one label write, read back and diffed against the pre-write set — nothing else added or stripped.The line above admits exactly
Clause-②: yesorClause-②: noand carries no other text, becausescripts/pm/check-clause2-carriers.mjsreads it as a machine predicate. The reasoning that belongs with it is here instead: the ruling's execution paragraph says it in its own words — "Published authorable keys are removed ⇒ Clause-② yes".Premise re-checked on
origin/main845d767c4at 17:45Z, before writing anything (the card was filed 2026-09-02, the ruling recorded 2026-09-03):grep -c EXPERIMENTALis still 0 in each — the tag has not been added in the meantime, so the enforce-or-remove premise has not been quietly satisfied by someone else.targetHours,withinMinutes,triageDeadlineHours,retentionDays(incident-response);durationMinutes,validityDays(training, anddurationMinutesalso in change-management);estimatedMinutes×2 (change-management);expirationDays,reminderDays(document).Held, not dispatched: the
ESignatureConfigpair (document.zod.tsexpirationDays,reminderDays). The ruling is explicit that the maintainer's reply did not settle the e-signature roadmap question, that the seat put it back, and that "until then the spec seat executes the three-family retirement; the e-signature pair is held in this card, not tagged and not retired." This dispatch therefore covers three families, not four, and this card stays open after the PR lands, carrying the unanswered branch.Generated by Claude Code
os-sales commentedon Sep 4, 2026
Claim:
os-dev, sessionsession_01G4138K1EG7kQ81FNba5Kp4(dispatched by thedomain:specPM seat, R1), 2026-09-04.Branch:
claude/issue-14477-inert-deadline-key-retirement(pushed empty as the write-route probe; worktree basea06faebbe)Clause-②: yes
Executing ruling A as recorded at comment
5518646938: the three compliance-shaped families (incident-response,training,change-management) retire under ADR-0049 enforce-or-remove via thespec-property-retirementplaybook. TheESignatureConfigpair indocument.zod.tsis held in this card and is not touched by this branch. The line above is the bare machine predicate forscripts/pm/check-clause2-carriers.mjs; the reasoning is the ruling's own execution paragraph — published authorable keys are removed.Mandatory first step, run before any edit: a reader census over
packages/**outsidepackages/spec(tests and changelogs excluded) for every key the three files declare, plus the held pair. The full table lands in the PR body and the report; the headline is zero readers for every key, and zero references to the three families' schema or type names anywhere outsidepackages/spec, including objectui at the pinned sha00d3f09c5.Generated by Claude Code
os-sales commentedon Sep 4, 2026
os-dev-report
{ "issue": 14477, "status": "done", "branch": "claude/issue-14477-inert-deadline-key-retirement", "pr": "https://github.com/objectstack-ai/objectstack/pull/15514", "premise_still_valid": true, "summary": "Executed ruling A: the three families' fourteen hour/minute/day-shaped deadline sites (thirteen names) are retiredKey() tombstones — six on incident-response, five on training, three nested on change-management — registered as fourteen RETIRED_KEYS_BY_MAJOR[18] entries plus three D3 semantic entries (no D2 conversion and no migrate sentence: none of the schemas is a stack collection member, the MetadataPluginConfig.additionalTypes precedent), with authorable-surface (+11 RETIRED rows), authorable-defaults (-6 rows), registry.ts and the three reference-doc pages regenerated by the repo tooling, a minor BREAKING changeset carrying adr-0087 registered for the three semantic ids (level derived from check-changeset-no-major and the 17.3.0 precedents; it agrees with the dispatch), and pins for refusal at every site and through every carrier, the tsc never channel, no-materialize for the six former defaults, the registration, and a tree-scoped absence scan. Mandatory census first, all fifteen keys: packages/** outside packages/spec with tests and changelogs excluded, exit 1 (zero hits) for every key at 097a01c4f and again at the merged head 83a3353e3 with a control leg; zero in the rest of the repo (the only retentionDays hits are an unrelated blog extensions-bag example and docs/launch-readiness.md on the removed service retention options); zero in objectui at the pinned 00d3f09c5; zero references to any of the families' schema or type names outside packages/spec — 14 of 14 in-scope sites retired, 0 returned to the inbox; the held ESignatureConfig pair also measures zero readers and is untouched, so the card stays open for it. Deviations declared: (1) the prescriptions carry no issue number and no os migrate meta sentence, following the 2026-09-02 connector.errorMapping and the additionalTypes precedents rather than the playbook's older spellings; (2) the commit trailer names a model per the dispatch's explicit trailer rule, which collides with its own no-model-identifier rule — the more specific instruction was followed; (3) @objectstack/spec has no workspace dependencies, so the dependency-closure build step is a stated no-op rather than a zero-match filter run; (4) the whole spec vitest suite was not run locally, narrowed to the eight suites named under tests, CI Test Core runs the rest; (5) my session id is the PM seat's own (subagent), stated in the claim. Clause-② yes: needs:contract-review is on the card and was added to PR #15514 through the additive REST label endpoint, read back as the exact union with the size-labeler's size/xl, nothing stripped; the PR is a draft, not flipped, not enqueued, not armed. One os-regen-merge.sh lap against origin/main (PR #15456's registry entry survived, driverless merge-tree clean, nothing left to regenerate). Worktree removed without force after the PR opened.", "tests": "Union on the final head 83a3353e3 (merge commit over 4ad24c0b6): pnpm --filter @objectstack/spec build under scripts/pm/os-verify-lock.sh, 'VERDICT command-exit 0' (137s); vitest run --maxWorkers=2 over 8 files (deadline-keys-retirement, incident-response, training, change-management, migrations, conversions, retired-key-migrate-sentence, alias-integrity): 'Test Files 8 passed (8) / Tests 425 passed (425)'; pnpm --filter @objectstack/spec typecheck exit 0 including 'check:test-typecheck: OK', and tsc --listFiles on tsconfig.test.json lists all four edited or new test files; check:generated: '✓ All 15 generated artifacts are up to date.'; pnpm check:nul-bytes exit 0. dispatch-gates --repo objectstack-ai/objectstack derived 89 families from the diff (no paths passed); every command run in the foreground with its exit captured before any pipe; --ran verdict: '✓ dispatch-gates --ran: 89 derived famil(ies) accounted for — 84 run, 5 NOT-MEASURED.' — the 84 all exit 0; the 5 NOT MEASURED, with reasons: check:type-check-debt (exit 3, needs 32 built workspace deps), check:dual-build-cjs-loads (exit 3, 86 packages without dist), lint check:doc-formula-expressions and check:doc-security-posture (exit 3, the lint dist imports the absent sdui-parser dist; building lint alone failed on it), check:skill-examples (exits before any check asking for a current client-react build, a 36-package closure; building client-react alone failed on the absent client dist). Environmental red understood and repaired: check:skill-examples leaves the gitignored packages/spec/.examples-build behind and check:docs-audit-scope / check-affected-docs then red their own self-test on it (already filed #15446 / #15457); removing that tree turned both green. Reverse leg from the committed fix: the three schema files restored from BASE a06faebbe into the tree only, mutation confirmed on disk (retiredKey count 0/0/0, git status M on exactly the three), vitest on the pin file under the lock: 29 tests, 26 failed — all 14 site refusals, all 6 carrier refusals, both prescription-content pins, the 3 no-materialize pins and the tsc/parse agreement pin; 3 stayed green exactly as predicted (registration reads the unchanged registry; the two tree-scan tests exclude the schema files by design); restored with git checkout HEAD -- on absolute repo-root paths under a trap, git diff HEAD empty, git status --porcelain empty, git hash-object equal to HEAD for all three, retiredKey count back to 7/6/4. Docs delta: content/docs/references/system/{incident-response,training,change-management}.mdx 28 insertions / 28 deletions with no changed line outside a retired-key row (a first regeneration lost the two module headers because the constants block preceded the file docblock; relocated below the first schema, verified with the renderer's own findModuleDocBlock, regenerated). Not run locally: the full spec vitest suite and repo-wide pnpm lint (CI-owned). No ablation of a build tool was needed.", "mcp_calls": "6 — add_issue_comment (claim), search_issues x2 (duplicate searches: REST /search/issues answered 403 while repo-scoped REST reads answered 200, so the channel switched to one targeted MCP search per finding, declared), issue_write create (#15513), create_pull_request (#15514), add_issue_comment (this report). All other reads went through REST and git; the PR label write went through the additive REST endpoint (200) with a REST read-back.", "open_questions": [], "out_of_scope_findings": [ "filed as #15513: the rest of the incident-response, training and change-management families (every remaining key, all fifteen defs) has zero readers anywhere outside packages/spec and in objectui at the pinned sha; whole-def enforce-or-remove per family is the open question (finding label, no assignee)", "not re-filed, already #15446 / #15457 (related #15328): check:skill-examples leaves the gitignored packages/spec/.examples-build tree behind and check:docs-audit-scope / check-affected-docs red their own self-test on it in the same tree; reproduced on this box" ] }Generated by Claude Code
os-sales commentedon Sep 4, 2026
Contract review returned PASS WITH CONDITIONS — adopted verbatim; this card stays open
PM seat
domain:spec, sessionsession_01G4138K1EG7kQ81FNba5Kp4(os-sales), 2026-09-04T19:55Z. This is condition 4 of the adopted verdict, which is the seat's to record. The verdict itself is at PR #15514 comment5545747371, adopted verbatim after transcript tier verification (183 harness-stampedmodelfields, all atCONTRACT_REVIEW_TIER; no fallback stop-reason; all 7 textualfallbackmatches inspected and every one is repository prose the reviewer quoted).(a) The
ESignatureConfigpair is still held, and this card does not close when PR #15514 landsPR #15514 is
Part of #14477, deliberately — notFixes. The ruling was explicit that the maintainer's reply never answered the e-signature roadmap question, and that "until then the spec seat executes the three-family retirement; the e-signature pair is held in this card, not tagged and not retired."The reviewer verified the fence held rather than taking anyone's word:
packages/spec/src/data/document.zod.tsis blobb1fe0ab42at bothmainand the PR head;content/docs/references/data/document.mdxandauthorable-surface/data.jsonare untouched; the only diff lines mentioningexpirationDays/reminderDays/ESignatureare the changeset and PR prose saying the pair is held. It also measured the held pair's own reader census to zero, so if the maintainer rules "no roadmap", retirement is ready to execute on the same evidence.⇒ After #15514 merges, this card stays open carrying exactly one question: does e-signature have a roadmapped consumer? A roadmap ⇒ the two keys get
[EXPERIMENTAL — not enforced]plus a liveness-ledger entry. No roadmap ⇒ they retire with the other three families. ⛔ The card must not be closed by anyone tidying up after the merge.(b) Two escalations the verdict routes away from this PR
Both are governed-surface questions about the retirement playbook (
.claude/skills/spec-property-retirement/SKILL.md), not defects in this change, and both are filed for thedomain:skillsseat rather than left as prose here:was removed in @objectstack/spec <version> (#issue[, ADR-XXXX Dn]), but the reviewer measured the tree: 87 tombstone prescriptions open with(ADR-…)and 2 open with(#NNNN. The playbook's spelling is the outlier, the two most recent precedents follow the tree, and an adjacent maintainer ruling in AGENTS.md (2026-08-12) reads 「处理 issue 时犯的错应该总结成经验,保留 issue id没有意义」. This PR followed the tree, which the verdict accepts; whether the playbook should be corrected to match is the playbook owner's call.@objectstack/spec's declaredturbo.jsoninputs, so a resurrection authored inexamples/**,apps/**, hand-writtencontent/docs/**or mostpackages/*/src/**would not put spec's tests inturbo ls --affectedand could replay a cached green — the Layer A/B failure AGENTS.md describes. Thetscneverchannel still catches every typed TS authoring site; untyped literals and prose are the residue. The verdict is explicit that "the gap is between playbook and gate, not a choice the dev made wrongly", and that what this PR owes is honesty in the pin's own header (condition 2), not a whole-repo declaration.Where the rest of the conditions sit
5545751888: the PR body's "thirteen distinct key names" is twelve, and its docs-delta description was too strong (9 of 28 changed lines are parent rows).packages/spechas moved onorigin/mainby then,scripts/pm/os-regen-merge.shplus a rebuild andcheck:generatedbefore arming.Test Coreis green on83a3353e3; condition 5 carries it to the final head. ⛔ Neither of them inferred a pass from the absence of a failure, and neither does this seat.Co-Authored-Bytrailer. That conflict is settled repo law — maintainer ruling on #14663 (2026-09-03), executed atdispatch-runbook.md:250-252, narrows the prohibition to content artifacts and names the commit trailer as an explicit carve-out, ending with ⛔ 不再申报为偏差. The seat's brief contradicted a landed ruling. Corrected for future dispatches; no card, because the runbook already says it and the failure was in not following it.Generated by Claude Code
claude commentedon Sep 4, 2026
os-dev-report
{
"issue": 14477,
"status": "done",
"branch": "claude/issue-14477-inert-deadline-key-retirement",
"pr": "#15514",
"premise_still_valid": true,
"summary": "Patch round on PR #15514 for contract-review conditions 1 and 2 only; nothing else in the PR changed. Both edits are prose or comment: no schema, assertion, registration, declaration, turbo.json or generated artifact moved, and the pin suite's 425/425 is unchanged. Condition 5's re-merge trigger FIRED - packages/spec had moved on origin/main since 5023630 (one commit, 615fac3, touching packages/spec/src/api/protocol.test.ts) - so a full os-regen-merge.sh lap plus rebuild and check:generated ran and are in this push. Two commits: 3273a34 (the two edits) and 3c7b84d (the merge). Final head 3c7b84d, tree clean, every measurement below taken on it. PR left as a draft, needs:contract-review untouched on both carriers, body unedited (footer intact), auto_merge null, nothing enqueued. Conditions 3 and 4 are the seat's RECORD actions and were not touched; the PR body still says 'thirteen distinct key names', which condition 3 assigns to a seat comment rather than a body edit. The wrong count survives nowhere else in the 31-file tree (the one other 'thirteen' in registry.ts is an unrelated pre-existing entry about filter preset names).",
"tests": "Every exit code captured into a variable BEFORE any pipe; every gate result quoted from the gate's own verdict line, never from a bare $?. All measurements on the final head 3c7b84d with a clean tree. See the 'gates' field for the full list with exit codes and the 'not_run' field for what was not measured and why. Headline: build 0, check:generated 0 with a clean tree afterwards (nothing generated moved, as the conditions require), 8 targeted vitest files 425/425 passed, typecheck 0, and eleven targeted check families all exit 0 including check:cross-package-test-inputs, which is the gate condition 2 is honest about and which stays green with no new declaration. NO ABLATION was run this round and none is owed: both edits are prose and a comment, there is no new claim for an ablation to prove, and the suite's pass count is identical to the pre-patch head. The implementation round's ablation evidence stands unchanged.",
"mcp_calls": "0 - the repo-scoped REST channel was probed first (GET /repos/objectstack-ai/objectstack returned 200) and carried every GitHub read and write this round, so no MCP GitHub call was made",
"open_questions": [],
"out_of_scope_findings": [],
"final_head": "3c7b84d4cab1323f8f93172474bb17ecb89e7ddc (short 3c7b84d)",
"commits": [
"3273a3420 conditions 1 and 2",
"3c7b84d4c merge of origin/main ed9d876 via os-regen-merge.sh"
],
"edits": [
{
"file": ".changeset/inert-deadline-keys-retired.md",
"condition": "1(a) - the count sentence",
"before": "Fourteen hour/minute/day-shaped deadline, SLA and duration keys (thirteen\ndistinct names) sat on the exported incident-response, training and\nchange-management schemas and in the generated reference docs, and nothing\nread them:",
"after": "Fourteen hour/minute/day-shaped deadline, SLA and duration key sites - twelve\ndistinct names, because
durationMinutesandestimatedMinuteseach occur at\ntwo sites - sat on the exported incident-response, training and\nchange-management schemas and in the generated reference docs, and nothing\nread them: (the dashes in the file are em dashes)"},
{
"file": ".changeset/inert-deadline-keys-retired.md",
"condition": "1(b) - the retirement kit bullet",
"before": "- generated baselines/docs follow the schema (
authorable-surface/gains\n eleven[RETIRED]rows,authorable-defaults/loses six rows,\njson-schema/,json-schema.manifest/, spec-changes, upgrade guide,\n reference docs)","after": "- generated baselines and docs follow the schema:
authorable-surface/gains\n eleven[RETIRED]rows,authorable-defaults/loses six rows, the three\n system reference pages are regenerated, and the gitignoredjson-schema/\n output is re-emitted on the next build\n-json-schema.manifest/is unchanged, and correctly so: it ratchets def\n names, and retiring keys removes no def from the published surface\n-spec-changes.jsonand the protocol upgrade guide are unchanged too: both\n project the migration chain at the current protocol major (17), so these\n protocol-18 registrations reach them at the 18 cut"},
{
"file": "packages/spec/src/system/deadline-keys-retirement.test.ts",
"condition": "2 - the tree-scan describe header (comment only, inserted immediately above the existing describe, which is unchanged)",
"before": "(no header comment; the describe followed the ADR-0087 registration block directly)",
"after": "// What this leg guarantees, and what it does not. The walk below reads the\n// whole repo tree from REPO_ROOT, but the inputs it reaches outside\n//
@objectstack/spec's declared cross-package globs inturbo.jsonare not\n// hashed by turbo. So a resurrection authored inexamples/**,apps/**,\n// hand-writtencontent/docs/**or mostpackages/*/src/**does not put this\n// suite intoturbo ls --affected, and the PR that authors it can replay a\n// cached green. Read this leg as a FULL-RUN guarantee - the merge queue and a\n// plainpnpm test- rather than an affected-path one.\n//\n//check:cross-package-test-inputsis green here as designed: every literal\n// path this file names is declared, and the gate's declaration file states the\n// trade for a walk that descends on a loop variable (the escape verdict\n// resolves and the name does not). Widening spec's declared inputs to the\n// walk's real radius would put this suite on every docs PR, so nothing is\n// widened here; the playbook-vs-gate question is filed as #15528 and is not\n// this PR's to answer.\n//\n// Independently of turbo, every typed TypeScript resurrection is caught at\n// author time by theneverchannel pinned above, which needs no tree walk.\n// The residue this leg covers is the untyped rest: JSON, YAML, MDX and\n// unannotated literals. (the dashes in the file are em dashes)"}
],
"count_confirmation": {
"command": "cd packages/spec/src/system && grep -hoE '^\s+[A-Za-z][A-Za-z0-9]*: retiredKey\(' incident-response.zod.ts training.zod.ts change-management.zod.ts | sed -E 's/^\s+//; s/: retiredKey\($//' then wc -l / sort -u | wc -l / sort | uniq -d",
"sites": 14,
"distinct_leaf_names": 12,
"duplicated_names": [
"durationMinutes (TrainingCourse + ChangeImpact.downtime, two files)",
"estimatedMinutes (RollbackPlan.steps[] + ChangeRequest.implementation.steps[], one file)"
],
"file_name_pairs": 13,
"verdict": "CONFIRMS the review. Twelve is right; thirteen is the (file, name) pair count. No contradiction, so the sentence was written."
},
"artifacts": {
"source": "GET /repos/objectstack-ai/objectstack/pulls/15514/files (31 files, matches the PR's changed_files), cross-checked with git diff --name-only origin/main HEAD which returns the same 31 paths and nothing else",
"this_PR_does_move": [
"packages/spec/authorable-surface/system.json (11 rows to [RETIRED])",
"packages/spec/authorable-defaults/system.json (6 rows gone)",
"content/docs/references/system/{incident-response,training,change-management}.mdx",
"packages/spec/src/migrations/registry.ts and the 17 entry files",
"the three system .zod.ts files and their suites, the new pin file, the changeset"
],
"this_PR_does_NOT_move": [
"packages/spec/json-schema.manifest/* - tracked, absent from the diff. Its system.json is a 'schemas' array of def paths, so it ratchets def NAMES; retiring keys removes no def, so unchanged is correct.",
"packages/spec/spec-changes.json - tracked, absent from the diff, header says protocolVersion 17.0.0 and it contains zero '18' entries.",
"docs/protocol-upgrade-guide.md - tracked, generated, absent from the diff, header says Current protocol: 17.0.0.",
"packages/spec/json-schema/ - not in the diff because it is gitignored (.gitignore:61 'packages/spec/json-schema/', confirmed by git check-ignore -v exit 0); it is build output, re-emitted on build. Kept in the changeset bullet for that reason, labelled gitignored.",
"packages/spec/src/data/document.zod.ts and anything ESignatureConfig - untouched, as the maintainer hold requires."
]
},
"origin_main_movement": {
"question": "has packages/spec moved on origin/main since 5023630",
"answer": "YES - condition 5's re-merge trigger fired (it had NOT fired at review time; the verdict recorded two commits, neither touching packages/spec).",
"commands": "git fetch origin main; git log --oneline 5023630..origin/main -- packages/spec and git diff --name-only 5023630 origin/main -- packages/spec",
"finding": "origin/main moved 5023630 -> ed9d876, six commits. Exactly one touches packages/spec: 615fac3 'fix(lint,metadata-protocol): a Studio publish refuses an object whose highlightFields ... names a missing field', and it touches exactly one file there, packages/spec/src/api/protocol.test.ts.",
"action_taken": "Ran bash scripts/pm/os-regen-merge.sh in the worktree (exit 0). Step 1 merged origin/main by ort, 26 files, no conflicts. Step 2 KEPT the branch's bytes of all five os-regen paths it examined (the three reference mdx files plus authorable-surface/system.json and authorable-defaults/system.json) because the branch changed them and main did not - the script's measured anti-revert case. Step 3 reported the merge left no additional changes to commit. Step 4 (mine): rebuilt and ran check:generated - 'All 15 generated artifacts are up to date' with a clean tree afterwards, so regeneration was a no-op and there is NO separate regeneration commit; nothing to commit is the honest outcome, not a skipped step. Sibling-swallow assertion: git diff origin/main HEAD -- packages/spec/src/migrations/registry.ts shows exactly ONE removed line, and it is the branch's own string-literal continuation being extended ('it never had an effect to lose).' becoming that text plus ' + ' and the new deadline-keys sentences) - no sibling entry and no previous implementation body was dropped. All three semantic ids and the three nested registrations are still present at HEAD.",
"merge_base_note": "The repo is a shallow checkout and 'git merge-base HEAD origin/main' answered 5023630, which looked wrong at first because HEAD is a merge of origin/main. Resolved structurally rather than by trusting the shallow walk: git rev-list --parents -n 1 HEAD shows HEAD's two parents are 4ad24c0 (the work commit) and 5023630 itself, so 5023630 is the true merge base and matches the base the reviewer used. The PR JSON's base.sha 2003259 is the base BRANCH TIP, not a merge base - it is an ancestor of origin/main (is-ancestor exit 0, self-certifying) but not of the pre-merge HEAD."
},
"gates": [
{
"command": "pnpm --filter @objectstack/spec build (via scripts/pm/os-verify-lock.sh)",
"exit": 0,
"evidence": "lock VERDICT line: command-exit 0, held the lock 135s, waited 0s. check-dts-emitted: 34/34 declared declaration file(s) present. This is also the apostrophe-in-literal check the dispatch warned about - the comment edit compiles."
},
{
"command": "pnpm --filter @objectstack/spec check:generated",
"exit": 0,
"evidence": "gate's own line: 'All 15 generated artifacts are up to date.' git status --porcelain empty afterwards - the changeset and the comment moved NOTHING generated, as condition 1/2 requires. check:spec-changes and check:upgrade-guide are among the 15 and are green with those files unchanged."
},
{
"command": "pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 (8 targeted files, via the lock)",
"exit": 0,
"evidence": "lock VERDICT command-exit 0, held 12s. 'Test Files 8 passed (8)', 'Tests 425 passed (425)' - identical to the dev's and the reviewer's counts, so nothing behavioural moved. No bare -- was used, so no argument was silently discarded."
},
{
"command": "pnpm --filter @objectstack/spec typecheck (via the lock)",
"exit": 0,
"evidence": "lock VERDICT command-exit 0, held 53s. 'check:test-typecheck: OK - @objectstack/spec's test layer compiles under packages/spec/tsconfig.test.json; 54 file(s) / 261 error(s) / 145 pinned signature(s)'. The pin file is inside that program, so the 14 ts-expect-error lines stay live."
},
{
"command": "node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack",
"exit": 0,
"evidence": "stderr names the tree: objectstack-ai/objectstack at commit 3c7b84d, repo assertion holds. Derived its own 31-path change set vs merge base ed9d876 (no path list was handed to it), which is the PR's own set - my two files were already in it, so the family set is unchanged from the implementation round."
},
{
"command": "pnpm check:nul-bytes",
"exit": 0,
"evidence": "self-test plus gate"
},
{
"command": "pnpm check:cross-package-test-inputs",
"exit": 0,
"evidence": "'All 117 self-test cases passed.' then 'OK: 26 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.' The comment added no declaration and the gate stays green as designed - the point of condition 2."
},
{
"command": "pnpm check:test-source-alias",
"exit": 0,
"evidence": "self-test plus gate"
},
{
"command": "pnpm check:adr-0087-registration",
"exit": 0,
"evidence": "'292 assertions' self-test, then '1 declared-breaking changeset(s), each carrying an ADR-0087 disposition' listing the three ids, all new here - the marker survived the changeset edit."
},
{
"command": "node scripts/check-changeset-no-major.mjs --base ed9d876 --head HEAD",
"exit": 0,
"evidence": "'This diff introduces no
majorbump.'"},
{
"command": "pnpm check:changeset-gate-self-tests",
"exit": 0,
"evidence": "self-tests of the three changeset gates"
},
{
"command": "pnpm check:objectui-changeset",
"exit": 0,
"evidence": "self-tests"
},
{
"command": "pnpm check:partof-closing-keyword",
"exit": 0,
"evidence": "self-test"
},
{
"command": "pnpm check:pm-governed-prose",
"exit": 0,
"evidence": "self-test plus gate"
},
{
"command": "pnpm check:doc-authoring",
"exit": 0,
"evidence": "self-test plus gate"
},
{
"command": "pnpm check:docs-single-h1",
"exit": 0,
"evidence": "self-test plus gate"
},
{
"command": "grep -naP over both edited files for control bytes",
"exit": 1,
"evidence": "exit 1 = zero hits = clean. Ran in addition to check:nul-bytes because the edits are prose."
}
],
"not_run": [
"The remaining derived families (dispatch-gates derives the whole PR's ~89-family set; the implementing dev ran it on the pre-patch head with 84 exit 0 and 5 NOT MEASURED). DECLARED NARROWING: my delta is two files already inside that set, one a changeset and one a comment, so I ran the subset that actually reads those two files plus everything condition 5 names. CI runs the farm regardless.",
"Repo-wide pnpm lint - CI-owned, as on the implementation round. I do NOT claim the three-part proven-narrowing evidence for it; it is simply not run.",
"The full @objectstack/spec vitest suite, again NOT run to completion locally - this is verdict item 6 carried forward unchanged, NOT MEASURED rather than green. CI Test Core is the measurement.",
"CI on the final head 3c7b84d was NOT waited for. Per the dispatch contract the report lands at draft-PR time; the seat reads the six required contexts on the final head before flipping ready. At the moment of this report their status is in_progress by definition."
],
"deviations": [
"Condition 1(a) wording is not a verbatim splice of the verdict's replacement string. The verdict gave the target facts and the dispatch asked for product prose rather than a correction note, so I wrote flowing prose carrying exactly the three required facts (fourteen sites, twelve distinct names, and the two names that occur twice). Declaring it so the seat can compare against the verdict text.",
"Condition 1(b) became three bullets instead of one. The verdict required removing three items from the kit list and adding two positive statements; that did not fit one bullet without burying it. No other changeset content moved.",
"os-regen-merge.sh step 4 prescribes committing the regeneration as its own commit. Regeneration produced zero changes (check:generated green, tree clean), so there is no such commit. Declared rather than silently skipped.",
"Worktree was created ON the existing PR branch rather than as a new branch off origin/main - required by a patch round on an open PR. Never edited the shared primary checkout; worktree removed afterwards without --force (clean removal, so nothing uncommitted was in it).",
"Process note, no effect on the result: my edit script's post-write assertion for the condition-2 edit reported FAIL because the replacement text contains the anchor line it was checking had disappeared. The edit itself landed correctly; verified on disk instead by git diff plus occurrence counts (1 describe line, 1 new header, 1 reference to the follow-up card).",
"NOT a deviation, stated because a previous dispatch got this wrong: the commit trailer carries a model identifier. That is the explicit carve-out (maintainer ruling on #14663, 2026-09-03), not a content artifact. No model identifier appears in the changeset text, the test comment, or any GitHub prose."
]
}
Generated by Claude Code
18 remaining items
claude commentedon Sep 5, 2026
Fold member note: the anchor's delta at
f8ccc4753is ACCEPTED (#15513 comment5553797140, 2026-09-05T18:12Z); this card's carrier is re-cycled at that head below. Landing waits onmaingreen (#15992).Generated by Claude Code
claude commentedon Sep 5, 2026
Fold member: PR #15973 flipped to ready + auto-merge (squash) at 22:21Z on
310ebe8cf, all checks green — provenance on #15513; this card closes with the PR (Fixes #14477).Generated by Claude Code
claude commentedon Sep 5, 2026
Release:
session_01M59rPZZFzqhfMUPFqqZTkf(domain:spec seat) — reason: landed; destination: closed by PR #15973 (Fixes #14477), no successor.Landing note (2026-09-05T22:51Z, member of the two-card fold): PR #15973 MERGED at 2026-09-05T22:51:10Z as
c463d03e0(squash; enqueued 2026-09-05T22:21:37Z). Probe onorigin/mainc463d03e0:IncidentResponsePolicySchema0 files underpackages/spec/src(control: present at0cf086759),system/incident-response.zod.tsabsent (control: present),retiredKey(EXPIRATION_DAYS_RETIRED)present indata/document.zod.ts. The three compliance families (19 defs) retired whole underRETIRED_DEFS_BY_MAJOR[18]+ three D3 entries; theESignatureConfigdeadline pair tombstoned with twoRETIRED_KEYS_BY_MAJOR[18]entries + one D3 entry; PR #15514's fourteen history entries kept; the tree-scoped absence pin's walk radius declared (examples/non-code files only). Anchor's landing note on #15513 carries the probe detail.pm:dispatchedstripped, assignee cleared in this stroke.Generated by Claude Code
feat(spec): retire the fourteen inert deadline keys of the incident-r…
feat(spec)!: retire the incident-response, training and change-manage…
test(spec): the second data/ file group's test titles state each cite…