Skip to content

Commit ad0e3cc

Browse files
RealDiligentclaude
andcommitted
fix: add the 6 missing published docs pages to the DocsNav sidebar
miner-quickstart, loopover-commands, ai-summaries, owner-checklist, self-hosting-docs-audit, and self-hosting-unified-ams-orb all have published, cross-linked content/docs/*.mdx pages but no docsNav entry, so they were unreachable from the persistent sidebar and skipped by DocsPrevNext. Adds a drift guard so a future page that forgets its entry fails a test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 962fa08 commit ad0e3cc

2 files changed

Lines changed: 59 additions & 0 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { readdirSync } from "node:fs";
2+
import { join } from "node:path";
3+
import { describe, expect, it } from "vitest";
4+
5+
import { docsNav } from "./docs-nav";
6+
7+
// REGRESSION (#8385): docsNav drives both the persistent /docs/* left rail and DocsPrevNext's
8+
// prev/next footer links, but it was maintained entirely by hand alongside docs.index.tsx's own
9+
// curated card list. Six published, cross-linked pages (miner-quickstart, loopover-commands,
10+
// ai-summaries, owner-checklist, self-hosting-docs-audit, self-hosting-unified-ams-orb) had real
11+
// content/docs/*.mdx files and index-page links but no sidebar entry, so a visitor landing on one
12+
// saw an unhighlighted rail with no route to any other group, and no page's prev/next ever reached
13+
// them. This is the drift guard: content/docs/ is the source of truth for what's published, so a new
14+
// .mdx that forgets its docsNav entry fails here instead of silently shipping unreachable.
15+
//
16+
// Filesystem-reading in a vitest test follows docs-source-server-isolation.test.ts's precedent --
17+
// process.cwd() is apps/loopover-ui because this file is only matched by that workspace's own
18+
// vitest.config.ts (`include: ["src/**/*.test.{ts,tsx}"]`); the root config takes `test/**` only.
19+
describe("docsNav covers every published docs page (#8385)", () => {
20+
const contentDir = join(process.cwd(), "content/docs");
21+
const publishedSlugs = readdirSync(contentDir)
22+
.filter((name) => name.endsWith(".mdx"))
23+
.map((name) => name.slice(0, -".mdx".length))
24+
.sort();
25+
26+
const navPaths = docsNav.flatMap((group) =>
27+
"items" in group
28+
? group.items.map((item) => item.to)
29+
: group.subgroups.flatMap((sub) => sub.items.map((item) => item.to)),
30+
);
31+
32+
it("reads a non-empty content/docs directory (guards against a silently-vacuous assertion)", () => {
33+
expect(publishedSlugs.length).toBeGreaterThan(40);
34+
});
35+
36+
it("has a sidebar entry for every published .mdx page", () => {
37+
const missing = publishedSlugs.filter((slug) => !navPaths.includes(`/docs/${slug}`));
38+
expect(missing).toEqual([]);
39+
});
40+
41+
it("has no sidebar entry pointing at a page that isn't published", () => {
42+
// "/docs" is the index route itself (docs.index.tsx), not a content/docs/*.mdx page.
43+
const dangling = navPaths
44+
.filter((to) => to !== "/docs")
45+
.filter((to) => !publishedSlugs.includes(to.replace("/docs/", "")));
46+
expect(dangling).toEqual([]);
47+
});
48+
49+
it("lists every page exactly once, so prev/next can't revisit a page", () => {
50+
const duplicates = navPaths.filter((to, index) => navPaths.indexOf(to) !== index);
51+
expect(duplicates).toEqual([]);
52+
});
53+
});

apps/loopover-ui/src/components/site/docs-nav.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export const docsNav: DocsGroup[] = [
1818
{ to: "/docs", label: "Overview" },
1919
{ to: "/docs/beta-onboarding", label: "Beta onboarding" },
2020
{ to: "/docs/quickstart", label: "Quickstart" },
21+
{ to: "/docs/miner-quickstart", label: "Quickstart by lane" },
2122
{ to: "/docs/mcp-clients", label: "MCP client setup" },
2223
],
2324
},
@@ -43,6 +44,7 @@ export const docsNav: DocsGroup[] = [
4344
title: "Self-hosting: integrations",
4445
items: [
4546
{ to: "/docs/self-hosting-github-app", label: "GitHub App & Orb" },
47+
{ to: "/docs/self-hosting-unified-ams-orb", label: "Unified ORB + AMS" },
4648
{ to: "/docs/self-hosting-ai-providers", label: "AI providers" },
4749
{ to: "/docs/self-hosting-rees", label: "REES enrichment" },
4850
{ to: "/docs/self-hosting-rees-analyzers", label: "REES analyzers" },
@@ -63,6 +65,7 @@ export const docsNav: DocsGroup[] = [
6365
items: [
6466
{ to: "/docs/self-hosting-releases", label: "Releases & images" },
6567
{ to: "/docs/self-hosting-release-checklist", label: "Release checklist" },
68+
{ to: "/docs/self-hosting-docs-audit", label: "Self-host docs audit" },
6669
{ to: "/docs/self-hosting-security", label: "Security" },
6770
{ to: "/docs/federated-fleet-intelligence", label: "Federated fleet intelligence" },
6871
],
@@ -73,6 +76,7 @@ export const docsNav: DocsGroup[] = [
7376
{ to: "/docs/github-app", label: "GitHub App configuration" },
7477
{ to: "/docs/maintainer-workflow", label: "Maintainer workflow" },
7578
{ to: "/docs/maintainer-install-trust", label: "Maintainer install & trust" },
79+
{ to: "/docs/owner-checklist", label: "Onboarding checklist" },
7680
],
7781
},
7882
{
@@ -97,6 +101,7 @@ export const docsNav: DocsGroup[] = [
97101
title: "Core concepts",
98102
items: [
99103
{ to: "/docs/how-reviews-work", label: "How reviews work" },
104+
{ to: "/docs/loopover-commands", label: "@loopover commands" },
100105
{ to: "/docs/branch-analysis", label: "Branch analysis" },
101106
{ to: "/docs/scoreability", label: "Scoreability" },
102107
{ to: "/docs/upstream-drift", label: "Upstream drift" },
@@ -109,6 +114,7 @@ export const docsNav: DocsGroup[] = [
109114
items: [
110115
{ to: "/docs/tuning", label: "Tuning your reviews" },
111116
{ to: "/docs/privacy-security", label: "Privacy & security" },
117+
{ to: "/docs/ai-summaries", label: "AI summaries policy" },
112118
{ to: "/docs/troubleshooting", label: "Troubleshooting" },
113119
],
114120
},

0 commit comments

Comments
 (0)