Skip to content

[#312] docs: website IA restructuring (Option A) — hub, dissolve guides/, dedupe, extend staleness gate#315

Merged
rucka merged 14 commits into
mainfrom
docs/website-structure-assessment
Jul 13, 2026
Merged

[#312] docs: website IA restructuring (Option A) — hub, dissolve guides/, dedupe, extend staleness gate#315
rucka merged 14 commits into
mainfrom
docs/website-structure-assessment

Conversation

@rucka

@rucka rucka commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Docs website IA restructuring (Option A)

Story: Closes #312
Type: Documentation · Priority: P2 · Risk: Low (content + static config only)

Motivation

Full IA assessment of apps/website/content/docs/** (69 pages, 12 sections + root) found: /docs root is a dead-end (15 lines, zero links, yet the landing page CTA points there); 8 internal links point at index-less section URLs that 404 under Fumadocs; guides/ is a 7-page grab-bag spanning three audiences with no shared theme; two active duplication pairs (FAQ vs troubleshooting, packaging vs organization); hardcoded skill counts already drifted (30/32/34 vs the real 35) and the staleness gate only checked one page. Option A (targeted consolidation) fixes every Major finding while changing only 9 URLs, leaving the healthy 70% of the tree untouched.

Changes Made

  • T1 — Hygiene (no URL changes): rewrote /docs root as a real hub (links to the 4 journeys + top tasks); added concepts/index.mdx + reference/index.mdx; fixed the 8 broken section links in tutorials/*.mdx; fixed 6 stale skill counts; extended docs-staleness-check.js to scan skill counts across all docs pages (not just skills-catalog.mdx) + added a dead-internal-link check; retitled quickstart variants ("Quickstart: Solo/Team/Organization"); unified developer-journey title; updated e2e sidebar-title assertions.
  • T2 — Support consolidation: merged support/faq.mdx + guides/troubleshooting.mdx into a new support/troubleshooting.mdx (union of Q&As, conflicting fixes reconciled — nvm recommended over sudo/npm-permissions, with the alternative noted); added the first redirects() block to next.config.mjs.
  • T3 — Dissolve guides/: 4 moves (adopter-checklistgetting-started/checklist, cli-workflowsreference/cli/workflows, install-from-urlcustomization/install-from-url, update-linkreference/cli/update-link), 2 content merges (customize-kbcustomization/team.mdx, packagingcustomization/organization.mdx, deduped); guides/ section removed entirely; root nav 13→12 entries; ~15 inbound links updated.
  • Remediation round: canonical CLI help URL fixed (update-link metadata pointed at the old /docs/guides/update-link), 2 stale skill counts fixed (skill-management.mdx table, claude-code.mdx "30+" that escaped the gate regex), e2e smoke tests added for /docs, /docs/concepts, /docs/reference, and a genuine negative test added for the extended staleness gate (spawns the real script against a fixture with a wrong count, asserts failure).
  • Remediation round 2 (post-approval IA challenge + re-review): 4 stale how-to guide counts fixed ("11" vs actual 9 in ai-assisted-sdlc, developer-journey/index, knowledge-base, quickstart) and the staleness gate extended to verify "N [sequential|step-by-step] [how-to|process] guides" claims against the dataset, failing loudly if the how-to dir is missing (d4fba2a, 0a302bf); concepts/index.mdx rewritten from a wall-of-text into a recommended reading order + deeper-mechanics split; orphaned install-from-url surfaced in customization/index.mdx; Migrations top-task row added to the /docs hub — the only section previously unreachable from it (0541e11).
  • Remediation round 3 (architectural: no test-on-script): the docs-staleness gate violated the owner's rule "tested functionality lives in production code, tested there — never unit-test scripts." Ported ALL gate logic verbatim into a proper website module apps/website/lib/docs-staleness-check.ts (ESM, functions exported individually, import.meta main-guard CLI wrapper, DOCS_STALENESS_ROOT retained); rewrote the test as white-box unit tests importing those functions directly — zero spawnSync/exec in vitest (real-tree parity asserted in-process via runAllChecks()); deleted scripts/docs-staleness-check.js; root docs:staleness now delegates pnpm --filter @pair/website docs:staleness (added tsx; quality-gate + CI step unchanged, now delegating). Recorded the rule as ADL 2026-07-13-gate-tooling-code-in-tested-modules.md, surfaced from way-of-working Quality Gates (bc83c37, 46292c8).

Files Changed

  • New: content/docs/concepts/index.mdx, content/docs/reference/index.mdx, content/docs/support/troubleshooting.mdx, apps/website/lib/docs-staleness-check.ts (gate module), apps/website/lib/docs-staleness-check.test.ts (white-box unit tests), .pair/adoption/decision-log/2026-07-12-docs-website-ia-restructuring-assessment.md (the full assessment — relocated from apps/website/docs-structure-assessment.md during review — analysis/decision artifact, not published site content), .pair/adoption/decision-log/2026-07-13-gate-tooling-code-in-tested-modules.md (ADL: gate/tooling code in tested modules, no unit-test on scripts).
  • Moved: 4 pages out of guides/ (see above); guides/ deleted.
  • Deleted: scripts/docs-staleness-check.js (logic ported to the website module; root gate delegates).
  • Modified: content/docs/index.mdx, root + section meta.json files, next.config.mjs (new redirects()), e2e/docs.e2e.test.ts, ~20 pages with fixed inbound links/counts; apps/pair-cli/src/commands/kb-info/migration-url.ts (+ 4 test URL updates across 3 test files) — dead /docs/guides/migrations base fixed to /docs/migrations; package.json + apps/website/package.json + pnpm-workspace.yaml (root docs:staleness delegates, website script runs the module via tsx, tsx added to catalog); .pair/adoption/tech/way-of-working.md (ADL surfacing bullet).

Redirects (9, permanent)

/docs/guides/{adopter-checklist,cli-workflows,customize-kb,install-from-url,packaging,troubleshooting,update-link}, /docs/support/faq, /docs/guides — all e2e-verified live.

Testing / Quality Gates

website vitest:              37/37 pass (incl. 6 staleness gate tests)
docs:staleness:               PASS — 35 skills, 8 commands in sync
knowledge-hub check:links:    All markdown links valid
mdlint:                        PASS
next build:                    PASS
e2e (docs, incl. redirects):   39/39 pass

Risk Assessment

Low — docs content + static config only, no dependencies added, no secrets. Only 7 URLs actually change; frozen anchors (reference/skills-catalog.mdx, reference/cli/commands.mdx) untouched except one unavoidable link-only edit inside commands.mdx (old link now points to the moved page, forced by the new dead-link gate — content itself untouched).

Reviewer notes (disclosures)

  • The analysis doc now lives at .pair/adoption/decision-log/2026-07-12-docs-website-ia-restructuring-assessment.md — relocated from apps/website/docs-structure-assessment.md during review (commit fe62307); the story's Documentation Links pointer was updated to match.
  • apps/pair-cli/src/commands/kb-info/migration-url.ts emitted /docs/guides/migrations/*, which 404s — initially deferred as out of scope, then fixed in this PR (commit cc9fcd2): DOCS_MIGRATIONS_BASE now points at /docs/migrations, with the 4 dependent test URLs updated.
  • 3 review rounds: initial (1 Major + 4 Minor, all fixed), re-review (Approved with Comments — 4 remaining items are nonActionable/by-design), independently re-verified.

🤖 Generated with Claude Code

@rucka

rucka commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

Code Review — PR #315 (Independent, consolidated)

Review Information

Review Summary

Overall Assessment

  • Approved with Comments

This PR went through 2 review rounds pre-PR (branch reviewed locally before push, per this session's convention): an initial round found 1 Major (CLI help emitting a moved URL) + 4 Minor (stale skill counts, missing e2e smoke for new pages, gate not proven by a negative test) — all fixed in the remediation commit and independently re-verified against the pushed head, not against the fix claims.

Acceptance Criteria — all verified met

AC Verdict
AC1 (hub) Met — real hub with 4 journey links + top-task table
AC2 (indexes/links) Met — concepts/index.mdx + reference/index.mdx real content; independent link-resolver over all 68 mdx: all resolve
AC3 (counts/gate) Met — 35 verified against dataset; gate scans all pages
AC4 (troubleshooting) Met — genuine 441-line union, conflicting fix reconciled with rationale
AC5 (dissolve guides) Met — 4 renames + 2 merges at exact targets, guides/ gone, root nav matches spec
AC6 (titles) Met
AC7 (redirects) Met — all 9 rows present, e2e-verified live
AC8 (gates) Met — staleness/vitest/mdlint/build/e2e all pass

Findings (all resolved, carried for transparency)

  • Minor, nonActionableapps/pair-cli/src/commands/kb-info/migration-url.ts: pre-existing dead /docs/guides/migrations URL, out of scope, untouched — track as separate follow-up issue.
  • Minor, nonActionabledocs-structure-assessment.md ships at app root: defensible (story's own cited source), not published.
  • Minor, nonActionable — new staleness-gate test lives in apps/website/lib/ reaching a root script: pragmatic given no root test harness exists.

No Critical or Major findings remain.

Risk Assessment

Low — docs + static config only, no dependencies, no secrets, 7 URLs change with permanent redirects covering all of them.

Verdict

Approved with Comments. All 8 ACs independently verified against the pushed head; gates green; remaining items are nonActionable disclosures, not blockers.

🤖 Independent review generated with Claude Code

@github-actions github-actions Bot temporarily deployed to Website Preview July 12, 2026 15:00 Inactive
@rucka rucka force-pushed the docs/website-structure-assessment branch from 0b0d65a to 75190b3 Compare July 12, 2026 16:42
@github-actions github-actions Bot temporarily deployed to Website Preview July 12, 2026 16:42 Inactive
@rucka rucka force-pushed the docs/website-structure-assessment branch from 75190b3 to 171378b Compare July 12, 2026 17:04
@github-actions github-actions Bot temporarily deployed to Website Preview July 12, 2026 17:04 Inactive
rucka and others added 5 commits July 12, 2026 19:16
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ate extension

- /docs rewritten as real hub (4 journeys + top tasks); new concepts/index + reference/index (F1/F2/F11)
- 6 stale skill counts fixed to 35 (verified vs dataset/.skills: 25 capability + 9 process + 1 meta)
- docs-staleness-check.js: skill-count check now scans ALL content/docs/**/*.mdx; regex extended
  with 'composable' variant (getting-started phrasing) — subset counts ('9 process skills') excluded
- gate also gains dead-internal-link check (resolves ](/docs/...) against content tree) — the
  optional check from the story, implemented since clean against the filesystem source
- test-first proof: extended gate FAILed with 6 count mismatches + 8 dead section links, PASSes after fixes
- 8 broken section links fixed (concepts/reference via new indexes; 4 /docs/guides links retargeted
  to stable pages ahead of T3 dissolve)
- quickstart variants retitled 'Quickstart: Solo/Team/Organization' (F6); developer-journey unified
  on 'Process Lifecycle' (meta.json + 4 prose labels) (F10)
- llms-txt orphan: inbound links from concepts/index + reference/kb-structure (F12)
- e2e title/sidebar assertions updated (docs + landing); CP5 QA doc: +2 index URLs, label sync

Refs: #312 T1

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…shooting

Union of support/faq.mdx (361L) + guides/troubleshooting.mdx (236L) into
support/troubleshooting.mdx; conflicting permission fix reconciled (nvm
recommended, npm-prefix alternative). Redirects /docs/support/faq +
/docs/guides/troubleshooting -> /docs/support/troubleshooting (new
redirects() block). Inbound links updated (grep zero in content/).
E2e: redirect test added, sidebar/smoke lists updated. CP5 inventory synced.
4 moves: adopter-checklist->getting-started/checklist, cli-workflows->
reference/cli/workflows, install-from-url->customization/install-from-url,
update-link->reference/cli/update-link. 2 merges: customize-kb->
customization/team (Quick Recipe section), packaging->customization/
organization (layout-modes detail kept, org flags reconciled with parser,
pair->pair-cli normalized). guides/ removed; 7 redirects added (full table
now 9 rows incl /docs/guides->/docs). Root meta: drop guides, promote
tutorials (13->12). Inbound links updated — grep /docs/guides zero in
content/ (incl. one link-only edit in frozen reference/cli/commands.mdx).
Hub: duplicate h1 fixed. E2e: moved-pages + dissolved-guides redirect
tests, smoke/prev-next lists updated — 31/31 green. CP5 inventory synced.
…smoke, gate negative test

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@rucka rucka force-pushed the docs/website-structure-assessment branch from 171378b to a303b60 Compare July 12, 2026 17:18
@github-actions github-actions Bot temporarily deployed to Website Preview July 12, 2026 17:18 Inactive
rucka and others added 2 commits July 12, 2026 19:43
apps/website/docs-structure-assessment.md was an analysis/decision
artifact sitting inside the published site's app directory (not
published content itself, but out of place there). Moved to
.pair/adoption/decision-log/ where decision records belong. Updated
the two references in the #312 issue body accordingly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
DOCS_MIGRATIONS_BASE built URLs under /docs/guides/migrations, a page that
never existed there (migrations live at /docs/migrations, top-level).
Found during #312's docs restructuring review — pre-existing, unrelated
to that PR's scope, so fixed here. Updated the 4 hardcoded test-expected
URLs across migration-url.test.ts, version-check.test.ts,
version-check-formatter.test.ts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to Website Preview July 12, 2026 17:45 Inactive
@rucka

rucka commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

Remediation update — 2 additional fixes + assessment re-verification

Pushed a303b60..cc9fcd2 (2 commits). Both fold into this PR per instruction (no new PRs for small related fixes).

1. Assessment re-verification (no code change — verification only)

Reconsidered the "nothing left to do" claim rather than trusting it: re-checked the full 69-page target structure from docs-structure-assessment.md against the actual current site tree, page by page. Result: exact match — every move/merge landed where planned, both merges' content verified present (customization/team.mdx has the "Quick Recipe" section from guides/customize-kb; customization/organization.mdx has "Package for Distribution" + layout-modes detail from guides/packaging). Page count reconciles precisely: 69 original → 68 after this story's own moves/merges/new-pages → 69 with pm-tools/azure-devops.mdx (added by the unrelated, already-merged #235). Nothing from Option A was left unimplemented; only the deliberately-deferred "batch 4" items (skill-management split, general-faq rename) remain untouched, as documented.

2. docs-structure-assessment.md relocated

Moved from apps/website/docs-structure-assessment.md to .pair/adoption/decision-log/2026-07-12-docs-website-ia-restructuring-assessment.md — it's an analysis/decision artifact, not published site content, so it doesn't belong inside the app directory. Updated #312's issue body (2 references) to point at the new path.

3. migration-url.ts fixed (previously flagged nonActionable — reconsidered)

DOCS_MIGRATIONS_BASE built URLs under /docs/guides/migrations, a page that never existed there (migrations live at /docs/migrations, top-level, confirmed by this story's own restructuring). Previously deferred as "pre-existing, out of scope, needs its own follow-up issue" — on reflection this was too quick a deferral for a 2-line fix. Fixed directly: the constant + 4 hardcoded test-expected URLs across migration-url.test.ts, version-check.test.ts, version-check-formatter.test.ts.

Gates (re-verified on final head cc9fcd2)

pair-cli:        71 files / 834 tests — pass
website (unit):   20/20 pass
docs:staleness:   PASS — 35 skills, 8 commands in sync
next build:       PASS
check:links:      all valid
mdlint:           pass
ts:check:         pass (all 7 packages)

🤖 Generated with Claude Code

rucka and others added 3 commits July 12, 2026 20:04
- ai-assisted-sdlc said "11 process guides", developer-journey/index
  "all 11 guides" — actual KB count is 9; normalize phrasing to
  "how-to guides"
- extend docs-staleness-check: "N how-to/process guides" claims now
  verified against dataset .pair/knowledge/how-to (test-first,
  negative + positive fixture cases added)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- concepts/index: replace wall-of-text with recommended reading order
  (4 core concepts) + deeper-mechanics list + forward link to lifecycle
- customization/index: surface install-from-url (moved here by T3 but
  invisible from the section index)
- docs hub: add Migrations row to top tasks (only section unreachable
  from the hub)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to Website Preview July 12, 2026 18:06 Inactive
@github-actions github-actions Bot temporarily deployed to Website Preview July 12, 2026 18:07 Inactive
@rucka

rucka commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

Remediation follow-up + IA challenge round

1. Remediation mapping (post re-review fixes already on the branch)

Two fixes were folded in after review round 2 and are hereby mapped to their findings:

Fix Finding it resolves Commit
Assessment doc relocated apps/website/docs-structure-assessment.md.pair/adoption/decision-log/2026-07-12-docs-website-ia-restructuring-assessment.md Review note: analysis/decision artifact should not ship at the app root (it is not published site content); story's Documentation Links pointer updated to match fe62307
kb-info/migration-url.ts DOCS_MIGRATIONS_BASE fixed /docs/guides/migrations/docs/migrations (+ 4 test URLs across 3 test files) Review finding initially triaged "out of scope / follow-up": CLI emitted a URL that 404s post-restructure — reversing that call, fixed in-PR since the 404 is caused by this PR's own tree change cc9fcd2

The PR body's "Files Changed" and "Reviewer notes" sections were stale on both points and have been corrected.

2. Independent verification (all 8 ACs re-checked on the branch)

AC1–AC8 verified against the actual tree, not the PR body: hub real, section indexes resolve, staleness gate scans all content/docs/**/*.mdx (35 skills confirmed against dataset/.skills/), single troubleshooting page with content union preserved (incl. platform-specific fixes folded into PATH/build sections), guides/ fully dissolved with root nav in the exact T3 order, no duplicate sidebar titles, all 9 redirects permanent, frozen paths untouched. Repo-wide grep for /docs/guides + /docs/support/faq: zero hits outside redirects config, e2e redirect tests, and the assessment doc. No gaps found.

Gates (fresh run): website vitest 35/35 · docs:staleness PASS (35 skills, 8 commands) · knowledge-hub check:links PASS · mdlint PASS · next build PASS · e2e 39/39.

3. IA challenge — implemented (same branch)

Critical read of the post-restructure tree against the full set of pair aspects (KB, skills, CLI, PM tools, journeys, customization, contributing). Low-risk, clearly net-positive fixes landed:

  • Stale how-to guide counts + gate coverage (d4fba2a): concepts/ai-assisted-sdlc.mdx claimed "11 process guides" and developer-journey/index.mdx "all 11 guides" — the KB ships 9; same drift class the story just fixed for skills, but unguarded. Counts fixed, phrasing normalized to "how-to guides", and docs-staleness-check.js extended (test-first, negative + positive cases) to verify "N how-to/process guides" claims against dataset/.pair/knowledge/how-to/.
  • concepts/index.mdx reading order (0541e11): the index was a single 8-link wall-of-text paragraph. Now: a numbered "recommended reading order" for the 4 core concepts (SDLC → KB → Skills → Adoption Files), a "deeper mechanics" list (canonical states, agent integration, llms.txt), and a forward link into the Process Lifecycle + tutorials — giving the docs a proper conceptual on-ramp.
  • Orphaned install-from-url (0541e11): T3 moved it into customization/ but the section index never mentioned it. Now linked from the Adopt stage and the "Which stage are you at?" table.
  • Migrations reachable from the hub (0541e11): it was the only section with no path from /docs. Added an "Upgrade .pair/ after a pair release" top-task row.

No URLs or page titles changed; all gates re-run green (incl. pre-push hook).

4. IA challenge — proposals for discussion (not implemented)

  1. Rename /docs/developer-journey/docs/process (or /docs/lifecycle). The section is titled "Process Lifecycle" everywhere in the UI; "developer-journey" survives only in the URL. Cost: 5 URL changes + redirects + inbound-link sweep — deliberate churn, needs a call.
  2. Split reference/skill-management.mdx. Its "The Problem / How It Works" narratives are explanation living in Reference; the naming rules and transform tables are true reference. Split explanation into concepts/ (near agent-integration). Already deferred by the story as batch 4 — still worth doing.
  3. support/general-faq.mdxfaq.mdx (F9) is now effectively blocked: /docs/support/faq is a live permanent redirect to troubleshooting. Reclaiming the URL means repointing a permanent redirect (bad for anyone who cached it). Recommend formally dropping F9 rather than leaving it "deferred".
  4. Slim developer-journey/index.mdx. The "Product Lifecycle" ASCII art and "Card Hierarchy" blocks are conceptual explanation (what initiatives/epics/stories are), not navigation; they would fit concepts/ai-assisted-sdlc.mdx, leaving the index as levels + entry points + /pair-next. Debatable — the page works today.
  5. Root nav order — concepts earlier? Current order (getting-started → tutorials → concepts) is task-first; a concept-first learning path would put concepts second. Both defensible; flagging only.

🤖 Generated with Claude Code

@rucka

rucka commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

Re-review of post-approval commits (cc9fcd2..a9d4764)

Review Information

PR Number: #315
Author: rucka
Reviewer: Independent reviewer (Claude Code) — blind re-review, story + PR + code only
Review Date: 2026-07-12
Story/Epic: #312
Review Type: Documentation (+ quality-gate script/tests)
Scope: Only the 3 commits pushed after the prior approval — d4fba2a (how-to counts + gate coverage), 0541e11 (IA polish), a9d4764 (prettier churn). Head reviewed: a9d4764.

Review Summary

Overall Assessment

  • Approved with Comments — Minor issues noted, can merge

Key Changes Summary

  • d4fba2a: fixed 2 stale how-to guide counts ("11 process guides", "all 11 guides" → 9), extended docs-staleness-check.js with Check 2b ("N how-to/process guides" verified against dataset/.pair/knowledge/how-to/), added negative + positive unit tests.
  • 0541e11: concepts/index.mdx rewritten as numbered reading order + deeper-mechanics list + forward links; customization/index.mdx surfaces install-from-url (para + table row); docs hub gains a Migrations top-task row.
  • a9d4764: formatting only (verified below).

Business Value Validation

All three changes extend the story's own goals (AC3 drift-class protection generalized to how-to counts; AC1/AC5 navigability gaps closed: install-from-url orphaned by the T3 move, Migrations unreachable from the hub). No story AC regressed; no scope contradiction.

Independent Verification (evidence, re-derived from the tree)

  • Real how-to count = 9packages/knowledge-hub/dataset/.pair/knowledge/how-to/ on head contains exactly 9 files matching NN-how-to-*.md (01–03, 06–11; no README/index.json present; the ^\d+-how-to-.*\.md$ filter would correctly exclude them, and the test fixture proves README exclusion).
  • All guide-count claims now correct — repo grep on head finds 5 occurrences of "N how-to/process guides" across 3 pages (concepts/ai-assisted-sdlc.mdx ×2, developer-journey/index.mdx ×2, developer-journey/execution.mdx ×1): all say 9. Pre-fix state had "11 process guides" and "all 11 guides". reference/guidelines-catalog.mdx enumerates exactly the same 9 guides (01,02,03,06–11) with the 04/05 removal explained (D24/map-subdomains/map-contexts reclassified process→capability (scoped, callers matrix) #246) — count is consistent everywhere.
  • Gate regex vs live phrasingsGUIDE_COUNT_RE = /(\d+)\s+(?:how-to|process)\s+guides/g matches all 5 live claims (probed programmatically). See Minor Setup & Project Management Integration #1 for the phrasings it does NOT cover.
  • Tests — genuine negative test (spawns the real script against a fixture with "11 how-to guides" vs 1 actual; asserts exit 1 + the specific "How-to guide count mismatch" message + offending file) and positive test (matching count → exit 0). Fixture keeps the skill claim correct, so a failure is attributable to Check 2b specifically. Good isolation.
  • concepts/index.mdx rewrite — all 7 links from the previous paragraph preserved (ai-assisted-sdlc, knowledge-base, skills, adoption-files, canonical-states, agent-integration, llms-txt) + 2 new (/docs/developer-journey, /docs/tutorials); every target resolves on head; ordering matches concepts/meta.json sidebar order exactly; SDLC → KB → Skills → Adoption Files is a factually sensible dependency order.
  • customization/index.mdx / hub/docs/customization/install-from-url and /docs/migrations both resolve (index-backed); Migrations was indeed the only hub-unreachable section.
  • a9d4764 is pure formatting — e2e + staleness-test hunks are line reflow only; apps/website/package.json change ( → literal ) verified JSON-equal via parse comparison. See Minor Workflow Customization #4 on scope.
  • Frozen pathsreference/skills-catalog.mdx and reference/cli/commands.mdx untouched by the range (9 files changed, neither among them).
  • Gates re-run from a detached worktree at a9d4764docs-staleness-check.js: PASS (35 skills, 8 commands); website vitest: 35/35 pass (incl. the 4 gate tests).
  • No new dependencies, no new tech decisions — Check 2b is a same-pattern extension of the existing script; no ADR needed. Commit messages follow the template ([#312] type: ...).

Testing Review

Test Results: All Passing (staleness script PASS; vitest 35/35 re-run independently)
New tests: 2 (negative + positive for Check 2b) — both meaningful, not tautological
Not re-run here: e2e/build (no heading/URL/title changed by the range; relying on CI)

Security Review

No security surface: static docs content, a read-only filesystem scan in a CI script, tests. No secrets, no input handling.

Detailed Review Comments

Positive Feedback

  • The gate extension is test-first with a real negative case (spawned script, asserted exit code and message) — exactly the DoD bar the story set for the skills check.
  • The fixture cleverly isolates Check 2b (skill claim kept correct) and proves the README exclusion.
  • concepts/index.mdx reading order mirrors meta.json sidebar order — no drift between prose and nav.

Issues to Address

Minor Issues 💡

  1. scripts/docs-staleness-check.js:105 (GUIDE_COUNT_RE) — the regex misses guide-count phrasings that are live on this branch in reference/guidelines-catalog.mdx: "9 sequential how-to guides" (line 6), "9 sequential guides" (line 12), "(9 sequential steps)" (line 3). Concrete failure case: a 10th how-to guide is added → gate stays green while guidelines-catalog claims 9 in three places — the exact drift class this commit set out to close, on the page the fixed links point at. Recommendation: allow an optional adjective (e.g. (?:sequential\s+)?) analogous to Check 1's (?:pair\s+|composable\s+)?, or normalize the catalog phrasing to the guarded form. (Related note, non-finding: the regex is case-sensitive — "9 How-to Guides" would escape — matching the skills-check convention; and "N process guides" as a subset phrase would false-positive, but no subset phrasing exists in docs today and the story explicitly accepted this risk with an allowlist fallback.)
  2. scripts/docs-staleness-check.js:99if (fs.existsSync(HOW_TO_DIR)) silently skips Check 2b if the dataset dir is ever moved/renamed, quietly disabling the gate; no test would catch it (the fixture always creates the dir). Contrast Check 1: a missing SKILLS_DIR crashes loudly. Recommendation: push an error (or at least log a warning) when the dir is absent. Noting fairly: Check 4 (TUTORIALS_DIR) uses the same guard pattern, so this partially matches file convention — still, for a source-of-truth dir a loud failure is the safer default.
  3. PR body (Testing / Changes Made) — stale w.r.t. this range: says "website vitest: 33/33" (now 35/35 after the 2 new gate tests) and "e2e 33/33" (the last remediation comment reports 39/39), and does not mention the how-to gate extension, the concepts/index reading-order rewrite, the install-from-url surfacing, or the Migrations hub row — these live only in a PR comment. Impact: merge-commit/history accuracy. Recommendation: refresh the body's test counts and add a second remediation bullet before merge.
  4. apps/website/package.json (a9d4764) — the prettier commit reformats a file this PR had not previously touched ( → literal ). Verified JSON-semantically identical, and produced by the adopted pre-push formatting hook (reverting it would fail the hook; the escape-form drift originates on main). nonActionable / by-design — reported for transparency only.

Critical / Major Issues

None.

Risk Assessment

Risk Impact Probability Mitigation
Guide-count drift via unguarded phrasings (Minor #1) Low Low Regex widening or phrasing normalization; count currently correct everywhere
Gate silently disabled on dataset dir move (Minor #2) Low Low Loud failure on missing dir

Tech Debt

Two small items surfaced (Minor #1, #2) — surfaced, not blocking. Additional same-class note for a future pass: "9 guideline categories" counts (developer-journey pages, guidelines-catalog) remain unguarded by any check.

Adoption Compliance

Inline check (docs-only incremental range): no new dependencies (package.json diff is formatting-only) → tech-stack clean; no architectural decisions → no ADR required; commit messages, branch, and this report follow the collaboration templates.

Follow-up Actions

Verdict: Approved with Comments. No Critical/Major findings; all story ACs remain met; frozen paths untouched; gates independently re-verified green at a9d4764. Merge remains human-gated.

…-dir

- GUIDE_COUNT_RE now covers adjective phrasings (sequential,
  step-by-step) with optional modifier — mirrors Check 1's shape;
  caught 2 more live stale counts on the real tree
  (knowledge-base.mdx, quickstart.mdx: "11 step-by-step ... guides"
  vs actual 9) — fixed
- guidelines-catalog description normalized "(9 sequential steps)" →
  "9 sequential how-to guides" so every guide-count claim is
  gate-covered
- missing how-to dataset dir now pushes an error instead of silently
  skipping the check (consistent with Check 1)
- tests: +2 (adjective-phrasing negative, missing-dir failure)

Refs: PR #315 re-review findings 1-2
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to Website Preview July 12, 2026 18:25 Inactive
@rucka

rucka commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

Remediation — re-review findings (#315 (comment))

Finding Resolution Commit
1 — GUIDE_COUNT_RE misses live phrasings in guidelines-catalog.mdx ("9 sequential how-to guides", "9 sequential guides", "(9 sequential steps)") Regex extended with optional adjective group (sequential, step-by-step) + optional modifier, mirroring Check 1's shape; catalog description normalized "(9 sequential steps)" → "9 sequential how-to guides" so every guide-count claim is regex-covered. Negative test added for the adjective phrasings. Bonus: the widened regex flushed out 2 more live stale counts — concepts/knowledge-base.mdx and getting-started/quickstart.mdx both claimed "11 step-by-step … guides" (actual 9) in code-block comments — fixed. 0a302bf
2 — existsSync(HOW_TO_DIR) silently disables the check if the dataset dir moves Missing dir now pushes an error (gate FAILs loudly, consistent with Check 1); missing-dir test added. 0a302bf
3 — PR body stale vs post-approval range Body updated via gh pr edit: Testing block now reads vitest 37/37, e2e 39/39 (fresh runs); "Remediation round 2" bullet added to Changes Made covering d4fba2a/0541e11/0a302bf. Rest verbatim.
4 — prettier escape-form in apps/website/package.json Acknowledged: nonActionable/by-design (hook-applied prettier normalization, no behavior change). No action.

Gates after fixes: website vitest 37/37 · docs:staleness PASS (35 skills, 8 commands) · mdlint PASS · next build PASS · e2e 39/39 · pre-push hook gates pass.

🤖 Generated with Claude Code

@rucka

rucka commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator Author

Remediation verified — Approve (re-review findings 1–3, commit 0a302bf)

Independent verification of the remediation for the post-approval re-review. All 3 actionable findings genuinely resolved — verified against the tree and by execution, not the remediation comment.

Finding 1 (regex coverage) — RESOLVED. GUIDE_COUNT_RE widened to /(\d+)\s+(?:sequential\s+|step-by-step\s+)?(?:how-to\s+|process\s+)?guides/g, catalog description normalized. Grepped all 10 live guide-count phrasings on 0a302bf (ai-assisted-sdlc ×2, knowledge-base, developer-journey index ×2 / execution, quickstart, guidelines-catalog ×3): every one says 9 and every one matches the widened regex; "9 guideline categories" correctly does not match. Confirmed the 2 newly-flushed stale counts ("11 step-by-step … guides" in concepts/knowledge-base.mdx:19, getting-started/quickstart.mdx:65) are fixed to 9 — real catches, not cosmetic.

Finding 2 (silent skip) — RESOLVED. Missing HOW_TO_DIR now pushes How-to guides dir not found … (exit 1) instead of silently skipping; dedicated test added (withHowToDir = false, rmSync properly imported).

Finding 3 (PR body) — RESOLVED. Body now carries an accurate "Remediation round 2" bullet (4 stale counts total across d4fba2a+0a302bf — matches the actual diffs) and Testing updated to 37/37 vitest / 39/39 e2e.

Red→green proven, not assumed: ran the 2 new tests against the pre-fix script (a9d4764 version) in a throwaway worktree → exactly those 2 fail; against 0a302bf → 37/37 pass. Fresh independent runs at 0a302bf: docs-staleness-check.js PASS (35 skills, 8 commands); website vitest 37/37 (6 gate tests). e2e not re-run here (commit touches no asserted heading/URL; quickstart hunk is inside a code block) — CI covers it.

Finding 4 (package.json prettier churn) remains nonActionable/by-design as agreed. Frozen paths still untouched.

Verdict: Approved. Merge remains human-gated.

@rucka

rucka commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Code Review — PR #315 (Canonical, /pair-process-review skill-run)

Review Information

Review Summary

Overall Assessment

  • Approved with Comments — no Critical/Major issues; two low-severity gate-robustness observations + accepted-by-design items noted for transparency.

Key Changes Summary

Targeted IA consolidation of apps/website/content/docs/**: /docs rewritten as a real hub; new concepts/index.mdx + reference/index.mdx; guides/ dissolved (4 moves + 2 content merges); support/faq.mdx + guides/troubleshooting.mdx merged into a single support/troubleshooting.mdx; 9 permanent redirects added (first redirects() block in next.config.mjs); docs-staleness-check.js extended to scan skill counts across all docs pages, verify how-to guide counts, and detect dead internal /docs links. Net 7 URLs change; healthy sections untouched.

Business Value Validation

Delivers the story's goal: every audience journey reaches content in ≤2 clicks, duplicated pages are unified, and stale counts now fail CI. Verified against the tree, not the PR body.

Acceptance Criteria — independently verified

AC Verdict Evidence (re-derived on 0a302bf)
AC1 (hub) Met content/docs/index.mdx = 4 journey links + 8-row top-task table (incl. Migrations, Support).
AC2 (indexes/links) Met concepts/index.mdx + reference/index.mdx real content; Check 5 dead-link gate passes → every ](/docs...) resolves.
AC3 (counts/gate) Met 35 skill dirs counted independently; gate scans all content/docs/**/*.mdx; docs:staleness PASS.
AC4 (troubleshooting) Met Single support/troubleshooting.mdx (441 lines, genuine union); nvm-vs-sudo conflict reconciled explicitly ("Recommended fix — use nvm" + "Alternatives"); support/faq.mdx gone.
AC5 (dissolve guides) Met guides/ absent; 4 moves + 2 merges at exact targets (team.mdx "Quick Recipe", organization.mdx "Package for Distribution" + layout-modes table); root meta.json = 12 entries in the exact T3 order.
AC6 (titles) Met Zero duplicate frontmatter titles across all docs; quickstarts retitled "Quickstart: Solo/Team/Organization"; developer-journey unified to "Process Lifecycle".
AC7 (redirects) Met 9 permanent rows in next.config.mjs; all 9 asserted in e2e/docs.e2e.test.ts.
AC8 (gates) Met website vitest 37/37 (re-run, incl. 6 gate tests); docs:staleness PASS (35 skills, 8 commands); e2e assertions cover every redirect + new-page 200 (CI-covered).

Frozen anchors: reference/skills-catalog.mdx — zero diff; reference/cli/commands.mdx — one disclosed link-only edit (/docs/guides/update-link/docs/reference/cli/update-link), content untouched. Neither moved. ✓

Repo-wide grep: zero stray /docs/guides or /docs/support/faq outside the redirect config, e2e, assessment doc, and one self-referential comment in the gate script. ✓

Testing Review

website vitest:   37/37 pass (re-run independently at 0a302bf) — incl. 6 staleness-gate tests
docs:staleness:   PASS — 35 skills, 8 commands (re-run standalone)
e2e (Playwright): CI-covered; assertions statically verified to cover all 9 redirects + new-page 200

The staleness gate is genuinely test-first: real spawned-script negative cases (wrong skill count, wrong how-to count, adjective phrasings) AND a missing-dir loud-failure test. Not tautological. Strong.

Security Review

No security surface: static docs content, a read-only CI filesystem scan, static redirect config, tests. No secrets, no input handling, no dependencies added.

Adoption Compliance (Phase 3)

Inline dependency check (docs + config only): package.json diff is prettier normalization only → tech-stack clean; no new libraries/patterns → no ADR required. The redirects() block and gate extensions are same-pattern extensions of existing code. Commit-per-task granularity present (605bdfe/d4500ba/090eca2 = T1/T2/T3), commit/PR/branch follow templates. Single-PR delivery aligns with the adopted 2026-07-12-one-pr-per-story-default.md ADL.

Detailed Review Comments

Positive Feedback

  • Gate extension is test-first with real spawned negative cases and a fixture that isolates each check — matches the DoD bar the story itself set.
  • Conflict reconciliation in the FAQ/troubleshooting merge is explicit and rationalized (nvm recommended, alternatives retained), not a lossy concat.
  • Frozen anchors respected precisely; the one unavoidable link edit is disclosed and content-preserving.

Minor Issues 💡 (surfaced, non-blocking)

  1. scripts/docs-staleness-check.js:110 (GUIDE_COUNT_RE) — the widened regex (\d+)\s+(?:sequential\s+|step-by-step\s+)?(?:how-to\s+|process\s+)?guides now matches bare "N guides" (both qualifier groups optional). Concrete failure case: a future docs sentence like "the 4 journey guides" or "3 migration guides" would fail CI with a misleading "How-to guide count mismatch". Currently green (every live "N guides" = 9), so latent only. This is a broadening the prior re-review's Minor Setup & Project Management Integration #1 fix introduced but did not flag. Recommendation: require at least one qualifier (make the how-to/process group non-optional) or add an allowlist — the story already reserved the allowlist fallback for exactly this.

  2. scripts/docs-staleness-check.js:186 (Check 5 dead-link)LINK_RE only matches markdown ](/docs/...) syntax; JSX/Fumadocs <Card href="/docs/..."> links are not scanned. The hub and section indexes use markdown links today (covered), but a dead link inside a JSX card would escape the gate. Recommendation: extend the link scan to href="/docs..." if card-based navigation grows. Gate-completeness debt, not a regression.

Accepted / by-design (nonActionable — reported for transparency)

  • DoD "3 PRs" clause vs delivery as 1 PR — the story's DoD says "Each batch delivered as its own PR (3 PRs)"; delivered as a single PR. Superseded by the adopted 2026-07-12-one-pr-per-story-default.md ADL (one PR per story is the default; batching survives as commit-per-task). Not a defect — the DoD line is stale relative to the ADL.
  • 3 branch commits lack the [#312] prefix (cc9fcd2, fe62307, b48cb7f) — moot under the adopted squash-on-merge policy.
  • apps/website/package.json prettier escape-form churn — hook-applied, JSON-semantically identical. As agreed in the prior round.

Risk Assessment

Risk Impact Probability Mitigation
Guide-count gate false-positive on a non-how-to "N guides" phrase (Minor #1) Low Low Require a qualifier / allowlist; currently green
Dead JSX-card link escapes Check 5 (Minor #2) Low Low Extend link scan to href= if card nav grows

Tech Debt (assess-debt — output-only, non-blocking)

Verdict

Approved with Comments. All 8 ACs independently verified against 0a302bf; frozen anchors respected; website vitest 37/37 and docs:staleness re-run green; no Critical/Major findings. The two Minor items are gate-robustness improvements (non-blocking, safe to defer); remaining items are accepted-by-design. Merge remains human-gated (Phase 6 not run).

🤖 Canonical review via /pair-process-review — generated with Claude Code

Canonical review found the gate could not catch the very phrasings it
was meant to guard:

- skill regex now matches "N+ skills" (trailing +) and the
  agent/idempotent adjectives, not just pair/composable — "30+ skills"
  and "N agent skills" previously slipped through silently
- guide regex tightened: requires a how-to qualifier (adjective OR
  how-to/process word), so arbitrary "N guides" prose no longer
  false-positives in CI (was over-broadened in prior remediation)
- Check 5 dead-link scan extended to JSX `href="/docs/..."` card
  attributes (Fumadocs <Card>), not just markdown `](/docs/...)`
- README.md documented as intentionally out of docs-gate scope
  (literal counts owned by PR #325)

tests: +6 (N+/agent/composable skill mismatches, bare "N guides"
non-false-positive, dead + valid JSX href). All test-first (red→green).

Refs: PR #315 canonical review
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to Website Preview July 13, 2026 18:03 Inactive
@rucka

rucka commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Remediation — canonical /pair-process-review findings

Fix commit: 2c25c96.

Stale counts (website docs)

Re-checked on-branch: all skill counts are already 35 — the flagged lines were fixed in earlier commits on this branch, so nothing further to change:

  • getting-started/index.mdx:18 → already "35 composable skills" ✓
  • integrations/claude-code.mdx:28 → already "35 skills" (no "+") ✓
  • developer-journey/{index,execution}.mdx → already "35 skills" ✓
  • Re-grep apps/website for 3[0-4][+ ].{0,15}skill|3[0-4] (composable|agent) skill and for any [0-9]+\+? (pair|composable|agent|idempotent)? skills: zero stale hits — every occurrence is 35.

The real exposure was that the gate could not have caught those forms — addressed below.

Gate hardening — scripts/docs-staleness-check.js (the actual value)

1. Guide regex over-broadened → tightened. It matched bare "N guides" (latent CI false-positive on any non-how-to "guides" prose).

  • before: /(\d+)\s+(?:sequential\s+|step-by-step\s+)?(?:how-to\s+|process\s+)?guides/g
  • after: /(\d+)\s+(?:(?:sequential|step-by-step)\s+(?:how-to\s+|process\s+)?|(?:how-to|process)\s+)guides/g

Now a match requires a how-to qualifier — either a recognized adjective (sequential/step-by-step) or a how-to/process word. Bare "N guides" no longer matches; all six real phrasings still do (incl. "9 sequential guides", "9 step-by-step guides").

2. Skill regex evaded "N composable skills" (adjective) and "N+ skills" (the +) → widened.

  • before: /(\d+)\s+(?:pair\s+|composable\s+)?skills/g
  • after: /(\d+)\+?\s+(?:pair\s+|composable\s+|agent\s+|idempotent\s+)?skills/g

Adds the optional trailing + and the agent/idempotent adjectives (mirroring the guide fix). "30+ skills" and "N agent skills" can no longer silently persist.

3. README.md out of scope. The gate governs the published docs site (apps/website/content/docs) only. Extending the scan to root README.md would fail CI immediately on its live "33 Agent Skills" — a literal owned by PR #325 — coupling this PR to that one. Decision: documented README as intentionally out of docs-gate scope via a one-line note in the script, pointing to #325 for the literal fix.

Dead-link gate (Check 5) — JSX href= coverage gap

Effort was small (<30 min): all 10 existing href="/docs/..." card targets already resolve, so no false positives. Extended Check 5 to scan JSX card href="/docs/..." attributes alongside markdown ](/docs/...) links, closing the gap for the card-based section indexes (tutorials, contributing, customization).

Tests (test-first, red→green)

+6 cases in apps/website/lib/docs-staleness-check.test.ts: wrong "N composable skills", wrong "N+ skills", wrong "N agent skills", matching "N composable/N+ skills", bare "N guides" prose must NOT false-positive, dead JSX href fails + valid JSX href passes. Confirmed 4 went red before the script change, all green after.

Gates

website vitest 44/44 · docs:staleness PASS (35 skills, 8 commands) · mdlint PASS · knowledge-hub check:links PASS · e2e 39/39 · pre-push hook gates pass. next build not re-run — no content/docs or app source changed (script + test only).

🤖 Generated with Claude Code

@rucka

rucka commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Re-review of gate-hardening 2c25c96 — Approve

Independent adversarial re-review of the delta since 0a302bf (only commit: 2c25c96). Verified against the tree and by execution — not the remediation comment. Guarded specifically against both over- and **under-**matching in the changed regexes.

Findings — all clear

  1. Stale skill counts — none. Every skill-count claim in content/docs/** is 35 (skills-catalog, kb-structure, skill-management, developer-journey ×2, getting-started, integrations/claude-code, contributing/writing-skills, guidelines-catalog). The lone 3[0-4] hit is apps/website/CHANGELOG.md ("31 skills catalog") — a historical .md changelog, correctly outside the gate's content/docs .mdx scope; not a live claim.
  2. Guide regex tightened — no false-positive, no new blind spot. Probed the new GUIDE_COUNT_RE: bare prose ("5 guides at the museum", "3 tour guides") no longer matches; and all 10 live guide-count phrasings on the branch (ai-assisted-sdlc ×2, developer-journey index ×2 / execution, quickstart, guidelines-catalog ×3) — every one a genuine how-to-guide claim saying 9, each carrying a how-to/process/sequential/step-by-step qualifier — still match. No legitimate claim uses bare "N guides", so tightening loses no coverage. "9 guideline categories" correctly does not match (not a guide count).
  3. Skill regex widened — catches the evaders, no over-match. New COUNT_RE matches "30+ skills" (trailing +), "N agent/idempotent/composable/pair skills"; and does not match subset/prose forms ("9 process skills", "5 soft skills", "people skills") — the whitelist keeps it narrow.
  4. README out of scope — sound. The NOTE block is present and the rationale holds: the gate governs the published docs site only; README's literal counts are owned by PR [#313] fix: router/catalog + correctness fixes (task T1) #325 (coupling avoided).
  5. Dead-link Check 5 → JSX href — works. Scan now covers href="/docs/..." alongside ](/docs/...). All 10 JSX <Card href> targets (5 contributing, 5 tutorials) resolve — proven by the gate passing with the href scan active; dead + valid href tests present.
  6. Tests genuinely red→green. Ran the 6 new tests against the pre-fix (0a302bf) script: exactly 4 fail red (N+ skills, agent skills, bare-"N guides" non-false-positive, dead JSX href); the other 2 (composable-skill, valid-href) were already green because that behavior pre-existed — matching the author's "4 confirmed red" claim precisely. Fresh run at 2c25c96: gate PASS (35 skills, 8 commands); website vitest 44/44.
  7. Scope/regression — clean. Only scripts/docs-staleness-check.js + apps/website/lib/docs-staleness-check.test.ts touched (no content/docs or app-source changes this commit). Frozen paths reference/skills-catalog.mdx and reference/cli/commands.mdx untouched. No story AC regressed — change is purely additive gate robustness.

Verdict: Approved. No Critical/Major/Minor findings. Merge remains human-gated.

rucka and others added 2 commits July 13, 2026 20:57
…p script

Owner rule: tested functionality lives in production code and is tested
there — do NOT unit-test scripts. The gate violated this (logic in
scripts/docs-staleness-check.js, test spawned it black-box).

- port ALL logic verbatim (incl. #315 hardening: tightened guide regex,
  widened skill regex with +/adjectives, JSX href dead-link scan, README
  out-of-scope note) into apps/website/lib/docs-staleness-check.ts —
  ESM module, functions exported individually, import.meta main-guard
  CLI wrapper, DOCS_STALENESS_ROOT retained, root resolved up 3
- rewrite the test as WHITE-BOX vitest unit tests importing the exported
  functions directly; ZERO spawnSync/exec — real-tree parity asserted
  in-process via runAllChecks(). red->green coverage preserved as
  per-function negatives (wrong N+/composable/agent skills, bare
  "N guides" non-false-positive, dead/valid JSX href, missing how-to dir)
- wire: tsx (catalog 4.23.1) + website script docs:staleness=tsx;
  root docs:staleness delegates to @pair/website, unchanged in
  quality-gate + ci.yml (now delegates)
- delete scripts/docs-staleness-check.js (single source of truth);
  update decision-log path refs

Refs: PR #315 architectural rule (no test-on-script)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…on scripts

Record the architectural rule the docs-staleness refactor implements as
a non-architectural ADL (adoption/decision-log/2026-07-13-gate-tooling-
code-in-tested-modules.md): gate logic lives in tested owning-package
modules; scripts/CLIs are thin entrypoints; root gates delegate; scripts
are never unit-tested (smoke tests cover CLI end-to-end).

- complements (does not amend) the test-file-colocation ADL — placement
  vs module-vs-script boundary are orthogonal; cross-linked
- surfaced from way-of-working Quality Gates ("Gate & tooling code" bullet)
- no dataset mirror (adoption decision-log is not auto-mirrored; siblings
  husky/colocation are adoption-only)

Refs: PR #315 architectural rule (no test-on-script)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot temporarily deployed to Website Preview July 13, 2026 19:01 Inactive
@rucka

rucka commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Refactor: docs-staleness gate → tested module (no test-on-script) + ADL

Applies the repo-owner architectural rule — tested functionality lives in production code and is tested there; scripts are not unit-tested (use a smoke test if you want CLI-level coverage). The docs-staleness gate violated it: logic sat in scripts/docs-staleness-check.js and its vitest test black-box spawnSync'd the script. Mirrors the skills-conformance treatment (#313/#324), homed in the website package since docs-staleness is a website-docs integrity gate.

What changed (bc83c37, 46292c8)

  • Module: apps/website/lib/docs-staleness-check.ts — ALL logic ported verbatim, incl. the [#312] docs: website IA restructuring (Option A) — hub, dissolve guides/, dedupe, extend staleness gate #315 hardening (tightened guide regex, widened skill regex with +/adjectives, JSX href="/docs/..." dead-link scan, README out-of-scope note). ESM, each check exported individually, import.meta main-guard CLI wrapper printing the same PASS/FAIL + exit codes, DOCS_STALENESS_ROOT retained. Root resolved up 3 (lib → website → apps → root).
  • Tests → white-box: docs-staleness-check.test.ts rewritten to import the exported functions and assert on them directly. Zero spawnSync/exec anywhere in the vitest suite (verified by grep). Real-tree parity is asserted in-process by calling runAllChecks(REPO_ROOT) (import, not spawn). Every prior assertion's intent is preserved as a direct function test — wrong N+/composable/agent skills, bare "N guides" non-false-positive, dead vs valid JSX href, missing how-to dir, catalog sync, command anchors.
  • Wiring: tsx added (catalog 4.23.1); website docs:staleness = tsx lib/docs-staleness-check.ts; root docs:staleness = pnpm --filter @pair/website docs:staleness — unchanged position in quality-gate, and the CI step pnpm docs:staleness is untouched (now delegates).
  • Deleted: scripts/docs-staleness-check.js. Repo-wide grep for scripts/docs-staleness-check / docs-staleness-check.js → zero dangling refs (decision-log path refs updated).

ADL

Recorded the rule as a non-architectural ADL: .pair/adoption/decision-log/2026-07-13-gate-tooling-code-in-tested-modules.md (Category: Convention Adoption). It complements — does not amend — the test-file-colocation ADL (2026-07-08-test-file-colocation-multi-module.md): that one governs where a test file sits; this one governs what becomes a tested module vs a thin script, and that scripts are never unit-tested (smoke tests cover CLI end-to-end). Surfaced from way-of-working.md Quality Gates ("Gate & tooling code" bullet). No dataset mirror — adoption decision-log is not auto-mirrored (siblings husky/colocation are adoption-only).

Verification

pnpm docs:staleness (delegated) → PASS (35 skills, 8 commands); DOCS_STALENESS_ROOT=<fixture with wrong count> → exit 1 with the mismatch message; website vitest 57/57 incl. the white-box suite; pnpm --filter @pair/website ts:check PASS; mdlint PASS; knowledge-hub check:links PASS; e2e 39/39. next build not re-run (no content/docs or app-runtime source touched). Confirmed: no spawnSync/exec of any script remains in the vitest suite.

🤖 Generated with Claude Code

@rucka

rucka commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

Re-review of docs-staleness module-ization + ADL — Approve

Independent re-review of the delta since 2c25c96 — commits bc83c37 (refactor) + 46292c8 (ADL) — applying the owner's rule "tested logic lives in production code; don't unit-test scripts; CLIs via smoke tests." Verified against the tree and by execution.

Findings — all clear

  1. Behavioral parity — complete. Diffed old scripts/docs-staleness-check.js vs new apps/website/lib/docs-staleness-check.ts. Every check preserved, byte-identical regexes incl. the [#312] docs: website IA restructuring (Option A) — hub, dissolve guides/, dedupe, extend staleness gate #315 hardening: SKILL_COUNT_RE = /(\d+)\+?\s+(?:pair\s+|composable\s+|agent\s+|idempotent\s+)?skills/g, tightened GUIDE_COUNT_RE (how-to qualifier required), JSX HREF_RE alongside markdown LINK_RE in the dead-link scan, loud missing-how-to-dir failure, catalog sync (both directions), command anchors, tutorial pair-cli refs, and the README-out-of-scope note. Same PASS/FAIL output wording and exit codes. Error ordering differs cosmetically (single per-file loop) — no effect on pass/fail outcome.
  2. No test-on-script — satisfied (core of the rule). docs-staleness-check.test.ts is white-box: imports the exported functions (findSkillCountMismatches, findGuideCountMismatches, findDeadLinks, checkCatalogSync, checkCommandAnchors, checkTutorialCommands, countHowToGuides, buildValidRoutes, runAllChecks) and asserts directly. Grep of the entire website suite for spawnSync|child_process|execSync|exec(|spawn(: zero. The old spawnSync-against-fixture approach is gone; tests now run in ~8ms.
  3. Wiring — correct. Root docs:staleness = pnpm --filter @pair/website docs:staleness; website script = tsx lib/docs-staleness-check.ts; quality-gate position unchanged (… hygiene:check && pnpm docs:staleness && pnpm dup:check), CI step unchanged. tsx@4.23.1 added via pnpm catalog. Lockfile delta is tsx/esbuild-only: additive tsx@4.23.1 + esbuild@0.28.1 (tsx's bundled esbuild) + peer-hash re-anchoring (identical vite@7.2.6/vitest@3.2.4/fumadocs-mdx@11.10.1 versions, only (tsx@4.23.1) appended to the fingerprint); zero removed resolutions, zero unrelated bumps. Ran pnpm docs:staleness from root → PASS (35 skills, 8 commands); a DOCS_STALENESS_ROOT fixture with a wrong count → exit 1 with the correct mismatch message.
  4. Path resolution — correct. resolve(MODULE_DIR, '../../..') (lib→website→apps→root) resolves the dataset/pair-cli/docs paths; the gate finds 35 skills, not 0 (confirmed by the PASS run). Repo grep for scripts/docs-staleness-check / docs-staleness-check.js: the only hits are inside the ADL narrative (intentional history) — zero dangling wiring.
  5. ADL — well-formed. 2026-07-13-gate-tooling-code-in-tested-modules.md: date-based, no sequence number, matching all siblings; classified "Convention Adoption" (non-architectural → ADL is the right instrument); explicitly complements 2026-07-08-test-file-colocation-multi-module.md (bidirectional cross-link, orthogonal scopes: co-location owns WHERE a test sits, this owns module-vs-script boundary — no contradiction); surfaced via a new Quality Gates bullet in way-of-working.md. No dataset mirror: rationale sound and verified — decision-log is adoption-only, the dataset is a curated sample not an auto-mirror; the diff touches no packages/knowledge-hub/dataset/**.
  6. No regression. Diff since 2c25c96 touches only the module, its test, the ADL, way-of-working, the assessment doc (accurate scripts/*.jslib/*.ts reference updates + one past-tense F5 phrasing), package/lock/workspace wiring, and the deleted script — no content/docs/** or app-source changes. Frozen paths reference/skills-catalog.mdx and reference/cli/commands.mdx untouched. Website vitest 57/57 (26 white-box staleness tests). e2e unaffected (no URL/heading/content change) — relying on CI's reported 39/39.

Verdict: Approved. No Critical/Major/Minor findings. Merge remains human-gated.

rucka added a commit that referenced this pull request Jul 13, 2026
- implement-batch.js Input: batch items are STORIES (one branch + one PR, create-or-update), never one-PR-per-task; second PR forbidden unless human instructs
- implementer.md: add one-PR-per-story operating rule + pointer to gate/test ADL
- implement SKILL (dataset + .claude mirror): one-PR-per-story reinforcement line
- git-workflow (dataset + root mirror): normative one-PR-per-story in branch/PR strategy
- reviewer.md unchanged (never opens PRs — Rule 2 no-op)

Refs owner rules 1 (gate/test) + 2 (one-PR-per-story); gate/test ADL lands on PR #315.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rucka added a commit that referenced this pull request Jul 13, 2026
- implement-batch.js Input: batch items are STORIES (one branch + one PR, create-or-update), never one-PR-per-task; second PR forbidden unless human instructs
- implementer.md: add one-PR-per-story operating rule + pointer to gate/test ADL
- implement SKILL (dataset + .claude mirror): one-PR-per-story reinforcement line
- git-workflow (dataset + root mirror): normative one-PR-per-story in branch/PR strategy
- reviewer.md unchanged (never opens PRs — Rule 2 no-op)

Refs owner rules 1 (gate/test) + 2 (one-PR-per-story); gate/test ADL lands on PR #315.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@rucka rucka merged commit c6f5184 into main Jul 13, 2026
2 checks passed
@rucka rucka deleted the docs/website-structure-assessment branch July 13, 2026 19:43
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.

Docs website IA restructuring (Option A): real /docs hub, dissolve guides/, dedupe FAQ/packaging, extend staleness gate

1 participant