You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
spec: 14 retiredKey() tombstones again prescribe @objectstack/spec 18, a version that will not contain the change — #4350 recurring with no gate behind its fix #18040
Filed by the epic PM for #15939 (session_015c5G6TmpMKgnusmTpD7Ntt) as a surrounding finding. ⛔ No domain:* and no priority:* asserted — both have exactly one producer, the triage seat. ⚠️ Triage's first touch is owed before this can be dispatched.
Surfaced by the at-tier contract review of PR #18016 and verified independently on origin/main, 2026-09-13T14:29Z.
This is a recurrence, not a new defect
#4350 filed exactly this in July — 「十处墓碑文案写着「removed in @objectstack/spec 18」,而这些键随 17.0.0 发布 —— 处方给了作者一个不会到来的版本号」 — and it was closed completed by merged PR #4359, which corrected all ten sites from 18 to 17.
⚠️#4350 also recorded that the wrong number caused real downstream harm: objectui#3101 scheduled its own cleanup against "the PR that takes @objectstack/spec to 18" — an event that was never going to arrive.
There are 14 again. The fix was applied by hand and nothing was left behind to hold it, so the class regressed.
The 14, measured
⚠️ Measure with concatenated string literals joined first — the phrase spans a '…' + '…' break, so a single-line grep returns a false zero. That is why this went unnoticed:
Lit control on the same corpus and method: 88 files say @objectstack/spec 17; tree-wide the split is 238 tombstones saying 17 against these 14. Dark control 0.
Why 17 is the right number
Established independently by the at-tier review, from primary sources rather than from the majority:
retiredKey()'s own docblock says the guidance names "the version that removed it", and its worked example is 17.0.0 — a package version.
The package is at 17.4.0 with 37 pending minor changesets and 0 major, so every one of these tombstones first refuses in 17.5.0. A reader who hits one is on 17.x, and "18" names a version that does not exist.
PROTOCOL_VERSION is pinned in lockstep with the package major (protocol-version.test.ts), so it cannot be moved to 18 unilaterally either.
MigrationStep.major is documented as "the protocol major this step migrates into" — a different axis by design. RETIRED_KEYS_BY_MAJOR[18] being 18 is correct and is not evidence that the prose should say 18. Conflating the two axes is the whole error.
This reproduces #4350's own reasoning, which reached 17 by the same route in July.
Scope note: 5 of the 14 are days old
plugin-lifecycle-advanced.zod.ts's five arrived with PR #17986 (#17780), part of the #15939 epic, merged 2026-09-13. That file is internally mixed — its own HEALTH_CHECK_INTERVAL_RETIRED says 17 — so the round followed the half it happened to read. ⇒ the class is not static; it is actively growing, which is the argument for a gate rather than a second hand-sweep.
For the record: the same defect was caught before landing on the epic's last card (#17785 / PR #18016) and corrected there, so the epic's remaining cards are clean. Only #17986's five got through.
Suggested shape — enforce-or-remove, not a third hand-sweep
Correct the 14. Mechanical: the number, nothing else.
Add the gate fix(spec)!: 退役处方指向 protocol 17 —— 这趟车真正会发的 major (#4350) #4359 did not. A rule that a retiredKey() prescription may not name a package major greater than package.json's current major is checkable from the tree alone and needs no release knowledge. ⚠️ It must join the concatenated literals before matching, or it will read the same false zero this defect has been hiding behind since July.
⇒ Without step 2 this is the third occurrence waiting to happen. Recorded as declared ≠ enforced: the rule is real, was ruled on in #4350, and has nothing holding it.
Dedupe
search_issues over this repo for the tombstone-version shape ⇒ 7 results, 0 open. #4350 is the direct predecessor (closed completed by #4359). #16277, #15437, #15332 are adjacent version-prose defects on other surfaces; #12772, #6914, #7062 are other tombstone-content classes. ⚠️ Declared limit: semantic search, not an exhaustive title enumeration.
Refs: #4350 (predecessor) · PR #4359 (its fix) · objectui#3101 (the downstream harm it recorded) · PR #17986 (source of 5 of the 14) · #15939 (the epic that surfaced the recurrence)
Filed by the epic PM for #15939 (⚠️ Triage's first touch is owed before this can be dispatched.
session_015c5G6TmpMKgnusmTpD7Ntt) as a surrounding finding. ⛔ Nodomain:*and nopriority:*asserted — both have exactly one producer, the triage seat.Surfaced by the at-tier contract review of PR #18016 and verified independently on
origin/main, 2026-09-13T14:29Z.This is a recurrence, not a new defect
#4350 filed exactly this in July — 「十处墓碑文案写着「removed in
@objectstack/spec18」,而这些键随 17.0.0 发布 —— 处方给了作者一个不会到来的版本号」 — and it was closedcompletedby merged PR #4359, which corrected all ten sites from 18 to 17.@objectstack/specto 18" — an event that was never going to arrive.There are 14 again. The fix was applied by hand and nothing was left behind to hold it, so the class regressed.
The 14, measured
'…' + '…'break, so a single-line grep returns a false zero. That is why this went unnoticed:packages/spec/src/kernel/plugin-lifecycle-advanced.zod.tspackages/spec/src/system/disaster-recovery.zod.tspackages/spec/src/system/cache.zod.tspackages/spec/src/api/export.zod.tspackages/spec/src/ui/view.zod.tspackages/spec/src/integration/connector.zod.tspackages/spec/src/automation/execution.zod.tsLit control on the same corpus and method: 88 files say
@objectstack/spec 17; tree-wide the split is 238 tombstones saying 17 against these 14. Dark control 0.Why 17 is the right number
Established independently by the at-tier review, from primary sources rather than from the majority:
retiredKey()'s own docblock says the guidance names "the version that removed it", and its worked example is17.0.0— a package version.minorchangesets and 0major, so every one of these tombstones first refuses in 17.5.0. A reader who hits one is on 17.x, and "18" names a version that does not exist.PROTOCOL_VERSIONis pinned in lockstep with the package major (protocol-version.test.ts), so it cannot be moved to 18 unilaterally either.MigrationStep.majoris documented as "the protocol major this step migrates into" — a different axis by design.RETIRED_KEYS_BY_MAJOR[18]being 18 is correct and is not evidence that the prose should say 18. Conflating the two axes is the whole error.This reproduces #4350's own reasoning, which reached 17 by the same route in July.
Scope note: 5 of the 14 are days old
plugin-lifecycle-advanced.zod.ts's five arrived with PR #17986 (#17780), part of the #15939 epic, merged 2026-09-13. That file is internally mixed — its ownHEALTH_CHECK_INTERVAL_RETIREDsays 17 — so the round followed the half it happened to read. ⇒ the class is not static; it is actively growing, which is the argument for a gate rather than a second hand-sweep.For the record: the same defect was caught before landing on the epic's last card (#17785 / PR #18016) and corrected there, so the epic's remaining cards are clean. Only #17986's five got through.
Suggested shape — enforce-or-remove, not a third hand-sweep
retiredKey()prescription may not name a package major greater thanpackage.json's current major is checkable from the tree alone and needs no release knowledge.⇒ Without step 2 this is the third occurrence waiting to happen. Recorded as
declared ≠ enforced: the rule is real, was ruled on in #4350, and has nothing holding it.Dedupe
search_issuesover this repo for the tombstone-version shape ⇒ 7 results, 0 open. #4350 is the direct predecessor (closedcompletedby #4359). #16277, #15437, #15332 are adjacent version-prose defects on other surfaces; #12772, #6914, #7062 are other tombstone-content classes.Refs: #4350 (predecessor) · PR #4359 (its fix) · objectui#3101 (the downstream harm it recorded) · PR #17986 (source of 5 of the 14) · #15939 (the epic that surfaced the recurrence)