Skip to content

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

Closed

Description

@os-zhuang

Found while working #8904 (retiring the Vercel and ObjectQL-migration pages). Pre-existing and unrelated to those two pages — not introduced by #8904's PR, and deliberately left untouched there to respect that card's scope ceiling.

The defect

Three entries in apps/docs/redirects.mjs have destinations with no page behind them. Each is a live URL that answers a permanent redirect (permanent: true, so 308) into a 404:

Source URL (still live) Destination Destination page
/docs/guides/solutions/role-based-interfaces /docs/ui/role-based-interfaces missing
/docs/guides/plugin-chatbot-integration /docs/ai/chatbot-integration missing
/docs/concepts/cloud-artifact-api /docs/deployment/cloud-artifact-api missing

Verified against the tree at a8189aef4 by resolving every destination the way Fumadocs routes it (/docs/x to content/docs/x.mdx, .md, or /index.mdx). 92 entries checked, these 3 fail; nothing else in the table is dead or chained.

Why nothing caught it

apps/docs/redirects.mjs is checked by no gate at all. Its only consumer is apps/docs/next.config.mjs; nothing in scripts/ or .github/workflows/ reads it. Check Documentation Links runs lychee --offline over content/**, root README.md and ARCHITECTURE.md — the redirect table is outside that surface, so a destination can rot indefinitely with CI fully green. This is the same blind spot #8904 was raised to handle for its own two pages.

Likely causes, for whoever picks this up

  • role-based-interfaces — content/docs/ui/audience-based-interfaces.mdx exists. The page looks renamed (consistent with the direction check:role-word enforces) without its redirect being updated. Re-pointing at /docs/ui/audience-based-interfaces is the probable fix.
  • chatbot-integration — no near-match under content/docs/ai/. Needs a judgement call on the successor (/docs/ai is the neutral default).
  • cloud-artifact-api — no near-match under content/docs/deployment/. Same judgement call (/docs/deployment).

The first is mechanical; the other two need a destination decision, so this is not a pure chore.

Suggested scope

Fix the three destinations, and consider whether the table deserves a gate — a dependency-free resolver over docsRedirects is roughly the 30-line script used to find this, and would close the blind spot permanently rather than one rotted entry at a time.

⚠️ Serialization note for triage: this edits apps/docs/redirects.mjs, which PR #8947 (for #8904) also edits. Schedule after that merges to avoid a conflict on the same file.

Generated by Claude Code

Activity

  1. added
    pm:queueReady for the PM dispatch loop
    domain:devxDomain lane — seat card indexed by label:pm:seat
    on Aug 16, 2026
  2. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator

    Triage: lands in apps/docs/redirects.mjs (plus, at the dev's option, a ~30-line resolver gate under scripts/ as the card suggests); rationale: concrete defect with a named landing spot — three dead redirect destinations, verified by the filer at a8189aef4. No maintainer decision required: the destination choice for the two no-near-match entries is in-PR discretion with the card's neutral defaults (/docs/ai, /docs/deployment). Routed domain:devx, type Bug, → pm:queue.

    Serialization: the card's stated same-file conflict window with PR #8947 has passed — #8904 closed completed at 02:52Z and PR #8947 is closed. Claimant must still re-verify redirects.mjs against current main before dispatch (same-day churn on this file).

    Dedup: redirect-rot queries return only this card.

    Size/model suggestion: S–M, sonnet.


    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Aug 16, 2026
  4. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator

    Claiming this card.

    • Session: session_011RB4waLuNbdruCo6X9oobm
    • Branch: claude/issue-8948-dead-redirect-destinations

    Starting now; will re-verify the three destinations against current main before editing.

    Generated by Claude Code


    Generated by Claude Code

  5. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    Collaborator
    {
      "issue": 8948,
      "status": "done",
      "branch": "claude/issue-8948-dead-redirect-destinations",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/9015",
      "premise_still_valid": true,
      "summary": "All three premises re-verified on current main before editing: the full-table sweep at baseline reproduced the filer's a8189aef4 numbers exactly (92 entries, 3 dead, 0 chained). Branch taken per entry, with the search behind it: role-based-interfaces -> /docs/ui/audience-based-interfaces (SUCCESSOR branch: git records a content-identical R100 rename 02f6af43c, plus an earlier R091 from guides/solutions, so the redirect stopped one hop short); chatbot-integration -> /docs/ai and cloud-artifact-api -> /docs/deployment (SECTION-INDEX branch: both pages were deleted, not renamed, in one commit 97ad5702c 'remove cloud-only intro pages' which names each explicitly; searches over git history for '*chatbot*' / '*cloud-artifact*' / '*artifact-api*', a filename scan of the whole current content/docs tree, and a content grep all found no successor, and publish-and-preview DROPPED its cross-link rather than absorbing the content, so pointing there would assert a move that provably did not happen). Both fallbacks match the precedent already recorded in this file under the maintainer ruling of 2026-08-15: a retired page with no successor lands on the section index. No source entry was deleted. The gate was evaluated and NOT built here - filed as #9014.",
      "tests": "All run in the worktree; union re-run after the final commit at 0b2d0f3ba (git rev-parse --short HEAD), working tree clean. (1) Full-table Fumadocs-resolution sweep (/docs/x -> content/docs/x.mdx | .md | x/index.mdx | x/index.md; bare /docs -> index.mdx; wildcard destinations -> target directory; chain matching per Next semantics where '/a/:path*' matches /a and /a/deep, first match wins): BASELINE on main = 'entries checked: 92, dead: 3, chained: 0' exit 1, naming exactly the card's three entries; AFTER on branch = 'entries checked: 92, dead: 0, chained: 0' exit 0. (2) Resolver proven capable of failing in both directions - dead detection showed a real red-to-green transition on the same script (3 -> 0), and chain detection, which never fires against the real table, got a positive control: one entry temporarily aimed at /docs/guides/skills (itself a source) produced 'DEAD/CHAIN ... [CHAIN -> matched by source /docs/guides/skills]', chained: 1, exit 1. Reverted from the commit, restore proven byte-identical (git hash-object = git rev-parse HEAD: = 62e2092c7, porcelain empty). (3) Consumer check: toNextRedirects() = 92 entries, 0 malformed, all permanent: true. (4) Gates - node scripts/pm/dispatch-gates.mjs apps/docs/redirects.mjs reports 'No check family names the given paths in its own source' across 98 discovered families (independently confirming the card's no-gate claim from the derivation side); pnpm check:nul-bytes OK (5947 files, 75 self-test assertions); npx eslint apps/docs/redirects.mjs clean; pnpm check:role-word OK (43 baselined files, no new occurrences) - not implicated by path since it scans only content/docs and skills .md/.mdx, run anyway because it is a ratchet family and the diff adds the words 'role-based' to a file. No ablation in this card, so no rebuild claim is made. Labels read back after bots settled: ['documentation', 'skip-changeset'] - skip-changeset was already present, so no write was issued and nothing could be clobbered.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #9014: nothing verifies apps/docs/redirects.mjs destinations resolve - the table can rot with CI fully green (the gate the card asked me to evaluate; recommendation included, deliberately not shipped in this PR)"
      ]
    }

    Generated by Claude Code


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

domain:devxDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatch

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions