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
34 changes: 34 additions & 0 deletions .changeset/7308-doc-snippet-nested-package-readmes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
---

Widen `check:doc-snippets`' package-README walk to every depth (objectui#7308).
Tooling only; no package is released by this change.

The gate collected `packages/<name>/README.md` and nothing deeper — and it stated
that one level in its own header's SCAN SURFACE paragraph, so this was a
specification drawn too small rather than drift from one. Four tracked pages were
therefore neither compiled nor named on `UNGATED_DOCS`: "neither covered NOR
declared ungated", objectui#5174's phrase for the state that is strictly worse
than a named debt, arriving one directory down instead of one level up. The
sibling gate `check-doc-links` had already closed the identical hole on the
identical four files (objectui#6026).

Sized before it was changed, which is the only order in which the numbers are
readings. Re-derived on `9ba7e9c3`: of the 43 tracked files under `packages/`
whose basename is `README.md`, 39 sit at a package root and 4 sit deeper. With
the surface widened and no ledger row yet written, those 4 documents bring 20
`ts`/`tsx` blocks, 13 of which fail — 3 in the syntax phase, 10 in the semantic
phase — for 37 diagnostics.

So the ledger GROWS, by three rows carrying those measured counts and what would
have to change on each page. It grows by three and not four because
`packages/plugin-gantt/docs/verification/README.md` holds no `ts`/`tsx` block at
all: it joins the covered tier at zero blocks, and a row naming it would fail the
gate's own re-derivation as a stale entry. Leaving any of the four outside the
surface to keep the ledger short was refused — that is the defect this card
reported, committed a second time.

One page was worth the widening on its own: `packages/core/src/adapters/README.md`
teaches a custom-adapter template that declares `implements DataSource<T>` while
omitting the interface's required `getObjectSchema`, so a reader who copies it
gets a class that does not satisfy the interface it claims.
75 changes: 71 additions & 4 deletions scripts/__tests__/check-doc-fence-languages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import {
AUDIT_DOCS as SNIPPET_AUDIT_DOCS,
auditDocsPages as snippetAuditDocsPages,
listDocuments as snippetDocuments,
NESTED_PACKAGE_READMES as SNIPPET_NESTED_PACKAGE_READMES,
nestedPackageReadmePages as snippetNestedPackageReadmes,
ROOT_DOCS as SNIPPET_ROOT_DOCS,
rootDocsPages as snippetRootDocsPages,
ROOT_PAGES as SNIPPET_ROOT_PAGES,
Expand Down Expand Up @@ -167,22 +169,40 @@ describe('check-doc-fence-languages: the scan surface is check-doc-snippet-types
* OTHER divergence still fails here, which is the whole point of keeping the
* comparison rather than deleting it.
*/
/** The snippet gate's three root-`docs/` legs, taken from the gate itself. */
/**
* The snippet gate's own legs, taken from the gate itself: its three
* root-`docs/` legs, plus objectui#7308's nested package READMEs.
*
* ⭐ objectui#7308 is the fourth enumerator and it arrives the way card 1 built
* this for: `check-doc-links` had already closed the same hole on the same four
* files (objectui#6026), but moving `check:doc-fences`' own surface is not that
* card's to do — so the divergence is SUBTRACTED BY IMPORT and every other
* drift between the two walks still fails here. A fifth nested README landing
* under `packages/` tomorrow travels into the snippet gate's side and into this
* subtraction by itself; a hand-written list of today's four filenames would
* have had to be re-typed for it.
*/
const snippetDocsLegs = () => [
...snippetRootDocsPages(ROOT),
...snippetAdrDocsPages(ROOT),
...snippetAuditDocsPages(ROOT),
...snippetNestedPackageReadmes(ROOT),
];

it('walks exactly the documents the snippet gate walks, minus that gate’s three docs/ legs', () => {
it('walks exactly the documents the snippet gate walks, minus that gate’s own legs', () => {
const legOnly = new Set(snippetDocsLegs());
expect(fenceDocuments(ROOT)).toEqual(snippetDocuments(ROOT).filter((d: string) => !legOnly.has(d)));
});

it('…and that subtraction is non-empty, so it is not silently subtracting nothing', () => {
// Each leg separately: a union that is non-empty overall would stay green
// with one of its three members returning nothing at all.
for (const leg of [snippetRootDocsPages(ROOT), snippetAdrDocsPages(ROOT), snippetAuditDocsPages(ROOT)]) {
// with one of its four members returning nothing at all.
for (const leg of [
snippetRootDocsPages(ROOT),
snippetAdrDocsPages(ROOT),
snippetAuditDocsPages(ROOT),
snippetNestedPackageReadmes(ROOT),
]) {
expect(leg.length).toBeGreaterThan(0);
}
// Every subtracted document really is on the snippet gate's side only.
Expand All @@ -192,6 +212,53 @@ describe('check-doc-fence-languages: the scan surface is check-doc-snippet-types
}
});

/**
* objectui#7308's leg, pinned where it stops rather than only that it is
* non-empty.
*
* Two claims a reading of the code cannot make: that the leg collects a README
* BELOW a package root and never the package's own top-level one (the
* no-double-collect guarantee objectui#6026 got structurally, by rooting the
* walk at each package's SUBdirectories), and that it does not follow pnpm's
* workspace symlinks out of the authored tree. The second is not hypothetical:
* `statSync` follows symlinks, and `packages/a/node_modules/@object-ui/b` leads
* back into `packages/b`, so an unguarded walk does not terminate.
*/
it('the nested-README leg collects below package roots only, and the tracked tree exactly', () => {
expect(SNIPPET_NESTED_PACKAGE_READMES).toEqual({
dir: 'packages',
name: 'README.md',
recursive: true,
});
const nested = snippetNestedPackageReadmes(ROOT);
// Below a package root, every one of them — never `packages/<name>/README.md`.
for (const doc of nested) {
expect(doc, `${doc} is not a README.md`).toMatch(/\/README\.md$/);
expect(doc, `${doc} sits at a package root, so the leg above already has it`).not.toMatch(
/^packages\/[^/]+\/README\.md$/,
);
expect(doc.split('/'), `${doc} left the authored tree`).not.toContain('node_modules');
}
// The leg plus the top-level README leg is EXACTLY the tracked population —
// measured against git, not against a hand-written list, so the walk cannot
// quietly gain a generated page or lose an authored one.
const tracked = execFileSync('git', ['ls-files', '--', 'packages/'], { cwd: ROOT, encoding: 'utf8' })
.split('\n')
.filter((f) => /(^|\/)README\.md$/.test(f))
.sort();
const walked = snippetDocuments(ROOT)
.filter((d: string) => d.startsWith('packages/') && d.endsWith('/README.md'))
.sort();
expect(walked).toEqual(tracked);
// Non-vacuous on both halves: the tracked population is not empty, and it
// really does contain pages at both depths.
expect(tracked.length).toBeGreaterThan(0);
expect(nested.length).toBeGreaterThan(0);
expect(tracked.filter((f) => /^packages\/[^/]+\/README\.md$/.test(f)).length).toBeGreaterThan(0);
// No document is collected twice by the two package legs together.
expect(new Set(walked).size).toBe(walked.length);
});

/**
* The boundary, pinned on the legs themselves. `recursive: false` on one and
* `recursive: true` on the other two are claims about where each surface stops,
Expand Down
Loading
Loading