Phase 0 Research: Docs Site IA & Onboarding Overhaul
All items below were either resolved directly with the user during specify/plan discovery (decision IDs referenced where applicable) or grounded in direct repository research. No [NEEDS CLARIFICATION] markers remain.
1. Redirect mechanism for moved/deleted pages
scripts/docs/redirect_map.yaml mechanism, adding one entry per moved/deleted path.
common-docs-consolidation mission (ADR docs/adr/3.x/2026-06-27-1-common-docs-reconciliation.md, decision D4) already solved this exact problem at much larger scale (~1,589 link occurrences) with a generated <meta http-equiv="refresh"> stub emitted at the old path by a post-build step reading a checked-in redirect map. Reusing it is both "use canonical sources" doctrine and the only tested option.
existing, proven infrastructure). Accepting URL churn with no redirects (rejected — breaks NFR-006's zero-orphaned-pages guarantee and regresses external links/SEO).
- Decision: Reuse the existing
scripts/docs/redirect_stub_generator.py+ - Rationale: DocFX on GitHub Pages has no native alias/redirect mechanism. The
- Alternatives considered: Building a new redirect mechanism (rejected — duplicates
2. Zone segregation approach (physical move scope)
move only genuinely misplaced content — contributor-only runbooks currently stranded inside docs/guides/ (e.g. pr-landing.md, testing-flakiness.md, recover-from-interrupted-merge.md) — into the existing docs/development/ contributor root. Already-correctly-scoped sections keep their current file locations and are grouped into one of the two zones purely via toc.yml nesting.
rule (specify-phase discovery), but also asked to "reduce overall volume ... not repeat ourselves or focus on minutiae." A full two-root rebuild would touch all ~600 files and regenerate proportionally more redirect-map churn than the actual problem (a 72-file mixed folder) warrants. Confirmed via Engineering Alignment in the plan-phase conversation.
churn for sections research already found structurally sound). Toc.yml-only cosmetic grouping with zero file moves (rejected — doesn't satisfy "STRICT" segregation, since a determined visitor could still browse from an end-user page directly into a contributor-only file at its unchanged path).
- Decision: Do not rebuild the entire
docs/tree into two fresh top-level roots. Instead, - Rationale: The user confirmed "restructure freely" with "STRICT segregation" as a binding
- Alternatives considered: Full physical two-root rebuild (rejected — disproportionate
3. Glossary term-linker mechanism
run in the same pipeline stage pattern as the existing seo_postprocess.py. Markdown source files are never mutated.
resolved). Keeps authored prose clean and diffable; linking logic lives in one script; re-running it never drifts from hand-edited source. DocFX's native xref system was investigated and rejected (see item 4).
drifts on every text edit). DocFX xref/@-uid cross-references (rejected — see below).
- Decision: Build-time HTML post-processing pass (new
scripts/docs/glossary_linker.py), - Rationale: User-confirmed via Decision Moment
01KY03YGX7GQEBKV45Q2Q8FXK3(plan flow, - Alternatives considered: Markdown source rewrite (rejected by user — pollutes prose,
4. Why DocFX xref is not used for glossary linking
this repository. DocFX's xref system expects build-time uid-tagged content (typically generated API-doc YAML), not ad hoc prose-term matching, and the glossary source (kitty-specs/glossary.html) is generated by a separate static-HTML build step (scripts/docs/generate_kitty_specs_docs.py) that is not part of the DocFX markdown content build at all — it's picked up only via docfx.json's resource.files glob. A markdown/HTML post-processing pass is the natural fit, not xref.
- Finding:
grepacrossdocs/anddocs/docfx.jsonfound zero existingxrefusage in
5. Canonical-term-usage check placement
— following the structural pattern of tests/architectural/test_no_legacy_terminology.py, but sourcing its term list from .kittify/glossaries/spec_kitty_core.yaml (104 terms) instead of a hardcoded denylist.
existing schema) with full alias/banned-synonym governance deferred to a follow-up GitHub issue (C-003). test_no_legacy_terminology.py checks a small, unrelated denylist (2 legacy terms) — conflating it with a 104-term canonical-form checker would make failures harder to diagnose. A sibling test keeps the two concerns separable while reusing the established pytest.mark.architectural / docs_scoped marker convention so it runs in the same CI job (integration-tests-core-misc) as the existing terminology guard.
conflates two different data sources and failure semantics). A standalone CLI command outside pytest (rejected — no existing precedent for a docs-only CLI gate in this repo; the pytest architectural-test pattern is already CI-wired and understood by maintainers).
- Decision: New, separate pytest test —
tests/architectural/test_glossary_canonical_terms.py - Rationale: User confirmed "lighter check now" (canonical spelling/casing only, against the
- Alternatives considered: Extending
test_no_legacy_terminology.pydirectly (rejected —
6. Hierarchical navigation mechanism (FR-015, added mid-plan)
≤6 unexpanded top-level entries each.
entry already uses nested items: and renders correctly in the site's default theme today. No template, theme, or pipeline change is required, keeping this compliant with C-001.
would require touching DocFX template/theme internals, which C-001 puts out of scope, for no benefit over the native mechanism DocFX already provides).
- Decision: Use DocFX's native nested
toc.ymlitems:syntax to group both zones into - Rationale: Verified by direct read of
docs/toc.yml— the existing "Historical Archive" - Alternatives considered: A custom hamburger-menu widget via injected JS/CSS (rejected —
7. Doctrine artifact kind vocabulary
procedure, agent_profile, mission_step_contract.
tactic, styleguide, toolguide, paradigm, template, agent_profile, mission_step_contract). Correction (post-plan, during WP06 implementation): CLAUDE.md's table was stale. Independently verified against src/charter/kind_vocabulary.py, src/doctrine/artifact_kinds.py, git history (commit 1e3dc8d2c, "first-class TEMPLATE + loose-contract ASSET doctrine kinds"), and the live installed CLI (spec-kitty charter activate bogus-kind x → lists valid kinds; spec-kitty charter list --all) — the real 8th charter-activatable kind is procedure, not template. template and asset became distinct, non-charter-activatable kinds in a later commit and CLAUDE.md was never updated. This mission's authored content (docs/doctrine/doctrine-kinds.md) uses the code/CLI-verified list; spec.md and data-model.md were corrected to match. Single canonical authority is the live source/CLI, not a cached doc table — consistent with this mission's own FR-007 rationale.
- Decision: Document exactly 8 kinds — directive, tactic, styleguide, toolguide, paradigm,
- Rationale: Originally sourced from project CLAUDE.md's documented table (directive,
8. Mission-type vocabulary
— each sourced from its own src/specify_cli/missions/<type>/mission.yaml.
itself uses documentation, confirming the type exists and is distinct from software-dev (which a prior docs mission, spec-kitty-3-2-docs, used instead — noted as a precedent inconsistency but not something this mission needs to correct retroactively).
- Decision: Document exactly 4 mission types — software-dev, research, documentation, plan
- Rationale: Verified by directory listing of
src/specify_cli/missions/; this mission
9. Reuse vs. rebuild of the abandoned charter-end-user-docs-828 mission's findings
IC-04/IC-05 authoring, never as ground truth (C-006 in spec.md).
validated against the current codebase and may be stale relative to this mission's own, fresher audit.
- Decision: Treat that mission's
gap-analysis.md/research.mdas optional input during - Rationale: That mission was abandoned with 0 of 10 WPs completed — its analysis was never
10. Auto-generated gap-analysis.md (mechanical tool output)
over the entire repository (605 files, including non-docs/ directories like specify_cli, kernel, runtime, templates that are not part of the published site). Its directory-level heuristic classification is too coarse to drive this mission's IA decisions directly.
one in spec.md's "Documentation Scope → Known gaps" section, built from targeted, verified research (homepage framing, orphaned tutorial, mixed guides/ folder, thin doctrine docs, scattered charter guidance, unlinked glossary) rather than the mechanical tool's per-directory Divio-type matrix.
- Finding:
spec-kitty agent mission setup-planauto-ran a generic coverage-matrix tool - Decision: Treat it as a supplementary data point only. The authoritative gap list is the