Repository navigation
feat(cli): doctor integration validate checks each doc against its published authoring type - #7673
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
AI review status for this pull request.
|
PR Analysis Report
|
There was a problem hiding this comment.
This PR is on hold for a maintainer decision: the doc type check it adds to astryx doctor integration validate (with the new data.docTypes field and the Core known-drift test) has no current spec yet, because the requirement it implements, AST-039 FR13, exists only in draft spec PR #7658 and AST-039 itself is still a draft. Approval needs a maintainer to approve that requirement, or point to another current record that covers it, including the warnings-only severity, whether findings belong in a separate report rather than the existing issues list, and whether Core's docs belong under the same check. Separately, two small fixes are needed:
- Print each finding's
exportandtype(and the number of docs checked) in the text output, since the CLI's response contract requires every JSON field in the text view. - When an integration has no doc files, say so instead of printing an empty "Checking docs…" section or asking the author to install TypeScript.
[Automated review]
| const files = new Set(report.findings.map(f => f.doc)).size; | ||
| blocks.push( | ||
| records(report.findings, { | ||
| fields: [ |
There was a problem hiding this comment.
The JSON findings also carry export and type, but these text records drop them, so findings for the same field in default, docsZh and docsDense are told apart only by line. AST-017 FR13 asks for every field in the text projection, and cli-surface INV5 keeps every field greppable. Suggest adding 'export' and 'type' here, and the checked count (report.docs) to the summary line below.
| records(report.unchecked, {fields: ['doc', 'reason']}), | ||
| ); | ||
| } | ||
| if (report.findings.length === 0 && !failed && report.docs > 0) { |
There was a problem hiding this comment.
When no root holds a doc file (a codemods-only package, say), docs is 0, so nothing is printed after the section heading; and without TypeScript the [skip] line asks the author to install TypeScript although there is nothing to check. Suggest returning early from integrationDocTypes() when integrationDocFiles() finds nothing (no TypeScript lookup) and printing one outcome line for docs: 0 here.
3640e4c to
86a34e4
Compare
33d1a5e to
1a3f69c
Compare
There was a problem hiding this comment.
This PR is on hold for a maintainer decision: the doc type check it adds to astryx doctor integration validate and validateIntegration() (with the new data.docTypes field and the Core known-drift test) has no current spec, because the requirement it implements, AST-039 FR13, exists only in draft spec PR #7658 and AST-039 itself is still a draft. Approval needs a maintainer to approve that requirement, or point to another current record that covers it, including the warnings-only severity, reporting findings in docTypes rather than in issues, which doc files the check covers, and whether Core's docs belong under the same check. The text output now shows every finding field and handles packages without docs, so no other change is required; as an optional cleanup, the no-TypeScript test still asserts against the old Checking docs against the authoring types heading, so that assertion can no longer fail.
[Automated review]
| expect(output).toContain( | ||
| '[skip] Docs not type-checked: TypeScript is not installed in this project', | ||
| ); | ||
| expect(output).not.toContain('Checking docs against the authoring types'); |
There was a problem hiding this comment.
Optional: the heading is now Checking N doc(s) against the authoring types (…), so this string can never appear and the assertion can't fail. expect(output).not.toMatch(/Checking \d+ doc\(s\)/) keeps the intent; a bare 'against the authoring types' would trip on the [skip] reason itself.
There was a problem hiding this comment.
Fixed at ccf0bd6: the assertion looks for the current heading (/Checking \d+ doc\(s\) against the authoring types/), so it can fail.
| records(report.unchecked, {fields: ['doc', 'reason']}), | ||
| ); | ||
| } | ||
| if (report.findings.length === 0 && !failed && report.docs > 0) { |
There was a problem hiding this comment.
Optional: when validate also reports an error-severity issue and every doc matches, the section ends at its heading with no outcome line, although the JSON shows the docs were checked with no findings. Saying so here too, or leaving out the heading in that state, would avoid an empty section.
There was a problem hiding this comment.
Fixed at ccf0bd6: when another check fails and every doc matches, the section says [info] No doc field differs from its authoring type (N checked). clients/cli/commands/doctor-integration.test.mjs › "validate says the docs matched even when another check failed" pins it.
1a3f69c to
ccf0bd6
Compare
There was a problem hiding this comment.
This PR is on hold for a maintainer decision. The doc type check it adds to astryx doctor integration validate and validateIntegration(), with the new data.docTypes field and the Core known-drift test, has no current spec: AST-039 is still a draft on main, and the FR13 it implements exists only in draft spec PR #7658. Approval needs a maintainer to approve that requirement, or point to another current record that covers it, and to settle four points: the warnings-only severity; reporting findings in docTypes rather than in issues; which doc files the check covers (it skips docs in __fixtures__, dot-folders and symlinked files that component discovery still reads); and whether Core's own docs belong under the same check. Both earlier cleanups are in, and no other change is needed unless that decision changes the file set or leaves out the Core test.
[Automated review]
| const DOC_FILE = /\.doc\.(?:ts|mjs|js)$/; | ||
| const TEMPLATE_FILE = /\.(?:doc|template)\.(?:ts|mjs|js)$/; | ||
| const OVERLAY_FILE = /\.doc\.(?:zh|dense)\.mjs$/; | ||
| const SKIP_DIRS = new Set(['node_modules', '__tests__', '__fixtures__']); |
There was a problem hiding this comment.
For the scope decision on this check: this walk skips __fixtures__ and dot entries (here and at line 99) and takes only regular files (line 102). Integration component discovery skips only node_modules and __tests__, and it reads symlinked doc files. So a served doc in one of those places is neither checked nor listed under unchecked, and the [ok] Every doc matches… line can overstate coverage. If the check should cover every doc the CLI reads, as draft FR13 words it, matching the readers' walk or listing skipped docs as unchecked would close the gap.
There was a problem hiding this comment.
The PR body now sets this out under "Which docs the check covers (for the FR13 decision)": what each walk skips, what that leaves unchecked, and my view that the two sets should match (check exactly the doc files discovery returns). The scope is the owner's call, so this head leaves the walk as it is.
c058058 to
fcb28b1
Compare
ccf0bd6 to
adf1aae
Compare
There was a problem hiding this comment.
This PR is on hold for a maintainer decision: the doc type check it adds to astryx doctor integration validate and validateIntegration(), with the new data.docTypes field and the Core known-drift test, has no current spec, because AST-039 is still a draft on main and the FR13 it implements exists only in draft spec PR #7658. Approval needs a maintainer to approve that requirement, or point to another current record that covers it, and to settle four points: the warnings-only severity, reporting findings in docTypes rather than in issues, which doc files the check covers, and whether Core's own docs belong under the same check. On the file set, the integration readers also serve docs this walk skips without listing them as unchecked: component docs in __fixtures__, dot-folders and symlinked files, and templates under __tests__. No other change is needed unless that decision changes the file set or leaves out the Core test.
[Automated review]
| return out; | ||
| } | ||
| for (const entry of entries) { | ||
| if (entry.name.startsWith('.') || SKIP_DIRS.has(entry.name)) continue; |
There was a problem hiding this comment.
For the file-set decision, the template reader differs more than the PR body's comparison says: integration template discovery (findIntegrationDocFiles() in foundation/discovery/template-adapter.mjs) walks the templates root with no skip list, so a template under __tests__ (or node_modules) is served, while this walk skips it without listing it under unchecked. On a fixture, templates/__tests__/acme-tested.doc.mjs lacked displayName and aspectRatio, and validate reported nothing for it. Also, the hooks and utils skips the PR body attributes to component discovery belong to Core's reader; integration component discovery skips only node_modules and __tests__. Taking each root's files from its reader, as the PR body proposes, would cover both.
There was a problem hiding this comment.
Corrected in the body's section on which docs the check covers. Integration template discovery walks the templates root with no skip list. Integration component discovery skips only node_modules and __tests__. The hooks and utils skips are Core's reader only. The view is unchanged: take each root's files from the reader that serves them. That decision waits on the spec owner.
There was a problem hiding this comment.
Done in 67852a2. The check now takes each root's files from the reader that serves them: component, template and docs discovery, each topic's overlays that a docs read applies, and theme descriptors as theme discovery resolves them. A themes root the reader cannot read is listed under unchecked. Tests cover a __fixtures__ doc, a dot-folder doc and a symlinked doc, through the file set and through validate's JSON.
adf1aae to
dcbfdf0
Compare
There was a problem hiding this comment.
This PR is on hold for a maintainer decision: the doc type check it adds to astryx doctor integration validate and validateIntegration(), with the new data.docTypes field and the Core known-drift test, has no current spec, because AST-039 is still a draft on main and the FR13 it implements exists only in draft spec PR #7658. Approval needs a maintainer to approve that requirement, or point to another current record that covers it, and to settle four points: the warnings-only severity, reporting findings in docTypes rather than in issues, which doc files the check covers, and whether Core's own docs belong under the same check. On the file set, the CLI's readers still serve docs this walk skips without listing them as unchecked (component and docs-topic files in __fixtures__, dot-folders or symlinks, and templates under __tests__), so a package can get [ok] Every doc matches its authoring type while those docs drift: if FR13 is approved as worded, take each root's files from its reader or list the skipped docs under unchecked, and if the current set is kept, say in the docs which docs the check leaves out. Nothing else needs to change.
[Automated review]
bd4443b to
257cec7
Compare
dcbfdf0 to
67852a2
Compare
1ede507 to
054ece7
Compare
There was a problem hiding this comment.
This PR is on hold for a maintainer decision: the doc type check it adds to astryx doctor integration validate and validateIntegration(), with the new data.docTypes field and the Core known-drift test, has no current spec, because the AST-039 FR13 it implements exists only in draft spec PR #7658 and AST-039 is still a draft on main. Approval needs a maintainer to approve that requirement, or point to another current record that covers it, and to settle the warnings-only severity, reporting findings in docTypes rather than in issues, the reader-based file set (the draft FR13 wording covers every descriptor a root holds), and whether Core's own docs belong under the same check. The unreadable-root fix works: an unreadable root, or an unreadable folder or doc file inside components, templates or docs, now gets the same unreadable_root and invalid_* issues as before, so no code change is needed unless that decision changes the file set or leaves out the Core test.
[Automated review]
257cec7 to
9e9f123
Compare
054ece7 to
0ee26db
Compare
There was a problem hiding this comment.
The doc type check now has current authority in architecture:cli-surface INV34, and the change matches it: warnings only, unchanged exit codes, a visible skip without TypeScript, and an additive data.docTypes field, each covered by the PR's tests. Approval waits on one maintainer ruling: whether INV34's "each descriptor an integration's roots hold" includes component docs that component discovery does not serve (a hidden: true doc, a second doc for one name, a doc under __tests__), which this PR neither checks nor lists under unchecked, so validate can print [ok] Every doc matches its authoring type while one of them is wrong. If INV34 covers them, please check them; if it means reader-served docs only, please narrow the new guide sentence that says validate reads "every doc your package ships", and the PR is otherwise ready once #7664 lands.
[Automated review]
| await take(components, 'components', async () => [ | ||
| [ | ||
| 'components', | ||
| discoverIntegrationComponents(integration).map(c => c.docPath), |
There was a problem hiding this comment.
This takes only the docs discoverIntegrationComponents() serves, so a hidden: true doc, a second doc for a name an earlier doc takes, and a doc under __tests__ are neither checked nor listed under unchecked; a package with a type error in each still gets [ok] Every doc matches its authoring type. INV34 says "each descriptor an integration's roots hold", and whether that covers these docs is waiting on a maintainer ruling. If it does, forEachIntegrationDoc() already visits hidden and shadowed docs (but not __tests__), so the components root could take its files from there; if it does not, this line can stay.
There was a problem hiding this comment.
Fixed in 87fdabd. Every descriptor the package ships under its roots is checked now, served or not: a hidden: true doc, a second doc for a name an earlier doc takes, a template doc without its source, and an overlay without its topic. A test fixture doesn't ship as a doc: a doc under __tests__ in the components or docs root, which those readers skip. It isn't checked, and validate says how many once: [info] N test fixture doc(s) not checked., and docTypes.fixtures in JSON. The template reader reads __tests__ and __fixtures__, so a template doc there is checked like any other. The new tests cover each kind, and the command test shows a package with a type error in a hidden doc and in a second doc for one name, now reported, with no [ok]. Both failed before.
| content: [ | ||
| { | ||
| type: 'prose', | ||
| text: "`doctor integration validate` reads every doc your package ships against the type `@astryxdesign/cli/authoring` publishes for its kind, the way `tsc` would. It reports a field the type does not have (`unknown_field`), a missing required field (`missing_field`), and a value outside the field's type (`wrong_type`).", |
There was a problem hiding this comment.
If the ruling is that INV34 means reader-served docs only, this sentence overstates the coverage: a hidden: true component doc ships with the package but is not checked. The CommandDoc's wording fits: "each doc the CLI's readers take from the package".
There was a problem hiding this comment.
With every shipped doc now checked, the sentence holds. It now also says that a hidden doc and a second doc for one name are checked, and that test fixtures under __tests__ in the components or docs root are counted, not checked.
9e9f123 to
a623c61
Compare
0ee26db to
87fdabd
Compare
There was a problem hiding this comment.
The doc type check matches architecture:cli-surface INV34, including the wider file set (every shipped doc, with __tests__ fixtures counted), but four small fixes are needed before approval:
- Document
docTypes.fixturesin thevalidateIntegrationFunctionDoc and in theintegration.validateresponse-types entry (regenerating the README row), asAST-017FR13 requires for every response field. - Bring the CommandDoc, the FunctionDoc and the changeset in line with the guide, since they still say only the docs the CLI's readers take are checked.
- Make
isFixture()test the path relative to its root, because today a package anywhere under a__tests__folder has its hidden or shadowed docs counted as fixtures and still prints[ok]. - Keep the fixture count in the text when no other doc exists, which now prints only
[info] No doc files to type-check.while the JSON reportsfixtures.
[Automated review]
| return ( | ||
| root !== 'templates' && | ||
| root !== 'themes' && | ||
| file.split(path.sep).includes('__tests__') |
There was a problem hiding this comment.
This splits the absolute path, so a package that sits anywhere under a folder named __tests__ has every unserved doc in its components or docs root counted as a fixture instead of checked. A hidden: true doc with an unknown field in such a package gives [info] 1 test fixture doc(s) not checked. and then [ok] Every doc matches its authoring type (1 checked). Testing the path relative to the root that holds it keeps the intent:
function isFixture(file, owner) {
return (
owner.root !== 'templates' &&
owner.root !== 'themes' &&
path.relative(owner.dir, file).split(path.sep).includes('__tests__')
);
}with the call site passing owner, plus a test whose package lives under a __tests__ folder.
There was a problem hiding this comment.
Fixed in 15254b0. isFixture() now reads the path relative to its root, so a package that sits under a folder named __tests__ has its hidden and second docs checked, not counted. The new test puts a package under __tests__/ with a hidden doc, now checked, and a real fixture, still counted. It failed before.
| report.findings.length === 0 && | ||
| report.unchecked.length === 0 | ||
| ) { | ||
| return [text('[info] No doc files to type-check.')]; |
There was a problem hiding this comment.
When a package's only doc files are __tests__ fixtures, the JSON carries docs: 0 and fixtures: 1, but this early return prints only [info] No doc files to type-check., so the text loses fixtures. Adding !report.fixtures to the condition above, or printing the fixture line here as well, keeps the two views aligned.
There was a problem hiding this comment.
Fixed in 15254b0. With fixtures as the only docs, the text prints [info] No doc files to type-check. and then [info] N test fixture doc(s) not checked., matching docTypes.fixtures in the JSON. The new command test covers it and failed before.
| type: 'integration.validate', | ||
| description: | ||
| 'The result envelope: `data.validated`, false when nothing was validated — with no `package.json` at all, `data.issues` carries one `no_package` error-severity issue so the command exits 1; with a `package.json` but no integration manifest, `data.issues` is empty, which means "not looked at", not "healthy"; `data.name` and `data.version` of the validated package (both null when `data.validated` is false; `data.name` is `(local package)` when the local package.json has no readable name), plus `data.issues`, an AstryxIntegrationIssue[] of {code, severity: `warning` | `error`, message}.', | ||
| 'The result envelope: `data.validated`, false when nothing was validated — with no `package.json` at all, `data.issues` carries one `no_package` error-severity issue so the command exits 1; with a `package.json` but no integration manifest, `data.issues` is empty, which means "not looked at", not "healthy"; `data.name` and `data.version` of the validated package (both null when `data.validated` is false; `data.name` is `(local package)` when the local package.json has no readable name), plus `data.issues`, an AstryxIntegrationIssue[] of {code, severity: `warning` | `error`, message}. When the manifest loads, `data.docTypes` holds the doc type check: `status` (`checked` | `skipped`), `reason` when skipped, `typescript`, `docs` (doc values checked), `findings` ({doc, line, export, type, field, problem: `unknown_field` | `missing_field` | `wrong_type`, severity: `warning`, message, fix}) and `unchecked` ({doc, reason}: a doc a reader takes that could not be checked, or a root its reader cannot read).', |
There was a problem hiding this comment.
data.docTypes.fixtures is missing here, and from the integration.validate entry in foundation/response/response-types.doc.mjs that generates the README row; AST-017 FR13 asks for every response field in the consumer docs. Since the check now covers docs no reader serves, unchecked can also hold a doc no reader takes (a second doc for one name that does not parse, say), so “a doc a reader takes” is narrower than the code.
There was a problem hiding this comment.
Done in 15254b0. data.docTypes.fixtures is documented in the FunctionDoc's returns and in the integration.validate response type, and the README row is regenerated. unchecked now reads "a doc that could not be fully checked, or a root its reader cannot read", with no reader wording.
| 'installed package resolved by name. It schema-checks the manifest, verifies ' + | ||
| 'every declared contribution root, and reports every finding. Safe as a CI gate.', | ||
| 'every declared contribution root, and reports every finding. Safe as a CI gate. ' + | ||
| "It then checks each doc the CLI's readers take from the package against the " + |
There was a problem hiding this comment.
The check now also covers docs no reader serves (a hidden doc, a second doc for one name, a template doc without its source, an overlay without its topic) and counts __tests__ fixtures, so “each doc the CLI's readers take” understates it. The FunctionDoc (validateIntegration.doc.mjs line 27) and the changeset say the same; the wording of the new guide section in check-your-docs.doc.mjs fits all three.
There was a problem hiding this comment.
Done in 15254b0. The CommandDoc, the FunctionDoc and the changeset now say that every doc the package ships under its roots is checked, served or not, and that test fixtures under __tests__ in the components or docs root are counted, not checked, as the guide does.
87fdabd to
15254b0
Compare
There was a problem hiding this comment.
Recommended for approval: the doc type check matches architecture:cli-surface INV34, and the four fixes from the last review (documenting docTypes.fixtures, aligning the command docs, API docs and changeset with the guide, judging __tests__ fixtures by their path inside the root, and keeping the fixture count in the text) are in and work as described. It still has to wait for #7664 to land, and it should ship no later than the release that first ships integration check. One optional cleanup: the hidden-doc command test writes hidden: true on the export default line, which component discovery does not treat as hidden, so moving it onto its own line would make that test cover an unserved hidden doc.
[Automated review]
| [ | ||
| 'components/AcmeHidden.doc.mjs', | ||
| 'AcmeHidden', | ||
| ', hidden: true, keyword: []', |
There was a problem hiding this comment.
Optional: component discovery reads hidden with a line-anchored text match (HIDDEN_RE in foundation/discovery/component-discovery.mjs), so this inline hidden: true is not seen and discovery still serves AcmeHidden; the hidden half of this test would pass even if only reader-served docs were checked. Putting hidden: true on its own line, as integration-doc-files.test.mjs does, makes it an unserved hidden doc:
export default {
type: 'component',
name: 'AcmeHidden',
hidden: true,
// …
};a623c61 to
2d52ec0
Compare
15254b0 to
def4748
Compare
…blished authoring type `astryx doctor integration validate` now finds every doc an integration ships (components, templates, docs topics, themes, and their translations) and checks each against the type `@astryxdesign/cli/authoring` publishes for its kind, with the project's own TypeScript, the way `tsc` checks a value written with that type. Each unknown field, missing required field, or value outside its field's type is a warning naming the doc, line, field, and a fix. The exit code is unchanged; JSON adds `data.docTypes`, present when the manifest loads. Without TypeScript it prints one `[skip]` line. A repository test checks Core's own docs with a shrink-only list of the current mismatches, all in translations.
…ocs matched after a failed check A test compares validate's JSON docTypes with its text for each problem kind and each doc not checked. When another check fails and every doc matches, the section now says so in an [info] line instead of ending at its heading. The no-TypeScript test looks for the current section heading, so it can fail. The changeset names the version of a TypeScript the check cannot use, and the no-docs line.
…tegration templates declare IntegrationTemplateDoc The doc type check takes each root's files from the reader that serves them: the doc component discovery records for each component (so a doc in `__fixtures__`, in a dot-folder, or behind a symlinked file is checked, while a `hidden` doc or a second doc for one name is not), the doc of each template template discovery serves (a template under `__tests__` too), the file of each topic, namespace and placed guide docs discovery serves (where it is, in a scoped package too) with each topic's and guide's `zh` and `dense` overlay, and each theme's descriptor as theme discovery resolves it. A root that `validate` already reports (missing, a file, or one it cannot read) is left to that issue, and a root whose reader fails inside it is listed under `unchecked` with the error, so nothing a reader serves is skipped silently. `integration add template` and the template guides' samples declare `IntegrationTemplateDoc`, the type the check holds integration templates to.
The "Check your docs" guide gains a section on the doc-type check: what it reports (`unknown_field`, `missing_field`, `wrong_type`), sample output, which type each root's docs are read against, where the findings are in JSON, and what it prints without TypeScript.
…fixtures
The doc type check read only the docs each root's reader serves, so a
`hidden` doc, a second doc for one name, a template doc without its
source and an overlay without its topic were never checked, yet an agent
can still open them. Now every doc file a root holds is checked, with
the kind its root reads. A test fixture, a doc under `__tests__` in the
components or docs root (which those readers skip), does not ship as a
doc: it is not checked, and validate says how many once
("N test fixture doc(s) not checked"), as `docTypes.fixtures` in JSON. The
template reader reads `__tests__` and `__fixtures__`, so a template doc
there is checked like any other.
`[ok] Every doc matches its authoring type` still prints only when
nothing was left unchecked, and with only fixtures the text still counts
them. A fixture is judged by its path inside its root. The "Check your
docs" guide, the validate command and API docs, the response types (with
the README row) and the changeset say so.
def4748 to
b75fc8c
Compare
User need
#7664 adds a check that reads each doc against the type
@astryxdesign/cli/authoringpublishes for its kind, the waytscwould. Nothing runs it yet, so an integration still learns about an unknown field, a missingdisplayName, or a malformed usage entry only when someone runstscon its docs, if ever.Problem and solution fit
astryx doctor integration validatenow finds every doc an integration's roots hold (components, templates, docs topics and their overlays, themes, each file given to the deepest root that holds it) and runs #7664's check on them. Each finding is a warning naming the doc, the line, the field path, the problem (unknown_field,missing_fieldorwrong_type), TypeScript's message, and a fix. Without TypeScript it prints one line saying the docs weren't type-checked.Core gets the same check as a repository test,
packages/cli/test/core-doc-types.test.mjs. Core's component, hook, template, theme and topic docs all pass; the 307 mismatches it has today are all in translations, listed incore-doc-types.known-drift.json, a list that only shrinks.Current specification
Implements
architecture:cli-surfaceINV34, "Every descriptor satisfies its published authoring type" (AST-039 FR13, which now points to it; DEC-5), with #7664. Its evidence row names the doc-types, doctor-integration and core-doc-types tests, which this PR's tests satisfy.Public delta and caller burden
astryx doctor integration validate: after its summary, a "Checking N doc(s) against the authoring types (TypeScript x.y)" section with the findings, each with every field it carries (doc, line, export, type, field, problem, message, fix), then[ok] Every doc matches its authoring type (N checked).(or, after another check failed,[info] No doc field differs from its authoring type (N checked).); or one[skip] Docs not type-checked: …line; or, with no doc files,[info] No doc files to type-check.Exit codes are unchanged: findings are warnings.data.docTypes={status: 'checked' | 'skipped', reason?, typescript?, docs, findings[], unchecked[]}. Each finding is{doc, line, export, type, field, problem, severity: 'warning', message, fix}.Example: an Acme component doc with
keyword:and a block template withoutdisplayNameoraspectRatio. Both load today, andvalidatereports no issues:(The same template's
displayNamefinding follows; the command still exits 0.)Design and alternatives
api/docs/_adapter.mjs(cli-surface INV21).validate-integration.mjsonly attaches the report. Finding the files is its own module,foundation/discovery/integration-doc-files.mjs.astryx integration check --strict(feat(cli): integration check runs every source check for a package's build, with --strict #7665).Evidence
foundation/discovery/integration-doc-files.test.mjs(each root's docs and overlays, a nested root's files given to that root, skipped folders),doctor-integration.test.mjs(text with each finding's export and type and the docs count, JSON, the skip line, the line for a package with no doc files, and a test that compares the JSON with the text field by field for each problem kind and each doc not checked, viatest-utils/text-projection.mjs), and the Core ratchet test above.Since the first automated review
exportandtype, and the section header says how many docs were checked, so every JSON field shows in the text.[info] No doc files to type-check., not an empty section or a request to install TypeScript.validatewarns about a template withoutdisplayNameoraspectRatiolands here, where it becomes true.docTypeswith its text, field by field, so every field stays in the text view. The no-TypeScript test looks for the current section heading, so it can fail.[info] No doc field differs from its authoring type (N checked).now, without an[ok]after the failure.IntegrationTemplateDoc, so the example's template findings name it. Its section inastryx docs authoringsaysvalidatechecks them against it. The Core test holds Core's own templates toTemplateDoc, which is unchanged.After the latest review
__fixtures__, in dot-folders or behind symlinks, and templates under__tests__. A package could get[ok]while those docs drifted. The check now takes each root's files from what the reader serves, as described above, and nothing else: an audit found a second component doc of one name checked thoughastryx componentserves the first, which no longer happens. A themes root the reader cannot read is listed underunchecked, so nothing is skipped silently. Tests cover a__fixtures__doc, a dot-folder doc and a symlinked doc, from the file set throughvalidate's JSON, and a hidden doc, a second doc of one name, a template without its source and an overlay without its topic, none of them checked.integration add templatewrites a template doc that declaresIntegrationTemplateDoc, and the page, block and replace-a-Core-template guides' samples do too.docs/widgets/…for@acme/widgets), so they weren't checked, anduncheckedlisted files that don't exist. Their paths come from the reader now: a guide'sref.topicFile, and a namespace'ssourcewithout its package name. A placed guide'szhanddenseoverlays, whichastryx docs <route> --zhapplies, are checked too. Tests cover a scoped package's namespace doc, placed guide and guide overlays.Which docs the check covers
Every doc the package ships under its roots. Each root's reader names the docs it serves, with the kind it reads each as:
__fixtures__, in a dot-folder or behind a symlinked file is checked;__tests__is checked too;zhanddenseoverlay that a docs read applies;uncheckedwith the reason.A doc no reader serves still ships, and an agent can still open it, so it is checked with its root's kind: a
hiddendoc, a second doc for one name, a template doc without its source, an overlay without its topic. A test fixture doesn't ship as a doc: a doc under__tests__in the components or docs root, which those readers skip. It isn't checked, andvalidatesays how many once ([info] N test fixture doc(s) not checked.,docTypes.fixturesin JSON). The template reader reads__tests__and__fixtures__, so a template doc there is checked like any other, asvalidate's own template check sees it. A doc that doesn't load is also reported by its reader's own check invalidate. One doc is checked that no route serves: a placed guide whose parent namespace doesn't exist.doctor integration docsreports it as an error, and its fields are checked so that the fix needs no second pass.After the review that came next
validatecouldn't read, or a folder inside one, madevalidatestop with a rawEACCES(ERR_UNKNOWNin JSON) instead of main'sunreadable_rootorinvalid_*issue. A rootvalidatealready reports is now left to that issue. Each reader runs in its own guard, so one that fails inside a root lists the root underuncheckedwith the error.validate, whose issue codes match main's. CLI runs give main's exact issue codes for an unreadable components, docs, templates or themes root, and for an unreadable folder inside components, docs or templates.Authoring docs
unknown_field,missing_field,wrong_type), real output, which type each root's docs are read against, where the findings are in JSON, and what it prints without TypeScript.Rebased
After the review of INV34's coverage
hiddendoc, a second doc for a name and a doc under__tests__were neither checked nor listed, and a package with a type error in each still got[ok]. INV34's "each descriptor an integration's roots hold" means every descriptor the package ships. The check now covers every doc file each readable root holds, as described above, and counts the test fixtures it leaves out: the docs under__tests__that the components and docs readers skip.[ok] Every doc matches its authoring typeprints only when nothing was left unchecked.[ok]isn't printed. Both failed before.type.After the review of the fixture count
__tests__had its hidden and second docs counted as fixtures, unchecked, and could print[ok].[info] No doc files to type-check., as the JSON does.docTypes.fixturesis documented invalidateIntegration's docs and in theintegration.validateresponse type, with the README row regenerated. The command docs, the API docs and the changeset now say that every shipped doc is checked and fixtures are counted, as the guide does.Merge order
The order is required:
doctor integration components, stacked on feat(cli): compare documented component props with the TypeScript source #7663), then feat(cli): read two written TypeScript types as one when they differ only in how they are written #7684 (reading two written types as one, stacked on feat(cli): doctor integration components compares documented props with the code #7676), then feat(cli): doctor integration components judges documented prop types against the code #7667 (prop types, stacked on feat(cli): read two written TypeScript types as one when they differ only in how they are written #7684).validate, stacked on feat(cli): check each authored doc against its published authoring type #7664).integration check) last, after a rebase that adds these PRs' fields and codes to its failures list. Merged earlier, it breaks main.This PR must ship in the same release as
integration check. If it slips past that release, it can ship only in a minor, because its findings failintegration check --strict.Overlap with open PRs
test-utils/text-projection.mjs, and the line that imports it indoctor-integration.test.mjs, are byte-identical in feat(cli): doctor integration components compares documented props with the code #7676, so the two merge cleanly in either order.astryx componentprints #7623, fix(cli): init writes agent docs every agent reads, at the project root, never in the home folder #7497, spec(AST-039, cli-surface): integration docs are found by their documented names and checked in one command #7658, feat(cli): a component doc can name a differently named export of the file beside it #7659, fix(cli): integration verify reads exports with the reader discovery uses #7660, feat(docsite): put the integration guide's pages under CLI Integrations in the sidebar #7661, feat(cli): integration family members are components under their own names #7674, or the other PRs in this set.Size
1,623 changed lines. 309 of them are
packages/cli/test/core-doc-types.known-drift.json, a data file the Core test reads, one line per mismatch Core's translations have today. Authored lines: 1,063.Scope
Testing
The CI test jobs run only for pull requests into main, so this PR's tests run in CI once it is retargeted after #7664 merges. On main 91cfb53 with #7664 and this branch: copyright, sync-exports, the published
./apitype check,readme:check, the four CLI typechecks (strict, json-api, authoring-contract, template-docs),check:changesets,check:cli-structure,check:repo, eslint on the changed files, prettier on the new files, and the fullpnpm vitest run --project nodesuite: 10,318 tests pass. The 21 failures are in the npm pack, packed real-world package, theme resolution and CSS graph tests, which fail the same way on current main on the same machine (they need a package registry it doesn't reach), plus one browser accessibility test that is flaky there. With all nine PRs merged into main, the fourdoctor integrationsubcommands were run in text and JSON on 64 package shapes, against main: templates output is byte-identical everywhere;validateandcomponentsonly add their new section and JSON field;docsdiffers only where the doc-links PR fixes a link warning.integration checkexits 1 exactly when one of the four would, each of its sections is byte-identical to that subcommand's output, and onlyintegration check's three list tests fail until its planned rebase.