Skip to content

fix(cli): doc links to a component, page, or block resolve - #7668

Merged
josephfarina merged 1 commit into
mainfrom
josephfarina/doc-links-components-templates
Oct 19, 2026
Merged

josephfarina merged 1 commit into
mainfrom
josephfarina/doc-links-components-templates

Conversation

@josephfarina

@josephfarina josephfarina commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

User impact

Integration authors can link a component or a template from a guide: {@link component:AcmeButton}, {@link block:acme-card}, or another provider's, such as {@link @astryxdesign/core:component:Button}. The CLI accepts component, page and block as link kinds, but today every such link fails:

  • astryx doctor integration docs warns that the link "names no doc". It does this for the package's own components and templates, and for Core's.
  • astryx docs <topic> prints the raw {@link …} syntax.
  • The warning's hint, astryx search <name> --type doc, can't find a component or a template.

After this change, each link reads as the command that opens its target, and the check stops warning:

  • astryx component AcmeButton --package @acme/widgets
  • astryx template acme-card --type block --package @acme/widgets
  • astryx component Button for a Core component

Problem and solution fit

  1. Why links fail: a link resolves only among the docs tree (CLI docs, namespace docs, placed guides), CLI authoring docs and flat topics. Component, page and block docs are never in that set.
  2. Why it harms authors: an author can't link a component from a guide without a false warning, and readers get raw link syntax instead of a command.
  3. Why it matters: the false warning shows up for every package that links a component. astryx integration check --strict (feat(cli): integration check runs every source check for a package's build, with --strict #7665) would turn it into a build failure. The links guide even tells authors not to write these links.

The fix: links of these three kinds now find their target among the component and template records that astryx component and astryx template read.

  • In an app, the records are the project's own: Core plus the configured integrations.
  • In doctor integration docs, the records are Core's plus the package's own.

Expected behavior and authority

  • foundation/doc-compiler/links.mjs lists component, page and block among LINK_KINDS.
  • The published authoring reference says a {@link [<provider>:]<kind>:<name>} "prints the command that opens it", and that Doctor warns only on a link that names no doc.
  • architecture:cli-surface INV27 (current): "A link between docs names its target by doc identity and is resolved on every read; Doctor warns on one that names no doc." AST-047 FR9 (draft) adds that a link reads as the command that opens its doc.

Smallest restoration

  • api/docs/_adapter.mjs:
    • links of the three kinds resolve through the component and template records;
    • doctor integration docs reads Core's records and the package's own;
    • the "names no doc" hint searches --type component or --type template.
  • foundation/discovery/docs-discovery.mjs: the docs catalog carries those records, loaded on first use.
  • foundation/config/project.mjs: an app's catalog gets the project's records.
  • foundation/doc-compiler/links.mjs: a resolved link's route may be null, because no docs route opens a component.
  • assets/docs/tree/links.doc.mjs: the links guide names the three kinds and drops "A link to a component or a template does not resolve".

No command, option, export or JSON field changes.

Evidence

  • Before, on main: an Acme package's guide links its own AcmeButton, its acme-card block, and Core's Button. astryx doctor integration docs warns three times:

    severity: [warn]
    code:     invalid_doc_graph
    message:  using-widgets § overview: "component:AcmeButton" names no doc. Find it with `astryx search AcmeButton --type doc`, then name it as `[<provider>:]<kind>:<name>`.
    

    In an app that configures the package, astryx docs using-widgets prints Start with {@link component:AcmeButton} or {@link block:acme-card}, built on {@link @astryxdesign/core:component:Button}.

  • After, on the same package:

    • doctor integration docs reports [ok] The docs tree and every link in these docs check out.
    • The app reads Start with `astryx component AcmeButton --package @acme/widgets` or `astryx template acme-card --type block --package @acme/widgets`, built on `astryx component Button`.
  • Unchanged paths:

    • Links to topics, guides, commands and functions resolve as before.
    • A link that names nothing still warns. The hint searches --type component or --type template for those kinds.
  • Regression tests: doctor-integration.test.mjs (own and Core component, block, Core page, and one link that names nothing) and api/docs/integrationDocs.test.mjs (a read in an app; and Core links in an app where an integration replaces Button and ships a page with a Core page's id, which select Core, beside a plain Core component and block, which stay short). Both fail on main.

  • The commands are real: in that app, astryx component Button opens the replacement and --package @astryxdesign/core opens Core's; the bare page id is ERR_AMBIGUOUS_TEMPLATE, and --package @astryxdesign/core opens Core's.

Since the first automated review

  • The typedefs sit above the docs catalog's class comment, so the class keeps its JSDoc.
  • A link to Core's own component or template adds --package @astryxdesign/core only where the bare name would open something else. That happens when an integration replaces it, or when another package ships a component, or a template of its kind, with the same name. Plain Core links stay short (astryx component Badge). An app's reads use its own active replacements and records. doctor integration docs, which checks one package alone, treats the package's declared replaces as taking the name.

Merge order

This PR stands alone on main. Merge it before #7665 (integration check), or in the same release: until it lands, integration check --strict fails every package that links its own components. It adds no finding, so it can also ship later as a patch. The rest of the set: #7663 and #7667 (prop names, required flags and types) and #7664 (doc types).

Overlap with open PRs

Scope

  • One defect is restored.
  • Separable contradictory or unsettled tagalongs were removed or split.
  • No new public API, visual representation, default, or interaction model is hidden under the bug-fix label.
  • Public text and artifacts contain no internal Meta context.

Testing

On main fbc03f7 with this branch: copyright, sync-exports, the published ./api type 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 full pnpm vitest run --project node suite: 10,222 tests pass. The 21 failures are in the npm pack, packed real-world package, theme resolution and CSS graph tests, plus one browser accessibility test that is flaky there, which fail the same way on current main on the same machine (they need a package registry it doesn't reach).

@vercel

vercel Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
astryx Ready Ready Preview Oct 17, 2026 10:00pm UTC

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 17, 2026
@astracat-bot

astracat-bot Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

AI review status for this pull request.

Review status Updated
🟢 Reviewed (for maintainers only) Oct 17, 2026, 10:27 PM UTC

@github-actions

github-actions Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR

🧪 Sandbox Preview

View Sandbox for this PR

No new or modified components detected.

Bundle Size Summary

No component packages changed.

Accessibility Audit

Status: No accessibility violations detected.

Visual Regression

40 of 478 shot(s) changed.

A change here is a question, not a failure: check whether the after is the
picture you intended. Record that review on the PR. Baseline maintenance is an
explicit dispatch of CI; this report never rewrites the baseline or adds a release gate.

component story theme mode pixels
Selector Indicator Space Bottom Sheet Narrow End RTL neutral light 754,077
Selector Indicator Space Bottom Sheet Wide Start neutral light 740,188
Chat Full AI Chat probe light 230,823
Chat Full AI Chat probe dark 229,805
RichTextEditor Markdown parity: side by side probe dark 94,866
RichTextEditor Markdown parity: side by side probe light 89,762
Collapsible Dividers probe dark 66,445
Collapsible Dividers probe light 66,445
Chat Default neutral dark 36,304
Chat Default neutral light 35,767
Chat Empty State probe light 23,531
Chat Empty State probe dark 22,622
ChatAutoScroll Scroll Behavior Comparison neutral dark 15,378
ChatAutoScroll Scroll Behavior Comparison neutral light 14,107
Chat With Attachments probe light 13,406
Chat With Attachments probe dark 11,232
ProgressBar With Target Mark probe dark 7,895
ProgressBar With Target Mark probe light 7,895
Markdown Default neutral dark 7,573
Markdown Default neutral light 7,566

and 20 more.


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This restores the doc-link behavior the CLI surface spec already requires, and the new tests show it, but one case needs a fix before approval. A link to a Core component reads as astryx component <Name> with no --package, so in an app where an integration replaces that component the command opens the replacement, and where another package ships a component of the same name it fails with ERR_AMBIGUOUS_COMPONENT. Please add --package @astryxdesign/core whenever the bare name would not open Core's component (or always), consider the same rule for Core template links, and add a regression test for both cases.

[Automated review]

Comment thread packages/cli/api/docs/_adapter.mjs Outdated
route: null,
title: entry?.displayName ?? name,
summary: entry?.description ?? doc?.description ?? '',
command: `astryx component ${name}${record.package === CORE_PACKAGE ? '' : ` --package ${record.package}`}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A Core component link drops --package here, so {@link @astryxdesign/core:component:SideNav} reads as astryx component SideNav. In an app where an opted-in integration replaces SideNav, that command opens the replacement (AST-035 FR11), and where another package ships a component with the same name it fails with ERR_AMBIGUOUS_COMPONENT. Emit --package @astryxdesign/core unless the bare name opens this record (or always), and add a regression test for both cases; the template branch below builds Core commands the same way.

A doc link to a component, page, or block (`{@link component:AcmeButton}`,
`{@link @astryxdesign/core:component:Button}`, `{@link block:acme-card}`)
is a link kind the CLI accepts, yet it always warned that it named no doc,
for every provider, because the docs tree holds no component or template
docs. Links now find them among the component and template records
`astryx component` and `astryx template` read, in an app and in
`doctor integration docs` for one package, and read as that command:
`astryx component AcmeButton --package @acme/widgets`. A link to Core's
own component or template adds `--package @astryxdesign/core` only where
the bare name would open something else: a replacement, or another
package's component or template with the same name. A link that names no
doc still says so, and its hint searches the right type. The links
guide no longer tells authors to avoid these links.

@astracat-bot astracat-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This restores doc links to components, pages, and blocks as the CLI surface spec requires, and the earlier --package concern is fixed: Core links now open Core's component or template even under a replacement or a same-name component, with regression tests, and I found nothing that blocks approval. One narrow case you may want to close here or in a follow-up: in an app, a link to an integration's own template whose id is also a Core template id, and which another package's replacement hides from default discovery, still prints as written and draws a "names no doc" warning, because Project builds integration template records from the default view rather than the package-scoped view that --package reads.

[Automated review]

...(await discoverCoreTemplates())
.filter(isPageOrBlock)
.map(template => linkable(template, CORE_PACKAGE)),
.../** @type {any[]} */ (await this.templates())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: these records come from this.templates(), the default view, which drops an integration template whose id is also a Core id when another package's replacement takes that id (or its own same-id replacement loses precedence). A link to it from that package's docs, such as {@link page:ai-chat}, then prints as written and astryx doctor warns that it names no doc, although astryx template ai-chat --type page --package <pkg> still opens it (AST-035 FR3). Building these records from the package-scoped view that --package reads (as packageContributions does), and taking replaces only from the active replacements, would close it.

@josephfarina
josephfarina merged commit 2b221e0 into main Oct 19, 2026
50 checks passed
josephfarina added a commit that referenced this pull request Oct 19, 2026
…ion-guides-cleanup

links.doc.mjs takes #7668's component, page and block kinds beside this branch's schema and enum, and #7668's sentence on naming a component or template replaces "does not resolve". The check-your-docs header keeps this branch's route and adds #7673's "each doc's fields".
@github-actions
github-actions Bot deleted the josephfarina/doc-links-components-templates branch October 20, 2026 06:22

This branch was successfully deployed

1 active deployment
Preview — 74ee9af4 Deployed Oct 17, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant