Skip to content

fix(cockpit): point docsPath at docs pages that actually exist - #918

Merged
blove merged 1 commit into
mainfrom
blove/cockpit-docspath-wire
Sep 1, 2026
Merged

fix(cockpit): point docsPath at docs pages that actually exist#918
blove merged 1 commit into
mainfrom
blove/cockpit-docspath-wire

Conversation

@blove

@blove blove commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

The finding

Every cockpit capability declared docsPath in a five-segment shape — /docs/<product>/core-capabilities/<topic>/overview/<lang>. The website serves docs on a three-segment route, /docs/[library]/[section]/[slug]. Every one of those URLs 404s, for every product:

$ curl -o /dev/null -w '%{http_code}' https://threadplane.ai/docs/langgraph/core-capabilities/streaming/overview/python
404

Two things kept it invisible: the field was rendered nowhere, so no link ever visibly broke; and the only assertion was a regex over the shape the generator itself produced, never a check against a real route.

What this does

Maps it. libs/cockpit-registry/src/lib/docs-links.ts holds the cockpit → docs mapping as a table, not a formula. The two trees do not share a naming scheme — that mismatch is exactly what made a formula wrong. Cross-library links are expected (an AG-UI demo whose best page lives under chat links to chat).

Sentinel. Empty string (NO_COCKPIT_DOCS_LINK) means "no published page yet". Seven deep-agents entries carry it — the website has no deep-agents library. Those render no link rather than a bad one. The sentinel list is pinned in a test, so a rename cannot silently blank a real link.

Rewrites consumers. All 83 per-example descriptors (cockpit examples are standalone, so each carries its own literal) and the 9 generated deployments/ag-ui-dev/deps/* copies. Generator re-run; drift check clean and idempotent.

Renders it. A "Read docs" link in the cockpit capability header, on --ds-* tokens, target="_blank". Labelled "Read docs" rather than "Docs" so it does not collide with the existing Docs mode tab.

Guards it. apps/cockpit/src/lib/docs-links.spec.ts derives the set of valid docs routes two ways — the .mdx files on disk and the website's docsConfig nav — and requires every mapped path in both. It also checks every descriptor on disk agrees with the table, and that no five-segment path survives anywhere.

Makes the matrix specs run. cockpit/*/matrix.spec.ts had no test target at all — that is how the stale assertion survived. They now run under nx test cockpit. Doing so surfaced a second piece of the same rot: the LangGraph slice asserted codeAssetPaths.length === 1 while examples had grown to 2+.

Mapping

Lives in libs/cockpit-registry/src/lib/docs-links.ts, commented per non-obvious choice. 35 distinct targets; all 35 verified 200 on production threadplane.ai.

Judgement calls worth a look:

Capability Target Why
langgraph/durable-execution /docs/langgraph/guides/persistence Checkpointing is the durability mechanism; no separate page
langgraph/client-tools, ag-ui/client-tools /docs/chat/guides/client-tools The demo's visible half is the browser-declared tool
ag-ui/streaming /docs/ag-ui/reference/event-mapping AG-UI has no streaming guide; token streaming is specified here
render/computed-functions /docs/render/api/provide-render $computed resolves against the functions map registered there
render/repeat-loops /docs/render/guides/specs The "Repeat Loops" section; shares a page with spec-rendering
chat/timeline /docs/chat/components/chat-trace No chat-timeline page yet; the trace row is the primitive it renders
deep-agents/* (7) sentinel No deep-agents docs library exists

Verification

  • nx test cockpit33 files, 214 tests green (baseline 30/209; +6 guard, matrix specs newly running)
  • nx test cockpit-registry, nx test cockpit-shell green; nx lint 0 errors; nx build cockpit green
  • Deployment generator re-run, output byte-identical on a second run
  • Render check against a live cockpit server — one page per product:
langgraph/streaming  -> https://threadplane.ai/docs/langgraph/guides/streaming
ag-ui/a2ui           -> https://threadplane.ai/docs/a2ui/getting-started/introduction
chat/theming         -> https://threadplane.ai/docs/chat/guides/theming
render/registry      -> https://threadplane.ai/docs/render/guides/registry
runtimes/aws-strands -> https://threadplane.ai/docs/runtimes/aws-strands/overview
deep-agents/planning -> NO DOCS LINK   (sentinel, as intended)

Guard mutation evidence

Every guard was mutation-tested and restored:

Mutation Result
Table → /docs/langgraph/guides/streaming-renamed 2 tests fail, naming the bad path
A descriptor drifts from the table fails, naming file + declared value
A real link silently blanked to the sentinel 2 tests fail (sentinel list + descriptor drift)
resolveDocsUrl always returns null render test fails — "Unable to find link /read docs/i"
Sentinel renders a link anyway deep-agents test fails — expected <a> to be null

🤖 Generated with Claude Code

@vercel

vercel Bot commented Sep 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
threadplane Ready Ready Preview Sep 1, 2026 3:59am UTC

Request Review

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove enabled auto-merge (squash) September 1, 2026 03:53

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

Every cockpit capability declared `docsPath` in a five-segment shape,
`/docs/<product>/core-capabilities/<topic>/overview/<lang>`. The website
serves docs on a three-segment route, `/docs/<library>/<section>/<slug>`,
so every one of those URLs 404s — and has for as long as the field has
existed. Nothing caught it because the only assertion was a regex over
the shape the code itself generated, never a check against a real route,
and the field was never rendered anywhere, so no link ever visibly broke.

- `libs/cockpit-registry/src/lib/docs-links.ts` holds the cockpit -> docs
  mapping as a table, not a formula: the two trees do not share a naming
  scheme, which is what made a formula wrong in the first place. Empty
  string is the documented "no published page yet" sentinel, carried by
  the seven deep-agents entries (the website has no deep-agents library).
- All 83 per-example descriptors and the generated ag-ui-dev deps are
  rewritten from that table.
- `apps/cockpit/src/lib/docs-links.spec.ts` checks every mapped path
  against the website's real content tree and its real nav config, checks
  every descriptor agrees with the table, and pins the sentinel list, so
  a docs rename breaks a test instead of a link.
- The per-product matrix specs had no test target at all, which is how
  their assertion drifted; they now run under `nx test cockpit`.
- The header renders a "Read docs" link where the path resolves.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@blove
blove force-pushed the blove/cockpit-docspath-wire branch from fa6a4b7 to 1cc662a Compare September 1, 2026 03:55
@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @blove's task in 0s —— View job


I'll analyze this and get back to you.

@blove
blove merged commit bb2db99 into main Sep 1, 2026
23 checks passed
blove added a commit that referenced this pull request Sep 1, 2026
`cockpit/deep-agents/footprint.spec.ts` and
`libs/cockpit-docs/src/lib/docs-bundle.spec.ts` were executed by nothing: no
vitest project included the first, and `cockpit-docs` had no `test` target at
all. Both are wired in here, following #916 (give the orphan a target) and
#918 (glob out-of-project cockpit specs into `nx test cockpit`).

Wiring surfaced three further gaps, all fixed:

- `cockpit-docs` and `cockpit-registry` were both unreachable. `nx test` does
  not walk `^test`, and the `library` job runs a hardcoded LIBS list that
  excludes them, so cockpit-registry's three specs had never run either. The
  cockpit job now uses `nx run-many` over all three projects.
- The footprint specs resolved paths from `process.cwd()`, which under
  `nx test cockpit` is `apps/cockpit`. Left as-is they would have asserted
  against `apps/cockpit/cockpit/...` and passed vacuously. They now resolve
  from `import.meta.url`.
- `cockpit/<product>/*.spec.ts` sits outside every project root, so
  `nx affected` attributes it to the untagged `root` project and a PR touching
  only those specs skipped the job that runs them. ci-scope now maps them onto
  the cockpit scope by path.

The website `.mdx` assertions in all three footprint specs asserted the
five-segment docs shape #918 deleted — the one docs-links.ts records as having
"produced a URL that 404s for every product". They are removed, not weakened:
that coupling is a table checked against the website's real content tree by
apps/cockpit/src/lib/docs-links.spec.ts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
blove added a commit that referenced this pull request Sep 1, 2026
`cockpit/deep-agents/footprint.spec.ts` and
`libs/cockpit-docs/src/lib/docs-bundle.spec.ts` were executed by nothing: no
vitest project included the first, and `cockpit-docs` had no `test` target at
all. Both are wired in here, following #916 (give the orphan a target) and
#918 (glob out-of-project cockpit specs into `nx test cockpit`).

Wiring surfaced three further gaps, all fixed:

- `cockpit-docs` and `cockpit-registry` were both unreachable. `nx test` does
  not walk `^test`, and the `library` job runs a hardcoded LIBS list that
  excludes them, so cockpit-registry's three specs had never run either. The
  cockpit job now uses `nx run-many` over all three projects.
- The footprint specs resolved paths from `process.cwd()`, which under
  `nx test cockpit` is `apps/cockpit`. Left as-is they would have asserted
  against `apps/cockpit/cockpit/...` and passed vacuously. They now resolve
  from `import.meta.url`.
- `cockpit/<product>/*.spec.ts` sits outside every project root, so
  `nx affected` attributes it to the untagged `root` project and a PR touching
  only those specs skipped the job that runs them. ci-scope now maps them onto
  the cockpit scope by path.

The website `.mdx` assertions in all three footprint specs asserted the
five-segment docs shape #918 deleted — the one docs-links.ts records as having
"produced a URL that 404s for every product". They are removed, not weakened:
that coupling is a table checked against the website's real content tree by
apps/cockpit/src/lib/docs-links.spec.ts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
blove added a commit that referenced this pull request Sep 1, 2026
#936)

`cockpit/deep-agents/footprint.spec.ts` and
`libs/cockpit-docs/src/lib/docs-bundle.spec.ts` were executed by nothing: no
vitest project included the first, and `cockpit-docs` had no `test` target at
all. Both are wired in here, following #916 (give the orphan a target) and
#918 (glob out-of-project cockpit specs into `nx test cockpit`).

Wiring surfaced three further gaps, all fixed:

- `cockpit-docs` and `cockpit-registry` were both unreachable. `nx test` does
  not walk `^test`, and the `library` job runs a hardcoded LIBS list that
  excludes them, so cockpit-registry's three specs had never run either. The
  cockpit job now uses `nx run-many` over all three projects.
- The footprint specs resolved paths from `process.cwd()`, which under
  `nx test cockpit` is `apps/cockpit`. Left as-is they would have asserted
  against `apps/cockpit/cockpit/...` and passed vacuously. They now resolve
  from `import.meta.url`.
- `cockpit/<product>/*.spec.ts` sits outside every project root, so
  `nx affected` attributes it to the untagged `root` project and a PR touching
  only those specs skipped the job that runs them. ci-scope now maps them onto
  the cockpit scope by path.

The website `.mdx` assertions in all three footprint specs asserted the
five-segment docs shape #918 deleted — the one docs-links.ts records as having
"produced a URL that 404s for every product". They are removed, not weakened:
that coupling is a table checked against the website's real content tree by
apps/cockpit/src/lib/docs-links.spec.ts.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant