Skip to content

test(docs): pin command parity for every ci-cd-pipeline.md section by default - #9467

Merged
os-try-charles merged 1 commit into
mainfrom
claude/issue-9463-ci-doc-parity-inverted-default
Sep 14, 2026
Merged

os-try-charles merged 1 commit into
mainfrom
claude/issue-9463-ci-doc-parity-inverted-default

Conversation

@claude

@claude claude Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Part of #9463 — the remaining pin appetite for content/docs/guide/ci-cd-pipeline.md, taken as one PR instead of ~thirty rounds.

Part of, not Fixes, deliberately. This PR delivers the card's steps ① and ② in full and makes the fallback in step ③ unnecessary. What it does not deliver is the card's own stop clause: the alias-rule question is reported here, not decided (see the three items under Reported, not decided below). Letting a merge auto-close #9463 would swallow that half, and the inbox filter only reads open cards. Close it once a maintainer has ruled on item 2, or split that into its own card.

The card's instruction was to measure the cheaper shape before starting the queue. It is measured, and it holds.

① Census re-derived on today's 38 sections

Counted on origin/main (f5b9c1797), never on the worktree — the card records a per-container stale-checkout hazard that silently confirms the obsolete "24 of 34".

population n how
heading lines naming a .yml 39 grep -cE '^#{1,6} .*\([^]+\.yml)\s*$'ongit show origin/main:…`
distinct workflows in headings 38 doc-snippet-types.yml carries two headings (its ### sub-gate)
workflow files 38 git ls-tree --name-only origin/main -- .github/workflows/

Bijection is exact: no workflow undocumented, no heading naming a file that is gone.

The delta from the census's 36 is 3 added and 1 removed, not "2 new". Net +2, but the list matters:

section status class today
doc-example-ids.yml added agrees, none of the above
line-citation-gate.yml added legitimate exception — names dependabot-merge-gate.mjs (classifies it NOT_A_GATE) and pnpm census:cross-file-line-citations, of which the page itself says "runs in no workflow"
required-check-set-patrol.yml added legitimate exception — names dependabot-merge-gate.mjs as the classifier every pull_request check run must pass, which is its stated reason for having no pull_request leg
stale.yml removed from the repo was "no job to compare"

Re-derived buckets, 38 total:

class census (36) today (38)
already pinned 4 8
true defect 4 (landed) 2 (new — see ②)
legitimate exception 11 13
no job to compare 4 3
agrees, none of the above 13 12

Note already pinned is 8, not the 5 the card's title says: 5 is the commandParity() call-site count, and one call site is a .map over four sections.

② The inverted default, measured

38 sections = 21 agree outright + 17 flagged. The 17 split in the only way that matters:

  • 15 phantom-only — the page names a command the job does not run. Every one has a reason stated on the page itself; each was re-read before being written down. This is the named false-positive population, and it is now an explicit table.
  • 2 in the direction that hides a gate.

With the exception table encoded, the residual is 0 — after repairing those 2. That is the card's step 2, and it answers "one PR".

The 2 real defects — repaired on the page, ⛔ not declared away

  • doc-component-types.yml runs pnpm check:prompt-keys in a step of its own with no continue-on-error — blocking — and the section named neither the script nor the alias. This is objectui#8420's check:sdui-registration-pins shape exactly: a gate that can stop your PR and that you cannot find from the page.
  • changeset-presence.yml grew a second job, changeset-claims (report-only); the section documented only the first.

Both landed on 2026-09-11 — two days after the census that had put both sections in its "agrees today, and nothing holds them that way" bucket. The census did not miss them; they did not exist yet. A thirty-deep one-section-per-PR queue would not have caught them either. That is the whole argument for inverting the default rather than queueing: a section added tomorrow is born pinned.

⛔ Gates weakened: NONE

No assertion relaxed, no accept set widened, no blocking check demoted. undocumentedCommands — the direction that hides a gate — admits no exception at all in the sweep. The existing per-job pins keep running unchanged on top of it. Everything here is added coverage.

DECLARED_NON_RUN_COMMANDS moves to module scope so the sweep re-keys it instead of growing a second copy of the same four claims — the same "two copies of a rule are two rules" move this file already made for the alias rule.

⚠️ Reported, ⛔ not decided — for the maintainer

  1. The alias rule's blast radius. The vi-mock/shadcn header says the alias decision "does not reach the other 32 sections … re-pointing them is a separate card". ci-cd-pipeline.md command-parity:38 节中仅 5 节已 pin —— 用当刻分母承接剩余 pin 需求,并在开始约三十轮之前先量「反转门禁默认」 #9463 is that separate card, so this is neither silent nor a side effect — but it is the thing to look at first. The rule itself is applied verbatim.
  2. The one open alias instance. ## Governed Surface Guard offers both pnpm governed -- PATHS and node scripts/check-governed-queue-guard.mjs --test PATHS as local spellings, while the job runs that script with --self-test and bare. Because governed carries --test, the settled rule refuses to merge it and it reads as a phantom. It is declared with that reason. Whether an argument-carrying alias should ever merge is a decision about the rule, not about this section — ⛔ not taken here.
  3. 13 of 38 sections need an exception entry (~34%). That is the cry-wolf number to judge. Each entry is a written reason re-read against the page, and the set is asserted exactly, in both directions, so a stale entry fails as stale rather than quietly becoming permission.

Verification

  • PRE pnpm exec vitest run --project unit scripts/__tests__/ci-cd-pipeline-doc.test.ts — exit 0, 80/80.
  • POST same file — exit 0, 84/84. POST whole scripts/__tests__ — exit 0, 156 files / 4606 tests.
  • tsc -p tsconfig.scripts.json --noEmit — exit 0, and --listFiles proves this test file is in the program (1 hit; control hits 2) rather than silently excluded.
  • Gates: check-changeset-presence (its own verdict line: no changeset is owed — doc + test, no published source), check-control-bytes, check-doc-component-types, check-doc-fence-languages, check-doc-links — all exit 0, exit codes captured by redirect-then-capture, never across a pipe.
  • ESLint on the changed file exit 0. Declared narrowing: repo-wide bare eslint . reports 95 pre-existing errors across 79 files in apps/, packages/, e2e/ — none in this diff, and eslint . is not this repo's lint gate (turbo run lint is). The farm is CI's.

Ablation — five legs, on-disk mutation proven, restore by hash equality

Every leg: git hash-object before/after proves the mutation reached disk; restore is git checkout HEAD -- PATH verified by hash equality and an empty git diff HEAD; the harness carries a trap … EXIT INT TERM with absolute paths.

leg mutation result
A page stops naming check:prompt-keys RED — names every first-party command…, message doc-component-types.yml: pnpm check:prompt-keys (1 failed / 83)
B page stops naming check:changeset-claims RED — same test, changeset-presence.yml: pnpm check:changeset-claims (1 failed / 83)
C delete one declared exception RED — declares every command… (undeclared)
D add a declaration nothing produces RED — same test (stale)
E heading regex no longer matches RED — reads one section per workflow (3 failed / 81): the vacuity control, proving the sweep is not green by reading nothing

Tree verified clean at HEAD afterwards.


🤖 Generated with Claude Code

https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr


Generated by Claude Code

… default

`ci-cd-pipeline.md` documents 38 workflows and only 8 of its sections were pinned
against what their workflow actually runs. objectui#8420 priced the rest at ~30
rounds, one section per PR, because the naive sweep flagged 24 of 34 and "a gate
that cries wolf gets switched off rather than fixed".

That ruling does not survive objectui#8420's own follow-up: its census named the
false-positive population, so the exceptions can now be written down and the
default inverted. Measured on origin/main at 38 sections: 21 agree outright, 15
are phantom-only (the page names a command the job does not run, for a stated
reason), and 2 are the direction that hides a gate.

The 2 are repaired on the page rather than declared away:

  - `doc-component-types.yml` runs `pnpm check:prompt-keys` in a step of its own
    with no `continue-on-error`; the section named neither script nor alias.
  - `changeset-presence.yml` grew a second job, `changeset-claims`; the section
    documented only the first.

Both landed on 2026-09-11, two days after the census that had put both sections
in its "agrees today, and nothing holds them that way" bucket — which is the
argument for inverting rather than queueing. A section added tomorrow is born
pinned.

Nothing is weakened: `undocumentedCommands` admits no exception at all in the
sweep, the per-job pins keep running unchanged, and the alias rule is applied
verbatim. The one argument-carrying alias (`pnpm governed`) is declared with its
reason and flagged as a decision about the rule, not taken here.

`DECLARED_NON_RUN_COMMANDS` moves to module scope so the sweep re-keys it rather
than growing a second copy of the same four claims.

Refs #9463

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
@github-actions github-actions Bot added the tests label Sep 14, 2026
@claude

claude Bot commented Sep 14, 2026

Copy link
Copy Markdown
Contributor Author

PM review — verified, ⛔ NOT landed. Seat is being handed over; the next seat lands this.

domain:devx @ objectui seat (#5748), 2026-09-14T06:20Z. The maintainer has instructed a handover to another session, so I am ⛔ not starting a landing cycle I cannot finish. CI still had 6 required checks running when I read it (Lint, Type Check, 4 Test shards; nothing failed). ⚠️ This PR is a DRAFT and stays one until the next seat probes it.

⭐ What I verified myself, because it is the load-bearing claim

This PR's case is not 「the sweep can be made to work」. It is 「the thirty-round queue would not have caught these」 — and that is measurable:

d2f0c108cc  2026-09-11  fix(prompts): teach only view keys a real renderer answers, and gate it (#9099)
d8b4739d4c  2026-09-11  feat(changeset): re-read a pending changeset when a later change touches …(#9112)
census comment #issuecomment-5607595817 — 2026-09-09
both --is-ancestor origin/main -> exit 0        NONSENSE control (impossible sha) -> correctly FAILS

⇒ both real defects were introduced two days AFTER the census that had classified those very sections as 「agrees today, and nothing holds them that way」. ⭐ The census did not miss them — they did not exist yet. A one-section-per-PR queue thirty deep would have been just as blind. That is the empirical argument for inverting the default rather than queueing, and it is the strongest thing in this PR.

Denominator, re-derived on origin/main

heading lines matching the card's own grep   -> 39
workflow .yml files                          -> 38
⚠️ the STALE shared worktree answers          -> 34

⭐ The dev is right that the card conflates two populations: heading lines ≠ sections (doc-snippet-types.yml carries two headings). ⚠️ And the 34 is the trap objectui#9463 itself documents, reproduced once more here — ⛔ always git show origin/main:PATH.

What the next seat should check before landing

  1. The alias question is REPORTED, ⛔ NOT DECIDED — exactly as the card's stop clause requires. One live instance: pnpm governed carries --test, so the settled rule reads it as a phantom and it was declared, ⛔ not merged. ⚠️ Declaring is the landed rule's consequence; merging would be a new decision. Do not let a landing quietly settle it.
  2. ⚠️ This PR extends the alias rule from 6 sections to all 38, which the vi-mock/shadcn header had reserved as 「a separate card」. The dev flags objectui#9463 as being that card and says so openly in the PR body. ⭐ Worth a maintainer's eye, ⛔ not a silent extension.
  3. ⭐ Ablation has five legs including a vacuity control (heading regex mutated to .yZZ so the sweep reads NO sections → 3 failed, including both parser floors). ⇒ the block cannot be green by reading nothing. Each leg carries on-disk hash proof and hash-equality restore. ⭐ Two legs were re-run standalone because the batch harness did not confirm where they went red — an unconfirmed red was not accepted.
  4. gates_weakened: NONEundocumentedCommands admits no exception at all, the per-job pins run unchanged on top, and DECLARED_NON_RUN_COMMANDS was re-keyed rather than copied.
  5. ⚠️ Part of #9463, ⛔ not Fixes — so the card will not auto-close. That is deliberate: the alias stop clause is still open and an auto-close would swallow it.

⇒ Over to the next seat. Everything above is measurement, ⛔ not recollection.


Generated by Claude Code

@os-try-charles
os-try-charles marked this pull request as ready for review September 14, 2026 06:51
@os-try-charles
os-try-charles added this pull request to the merge queue Sep 14, 2026
Merged via the queue into main with commit db6aa19 Sep 14, 2026
35 checks passed
@os-try-charles
os-try-charles deleted the claude/issue-9463-ci-doc-parity-inverted-default branch September 14, 2026 07:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants