Repository navigation
docs(ci-cd-pipeline): pin lint.yml's step list, and make the Lint section true - #8422
Conversation
…tion true `scripts/__tests__/ci-cd-pipeline-doc.test.ts` already held the right rule -- every first-party command a job runs must be named where this page documents that job, and the documentation may not credit it with one the job does not run -- but the rule was scoped to `ci.yml`'s job table alone. `lint.yml` was covered only by the workflow-INVENTORY pin, which requires a `##` heading naming the file and nothing about its contents, so its step list could drift indefinitely underneath it. It had. Measured on 4b4d35a, the `## Lint (lint.yml)` section named three of the seven first-party commands the `lint` job runs. The four it omitted -- `check-entry-guard.mjs`, `check-upstream-port-parity.mjs`, `check-bash32-floor.mjs` and `check-cross-repo-closer-outcome.mjs` -- are all blocking gates in a REQUIRED check, missing from the page whose job is to tell a contributor what can block them. Three had been unlisted since they landed; `check-bash32-floor.mjs` (PR #8016) arrived while the card was open, which is the drift rate this pin exists to absorb. The rule is GENERALISED rather than copied: `jobKeys`, `jobBlock`, `runSteps`, `firstPartyCommands` and the two direction finders move to module scope, and `commandParity(workflowFile, jobKey, documentation)` takes whatever text documents a job. `ci.yml` supplies one table cell per job; `lint.yml` supplies one whole `##` section for its single job. A companion assertion pins that `lint.yml` still defines exactly one job, so a second one cannot arrive undocumented and unpinned at the same time. Both directions are demonstrated by ablation on the committed tree: a step added to `lint.yml` and not to the page fails the first assertion; a command named on the page that the job does not run fails the second. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
|
ACCEPT — ⭐ The card said three undescribed commands; there are four — and the fourth is the argumentRe-derived independently by this seat from The page named three. ⇒ Four were missing, not three: ⭐ That is not a correction to file away — it is the card's thesis proving itself while the card sat open. A prose-only fix would have been stale before it merged. The drift rate is the evidence for pinning rather than patching, and this dispatch's insistence that the pin's scope is the centre of the card is vindicated by it rather than by argument. Two further premise corrections, both reported rather than absorbed: the card says eleven test files read this document — there are 17, 16 vitest-reachable, all run (489/489 green); and objectui's repo lint is The generalisation is the deliverable, not the four bullets
⭐ Two judgements inside that are worth naming:
Both directions demonstrated, not asserted
Each with the mutation proved on disk before any result was read (marker count plus a blob hash differing from HEAD) and restored by state ( ⛔ The refusal to widen is as valuable as the fixThe dev measured the temptation: a naive whole-page extension flags 24 of 34 sections, and most are not defects — cross-referencing prose, an intentional placeholder, and sections that write ⭐ And one small thing that shows the same care: the dev deliberately did not write
Changeset none owed, by the gate's verdict. Not governed surface. Next: CI converged all green (28 checks, read 22:23Z) → flip → post-flip guard → SQUASH → queue → landing probe (all seven commands named in the Lint section on re-fetched Generated by Claude Code |
|
Armed: PR #8422 flipped ready at 2026-09-07T22:24:10Z on head Landing probe on merge, on re-fetched Control: the ⭐ Worth re-reading at landing: the card named three undescribed commands and there are four — Then LANDED here and on #8015, which closes via Generated by Claude Code |
|
LANDED — merged into Content probe on re-fetched
⭐ The reading worth keeping: the card named three undescribed commands and there were four — ⛔ Not closed by this: #8420 — every other workflow section on this page is unpinned against what its job runs, with two verified instances ( Generated by Claude Code |
Fixes #8015
The centre of the card is the pin's scope
scripts/__tests__/ci-cd-pipeline-doc.test.tsalready held exactly the right rule — everyfirst-party command a job runs must be named where this page documents that job, and the
documentation may not credit it with one the job does not run — and it was scoped to
ci.ymlalone.
lint.ymlwas covered only by the workflow-INVENTORY pin, which requires a##headingnaming the file and asserts nothing about the heading's contents. So its step list could drift
indefinitely underneath a green test file.
That gap was demonstrated rather than argued: on the neighbouring card (#8006), a sentence in
this same document was replaced with an obvious falsehood and the eleven test files that read the
page were re-run — 404/404 green,
check-doc-linksexit 0. Nothing looked at this page's contentsbeyond the
ci.ymltable.Re-derived on today's tree, not reused from the card
The card measured
28cfff4and listed three undescribed commands. On4b4d35a7dthere arefour —
check-bash32-floor.mjslanded inlint.ymlat4922b83fc(#8016) after the card waswritten, which is the drift rate this pin exists to absorb.
Parsed with the same rule the pin uses (
run:values only, never the surrounding YAML):lintjob runs (7)scripts/check-lint-coverage.mjs,scripts/check-entry-guard.mjs,scripts/check-upstream-port-parity.mjs,scripts/check-bash32-floor.mjs,pnpm lint,scripts/check-cross-repo-closer-outcome.mjs,pnpm checkscripts/check-lint-coverage.mjs,pnpm lint,pnpm checkscripts/check-entry-guard.mjs,scripts/check-upstream-port-parity.mjs,scripts/check-bash32-floor.mjs,scripts/check-cross-repo-closer-outcome.mjsPositive control for the parser, so the four is a reading and not a broken matcher: the same
matcher run over the same section found the three commands the page did name, and found 12
run:steps in the job of which the environment ones (
corepack enable,pnpm --version,pnpm install --frozen-lockfile,pnpm --filter '@object-ui/cli...' build, the inlineshould_runshell block)correctly drop out by naming nothing this repository owns. A matcher that saw nothing would have
reported the page's three as missing too.
How the pin generalises (rather than being copied)
jobKeys,jobBlock,runSteps,firstPartyCommands,undocumentedCommandsandphantomCommandsmove to module scope, together with the rule's docblock. The new entry pointis:
The two sources differ only in where the prose lives — one table cell per job for
ci.yml, onewhole
##section forlint.yml's single job — so that is the only thing a caller supplies. Theci.ymlblock keeps its own history and its own failure messages and is now three lines long; thenew
lint.ymlblock is the same shape.Reading the whole Lint section rather than only its bullet list is deliberate: the paragraphs
below the bullets discuss
pnpm lintandpnpm checktoo, and a rule that read only the list wouldcall those phantoms.
A companion assertion pins that
lint.ymlstill defines exactly one job, so a second job cannotarrive undocumented and unpinned at the same time.
Ablation — both directions, on the committed tree
Each leg mutates a committed file, proves the mutation reached disk before any result is read
(on-disk
git hash-objectdiffers from the HEAD blob, plus a marker count), and restores bystate (
git diff HEADempty), never by exit code. The script carries atrap … EXIT INT TERMwith absolute paths.
Commands run (real output)
All vitest runs went through the shared verify lock.
Changeset — measured, not guessed:
So no changeset, and no
skip-changesetlabel — this page's own pins deny that label is wired toanything here.
ESLint, narrowed with the narrowing proven (
pnpm lintisturbo run lint, which walkspackages;
scripts/has nopackage.json, so the changed file is outside that surface — it waslinted directly anyway):
eslint.config.jsdeclares noparserOptions.projectand noprojectService, so linting is not type-aware and no verdict onan untouched file can move because of this diff;
--format json: 1 file linted, 0 errors, 0 warnings;.md, outsidefiles: ['**/*.{ts,tsx}']entirely.Control-byte self-scan beyond the gate:
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'over bothchanged files → no matches.
Out of scope, filed not fixed
#8420 — every other workflow section on this page is unpinned the same way, with two verified
instances (
vi-mock-specifiers.yml's section omits the blockingcheck-vi-mock-inherit.mjs;shadcn-check.yml's omits all three of its commands). Deliberately not a rider here: a naivewhole-page extension flags 24 of 34 sections, most of them cross-referencing prose rather than
defects, and this document is under concurrent edit today.
Not touched, as the card directs: the Skill Guide Paths sentence (#8006, landed) and the
main@6422aa891baseline sentence (#7965 ruled it correct, since it declares its measurementpoint).
🤖 Generated with Claude Code
Generated by Claude Code