Skip to content

fix(docs): three redirect destinations point at pages that do not exist - #9015

Merged
os-project-manager merged 1 commit into
mainfrom
claude/issue-8948-dead-redirect-destinations
Aug 16, 2026
Merged

fix(docs): three redirect destinations point at pages that do not exist#9015
os-project-manager merged 1 commit into
mainfrom
claude/issue-8948-dead-redirect-destinations

Conversation

@os-project-manager

Copy link
Copy Markdown
Collaborator

Fixes#8948

Three entries in apps/docs/redirects.mjs had destinations with no page behind them. Each was a live URL answering a permanent redirect (308) into a 404 — user-facing breakage, not tidying.

Source URLWasNow
/docs/guides/solutions/role-based-interfaces/docs/ui/role-based-interfaces/docs/ui/audience-based-interfaces
/docs/guides/plugin-chatbot-integration/docs/ai/chatbot-integration/docs/ai
/docs/concepts/cloud-artifact-api/docs/deployment/cloud-artifact-api/docs/deployment

No source entry was deleted: a live URL that 404s is bad, but a live URL that becomes an unhandled 404 is no better and loses the record that the URL was once real.

How each destination was chosen

Two branches were possible per entry — a real successor page, or the section index as the conservative landing. Which branch was taken, and the search behind it:

1. role-based-interfaces → successor page. Git records the rename directly:

02f6af43c R100 content/docs/ui/role-based-interfaces.mdx -> content/docs/ui/audience-based-interfaces.mdx
f7606a100 R091 content/docs/guides/solutions/role-based-interfaces.mdx -> content/docs/ui/role-based-interfaces.mdx

R100 is a content-identical rename, in the direction check:role-word enforces. The redirect was simply never updated to follow the second hop. Successor verified present: content/docs/ui/audience-based-interfaces.mdx.

2. chatbot-integration → section index. No successor exists. The page was deleted, not renamed, in 97ad5702c ("remove cloud-only intro pages"), whose message names it explicitly: "ai/chatbot-integration.mdx — in-product chat / HITL wiring on @objectstack/service-ai (cloud, ADR-0025)". The same commit removed its meta.json nav entry and rewrote the inbound cross-link in ai/index.mdx rather than re-pointing it anywhere. Searches run: git log --all --diff-filter=ADR -- '*chatbot*'; filename scan of the whole current content/docs tree for chat|bot; content grep for chatbot. Only hit outside releases/ is the deleted path itself.

/docs/ai is more than a neutral default here: that index's callout is what now carries the in-product chat runtime's story, and it links onward to where that content actually lives.

3. cloud-artifact-api → section index. Same commit, same reason ("the Cloud control-plane artifact HTTP contract"), also a D, not a rename. Notably deployment/publish-and-preview.mdxdropped its two cross-links to the page instead of absorbing the content, so pointing there would assert a content move that provably did not happen. Searches run: git log --all --diff-filter=ADR -- '*cloud-artifact*' '*artifact-api*'; filename and content scans as above. The references/** hits (package-artifact, environment-artifact) are spec-generated schema pages, not a successor to a hand-written HTTP-contract guide.

Both fallbacks match the precedent already in this file, from the maintainer ruling of 2026-08-15 recorded in the retired-deployment-pages comment: a retired page with no successor lands on the section index (/docs/deployment/migration-from-objectql and /docs/guides/objectql-migration both do exactly this).

Verification

"The table looks right now" is not evidence, so every destination in the table was resolved the way Fumadocs routes it — /docs/x to content/docs/x.mdx, .md, x/index.mdx or x/index.md; bare /docs to content/docs/index.mdx; wildcard destinations to their target directory. Chain detection follows Next's own matching ('/a/:path*' matches /a and /a/deep, exact otherwise, first match wins).

entries checkeddeadchained
main (baseline)9230
this branch9200

The baseline reproduces the filer's numbers from a8189aef4 exactly. The three repaired destinations land on files that other, already-accepted entries in the same table also land on (/docs/ai from ai-capabilities, /docs/deployment from cloud-deployment and objectql-migration), so no new destination shape was introduced.

The resolver was proven capable of failing in both directions — a sweep that silently resolves everything would be worthless here:

  • Dead detection: a real red-to-green transition on the same script (3 → 0), not a constructed case.
  • Chain detection: never fires against the real table, so it got a positive control. One entry was temporarily aimed at /docs/guides/skills (itself a source in the table); the sweep reported DEAD/CHAIN … [CHAIN -> matched by source '/docs/guides/skills'], chained: 1, exit 1. Reverted, and the restore confirmed byte-identical to the commit (git hash-object = git rev-parse HEAD: = 62e2092c7), working tree clean.

Consumer output checked too: toNextRedirects() yields 92 well-formed entries, 0 malformed, all still permanent: true.

The sweep script is not shipped in this PR — it was the verification method. Gate recommendation below.

Gates

Run after the final commit, at 0b2d0f3ba:

  • node scripts/pm/dispatch-gates.mjs apps/docs/redirects.mjs"No check family names the given paths in its own source" (98 families discovered). This independently confirms the card's "nothing gates this table" claim, from the derivation side.
  • pnpm check:nul-bytes → OK, 5947 files scanned, self-test 75 assertions.
  • npx eslint apps/docs/redirects.mjs → clean.
  • pnpm check:role-word → OK, 43 baselined files, no new occurrences. Not implicated by path (it scans content/docs and skills, .md/.mdx only, so apps/docs/*.mjs is out of its reach) — run anyway because it is a ratchet family and the diff adds the words "role-based" to a file.

No changeset: apps/docs/ is not published package source, so this is skip-changeset.

The gate question — filed, not shipped

The card's suggestion that this table deserves a gate is correct, and it is the reason the rot went unnoticed. Deliberately not built here to keep this PR to the user-facing fix; filed as #9014 with the full recommendation — what it would assert (destination resolution, wildcard directories, chain freedom), where it would hook in (the required lint.yml lane rather than the advisory links lane, which carries no merge_group trigger), and how it would be proven capable of failing, including the note that its chain and wildcard limbs have no live failing example and need self-test fixtures rather than inspection.

Generated by Claude Code


Generated by Claude Code

…st (#8948)
Three entries in apps/docs/redirects.mjs answered a permanent redirect (308)
into a 404. Resolving every destination the way Fumadocs routes it
(/docs/x -> content/docs/x.mdx | .md | x/index.mdx) reports 92 entries
checked, 3 dead before this change, 0 after; no chains either way.
- role-based-interfaces: the page was renamed to audience-based-interfaces
(git records the rename, R100) and the redirect was never updated.
Re-pointed at the successor page.
- chatbot-integration and cloud-artifact-api: both pages were deleted as
cloud-only content, in one commit, with no successor -- nav entries and
inbound cross-links were removed rather than re-pointed. Both land on
their section index, matching the objectql-migration entry already in the
table under the same maintainer ruling.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011RB4waLuNbdruCo6X9oobm
@vercel

vercelBot commented Aug 16, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 16, 2026 6:11am

Request Review

@os-project-manageros-project-manager added documentation Improvements or additions to documentation skip-changeset PR has no user-facing published change; bypasses the changeset gate labels Aug 16, 2026 — with Claude
@os-project-manager
os-project-manager marked this pull request as ready for review August 16, 2026 06:13
@os-project-manager
os-project-manager added this pull request to the merge queueAug 16, 2026
Merged via the queue into main with commit 62b2655Aug 16, 2026
29 checks passed
@os-project-manager
os-project-manager deleted the claude/issue-8948-dead-redirect-destinations branch August 16, 2026 06:34
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/sskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(redirects): three entries in apps/docs/redirects.mjs point at pages that do not exist — live URLs 308 into a 404

2 participants

@os-project-manager@claude