Skip to content

test(ui): doc-version-claims anchors CI's Node on .nvmrc as well as literal node-version lines - #26432

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-lwv5hl
Oct 27, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-lwv5hl

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Steve · project thread
Fixes #26421

Clause-②: no
Metadata-protocol: none

维护者速读

What changes

doc-version-claims.test.ts used literal node-version: lines in .github/workflows/*.yml as the anchor for every Node version the docs state, floored at 15. #26419 moved about forty jobs onto node-version-file: .nvmrc (mostly through the new .github/actions/setup-workspace composite), which left one literal line and turned the file red over a CI whose Node had not moved. #26419 merged at 03:41Z (d15f99d), so the file is red on main today.

  • Anchor. workflowVersionDeclarations now reads both spellings actions/setup-node accepts, across .github/workflows/*.yml and every action.yml under .github/actions/: a literal node-version: and a node-version-file: reference, resolved against the checkout root and read the way setup-node reads it (first non-blank, non-comment line). Each declaration carries via (the version file, or null for a literal). A .nvmrc that disagrees with a leftover literal is a split vote; a missing or unreadable version file is an UNKNOWN declaration, named, never agreement.
  • Comparison. The per-entry comparison moved into workflowVersionFailures(check), so the corpus assertion and the fixture run the same code. Failure text names both directories and labels file-read values as .nvmrc -> "22".
  • Floors. Re-based on readings of both trees as ANCHOR_DECLARATION_FLOOR = 10 (readings in the next section). The old 15 was a reading of one shape of the tree; each further job moved into the composite lowers the count by design, and a floor tight to today's count would make the next such move a ui test edit again. A collapse to zero or near it still goes red (ablation below).
  • Census cross-check. Still honest, now over both keys: workflowKeyMentions(['node-version', 'node-version-file']) walks the same file list as the parser, and the two must name the same lines.
  • Fixture. The two-direction fixture stays (now a root with .github/workflows/), and gains a .nvmrc arm: a workflow and a composite action that both read .nvmrc, compared against a page stating Node 22.x. It is green at .nvmrc 22, red at v24 (naming the page line, major 24 and .nvmrc -> "v24"), a split vote when a leftover literal '22' disagrees with .nvmrc, UNKNOWN at lts/*, and reported (not dropped) when .nvmrc is missing.
  • Header section and the three workflowVersionKey ledger reasons updated to name the new anchor.

Forced test edits: none outside this file. The whole diff is this card's own test file; no other test changed.

Why

The workflow Node version is still single-sourced; the truth moved from ~forty literal lines into .nvmrc, which check:node-version already holds the remaining literals to. The anchor has to follow it, or this file reads a CI whose Node never moved as a CI with no Node.

Tests

All runs under scripts/pm/os-verify-lock.sh, pnpm --dir ui exec vitest run scripts/__tests__/doc-version-claims.test.ts.

tree head result
(a) main at 9a0108c + this change 79e6d72 29/29 passed, VERDICT command-exit 0
(b) scratch merge of #26419's head 2cb5ee1 onto (a), local, not pushed afc11ebf 29/29 passed, VERDICT command-exit 0
(c) main at 75afeff (#26419 landed) merged into this branch 50e2f7b 29/29 passed, VERDICT command-exit 0
control: main's ORIGINAL test file on tree (b) afc11ebf 2 failed / 27 passed: "expected 1 to be greater than or equal to 15" (both floors), the premise reproduced
Anchor readings per tree (floor probe: ANCHOR_DECLARATION_FLOOR set to 1000 through scripts/ablation-replace.mjs, restored, blob == HEAD)
  • (a) 9a0108c: 59 declarations, all literal, all major 22. Parser and key-only counter agree (59 = 59).
  • (b) afc11ebf: 23 = 1 literal (scaffold-e2e.yml's registry canary) + 22 node-version-file: .nvmrc (21 in workflows, 1 in setup-workspace/action.yml). Parser 23 = counter 23.
  • (c) 50e2f7b: 23, same shape. Cross-checked by git grep: 1 literal, 22 file references under .github/.
Ablation: the anchor pointed back at literals only goes red on tree (b)

Both mutations through node scripts/ablation-replace.mjs (anchor hit 1 -> 0, blob d54c9e19855b -> 0d6f06d8eb46 -> 666e75b1eab5; restored, blob == HEAD d54c9e19855b, git diff HEAD empty):

  1. Parser -file arm removed AND counter given only node-version: 3 failed / 26 passed.
    • pins every workflow-anchored claim: "expected 1 to be greater than or equal to 10"
    • reads every declaration: "control for the agreement above … expected 1 to be greater than or equal to 10"
    • fixture .nvmrc arm: "expected [] to deeply equal [ [ …(3) ], [ …(3) ] ]"
  2. Parser -file arm removed only (counter keeps both keys): 3 failed / 26 passed, and the census cross-check names the loss: "the parser and a counter that knows only the KEYS disagree … expected [ Array(1) ] to deeply equal [ …(23) ]".

Acceptance notes

  • Not touched, per the card: .github/** (root ci.yml, ui/.github), and the five ui jobs' pins (ci-setup-pnpm-wiring, turbo-cache-save-bound, the eight pnpm install --frozen-lockfile readers). Moving those jobs onto the composite is a later card that needs a ci.yml edit.
  • Coverage gap, noted, not filed (needs ci.yml, out of bounds): ci.yml's ui paths filter lists .github/workflows/** but not .nvmrc or .github/actions/**. A PR that changes only .nvmrc (a Node bump) or only the composite action does not run Test UI, so this assertion would first see such a drift on the next ui-touching PR or main run rather than on the PR that caused it. Carrier: the later ci.yml card that moves the five ui jobs onto the composite.
  • The floor is deliberately loose (10 against readings of 59 and 23); its job is to catch a parser or file walk that stopped reading, not to pin today's count.
  • type-check:scripts was run locally; it reports 20 errors, all TS2307 / TS7006 in five other scripts/__tests__ files that import an unbuilt @objectstack/spec dist in this container, and none in this file. CI's Type Check UI is the authority.

Verification

Local gate subset from node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (change set: this one file), 17 commands, all exit 0 on 79e6d72; re-run on the final head is reported in the card's os-dev-report. Derived list: check-closing-keyword-parity (+ --self-test), check-comment-mask-corpus, check:cross-package-test-inputs, check:driver-memory-census, check:engine-double-contract, check:gitlink-declared, check:nul-bytes, check:published-files, check:query-options-erasure, check:refd-timer-probe, check:tier-file-adoption, check:type-check-coverage, check:type-check-debt, check:undeclared-dep-imports, check:watch-hint-literal, check:where-matcher. eslint on the file: clean.

Test-only, publishes nothing: skip-changeset label on this PR, no changeset.


Generated by Claude Code

…iteral node-version lines

The workflow-version assertion read only literal `node-version:` lines in
.github/workflows and floored them at 15. The setup-workspace composite
moves most jobs onto `node-version-file: .nvmrc`, which leaves one literal
line and turned this file red over a CI whose Node had not moved.

The anchor now reads both spellings setup-node accepts, across
.github/workflows and .github/actions: a literal `node-version:` and a
`node-version-file:` reference resolved to the major of the file it names.
The census cross-check counts both keys over the same file list, the floor
is re-based on readings of both trees, and the two-direction fixture gains a
.nvmrc arm run through the same comparison the corpus assertion runs.

Claude-Session: https://claude.ai/code/session_01ADHkmPpSHhxJghrkXZFn8E
Co-authored-by: Claude <noreply@anthropic.com>
…ect-thread-lwv5hl

Claude-Session: https://claude.ai/code/session_01ADHkmPpSHhxJghrkXZFn8E
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 27, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT · seat domain:ui#1 · 2026-10-27T03:59Z · main-red fix

Head 50e2f7be (read from the PR object). It merges main 75afeffd, which contains #26419 (d15f99d7).

Landing: ready + auto-merge through the relay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/l skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants