pm(labels): declare repo:objectstack retired from circulation - #14156
Merged
Conversation
The label ledger creates three `repo:*` seam labels and never created a fourth, but the board carried `repo:objectstack` on 4 open cards. The absence was therefore true but UNDECLARED: a reader of the three seam rows could not tell an oversight from a decision. Record the retirement the way the header records the retired lanes — deliberately absent so `--reconcile` never names it, label OBJECT kept so closed cards keep their history — placed beside the seam rows, where a future author would otherwise supply the missing fourth row. Comment-only: no create row is added or removed, and no label API call is made from this diff. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WLJQhde67SeTccsmnBVarV
baozhoutao
marked this pull request as ready for review
September 1, 2026 09:21
This was referenced Sep 1, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #13991
Comment-only change to
scripts/pm/ensure-pm-labels.sh. 50 insertions, 0 deletions, one file. Nogh label createrow is added or removed, and no label API call is made from this diff.What the card asked for, and what actually needed writing
The card is right on both limbs, verified against
origin/mainat2bff79abefore any edit: the ledger creates exactly threerepo:*labels (lines 293-295) and createsrepo:objectstacknowhere. A whole-repo grep finds the name in only one other place — three prose/pin lines inscripts/pm/check-half-states.mjs, which is out of scope here.But the retirement here has a different shape from every retirement the file already records, and that difference turned out to be the deliverable. The retired lanes in the header (
domain:ui,domain:spec-surface,domain:engine-core, …) were each created by this file once and had their rows deleted; "deliberately ABSENT" is a statement about a row that used to exist.repo:objectstacknever had a row — its label object was auto-created by a hand-application, the same grey / empty-description drift the header describes forpriority:p0andneeds:contract-review.So its absence was already true, and undeclared. A reader of the three seam rows could not tell an oversight from a decision, and the honest default reading was oversight — which is exactly what invites a future author to "fix" it by supplying the fourth row. This PR converts the accidental absence into a declared retirement. There is nothing to delete.
The convention followed
PM's dispatch flagged this as an assumption to test: the file does have a textual convention for deliberately-absent labels, in its header (lines 39-53). Two terms, and the record here carries both:
--reconcilenever names it and can neither recreate it nor align its (empty) description;Placement: beside the three seam rows, not in the header paragraph, with a one-sentence pointer added to the header so its retired-inventory does not silently read as complete. The reason is in the file: the header paragraph answers "what is retired?", while the question that actually recreates a label is "should there be a fourth
repo:*row?" — and that one is only ever asked where those rows are.The record carries the ruling date and the operative ruling verbatim, attributed to the triage seat (comment 5487742846, R+82). See "One judgment call" below.
What this record deliberately does NOT do — all three are written into the file
needs:contract-reviewblock already states.repo:*predicate incheck-half-states.mjsH14 stays literal. Narrowing it is a predicate change ruled on [finding] No reader anywhere answers a cross-repo Blocked-by: question — H14 can only decline, and 58 of 67 cross-repo cards carry no repo:* label to decline on #13992, never a side effect of a vocabulary record.check-half-states.mjsis untouched by this diff.One judgment call, flagged for review
Every other retirement in this file quotes a maintainer ruling. This one's authority is a triage seat ruling. I wrote it as "triage ruling on #13991, 2026-09-01" rather than borrowing the maintainer spelling — writing 「maintainer ruling」 over a triage ruling would fabricate authority, and the file's retirement records are read later as the reason a label may not come back. If the maintainer would rather this retirement carry a maintainer ruling before it is treated as settled, that is a one-line change to the attribution.
The BY-PR sync question, measured rather than assumed
The domain-lane block requires the ledger and SKILL.md to be kept in sync BY PR whenever a lane is added or retired, and the triage ruling cited that rule. Measured 2026-09-01:
SKILL.mdand the whole of.claude/namerepo:objectstacknowhere, so the prose sync has nothing to carry here and this PR stays single-file as dispatched. That measurement is recorded in the file so the next author does not have to redo it.Gates — derived from the actual diff, run on the final commit
98960feDerived with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack(no hand-written path list; the script takes its own changeset from the merge base). 13 families, run under the shared verify lock, exit codes captured before any pipe:check:agent-test-spellingcheck:bash32-floorcheck:cli-command-idscheck:cross-package-test-inputscheck:entry-guardcheck:parse-guardcheck:pm-label-desc-capcheck:pnpm-filter-targetscheck:watch-hint-literalscripts/check-ci-filter-parity.mjsscripts/check-cross-package-test-inputs.mjsscripts/check-shard-attestation.mjsscripts/check-test-completeness.mjscheck:ratchet-remedy-authority(PM-requested sweep)check-test-completeness.mjsexit 3 is its documented PREREQUISITE-NOT-MET branch, in its own words: "this gate grades a savedturbo run testlog, and no log was named… running the family locally, record this gate as NOT MEASURED. ⛔ It is not a red, and there is nothing here to fix." CI passes it a teed log, so CI behaviour is unchanged.check:pm-label-desc-capis the gate that actually parses this file. It stays green because the parser strips whole-line comments before looking for-dtext, so the new block adds no measured description, and the diff removes no create row (itsMIN_DESCRIPTIONSfloor is untouched).check:ratchet-remedy-authorityis green but, stated honestly, is not evidence about this diff: its corpus isscripts/*.{mjs,mts}by construction (its own header), so ascripts/pm/*.shfile is outside it. Run because PM asked; reported for what it measured.ESLint — a measured narrowing, not a skip
pnpm lint(eslint . --no-inline-config) runs unconditionally on every PR and is CI's. Locally the check was narrowed to the changed file, and here is why that narrowing excludes nothing:filesblock ineslint.config.mjsdeclares a JS/TS extension set (**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}and narrower)..shmatches none of them.--format json: the changed file yields one entry,errorCount: 0, whose only message is"File ignored because no matching configuration was supplied."— zero files in this diff are linted at all.eslint.config.mjs:325-332records, with its own planted positive control, that this repo "never enables type-aware linting (noparserOptions.project, no typed@typescript-eslintrules) for ANY file". With no cross-file type program, a diff cannot move the verdict of a file it does not contain.Changeset
skip-changeset, applied by me at PR open. This diff publishes nothing from any package — it is comment-only prose insidescripts/pm/**— andCheck Changesetinpr-automation.ymloffers no path-based exemption, so the label is the mechanism.skip-changeseton this PR under the standing clause, rather than silently choosing between the two. Trivially reversible if PM meant the fence literally.Generated by Claude Code