fix(qa): drop the rotting :NNN source-line citations from the platform checklist - #13786
Merged
os-project-manager merged 3 commits intoAug 31, 2026
Merged
Conversation
This was referenced Aug 31, 2026
os-project-manager
marked this pull request as ready for review
August 31, 2026 12:34
os-project-manager
deleted the
claude/issue-13482-checklist-line-citations
branch
August 31, 2026 12:51
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 #13482
Ruling step (1): drop the
:NNNsuffixes from the QA platform checklist, because the file plus the symbol name is already the load-bearing half and the line number is the only part that rots. Plus the cheap half of the enforcement the card was actually graded on — the gate now refuses a line citation instead of parsing past it.The card demonstrated its own defect between being written and being dispatched
The card recorded the post-#13479 positions as
PluginRuntimeSchema103,PluginPackagingSchema119,ManifestSchema156. Measured on the tree this branch forks from:ManifestSchemamoved another two lines while the card sat in the queue. Nothing in the repo noticed, because nothing resolves a citation. That is the argument for this change, made by the card about itself.What counts as a source-line citation, and how many there were
Criterion. A colon followed by digits (optionally a range), reached one of two ways, because the ledger spelled it both ways:
manifest.zod.ts:NNN;ManifestSchema id :NNN and version :NNN.Everything else that shares the colon-then-digit shape is excluded by a negative lookbehind on a word character or a quote: HTTP status (
status:409), config literals in prose ({maxRetries:3}), URL ports (http://localhost:3000), clock times (08:00,...T00:00:00Z) and JSON quoted in prose ({"scannedTypes":1}). Each of those five is pinned as a silent case in the gate's self-test.Census: 1,647 citations across 18 files — 1,034 file-anchored, 613 bare; 1,051 of them ranges.
areas/cli.jsonareas/api-backend.jsonareas/identity-auth.jsonareas/attachments-storage.jsonareas/integration-system.jsonareas/studio-authoring.jsonareas/platform-core.jsonareas/approvals.jsonareas/records-forms.jsonareas/dashboards.jsonFOLLOW-UPS.mdareas/search.jsonareas/access-security.jsonareas/ai.jsonareas/automation.jsonareas/i18n.json,RUNNER.md,SWEEP.mdThe number was arrived at twice by different tools — a Python pass over JSON string values only (so JSON syntax could never be counted) and the gate's own JavaScript detector run against the pre-change tree. Both give 1,647.
On the crude
grep -ohE ':[0-9]{2,4}\b'figure of 1,621: it was wrong in both directions and the two errors nearly cancelled. Compared position by position against the real census: 1,601 agree, 20 crude false positives (all timestamps, config literals and ports) and 46 real citations the crude pattern missed — five-and-more-digit line numbers such asrest-server.ts:11298-11311, where[0-9]{2,4}matches four digits and then\bfails, plus single-digit ones likeuseAiSurface.ts:9-40. Net −20 +46 = +26, and 1,621 + 26 = 1,647. Treating it as an upper bound was the right call; it was in fact an under-count.The citations that carried only a line number (A2.3 — the real difficulty)
613 of the 1,647 carried no filename of their own. Stripping those cannot simply delete a suffix, so they were split by what the deletion leaves behind:
holds ONLY auditor (:NNN), so .... The parentheses went with the citation; nothing else in the sentence referred to it.the maxSize guard at :NNN and the mime read at :NNN both require .... Deleting the number alone leavesguard at and, so the orphaned connector went too:the maxSize guard and the mime read both require .... Consumed:at65,and8,from1.renderSubject :NNN,beforeInsert :NNN— where the symbol name is precisely the load-bearing half the ruling relies on, and removal needs no repair.Two words were nearly lost to over-eager rules and were caught before they landed:
lineis a noun in this ledger (the mode line :NNN,the aggregate sweep line :NNN), not a preposition, so it is not consumed; and a blanket empty-bracket cleanup would have deleted a real[]literal inreturns [] on a clean ledger. The corpus holds 146[]literals and 26()call spellings, all preserved.Integrity check on the result, over all 887 changed strings: the only words that disappear are the 74 connectors listed above (zero non-connector word losses, zero words gained);
[],()and backtick counts are identical before and after; the open-paren count drops by exactly 43, matching the parenthesised groups; and zero citation-shaped tokens remain. The 36 colon-then-digit tokens that are not citations are all still there.The area files are edited as raw text at the string-literal level, never re-serialised — every citation token was first proven to sit inside a JSON string value, so the diff is 887 insertions against 887 deletions with no reformatting.
The gate half
scripts/check-platform-checklist.mjsgains a source-line-citation refusal over the whole family (20 files;runs/excluded, since run records are outputs written against whatever the ledger said at the time).⛔ This is not the symbol resolver from ruling step (2). It is the cheap half: it keeps the class from coming back, and it is what turns "nothing validates them" into a red. The self-test pins both directions — 6 firing cases covering every spelling the ledger actually carried (file-anchored, range, bare continuation, parenthesised,
~:approximate, comma/slash-chained) and 7 silent cases covering the neighbours above plus the README's own placeholder spelling of the ban. It also carries an inline positive control, for the reason this gate's siblings do: the ledger is clean now, so the check's real output is permanently empty and a detector that quietly stopped matching would look exactly like a ledger that stayed clean — which is the same exit-0-by-construction shape the card is about.README.mdcarried the convention that reproduced the defect — "Every call cites framework source atfile:line" — and now states the opposite, with the reason and the ban.Ablation (the check must be able to go red). Re-introducing the card's own citation into
areas/cli.json, with the mutation proven on disk before the run and the restore proven by observed state after it:Restore verified by state, not by an exit code:
git diff HEADempty,git status --shortempty, worktree blob0c8f36dd...byte-identical to the HEAD blob, marker count back to 0. Gate green again afterwards.pnpm check:platform-checklistis not wired into CI —lint.ymlrecords that as a standing maintainer decision, and the gate runs on a manual periodic cadence instead. So this refusal fails for whoever runs it, which is not the same as failing every PR. The gap between "there is a gate" and "its red reaches somebody" is already carded and awaiting the maintainer in #11730; nothing here changes that decision or pre-empts it. It is called out because this card is about a signal that reads as verified when it is not, and a new check whose reach is overstated would be the same defect one level up.The
file:selector inscripts/checklist-select.mjs— the one consumer that readssource[]— matches by path substring, so dropping a line suffix cannot change what it selects; its 17-case self-test passes.Why step (2) is not in this PR
The ruling fixed the order, not the packaging. The census is the basis for splitting: step (2) means re-authoring 1,647 citations across 260 items into a structured, resolvable anchor and adding a resolver with its own registration, self-test and baseline. The shape to copy already exists in this very gate —
enumSource {file, export, expect}is resolved today (file existence, export presence, member count), so the follow-up is a known quantity rather than a design question. Doing it here would bury a 1,647-line prose cleanup inside a new verification surface and make both unreviewable. Step (1) removes a false "verified against source" signal today; step (2) should be its own card, and this PR leaves the ledger in exactly the state that card wants as input.Verification
Union run at
137e04a17, on the merged tree.pnpm check:platform-checklist— GREEN, exit 0.source citations: 20 family files carry no file:line pin; (self-checks: ... + 13 source-line-citation assertions)node scripts/check-platform-checklist.mjs --self-test— GREEN, exit 0, 141 assertions (13 new)pnpm lint(eslint . --no-inline-config, whole repo, not narrowed) — GREEN, exit 0pnpm check:nul-bytes— GREEN, exit 0, 7,583 files scannednode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack— 14 families: 13 GREEN, 1 NOT MEASURED (scripts/check-test-completeness.mjs, exit 3,PREREQUISITE NOT MET— it grades a savedturbo run testlog and its own text says to record it as NOT MEASURED locally).check:doc-formula-expressionswasPREREQUISITE NOT METuntil@objectstack/formulaand@objectstack/lintwere built, then GREEN.Every exit code above was captured before any pipe.
Authored by Claude Code, session
session_01Pk26oZ12t5N1hwGW1m1MgC(os-dev seat).No changeset: the diff publishes nothing — internal QA ledger under
docs/qa/**plus one repo gate script.skip-changesetapplied.Generated by Claude Code