Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .changeset/6307-bold-version-literals.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
---
---

Docs and gate change; no published surface.

Two consumer-facing guides stated Node/pnpm floors this project neither declares nor
tests: `content/docs/guide/quick-start.md` carried `**Node.js** 20+` / `**pnpm** 9+ or
npm/yarn`, and `content/docs/guide/building-crud-app.md` the same pair on one line. Both
pages address the reader's OWN project, so the root `engines` field never governed them,
and no published package supplies a floor either — of the 46 workspace manifests, zero
declare `engines.node` or `engines.pnpm` (the only `engines` block outside the root is
`packages/vscode-extension`'s `engines.vscode`). The pages now state what is measurable
instead: the packages are built and tested on Node 22.x with pnpm 10.x — 26 of the 27
`node-version:` declarations in `.github/workflows` read `'22.x'` and the 27th reads
`'22'`; the root `packageManager` field is `pnpm@10.31.0`, which is what `corepack enable`
hands every CI job. Worded as what CI exercises, not as a requirement the project has not
measured.

The reason nothing objected: `scripts/__tests__/doc-version-claims.test.ts` scans
`content/docs` for exactly this, and the `SEP` character class between a toolchain name
and its version admitted backticks, quotes, whitespace, colons, commas, pipes and brackets
— but not `*`. So `**Node.js** 20+` never matched `TOOLCHAIN + SEP + VERSION`, and the
ratchet reported green over four literals it had never examined. `SEP` now admits `*` and
`_`; measured over the 241 files the three scan roots resolve to, the corpus goes from 33
matched literals to 37 — exactly those four, none lost. None of the four was ledgered:
they were deleted, which is what the gate's own failure message asks for when a literal
restates no manifest and no lane tests it, and the sentences replacing them are inventoried
as `anchored` entries naming the anchor each can be re-measured against.

A new fixture test keeps the widening measurable now that the repaired corpus carries no
emphasised claim at all, and pins the one boundary it does not cross: `_Node.js_ 20+` stays
invisible, because `_` is a word character and the `\b` on each side of the toolchain name
therefore fires on neither side of it (measured: zero such spellings in the corpus today).

objectui#6307.
2 changes: 1 addition & 1 deletion content/docs/guide/building-crud-app.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,7 +9,7 @@ This tutorial walks you through building a **Task Manager** CRUD application wit

## Prerequisites

- **Node.js** 20+ and **pnpm** 9+
- **Node.js** and **pnpm** (or npm/yarn) — ObjectUI is tested on Node 22.x with pnpm 10.x.
- Basic knowledge of **React** and **TypeScript**

## Step 1: Project Setup
Expand Down
3 changes: 1 addition & 2 deletions content/docs/guide/quick-start.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,8 +9,7 @@ Get up and running with ObjectUI in a small Vite app. This guide installs the co

## Prerequisites

- **Node.js** 20+
- **pnpm** 9+ or npm/yarn
- **Node.js** and **pnpm** (or npm/yarn) — ObjectUI is tested on Node 22.x with pnpm 10.x.
- Basic knowledge of **React** and **TypeScript**

## Step 1: Create a React Project
Expand Down
126 changes: 125 additions & 1 deletion scripts/__tests__/doc-version-claims.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -277,6 +277,46 @@ import { fileURLToPath } from 'node:url';
* manifests (it wires Tailwind 4 through `@tailwindcss/postcss` instead), so there is
* nothing here to compare against, whatever the page teaches.
*
* ## What objectui#6307 added: the SPELLING the scan could not see
*
* Every widening above added a surface or a name. This one added a SEPARATOR, and it is
* the first whose absence was invisible from inside this gate's own output: a green
* ratchet looks identical whether it examined a line or never matched it at all.
*
* `SEP` admitted backticks, quotes, whitespace, colons, commas, pipes, brackets and a
* dash — and not `*`. So `**Node.js** 20+` never matched `TOOLCHAIN + SEP + VERSION`,
* while markdown emphasis around a toolchain name is one of this corpus's ordinary
* spellings: measured at this cut, six files across the three scan roots write one in
* bold. Two of them were the consumer guides' prerequisite bullets, where the number is
* exactly what a reader acts on.
*
* Measured across the widening, over the 241 files the three roots resolve to: 33
* matched literals before, 37 after — four new, none lost, all four on the two pages
* objectui#6307 names (`quick-start.md:12-13` and `building-crud-app.md:12`).
*
* NOT ONE of the four earned an inventory entry, and that is the half of this change
* worth carrying forward. They were not a floor this project declares — of the 46
* workspace manifests, ZERO declare `engines.node` or `engines.pnpm`, the only
* `engines` block outside the root being `packages/vscode-extension`'s `engines.vscode`
* — and not one it tests: 26 of the 27 `node-version:` declarations in
* `.github/workflows` read `'22.x'` and the 27th reads `'22'`, so nothing anywhere runs
* the Node 20 those bullets named. A number a reader will act on, restating no manifest
* and tested by no lane, is precisely what the ratchet's own failure message says to
* DELETE rather than ledger. The pages now state what CI exercises instead, and THOSE
* sentences are the four `anchored` entries below — an entry per literal, each naming
* the anchor it can be re-measured against.
*
* Which leaves the trap this section exists to stop. After that repair the corpus holds
* no emphasised claim at all, so reverting `SEP` would change nothing observable and
* this file would report green over the same blind spot again.
* `it('reads a claim through markdown emphasis…')` is the permanent witness, and it
* also pins the boundary the widening does NOT cross: `_` is in the class, yet
* `_Node.js_ 20+` still cannot match, because `_` is a word character and the `\b` on
* each side of `TOOLCHAIN` therefore fires on neither side of the name. Measured: zero
* underscore-emphasised toolchain names in the corpus today (control, same sweep: six
* files carry the bold spelling), so it is recorded as a boundary rather than repaired
* by widening those boundaries into a lookaround nothing has asked for.
*
* ## The census that set the design (measured on d46b40324, the merge of PR #3698)
*
* The dispatch expected the bare-claim count to be zero, since #3688 and #3698 had just
Expand DownExpand Up@@ -446,7 +486,7 @@ const TOOLCHAIN =
* spelled without the wildcard in the comments here.
*/
const TICK = '\u0060';
const SEP = '[' + TICK + '\'"\\s:,|)\\]]{0,6}(?:[-—]\\s*)?[' + TICK + '\'"]?\\s*';
const SEP = '[' + TICK + '\'"\\s:,|)\\]*_]{0,6}(?:[-—]\\s*)?[' + TICK + '\'"]?\\s*';

/**
* Case-insensitive, and the reason is the biggest single class in the corpus: the
Expand DownExpand Up@@ -686,6 +726,18 @@ const PEER_RESTATEMENT_OK =

const KNOWN_CLAIMS: KnownClaim[] = [
// --- content/docs ------------------------------------------------------------
{
file: 'content/docs/guide/building-crud-app.md',
claim: 'Node 22.x',
kind: 'anchored',
why: "Anchored on the workflows: of the 27 node-version declarations in .github/workflows, 26 read '22.x' and the 27th (half-state-patrol.yml) reads '22'. Written by objectui#6307, which replaced an invented consumer floor (`**Node.js** 20+`) on this page. The sentence around it states what CI EXERCISES, not what a reader's project requires - no manifest in this tree declares a consumer engines.node, so a floor here would be a number nobody measured.",
},
{
file: 'content/docs/guide/building-crud-app.md',
claim: 'pnpm 10.x',
kind: 'anchored',
why: 'Anchored on the root packageManager field, pnpm@10.31.0: 17 corepack enable steps across 12 workflow files mean the pnpm that installs and builds these packages in CI is the one that field names. Same objectui#6307 rewrite as the Node line above, replacing `**pnpm** 9+` - a floor zero manifests in this workspace declare.',
},
{
file: 'content/docs/guide/ci-cd-pipeline.md',
claim: 'Node 22.x',
Expand DownExpand Up@@ -724,6 +776,18 @@ const KNOWN_CLAIMS: KnownClaim[] = [
skeletonDep: 'vite',
why: 'Same skeleton, same anchor, same assertion (objectui#3855). This was the worst of the pair: it read ^5.0.0 against a workspace unanimously on ^8.2.1 — three majors — and the entry excusing it said the plugin author picks their own bundler version, which is not what a workspace:* manifest with a vite build script means.',
},
{
file: 'content/docs/guide/quick-start.md',
claim: 'Node 22.x',
kind: 'anchored',
why: "Same anchor and same objectui#6307 rewrite as the building-crud-app.md entry above (26 of 27 node-version declarations read '22.x'); this page carried the same invented floor in two bullets, `**Node.js** 20+` and `**pnpm** 9+`, and both were invisible to this scan until SEP admitted emphasis markers.",
},
{
file: 'content/docs/guide/quick-start.md',
claim: 'pnpm 10.x',
kind: 'anchored',
why: 'Same anchor as the building-crud-app.md pnpm entry above: the root packageManager field, pnpm@10.31.0, is what corepack hands every CI job that installs this workspace. Written by objectui#6307 in place of `**pnpm** 9+`.',
},
{
file: 'content/docs/guide/theming.md',
claim: 'Tailwind CSS v3.3',
Expand DownExpand Up@@ -1374,6 +1438,66 @@ describe('doc version claims - the scan itself', () => {
}
});

it('reads a claim through markdown emphasis, so the widened separator is not decorative', () => {
// objectui#6307. `SEP` admitted backticks, quotes, whitespace, colons, commas,
// pipes and brackets — and not `*` — so `**Node.js** 20+` never matched
// `TOOLCHAIN + SEP + VERSION`. Both consumer guides spelled their prerequisite
// floors that way, four literals across two pages, and this gate reported green
// over every one of them: the failure its own header warns about for other
// classes, arriving through the scan instead.
//
// This fixture is the widening's only PERMANENT witness, which is why it is here
// rather than left to the corpus. The four literals that motivated the change
// were DELETED by the same change (they stated a consumer floor this project
// neither declares nor tests, objectui#6307 half 1), and the sentences that
// replaced them put a plain space between each name and its version. So on the
// corpus alone, reverting `SEP` to its pre-#6307 spelling would change nothing
// observable and the blind spot would come back unnoticed.
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'doc-version-claims-emphasis-'));
try {
const fixture = path.join(dir, 'prerequisites-shaped.md');
fs.writeFileSync(
fixture,
['# Prerequisites', '', '- **Node.js** 20+', '- *pnpm* 9+ or npm/yarn', ''].join('\n'),
'utf8',
);

expect(
claimsIn(fixture).map((c) => c.claim),
'a toolchain name wrapped in markdown emphasis must still produce a claim',
).toEqual(['Node.js** 20+', 'pnpm* 9+']);
} finally {
fs.rmSync(dir, { recursive: true, force: true });
}

// The two spellings pinned side by side, so that "the widening bought something"
// is asserted rather than believed: the pre-#6307 class, rebuilt here, must FAIL
// on the same line the current one matches.
const claimWith = (sep: string): RegExp =>
new RegExp('(?:@[a-z0-9-]+/)?\\b' + TOOLCHAIN + '\\b' + sep + '(' + VERSION + ')', 'i');
const SEP_BEFORE_6307 = '[' + TICK + '\'"\\s:,|)\\]]{0,6}(?:[-—]\\s*)?[' + TICK + '\'"]?\\s*';

expect(claimWith(SEP).test('- **Node.js** 20+'), 'the current SEP must match the bold spelling').toBe(true);
expect(
claimWith(SEP_BEFORE_6307).test('- **Node.js** 20+'),
'the pre-objectui#6307 SEP must be shown NOT to match, or nothing here says what the widening changed',
).toBe(false);

// The residual, asserted rather than left for someone to assume away: `_` is in
// the class (it costs nothing between a name and a version) but underscore
// EMPHASIS around the name is still invisible, and no character class can reach
// it. `_` is a word character, so `\b` fires on neither side of `_Node.js_` —
// the match fails before `SEP` is ever consulted. Measured at this cut across the
// three scan roots: ZERO underscore-emphasised toolchain names (control, same
// sweep: six files carry the bold spelling), so this is a documented boundary and
// not a live hole. A corpus that starts spelling it that way needs the BOUNDARIES
// widened, not the class.
expect(
claimWith(SEP).test('- _Node.js_ 20+'),
'if this ever goes true the boundary was changed too - update this comment with what it now covers',
).toBe(false);
});

it('does not treat a numbered section heading as a release section', () => {
// The trap that would make this whole file vacuous. `0001-clipboard-paste.md`
// numbers 18 of its headings `### N.M`; a loose "heading contains a version"
Expand Down
Loading