Skip to content

Astro + Starlight docs site + Warp docubot port + /update-docs decommission — PLAN

Astro + Starlight docs site + Warp docubot port + /update-docs decommission — PLAN

Section titled “Astro + Starlight docs site + Warp docubot port + /update-docs decommission — PLAN”

Status: DRAFT ({9.4}, kh-prod-readiness-S61). Authored by a FRESH task-planner instance per Q-PLANNER-2 (NOT the {9.2} PRODUCT or {9.3} TECH Planner). Decomposes the ratified PRODUCT.md (52 invariants) + TECH.md (1342 lines, §0–§7 + Testing-and-validation 52-row 1-to-1 mapping + §Parallelization 17-slice sketch) into seventeen implementation Subtasks (9.5 through 9.21) plus this PLAN Subtask (9.4). Sibling-only Subtask dependency constraint honoured throughout (no cross-Task dependency surfaced; escalation tripwire was not hit).


  • PRODUCT spec (ratified {9.2} S59): ./PRODUCT.md — 52 numbered Behaviour invariants across four scope-thirds plus supporting deliverables.
    • Third 1 (Docs site): Inv-1..24 (24 invariants — IA, rendering, sync hierarchy, AI-invisibility, UK English).
    • Third 2 (Docubot port): Inv-25..35 (11 invariants — trigger, authoring, auth, Phase-2 composability).
    • Third 3 (5-skill port): Inv-36..43 (8 invariants — scope, per-skill triggers, workflow shape).
    • Third 4 (Decommission): Inv-44..50 (7 invariants — successor mapping, two-session sequence, hard deadline).
    • Supporting deliverables (OQ-1 DEFAULT): Inv-51..52 (2 invariants — AGENTS.md + keep-docs-in-sync).
  • TECH spec (ratified {9.3} S60): ./TECH.md — §0 name resolution + 4 critical locks (Inv-30 docubot direct-write; KH-persona prompt template; canonical 5-skill workflow shape; Vercel-default-subdomain framing); §1 Context; §2 Docs site infrastructure (11 subsections); §3 Docubot port (7 subsections); §4 Five-skill port (canonical shape + 5 per-skill); §5 /update-docs decommission; §6 Cross-third integration (AGENTS.md + keep-docs-in-sync); §7 Cross-project packaging; Testing-and-validation table (52-row 1-to-1 invariant → test mapping); End-to-end Mermaid sequence diagram; Risks (15 rows); Parallelization (17-slice sketch); Follow-ups (13 explicit non-goals); 3 new OQs (T1/T2/T3 — all ratified at S60 close).
  • Research (background, {9.1}): docs/research/docs-site-rebuild-research.md — 716 lines, 6 Warp docs skills inventoried + docubot mechanism + KH docs/ IA audit + delta vs stale S47 specs.

Ratifications absorbed at {9.3} close (S60)

Section titled “Ratifications absorbed at {9.3} close (S60)”

The three new TECH OQs were Liam-ratified at S60 close:

OQRatificationPLAN consequence
OQ-T1 (docubot divergence handling)DEFAULT — front-matter flag (kh_docubot_owned: true) + sync-script honour9.6 sync script honours the flag; 9.11 docubot prompt enforces the flag
OQ-T2 (per-skill cron-trigger enablement)DEFAULT — enable all 4 active crons at foundation9.15 (sync-source-docs weekly), 9.17 (check-for-broken-links daily), 9.18 (docs-seo-audit — cron present but commented per OQ-T3) ship with crons enabled
OQ-T3 (docs-seo-audit deferred-enable)DEFAULT — workflow file committed with schedule: commented out, uncomment post-deploy9.18 docs-seo-audit ships workflow file with schedule: block commented; Follow-up commit (NOT a Subtask) uncomments post first-deploy

The three PRODUCT OQs (OQ-6 ci.yml direct-commit-vs-side-PR, OQ-7 cross-worktree preview, OQ-8 AGENTS.md vs CLAUDE.md separation) were ratified at S59 close per {9.2} PRODUCT close-out notes — folded into TECH §5.2 (direct-commit with side-PR fallback), §2.5 (--source-root flag), §6.1 (complementary AGENTS.md cross-references CLAUDE.md).


  1. Vertical slicing. Each Subtask delivers a vertical capability slice leaving the system in a working state. Horizontal slicing (build all infra first then all features) is explicitly avoided. The scaffold-first Subtask (9.5) is the one foundation slice; everything thereafter is a capability that adds independently-verifiable value.
  2. Sibling-only Subtask dependencies (§3.3 / A6 forcing function). Every implementation Subtask depends only on other Subtasks of ID-9. No cross-Task dependency surfaced during decomposition. ID-19.x (worktree isolation hooks) is referenced in TECH only as a brief-authoring discipline pointer (CLAUDE.md ID-19.4) and requires no co-edit. ID-15 (legacy ID migration) is independent — docubot reads task-list.json / roadmap / backlog via standard tooling.
  3. ≤2-3h per Subtask. Aligned with the workflow rule “max 2h per Executor dispatch” (CLAUDE.md). Most Subtasks sit at ~1.5-2h; the four marked ~2-3h (9.5 scaffold + 9.6 sync + 9.11 composite action + 9.16 missing-docs) carry buffer for unforeseen scope mid-flight.
  4. Dependency-graph foundations first. Scaffold (9.5) precedes sync (9.6) and theming (9.7); AGENTS.md (9.9) precedes anything that loads it in prompt context (9.10, 9.11, 9.13); composite action (9.11) precedes workflow (9.12) and skill-driver inheritance (9.13).
  5. Parallelization-friendly per TECH §Parallelization. After 9.5 lands: 9.6 + 9.7 can run in parallel worktrees. After 9.9 + 9.10 land: 9.11 + 9.19 (independent ci.yml edit) parallelize. After 9.13 lands: 9.14-9.18 (five skill bodies) parallelize fully. After 9.12 + 9.14 land: Session A (9.20) can begin while 9.15-9.18 still settle. Worktree parallelization guidance is per-Subtask under §Notes for Orchestrator dispatch.
  6. Coverage transitivity, not invariant-per-Subtask 1:1. TECH’s Testing-and-validation table already maps each PRODUCT invariant to a concrete test colocated with the TECH §. Each Subtask below cites the invariant range and TECH § it implements; full 52/52 coverage verified under §Coverage verification.
  7. Sub-agent worktree heritage discipline (per CLAUDE.md ID-19.4). Every Subtask’s details field opens with a verbatim worktree-first-action gate (pwd && git branch --show-current && git fetch origin production-readiness && git reset --hard origin/production-readiness && git branch --show-current && git status). No cd prefix anywhere in dispatch text. Absolute paths reserved for the worker’s own worktree only; sibling-worktree absolute paths NEVER mentioned in dispatch text (primer effect risk).
  8. Test philosophy alignment (docs/reference/test-philosophy.md). Every Subtask’s testStrategy line names the concrete file paths under docs-site/__tests__/, __tests__/skills/, __tests__/workflows/, or __tests__/scripts/ that the Executor authors. Where a behaviour is only verifiable by manual session-close inspection (e.g. docubot run quality on 3 sample PRs), the testStrategy says so explicitly with the Inv-X acceptance criterion cited.

9.4 PLAN.md (this Subtask, in_progress at dispatch)
├── 9.5 Docs-site scaffold (§2.1 + §2.3 + §2.4)
│ └── (foundation; no deps)
├── 9.6 Sync script + manifest + divergence-flag honour (§2.5 + §2.6 + §3.4)
│ └── depends on 9.5 (needs content-collection schema + spaces config)
├── 9.7 Warm Meridian theming + token-drift guard (§2.7 + §2.8)
│ └── depends on 9.5 (needs customCss path + astro.config.mjs surface)
├── 9.8 AI-invisibility + UK English CI guards + 404 + empty states (§2.9 + §2.10 + §2.11)
│ └── depends on 9.6 (operates on synced output)
├── 9.9 AGENTS.md at repo root (§6.1)
│ └── (foundation; no deps; standalone repo-root file)
├── 9.10 keep-docs-in-sync skill (§6.2)
│ └── depends on 9.9 (cross-references AGENTS.md)
├── 9.11 Docubot composite action + KH-persona prompt template (§3.1 + §3.3 + §3.6)
│ └── depends on 9.9 + 9.10 (prompt rule names both)
├── 9.12 Docubot workflow + Claude Agent SDK driver (§3.2 + §3.5 + §3.7)
│ └── depends on 9.11 (workflow invokes composite action)
├── 9.13 5-skill canonical workflow scaffold + shared driver (§4.1 + §4.2)
│ └── depends on 9.9 + 9.10 + 9.11 (driver loads AGENTS.md +
│ keep-docs-in-sync; inherits composite action shape)
├── 9.14 review-docs-pr skill body + workflow (§4.3)
│ └── depends on 9.13 (uses shared driver)
├── 9.15 sync-source-docs skill body + workflow (§4.4)
│ └── depends on 9.13 (uses shared driver)
├── 9.16 missing-docs skill body + Python audit script + workflow (§4.5)
│ └── depends on 9.13 (uses shared driver)
├── 9.17 check-for-broken-links skill body + Python link-walker + workflow (§4.6)
│ └── depends on 9.13 (uses shared driver)
├── 9.18 docs-seo-audit skill body + Python audit + workflow (§4.7)
│ └── depends on 9.13 (uses shared driver)
├── 9.19 ci.yml regenerate-stats job (§5.2)
│ └── (independent ci.yml edit; no deps)
├── 9.20 Session A decommission verification gate (§5.3 gate 1)
│ └── depends on 9.12 (docubot live) + 9.14 (review-docs-pr live for
│ Inv-35 second-pass requirement); Liam manual review of 3 sample
│ docubot PRs
└── 9.21 Session B atomic decommission: ci.yml verified + remove update-docs
+ CLAUDE.md atomic edit (§5.4 + §5.5)
└── depends on 9.19 (regenerate-stats job verified live) + 9.20
(Session A gate closed)

Total: 4 spec Subtasks (9.1 RESEARCH done, 9.2 PRODUCT done, 9.3 TECH in_progress→done at S61, 9.4 this PLAN) + 17 implementation Subtasks (9.5 through 9.21) = 21 total Subtasks under ID-9. Within the 25-Subtask soft ceiling per §3.4 / A7.


Phase 1 — Docs-site foundation (must land before any docubot work)

Section titled “Phase 1 — Docs-site foundation (must land before any docubot work)”
  • 9.5 Docs-site scaffold (Astro + Starlight + Vercel + content collection)
  • 9.6 Sync script + manifest + divergence-flag honour (parallel-eligible after 9.5)
  • 9.7 Warm Meridian theming + token-drift guard (parallel-eligible after 9.5)
  • 9.8 AI-invisibility + UK English CI guards + 404 + empty states (parallel-eligible after 9.6)

Checkpoint after Phase 1 (9.5+9.6+9.7+9.8):

  • cd docs-site && bun install && bun run build succeeds from a fresh clone (acceptance criterion third 1 row 1).
  • All 5 canonical front-door directories publish to their assigned spaces in the visible 5-space sidebar.
  • Vercel sibling project knowledge-hub-docs deploys to a default subdomain Liam can browse.
  • Warm Meridian palette visibly applied; no default Starlight cobalt-blue.
  • CI gates the docs build (malformed front matter / broken internal link / removed referenced page → build fails).
  • AI-invisibility grep guard fails build on forbidden phrases.

Phase 2 — Style guide + skill foundation (parallel-eligible with Phase 1 sync work)

Section titled “Phase 2 — Style guide + skill foundation (parallel-eligible with Phase 1 sync work)”
  • 9.9 AGENTS.md at repo root (independent of docs-site; can run in parallel with 9.5-9.8)
  • 9.10 keep-docs-in-sync skill (depends on 9.9)

Checkpoint after Phase 2 (9.9+9.10):

  • AGENTS.md exists at repo root with the 5 required sections per Inv-51.
  • .claude/skills/keep-docs-in-sync/SKILL.md exists with the 7 required sections per Inv-52.
  • Both files validated by __tests__/agents-md/agents-md-shape.test.ts + __tests__/skills/keep-docs-in-sync-shape.test.ts (NEW).

Phase 3 — Docubot (depends on Phase 1 docs-site + Phase 2 style guide)

Section titled “Phase 3 — Docubot (depends on Phase 1 docs-site + Phase 2 style guide)”
  • 9.11 Docubot composite action + KH-persona prompt template
  • 9.12 Docubot workflow + Claude Agent SDK driver

Checkpoint after Phase 3 (9.11+9.12):

  • .github/actions/docubot/action.yml + .github/workflows/docubot.yml
    • .github/actions/docubot/prompt.txt all present.
  • workflow_dispatch invocation succeeds end-to-end on at least one sample run (Inv-25 acceptance).
  • pull_request.types: [closed] filter on merged == true triggers docubot on at least one real source-PR merge.
  • Run artefacts (prompt.output.txt + SDK log) upload on every run via actions/upload-artifact@v4 with if: always().

Phase 4 — 5-skill port (depends on Phase 3 docubot composite action)

Section titled “Phase 4 — 5-skill port (depends on Phase 3 docubot composite action)”
  • 9.13 5-skill canonical workflow scaffold + shared driver
  • 9.14-9.18 Five per-skill bodies + workflows (parallelizable after 9.13)

Checkpoint after Phase 4 (9.13+9.14+9.15+9.16+9.17+9.18):

  • All 5 skills present at .claude/skills/<name>/SKILL.md (review-docs-pr, sync-source-docs, missing-docs, check-for-broken-links, docs-seo-audit).
  • Each has its .github/workflows/<name>.yml workflow file matching docubot.yml’s canonical shape per Inv-43.
  • update-changelog is explicitly NOT present (OQ-3 OVERRIDE confirmed via __tests__/skills/skill-inventory.test.ts).
  • Each skill loads AGENTS.md (verified by grep of scripts/skills/run-skill.ts).

Phase 5 — Decommission (depends on Phase 3 docubot + Phase 4 review-docs-pr)

Section titled “Phase 5 — Decommission (depends on Phase 3 docubot + Phase 4 review-docs-pr)”
  • 9.19 ci.yml regenerate-stats job (independent; can land any time after 9.5 stabilises)
  • 9.20 Session A decommission verification gate
  • 9.21 Session B atomic decommission + CLAUDE.md edit

Final checkpoint after Phase 5 (9.19+9.20+9.21):

  • ci.yml regenerate-stats job runs successfully on at least one merge-to-main commit (Inv-48 acceptance).
  • Session A gate closed: docubot demonstrably handled (a)+(b)+(d) workloads on at least 3 sample source-PR merges (per OQ-PLAN-1, synthetic via workflow_dispatch on 3 historical PRs is acceptable).
  • .claude/skills/update-docs/ directory removed.
  • CLAUDE.md atomically updated to remove /update-docs references + add docubot + keep-docs-in-sync references (same commit as the directory removal — Inv-49).
  • Hard deadline honoured per Inv-50 (no /update-docs lingering beyond Session B).

Every dependency emitted by the Subtasks below points to another Subtask of ID-9. No cross-Task dependency surfaced.

SubtaskDepends onAll deps are siblings of ID-9?
9.5(none)yes — no deps
9.69.5yes
9.79.5yes
9.89.6yes
9.9(none)yes — no deps
9.109.9yes
9.119.9, 9.10yes
9.129.11yes
9.139.9, 9.10, 9.11yes
9.149.13yes
9.159.13yes
9.169.13yes
9.179.13yes
9.189.13yes
9.19(none)yes — no deps
9.209.12, 9.14yes
9.219.19, 9.20yes

No cross-Task dependency surfaced. The forcing-function escalation tripwire (Q-PLANNER-2 / A6) was not hit. ID-19.x (worktree-isolation hooks) is referenced as brief-authoring discipline only — non-coupling. ID-15.x (legacy ID migration) reads/writes occur via standard tooling; no ID-9-Subtask depends on an ID-15-Subtask outcome.


Total Subtasks under ID-9 after this PLAN lands: 21 (9.1 through 9.21). Within the 25 soft ceiling (per workflow-orchestration §3.4 / A7). The 4-spec-chain + 17-implementation split keeps the boundary correct — no Task split surfaced as necessary.

If 9.16 (missing-docs) blows up during implementation (Python audit script has four sub-audits and could realistically split per-sub-audit), the Orchestrator may add 9.22+9.23+9.24+9.25 sub-slicing missing-docs into 4 sub-audits. That would land at exactly 25 — still within the ceiling. A fifth split would breach. If breached, the Orchestrator escalates and splits into ID-9a / ID-9b (per workflow §3.4 escalation pattern).


This PLAN surfaces THREE new OQs (one per workflow rule ≤3 ceiling), all with defaults the Executor may proceed against unless Liam overrides.

New OQ-PLAN-1 — Session A docubot acceptance gate: synthetic vs organic source-PR merges

Section titled “New OQ-PLAN-1 — Session A docubot acceptance gate: synthetic vs organic source-PR merges”

Question: Per PRODUCT Inv-47 + acceptance criteria third 4: “Docubot opens at least 3 sample docs-PRs on real source-PR merges.” Is “real” a hard requirement (3 organic post-Phase-3 source-PR merges in steady state), or is workflow_dispatch invocation against 3 historical PR numbers acceptable (synthetic)? The trigger path (pull_request.types: [closed] + merged == true filter) is identical to workflow_dispatch for the docubot’s actual run — only the launch event differs.

Default proposed: Synthetic is acceptable. Rationale: (a) the trigger path is functionally identical from docubot’s perspective (same composite action, same prompt template, same SDK invocation, same single-comment guardrail); (b) waiting for 3 organic merges post-Phase-3 could delay the Session B gate by days/weeks depending on PR cadence, breaching the Inv-50 two-session bound; (c) the synthetic path exercises the same gh pr view

  • gh pr diff context gather + envsubst + SDK + git-commit + gh-pr-create
  • gh-pr-comment chain.

Why this is an OQ: “Real source-PR merges” in Inv-47 could reasonably read either way. Liam may prefer to wait for organic merges if the goal is to exercise the natural trigger event under real load. The default unblocks Session A; the override pushes Session A close-out into a later session.

New OQ-PLAN-2 — 5-skill rollout ordering relative to Session A gate

Section titled “New OQ-PLAN-2 — 5-skill rollout ordering relative to Session A gate”

Question: Per Phase 4 (5-skill port) + Phase 5 (decommission Session A), which of the five skills MUST be live before Session A’s gate closes?

  • Inv-35 (Phase 2 composability) requires review-docs-pr to run against the docubot-opened docs-PR as a second-pass auto-review. So review-docs-pr (9.14) is hard-required for Session A.
  • The other 4 skills (sync-source-docs, missing-docs, check-for-broken-links, docs-seo-audit) are scheduled-cron skills. They operate independently of docubot per Inv-35 (“Other scheduled skills operate independently of docubot but share the same keep-docs-in-sync + AGENTS.md context”).

Three options:

  • Option A (recommended): Session A (9.20) depends on 9.12 + 9.14 ONLY. Skills 9.15-9.18 can land before, parallel with, or after Session A. Session B (9.21) does not require any of 9.15-9.18 to have shipped.
  • Option B: Session A depends on ALL of 9.14-9.18. 5-skill port + docubot both verified before Session A close. Slower but more comprehensive.
  • Option C: Skills 9.15-9.18 ship in a separate Task (ID-9 successor) entirely.

Default proposed: Option A. Rationale: tighter Session A scope; faster Session B close; the 4 cron skills are low-risk (they write to PRs, not main; failure mode is low-signal PR opening which review-docs-pr catches); PRODUCT acceptance criteria third 3 only requires each skill to “run at least once” + emit findings, NOT for Session A close.

Why this is an OQ: Reasonable to insist on the full skill suite live before declaring docubot “verified” — Inv-35 Phase-2 composability is the whole point of the skill set. Liam may prefer Option B for cohesion.

New OQ-PLAN-3 — AGENTS.md vs keep-docs-in-sync content overlap

Section titled “New OQ-PLAN-3 — AGENTS.md vs keep-docs-in-sync content overlap”

Question: Per Inv-51 + Inv-52, AGENTS.md has 5 sections (voice + tone, terminology, frontmatter contract, content-type style guides, AI-invisibility) and keep-docs-in-sync has 7 sections (IA, palette, AI-invisibility policy reference, UK English requirements, documentation-inventory index, commit + PR conventions, single-comment guardrail). There is overlap on UK English + AI-invisibility.

Three options for handling the overlap:

  • Option A (recommended): AGENTS.md is canonical for UK English + AI-invisibility (the voice + tone surfaces). keep-docs-in-sync references AGENTS.md for those subjects (one sentence “see AGENTS.md §X”) rather than re-stating them. keep-docs-in-sync owns the KH-specific content not in AGENTS.md (IA, palette, doc-inventory, single-comment guardrail, commit conventions).
  • Option B: Both files re-state UK English + AI-invisibility in full (duplication). Risk: drift over time as one file updates.
  • Option C: Move UK English + AI-invisibility to a shared third file both reference. Increases file count.

Default proposed: Option A. Same pattern as PRODUCT OQ-8 ratification (AGENTS.md complementary to CLAUDE.md, cross-references rather than duplicates). Cheapest to maintain, preserves AGENTS.md as the Warp-canonical docs-style oracle, keep-docs-in-sync stays KH-conventions-specific.

Why this is an OQ: Without explicit handling, two Executors authoring 9.9 + 9.10 in parallel could redundantly write the same UK English + AI-invisibility content. The default sets the ownership contract; override is duplicate-and-tolerate or shared-third-file.


All Subtask testStrategy lines reference docs/reference/test-philosophy.md discipline transitively: tests verify real behaviour, not mock-internal state. Per TECH’s Testing-and-validation table, every test colocates with the TECH § proposing the change. The implementation Subtasks below adopt the TECH test layout directly — no separate “test scaffolding” Subtask needed. The shared createMockSupabaseClient() helper applies only where a test touches Supabase; the docs-site / docubot / skill tests are filesystem + YAML + grep based and do NOT need it.

Date-sensitive tests (Inv-14 last-updated timestamps) pin time via vi.spyOn(Date, 'now') per CLAUDE.md test-philosophy gotcha. Workflow-shape tests parse YAML via js-yaml + assert shape — they do NOT execute the workflow runtime (that’s CI’s job).


Coverage verification — all 52 PRODUCT invariants mapped transitively

Section titled “Coverage verification — all 52 PRODUCT invariants mapped transitively”

Each invariant range maps to one or more implementation Subtasks. Coverage is transitive: the Subtask author implements the spec slice + the test file named in TECH’s Testing-and-validation table.

Invariant rangeImplemented in Subtask(s)TECH § anchor
Inv-1 (authoring stays in docs/)9.6 (sync reads from ../docs)§2.1 + §2.5
Inv-2 (Vercel default subdomain)9.5 (astro.config.mjs site:)§2.2 + §2.3
Inv-3 (include-by-default + deny-list)9.6 (sync-manifest.json shape)§2.5
Inv-4 (5-space IA sidebar order)9.5 (astro.config.mjs sidebar array)§2.3
Inv-5 (space landing index pages)9.5 + 9.6 (sync produces index pages)§2.3 + §2.5
Inv-6 (cross-space absolute paths)9.6 (sync script detect+rewrite)§2.6
Inv-7 (single-version)9.5 (no versions config)§2.3
Inv-8 (Pagefind 5-space search)9.5 (Starlight default)§2.3
Inv-9 (keyboard / SR / mobile / WCAG / callouts)9.5 (Starlight Aside component)§2.3 + §2.8
Inv-10 (Warm Meridian palette + dark mode)9.7 (warm-meridian.css mirror)§2.7
Inv-11 (code blocks + tables + callouts)9.7 + 9.5 (Starlight Code component)§2.7 + §2.8
Inv-12 (internal links resolve; broken → build fail)9.6 + 9.8 (sync link validator)§2.5 + §2.9
Inv-13 (edit-on-GitHub link)9.5 (editLink.baseUrl)§2.3
Inv-14 (last-updated DD/MM/YYYY)9.5 (lastUpdated: true + format)§2.3
Inv-15 (pure-.md rendering)9.5 (default Starlight behaviour)§2.5
Inv-16 (Zod-validated front matter)9.5 (content.config.ts)§2.4
Inv-17 (empty / loading / error / 404)9.5 + 9.8 (Starlight default 404 + axe scan)§2.9
Inv-18 (docubot PRIMARY)9.11 + 9.12 + 9.6 (combined: docubot writes + sync honours flag)§3 + §3.4
Inv-19 (build-time sync SUPPLEMENTARY)9.6 (sync script)§2.5
Inv-20 (schema-driven scheduled syncs)9.15 (sync-source-docs)§4.4
Inv-21 (search/nav stable across worktrees)9.5 (deploy from main)§2.2
Inv-22 (content removal explicit + tracked)9.6 (sync diff + removal report)§2.5
Inv-23 (AI-invisibility CI guard)9.8 (check-ai-invisibility.ts)§2.10
Inv-24 (UK English)9.8 + 9.9 (AGENTS.md enforces; lint deferred)§2.11 + §6.1
Inv-25 (workflow_dispatch + pull_request:closed + merged==true)9.12 (docubot.yml triggers + if filter)§3.2
Inv-26 (one docs-PR per source-PR merge)9.11 (prompt rule)§3.3
Inv-27 (one comment per run)9.11 (prompt rule)§3.3
Inv-28 (time-to-docs-PR 15min / 30min timeout)9.12 (timeout-minutes: 30 in workflow)§3.2 + §3.7
Inv-29 (KH commit conventions)9.11 (prompt rule)§3.3
Inv-30 (docubot writes to docs-site directly)9.11 + 9.6 (prompt rule + sync honour)§3.3 + §3.4
Inv-31 (loads AGENTS.md + keep-docs-in-sync + inventory)9.11 (prompt rule + driver reads files)§3.3 + §6.3
Inv-32 (Claude Agent SDK integration)9.12 (run-agent.ts imports)§3.5
Inv-33 (secrets contract + ubuntu-latest)9.12 (workflow env block)§3.6
Inv-34 (run artefacts upload on every run)9.11 (action.yml upload-artifact if: always())§3.1
Inv-35 (Phase-2 composability with review-docs-pr)9.14 (review-docs-pr workflow trigger filter)§4.3
Inv-36 (5 skills port; update-changelog NOT)9.13 + 9.14..9.18 (5 skills land; no 6th)§4.2
Inv-37 (each skill loads AGENTS.md)9.13 (run-skill.ts loads it)§6.3
Inv-38 (review-docs-pr emits review.json)9.14§4.3
Inv-39 (sync-source-docs three KH source pairs)9.15§4.4
Inv-40 (missing-docs two-phase + four sub-audits)9.16§4.5
Inv-41 (check-for-broken-links five error types)9.17§4.6
Inv-42 (docs-seo-audit 11+ issues + ASK-before-fixing)9.18§4.7
Inv-43 (canonical workflow shape)9.13 + 9.14..9.18 (all share shape)§4.1
Inv-44 ((a)+(b)+(d) to docubot)9.20 (Session A gate verifies via 3 samples)§5.1 + §5.3
Inv-45 (ci.yml regenerate-stats job)9.19§5.2
Inv-46 (/handoff preserved standalone)9.21 (CLAUDE.md atomic edit verifies)§5.1
Inv-47 (Session A acceptance)9.20§5.3
Inv-48 (Session B acceptance)9.21§5.3
Inv-49 (CLAUDE.md atomic update)9.21 (same commit as removal)§5.4
Inv-50 (hard deadline)9.21 (Orchestrator enforces)§5.5
Inv-51 (AGENTS.md 5 sections)9.9§6.1
Inv-52 (keep-docs-in-sync 7 sections)9.10§6.2

52/52 invariants covered transitively. Acceptance per third-by-third criteria in PRODUCT.md §Acceptance criteria.


Subtask records (TM-shape, ready for task-list.json append)

Section titled “Subtask records (TM-shape, ready for task-list.json append)”

The seventeen records below are the implementation Subtasks 9.5-9.21. Each is a complete TM-shape record ready for the Orchestrator to splice into docs/reference/task-list.json under ID-9’s subtasks array.

Each details field is load-bearing per workflow-orchestration: the Executor receiving the brief should NOT need to re-read PRODUCT.md or TECH.md to start work. The details cites TECH § anchors so an Executor that wants spec-slice detail can navigate, but the Subtask is self-sufficient for dispatch.

9.5 — Docs-site scaffold (Astro + Starlight + Vercel + content collection schema)

Section titled “9.5 — Docs-site scaffold (Astro + Starlight + Vercel + content collection schema)”
  • Implements: TECH §2.1 (sibling docs-site/ directory layout) + §2.2 (Vercel sibling project shape) + §2.3 (astro.config.mjs with Starlight 5-space sidebar, editLink, lastUpdated, Pagefind defaults) + §2.4 (Zod content-collection schema with kh_source / kh_last_verified / kh_docubot_owned extensions).
  • PRODUCT invariants covered: Inv-2 (Vercel default subdomain), Inv-4 (5-space IA sidebar order), Inv-7 (single-version), Inv-8 (Pagefind), Inv-9 (keyboard/SR/mobile/WCAG), Inv-13 (edit-on-GitHub), Inv-14 (last-updated), Inv-15 (pure-md), Inv-16 (Zod frontmatter), Inv-17 (404 + empty states), Inv-21 (stable across worktrees).
  • Dependencies: none.
  • Effort estimate: ~2-3h.
  • Acceptance gate: cd docs-site && bun install && bun run build succeeds from a fresh clone; sidebar shows 5 spaces in the order product-functionality → ontology → reference → runbooks → decisions; site field uses <vercel-default-subdomain> placeholder (no docs.kh.phew.org.uk framing surviving); content.config.ts validates fixture front-matter via Zod; build fails on unknown / malformed frontmatter field per Inv-16; light + dark theme switcher renders.
  • Test files (NEW): docs-site/__tests__/astro-config-sidebar.test.ts, docs-site/__tests__/frontmatter-schema.test.ts, docs-site/__tests__/pure-md-render.test.ts, docs-site/__tests__/astro-config-versioning.test.ts, docs-site/__tests__/last-updated.test.ts, docs-site/e2e/edit-link.spec.ts.

9.6 — Sync script + manifest + divergence-flag honour (build-time SUPPLEMENTARY path)

Section titled “9.6 — Sync script + manifest + divergence-flag honour (build-time SUPPLEMENTARY path)”
  • Implements: TECH §2.5 (sync-content.ts include-by-default + deny-list + kh_docubot_owned honour + --source-root flag for cross-worktree preview) + §2.6 (cross-space link rewriting absolute-paths-only) + §3.4 (sync script honours kh_docubot_owned: true front matter — divergence Option A per OQ-T1 ratified default).
  • PRODUCT invariants covered: Inv-1 (authoring in docs/), Inv-3 (include-by-default + deny-list), Inv-5 (each space landing index), Inv-6 (cross-space absolute paths), Inv-12 (broken-link build fail), Inv-19 (build-time SUPPLEMENTARY), Inv-22 (content removal explicit + tracked), Inv-30 (Option A divergence handling — sync skips kh_docubot_owned: true paths).
  • Dependencies: 9.5.
  • Effort estimate: ~2-3h (sync script is the biggest single-file change in this scope-third; LOC budget ~250 per TECH risk row).
  • Acceptance gate: bun run sync against ../docs produces a populated docs-site/src/content/docs/ tree with all 5 spaces; deny-list entries do not appear in output; deliberate kh_docubot_owned: true fixture is skipped on sync; deliberate cross-space relative link in fixture is rewritten to absolute path-style URL OR build fails per Inv-12; --source-root ../../knowledge-hub/docs works against sibling worktree (manual smoke test); removal-tracking: removed source surfaces in sync diff output.
  • Test files (NEW): docs-site/__tests__/sync-content.test.ts, docs-site/__tests__/sync-manifest.test.ts, docs-site/__tests__/cross-space-links.test.ts, docs-site/__tests__/removal-tracking.test.ts, docs-site/__tests__/sync-hierarchy.test.ts (verifies kh_docubot_owned honour), docs-site/__tests__/build-time-sync.test.ts.

9.7 — Warm Meridian theming + token-drift guard + code/tables/callouts

Section titled “9.7 — Warm Meridian theming + token-drift guard + code/tables/callouts”
  • Implements: TECH §2.7 (mirror oklch primitives + KH semantic tokens into warm-meridian.css; Instrument Sans load; sidebar + --sl-content-width) + §2.8 (Code component + line numbers + copy + language label via expressive-code; Aside icon-and-label; table styling). Token-drift guard at docs-site/scripts/check-token-parity.ts asserts mirrored block matches app/globals.css snapshot.
  • PRODUCT invariants covered: Inv-10 (Warm Meridian palette + dark mode), Inv-11 (code blocks + tables + callouts at KH quality).
  • Dependencies: 9.5.
  • Effort estimate: ~1.5-2h.
  • Acceptance gate: Light + dark mode renders with Warm Meridian palette (visual smoke on deployed preview); no default Starlight cobalt-blue accent surviving; token-drift guard CI script passes against current app/globals.css; deliberate drift fixture (mutated warm-meridian.css) makes the guard exit non-zero; code blocks show language label + copy button + line numbers; Aside components render with icon + text label per Inv-9; Instrument Sans loaded.
  • Test files (NEW): docs-site/__tests__/warm-meridian-tokens.test.ts, docs-site/__tests__/code-block-rendering.test.ts, docs-site/__tests__/callout-icon-label.test.ts.

9.8 — AI-invisibility + UK English CI guards + 404 + empty states

Section titled “9.8 — AI-invisibility + UK English CI guards + 404 + empty states”
  • Implements: TECH §2.9 (404 page branding + empty sidebar group + no-match search) + §2.10 (docs-site/scripts/check-ai-invisibility.ts regex guard with deny-list for ai-visibility-policy.md itself) + §2.11 (UK English enforcement via AGENTS.md style guide; retext-british lint deferred to Follow-up).
  • PRODUCT invariants covered: Inv-12 (broken-link build fail; tested via deliberate-broken-link fixture), Inv-17 (404 branded + empty states), Inv-23 (AI-invisibility CI guard), Inv-24 (UK English).
  • Dependencies: 9.6.
  • Effort estimate: ~1-1.5h.
  • Acceptance gate: Fixture with “AI-powered” string in body fails build via check-ai-invisibility.ts exit non-zero; deny-list path (docs-site/src/content/docs/reference/ai-visibility-policy.md) passes; deliberate broken internal link in fixture fails Starlight build; 404 page renders branded with search + home link (E2E smoke); empty sidebar group does not render an empty header (Starlight default verified).
  • Test files (NEW): docs-site/__tests__/ai-invisibility-guard.test.ts, docs-site/__tests__/uk-english.test.ts (placeholder; lint deferred), docs-site/__tests__/link-validator.test.ts, docs-site/e2e/404-page.spec.ts.

9.9 — AGENTS.md at repo root (5-section style guide)

Section titled “9.9 — AGENTS.md at repo root (5-section style guide)”
  • Implements: TECH §6.1 (AGENTS.md at repo root, sibling to CLAUDE.md, cross-references CLAUDE.md for project-wide rules per OQ-8 Option A ratified default).
  • PRODUCT invariants covered: Inv-51 (AGENTS.md 5 content sections).
  • Dependencies: none (foundation; can run in parallel with 9.5-9.8).
  • Effort estimate: ~1.5-2h.
  • Acceptance gate: AGENTS.md exists at repo root; contains 5 numbered sections per Inv-51:
    1. Voice + tone rules (UK English, professional-direct, no marketing copy, no emoji).
    2. Terminology table (Knowledge Hub vs “the platform” vs “the app”; “Change Reports” vs “Digest”; canonical taxonomy terms; “docubot” vs Claude vs the SDK).
    3. Frontmatter contract (matching Zod schema in TECH §2.4).
    4. Content-type style guides (concept / procedural / reference / troubleshooting).
    5. AI-invisibility rules (per Inv-23 + docs/reference/ai-visibility-policy.md). Section opener cross-references CLAUDE.md: “For project-wide conventions, see CLAUDE.md. This file adds docs-corpus-specific conventions on top.”
  • Test files (NEW): __tests__/agents-md/agents-md-shape.test.ts (asserts all 5 sections present with the canonical section titles).

9.10 — keep-docs-in-sync skill at .claude/skills/keep-docs-in-sync/SKILL.md

Section titled “9.10 — keep-docs-in-sync skill at .claude/skills/keep-docs-in-sync/SKILL.md”
  • Implements: TECH §6.2 (keep-docs-in-sync skill with 7 content sections per Inv-52; cross-references AGENTS.md for UK English + AI-invisibility subjects per OQ-PLAN-3 Option A default).
  • PRODUCT invariants covered: Inv-52 (keep-docs-in-sync 7 content sections).
  • Dependencies: 9.9.
  • Effort estimate: ~1.5h.
  • Acceptance gate: .claude/skills/keep-docs-in-sync/SKILL.md exists; contains 7 sections per Inv-52:
    1. KH docs/ IA conventions (5-space layout + cross-space absolute-path rule).
    2. Warm Meridian palette + typography references (link to docs/design/warm-meridian-implementation-spec.md).
    3. AI-invisibility policy reference (link to AGENTS.md §5 + docs/reference/ai-visibility-policy.md).
    4. UK English requirements (cross-reference AGENTS.md §1).
    5. docs/reference/documentation-inventory.md index (so docubot does not recreate existing docs).
    6. Commit + PR conventions (matching commit-commands:commit-push-pr).
    7. Single-comment guardrail (matching Warp’s pattern + Inv-27). Skill frontmatter includes proper name: + description: per skill schema; body remains under ~250 LOC.
  • Test files (NEW): __tests__/skills/keep-docs-in-sync-shape.test.ts (asserts SKILL.md contains all 7 sections; frontmatter shape valid).

9.11 — Docubot composite action + KH-persona prompt template + secrets contract

Section titled “9.11 — Docubot composite action + KH-persona prompt template + secrets contract”
  • Implements: TECH §3.1 (.github/actions/docubot/action.yml composite action with checkout / setup-bun / install / gather-pr-context / render-prompt / run-agent / upload-artifact steps) + §3.3 (KH-persona prompt template at .github/actions/docubot/prompt.txt — verbatim shape per TECH §3.3 embedded text body) + §3.6 (secrets contract: ANTHROPIC_API_KEY + GITHUB_TOKEN; runs-on ubuntu-latest).
  • PRODUCT invariants covered: Inv-26 (one docs-PR per merge — prompt rule), Inv-27 (one comment per run — prompt rule), Inv-29 (KH commit conventions — prompt rule), Inv-30 (docubot writes to docs-site directly
    • kh_docubot_owned: true frontmatter — prompt rule per OQ-T1 ratified default), Inv-31 (loads AGENTS.md + keep-docs-in-sync + documentation-inventory — prompt rule), Inv-33 (secrets contract + ubuntu-latest), Inv-34 (upload-artifact if: always()).
  • Dependencies: 9.9, 9.10.
  • Effort estimate: ~2h (prompt template body is ~89 lines of text; the action.yml itself is ~50 lines).
  • Acceptance gate: .github/actions/docubot/action.yml exists with the six composite steps per TECH §3.1; .github/actions/docubot/prompt.txt contains the KH-persona body verbatim per TECH §3.3 (no Warp persona surviving; no warpdotdev/gitbook references; Vercel default subdomain framing); upload-artifact@v4 step has if: always() per Inv-34; shape-test on action.yml passes.
  • Test files (NEW): __tests__/workflows/docubot-action-shape.test.ts (parse YAML; assert composite steps + if: always() on upload), __tests__/actions/docubot-prompt-shape.test.ts (grep prompt.txt for the six required rule sections: persona / scope / divergence flag / style / commit-conventions / output-instructions).

9.12 — Docubot workflow + Claude Agent SDK driver

Section titled “9.12 — Docubot workflow + Claude Agent SDK driver”
  • Implements: TECH §3.2 (.github/workflows/docubot.yml with workflow_dispatch + pull_request.types:[closed] + merged==true filter + timeout-minutes:30 + composite-action invocation) + §3.5 (scripts/docubot/run-agent.ts driver: imports @anthropic-ai/claude-agent-sdk, reads AGENTS.md + keep-docs-in-sync into prompt context, invokes Agent with cwd=GITHUB_WORKSPACE) + §3.7 (time-to-docs-PR observability via timeout-minutes:30; soft target 15min).
  • PRODUCT invariants covered: Inv-25 (trigger surface), Inv-28 (timeout-minutes:30; 15min soft target), Inv-32 (Claude Agent SDK integration), Inv-33 (runs-on ubuntu-latest verified in workflow).
  • Dependencies: 9.11.
  • Effort estimate: ~2h (SDK driver is ~80-120 LOC; workflow YAML is ~50 lines).
  • Acceptance gate: .github/workflows/docubot.yml exists with both triggers (workflow_dispatch + pull_request.types: [closed]) + the job-level if: containing merged == true; runs-on: ubuntu-latest; timeout-minutes: 30; permissions block grants contents: write + pull-requests: write + issues: write; scripts/docubot/run-agent.ts exists; imports from @anthropic-ai/claude-agent-sdk directly (no barrel re-export); reads AGENTS.md + keep-docs-in-sync via fs.readFile; invokes Agent with cwd=$GITHUB_WORKSPACE; SDK version pinned in package.json devDependencies.
  • Test files (NEW): __tests__/workflows/docubot-workflow-shape.test.ts (parse YAML; assert triggers + merged-filter + timeout + permissions), __tests__/scripts/docubot-prompt-loading.test.ts (grep run-agent.ts for AGENTS.md + keep-docs-in-sync references), __tests__/dependencies/claude-agent-sdk.test.ts (assert SDK package in devDependencies; assert direct import in run-agent.ts).

9.13 — 5-skill canonical workflow scaffold + shared driver

Section titled “9.13 — 5-skill canonical workflow scaffold + shared driver”
  • Implements: TECH §4.1 (canonical workflow shape at .github/workflows/<skill-name>.yml per Inv-43 lock; ONE template shared by all 5 skills) + §4.2 (skill set scope: 5 skills port; update-changelog NOT ported per OQ-3 OVERRIDE) + shared driver script scripts/skills/run-skill.ts (~100 LOC; —skill + —skill-md flags; loads AGENTS.md + keep-docs-in-sync + per-skill SKILL.md + per-skill references/*.md; invokes Claude Agent SDK identical to run-agent.ts shape).
  • PRODUCT invariants covered: Inv-36 (5 skills port; update-changelog NOT), Inv-37 (each skill loads AGENTS.md — verified via run-skill.ts reads), Inv-43 (canonical workflow shape).
  • Dependencies: 9.9, 9.10, 9.11.
  • Effort estimate: ~1.5-2h (driver is parameterised version of run-agent.ts; workflow template lifts from docubot.yml).
  • Acceptance gate: scripts/skills/run-skill.ts exists; reads AGENTS.md + keep-docs-in-sync + per-skill SKILL.md by --skill-md arg; invokes Claude Agent SDK; placeholder .github/workflows/ files for all 5 skills exist with the canonical workflow shape per §4.1 (workflow_dispatch
    • optional schedule + the shared driver invocation); none of the 5 skill SKILL.md bodies exist yet (those land in 9.14-9.18); update-changelog workflow / skill NOT present.
  • Test files (NEW): __tests__/scripts/run-skill-loading.test.ts (grep run-skill.ts for AGENTS.md + keep-docs-in-sync references), __tests__/workflows/skill-workflow-shape.test.ts (parse all 5 workflow YAMLs; assert canonical shape match per §4.1), __tests__/skills/skill-inventory.test.ts (assert 5 skill directories exist post-9.14-9.18; assert no update-changelog/ directory).

9.14 — review-docs-pr skill body + workflow

Section titled “9.14 — review-docs-pr skill body + workflow”
  • Implements: TECH §4.3 (review-docs-pr SKILL.md body adapted from Warp’s review-docs-pr; trigger override pull_request_review for docubot-opened docs PRs; emits review.json with summary + comments[] schema; severity prefixes [CRITICAL] / [IMPORTANT] / [SUGGESTION] / [NIT] without emoji per KH no-emoji rule; comments posted via gh pr comment).
  • PRODUCT invariants covered: Inv-35 (Phase-2 composability — review-docs-pr runs against docubot-opened PRs), Inv-38 (review-docs-pr contract).
  • Dependencies: 9.13.
  • Effort estimate: ~1.5-2h (skill body ~150 LOC; workflow inherits from §4.1 template; trigger override adds ~10 lines to workflow YAML).
  • Acceptance gate: .claude/skills/review-docs-pr/SKILL.md exists with Warp-template body adapted to KH (UK English, no emoji); .github/workflows/review-docs-pr.yml exists with canonical shape + pull_request_review trigger override; job’s if: filters head-branch matching docubot/* OR base-branch main with title starting Docs:; output contract for review.json defined in SKILL.md; severity labels use prefix not emoji.
  • Test files (NEW): __tests__/skills/review-docs-pr.test.ts (fixture: sample PR diff → assert review.json emitted with summary + comments[]; assert no emoji in comment bodies; assert severity prefix format).

9.15 — sync-source-docs skill body + workflow

Section titled “9.15 — sync-source-docs skill body + workflow”
  • Implements: TECH §4.4 (sync-source-docs — KH-renamed from Warp’s sync-error-docs; three KH source pairs: schema/schema-quick-reference.md, MCP registrations/mcp-inventory.md, route definitions/api-routes.md — third is NEW page authored on first run; weekly Monday 06:00 UTC cron per OQ-T2 ratified default; opens docs-PR per detected drift; marks output file kh_docubot_owned: true).
  • PRODUCT invariants covered: Inv-20 (schema-driven SUPPLEMENTARY for code-generated content), Inv-39 (sync-source-docs three KH source pairs).
  • Dependencies: 9.13.
  • Effort estimate: ~2h (skill body + 3-pair drift detection logic; third pair api-routes.md is NEW page, needs first-creation flow).
  • Acceptance gate: .claude/skills/sync-source-docs/SKILL.md exists with three KH source pairs documented; .github/workflows/sync-source-docs.yml exists with canonical shape + schedule: cron '0 6 * * 1' enabled per OQ-T2; fixture run against each source pair detects drift + emits docs-PR draft; first-creation flow for api-routes.md documented.
  • Test files (NEW): __tests__/skills/sync-source-docs.test.ts (fixture per source pair: drift detected → docs-PR opens with kh_docubot_owned: true frontmatter on rewritten file).

9.16 — missing-docs skill body + Python audit script + workflow

Section titled “9.16 — missing-docs skill body + Python audit script + workflow”
  • Implements: TECH §4.5 (missing-docs two-phase audit + draft; Phase 1 audit_docs.py with four sub-audits: env vars, CLI commands, MCP/route surfaces, terminology staleness; Phase 2 reads kh_surface_map.md for draft; workflow_dispatch only at foundation, Phase 2 may add monthly cron later).
  • PRODUCT invariants covered: Inv-40 (missing-docs two-phase + four sub-audits).
  • Dependencies: 9.13.
  • Effort estimate: ~2-3h (Python audit script with 4 sub-audits is the largest LOC contributor among the 5 skills; pre-identified split point if mid-flight scope blows up: 9.22-9.25 sub-slice the 4 sub-audits).
  • Acceptance gate: .claude/skills/missing-docs/SKILL.md exists with two-phase contract; .claude/skills/missing-docs/scripts/audit_docs.py exists with 4 sub-audit entrypoints (env-vars / cli-commands / mcp-routes / terminology); .claude/skills/missing-docs/references/stale_terms.md
    • kh_surface_map.md exist; .github/workflows/missing-docs.yml exists with canonical shape + workflow_dispatch only (no schedule cron at foundation per OQ-T2; Phase 2 schedule is FU).
  • Test files (NEW): __tests__/skills/missing-docs-audit.test.ts (per sub-audit fixture: deliberate-gap detected → reported in audit output).
Section titled “9.17 — check-for-broken-links skill body + Python link-walker + workflow”
  • Implements: TECH §4.6 (check-for-broken-links Python link-walker; five error types: file-not-found / case-mismatch / missing-mdx-ext / cross-space-relative / external-4xx-or-timeout; daily 05:00 UTC cron per OQ-T2; invoked from inside review-docs-pr per Warp pattern; --gh-pr-comment flag replaces Warp’s --slack-notify).
  • PRODUCT invariants covered: Inv-41 (check-for-broken-links 5 error types + --gh-pr-comment mode).
  • Dependencies: 9.13.
  • Effort estimate: ~2h.
  • Acceptance gate: .claude/skills/check-for-broken-links/SKILL.md exists; .claude/skills/check-for-broken-links/scripts/check_links.py exists with 5 error-type detection; .github/workflows/check-for-broken-links.yml exists with canonical shape + schedule: cron '0 5 * * *' enabled per OQ-T2; --gh-pr-comment flag posts findings via gh pr comment.
  • Test files (NEW): __tests__/skills/check-for-broken-links.test.ts (per error-type fixture: deliberate-broken-link detected; --gh-pr-comment mode mocks gh pr comment invocation).

9.18 — docs-seo-audit skill body + Python audit + workflow (cron commented per OQ-T3)

Section titled “9.18 — docs-seo-audit skill body + Python audit + workflow (cron commented per OQ-T3)”
  • Implements: TECH §4.7 (docs-seo-audit Python SEO audit; 11+ issue types across 3 severity tiers; ASK-before-fixing guardrail preserved verbatim from Warp; monthly 1st 07:00 UTC cron — but per OQ-T3 ratified default, workflow file committed with schedule: block COMMENTED OUT at foundation; a Follow-up commit uncomments post first-deploy when sitemap exists).
  • PRODUCT invariants covered: Inv-42 (docs-seo-audit 11+ issues + 3 tiers + ASK-before-fixing).
  • Dependencies: 9.13.
  • Effort estimate: ~2h.
  • Acceptance gate: .claude/skills/docs-seo-audit/SKILL.md exists with ASK-before-fixing rule preserved verbatim; .claude/skills/docs-seo-audit/scripts/audit_seo.py exists; .claude/skills/docs-seo-audit/references/seo_issues.md enumerates 11+ issue types across 3 severity tiers; .github/workflows/docs-seo-audit.yml exists with canonical shape + workflow_dispatch trigger + schedule: block PRESENT BUT COMMENTED OUT per OQ-T3 (comment explicitly cites OQ-T3 + Follow-up commit expectation).
  • Test files (NEW): __tests__/skills/docs-seo-audit.test.ts (fixture sitemap → per-issue detection; SKILL.md grep assert “ASK before fixing” rule present), __tests__/workflows/docs-seo-audit-cron.test.ts (assert schedule: block exists in YAML AND is commented per OQ-T3).

9.19 — ci.yml regenerate-stats job (independent decommission glue)

Section titled “9.19 — ci.yml regenerate-stats job (independent decommission glue)”
  • Implements: TECH §5.2 (new regenerate-stats job appended to .github/workflows/ci.yml; triggers on push: main only; runs bun run stats + bun run generate:mcp-inventory; direct-commit per OQ-6 Option A with side-PR fallback if branch protection blocks the github-actions[bot] push; [skip ci] commit suffix prevents infinite CI loop).
  • PRODUCT invariants covered: Inv-45 ((c) function moves to ci.yml).
  • Dependencies: none (independent ci.yml edit; can land any time after 9.5 stabilises).
  • Effort estimate: ~1h.
  • Acceptance gate: regenerate-stats job exists in .github/workflows/ci.yml with the seven steps per TECH §5.2 (checkout + setup-bun + install + run stats + check-for-changes + commit-or-side-PR); if: github.event_name == 'push' && github.ref == 'refs/heads/main'; commit message contains [skip ci]; first run on push:main produces a commit OR side-PR with regenerated docs/generated/ files.
  • Test files (NEW): __tests__/workflows/ci-regenerate-stats.test.ts (parse ci.yml; assert regenerate-stats job + push:main filter + bun run stats + bun run generate:mcp-inventory + direct-commit-with-side-PR-fallback shape + [skip ci] suffix).

9.20 — Session A decommission verification gate

Section titled “9.20 — Session A decommission verification gate”
  • Implements: TECH §5.3 Session A (gate 1) acceptance verification: docubot opens at least 3 sample docs-PRs on source-PR merges (synthetic via workflow_dispatch against 3 historical PR numbers per OQ-PLAN-1 default); all 3 narrative-doc updates ((a)+(b)+(d) workloads) execute correctly (Liam manual review); docubot’s single-comment + commit-conventions hold across all 3 samples.
  • PRODUCT invariants covered: Inv-44 ((a)+(b)+(d) move to docubot — verified by 3 sample runs), Inv-47 (Session A acceptance).
  • Dependencies: 9.12 (docubot live + functional), 9.14 (review-docs-pr live for Inv-35 Phase-2 composability requirement).
  • Effort estimate: ~1.5h (verification, not implementation; manual Liam review of 3 sample docubot PRs + Checker grep of single-comment guardrail across 3 runs).
  • Acceptance gate: 3 sample docubot PRs opened via workflow_dispatch against 3 historical source-PR numbers (per OQ-PLAN-1 synthetic default); each PR has exactly ONE source-PR comment (single-comment guardrail verified); each PR title matches Docs: <summary> (from #<N>); each commit message matches docs(<area>): <summary>; each branch matches docubot/<slug>; manual Liam review verifies (a)+(b)+(d) workload faithfulness on the 3 samples; review-docs-pr workflow ran against each of the 3 docubot-opened PRs and emitted review.json.
  • Test files (NEW): __tests__/decommission/session-a-acceptance.test.ts (assert 3 docubot PRs exist in repo with the expected branch/title/commit shapes; for each, assert exactly-one comment on source PR; assert review-docs-pr workflow ran). Liam manual review captured in Subtask <info added on ...> journal block.

9.21 — Session B atomic decommission: ci.yml verified + remove update-docs + CLAUDE.md atomic edit

Section titled “9.21 — Session B atomic decommission: ci.yml verified + remove update-docs + CLAUDE.md atomic edit”
  • Implements: TECH §5.3 Session B (gate 2) + §5.4 (CLAUDE.md atomic update — same commit as .claude/skills/update-docs/ removal) + §5.5 (hard deadline forcing function per Inv-50).
  • PRODUCT invariants covered: Inv-46 (/handoff preserved standalone), Inv-48 (Session B acceptance: ci.yml regenerate-stats runs + update-docs removed + callers updated), Inv-49 (CLAUDE.md atomic update — same commit), Inv-50 (hard deadline).
  • Dependencies: 9.19 (regenerate-stats job verified live), 9.20 (Session A gate closed).
  • Effort estimate: ~1.5h.
  • Acceptance gate: .claude/skills/update-docs/ directory removed in same commit as CLAUDE.md edit; commit diff shows BOTH the directory deletion AND the CLAUDE.md edits in ONE atomic git operation (verifies Inv-49); CLAUDE.md’s /update-docs references replaced with docubot + keep-docs-in-sync references in Implementation Workflow section + any reference-doc tables that cited it; /handoff preserved as standalone skill (not removed); regenerate-stats job has run successfully on at least one merge-to-main commit (verified by ci.yml run history + a resulting docs/generated/ commit on main); grep .claude/ for stale /update-docs references returns zero hits (except in deletion-comment lines).
  • Test files (NEW): __tests__/decommission/update-docs-removed.test.ts (assert .claude/skills/update-docs/ does NOT exist; grep .claude/ for /update-docs returns zero stale hits; grep CLAUDE.md for update-docs returns zero references; grep CLAUDE.md for docubot + keep-docs-in-sync returns the expected references), __tests__/skills/handoff-preserved.test.ts (assert .claude/skills/handoff/SKILL.md exists post-removal).

Risks specific to this PLAN’s decomposition

Section titled “Risks specific to this PLAN’s decomposition”
RiskImpactMitigation
9.5 scaffold underestimates Astro+Starlight+Vercel integration friction (Vercel default subdomain TBC could block first deploy)MediumSubdomain string deferred to first-deploy; <vercel-default-subdomain> placeholder used in astro.config.mjs. Liam confirms subdomain at 9.20 verification gate (or earlier, opportunistic). 9.5 ships without the live URL — verified at staging preview.
9.6 sync script grows beyond 250 LOC budgetMediumTECH §Risks names the 250 LOC budget; if mid-flight scope creep surfaces, Executor escalates and Orchestrator may split into 9.6a (manifest + walk) + 9.6b (link rewriting + diff).
9.11 prompt template body too long to embed in 9.11 Subtask details verbatimLowThe full prompt body is in TECH §3.3 — Executor reads TECH for the verbatim content. 9.11’s details cite TECH §3.3 explicitly and require the Executor to copy the body into prompt.txt without rewording.
9.13 + 9.14-9.18 5-skill parallel-wave merge conflicts (each skill touches .github/workflows/ + scripts/skills/run-skill.ts)MediumAll 5 skill workflows are NEW files (distinct paths) — no merge conflict on workflow YAMLs. scripts/skills/run-skill.ts is ONE file authored at 9.13; 9.14-9.18 do not modify it (they consume it via --skill flag). Cherry-pick sequence: 9.13 first, then 9.14-9.18 in any order.
9.16 missing-docs Python audit script exceeds 2-3h estimateHighPre-identified split point. If mid-flight, Orchestrator adds 9.22+9.23+9.24+9.25 sub-slicing the 4 sub-audits (env-vars / CLI / MCP-routes / terminology). Stays within 25 ceiling at 25 exactly.
9.20 Session A gate fails because synthetic workflow_dispatch doesn’t match real PR-merge load (per OQ-PLAN-1 default)LowIf synthetic is insufficient, Liam overrides OQ-PLAN-1 default → Session A waits for organic PR merges. This delays Session B but doesn’t break the workflow.
9.21 CLAUDE.md atomic edit accidentally drops MemPalace section referenceLowPre-edit grep of CLAUDE.md for /update-docs mentions + careful per-occurrence replace. Test update-docs-removed.test.ts checks for stale hits post-removal.
Hook propagation discipline failure on parallel sub-agent dispatch (CLAUDE.md ID-19.4)HighPre-dispatch check `git show origin/main:.claude/settings.json
Brief-authoring discipline failure (sibling-worktree absolute paths in dispatch text)MediumThis PLAN.md follows the discipline (relative paths only, no sibling-worktree absolute paths). Orchestrator must preserve discipline when composing dispatch briefs from these Subtask details fields.
docubot direct-write divergence handling regression (OQ-T1 front-matter flag interaction with sync script)Medium9.6 sync script unit test (sync-hierarchy.test.ts) asserts kh_docubot_owned: true paths are skipped on sync. 9.11 docubot prompt enforces flag-set on every docubot write. Both invariants tested independently before 9.20 verification.

  • Worktree-parallelizable pairs (per TECH §Parallelization + PLAN refinement):
    • Phase 1 sub-parallel: 9.6 + 9.7 (sync + theming) after 9.5 lands. They touch disjoint files (docs-site/scripts/sync-content.ts + docs-site/sync-manifest.json vs docs-site/src/styles/warm-meridian.css
      • docs-site/scripts/check-token-parity.ts).
    • Phase 1 ↔ Phase 2 parallel: 9.9 (AGENTS.md) is independent of all of 9.5-9.8 — can dispatch alongside any Phase 1 worker. 9.10 chains on 9.9.
    • Phase 3 ↔ 9.19 parallel: 9.19 (ci.yml regenerate-stats) is an independent .github/workflows/ci.yml edit; can dispatch in parallel with 9.11+9.12 (docubot).
    • Phase 4 wide-parallel: 9.14-9.18 all parallelize after 9.13. Each touches a distinct .claude/skills/<skill-name>/ subdirectory plus a distinct .github/workflows/<skill-name>.yml file. Cherry-pick wave = 9.13 first, then 9.14-9.18 in any order, then 9.19 (if not already landed).
  • Sub-agent worktree heritage gotcha (per CLAUDE.md ID-19.4): Before EACH isolation: "worktree" dispatch, the Orchestrator MUST run git show origin/main:.claude/settings.json | grep -c "Tier 2.2 hook (ID-19.3)" and verify the count is ≥1. The Tier 2.2 hook is on production-readiness at the time of this PLAN authoring; if main has not yet received the hook propagation, the Orchestrator MUST merge/cherry-pick to main BEFORE dispatching any Phase-1+ Subtask.
  • Brief-authoring discipline: When composing dispatch briefs from the Subtask details fields below, the Orchestrator MUST use relative paths only. The only absolute path acceptable is the worker’s own worktree path. NEVER mention sibling-worktree absolute paths like knowledge-hub-production-readiness/ or knowledge-hub/ in dispatch text — primer effect causes the sub-agent’s Write tool to autocomplete the wrong path. The Tier 2.2 hook is the backstop; brief-authoring discipline is the cheapest defense layer.
  • OQ-T1 / OQ-T2 / OQ-T3 ratifications applied throughout: Where any Subtask details field reaches into these decision spaces, the ratified default is cited inline. Executor proceeds against the default unless Liam overrides. No details field re-derives a ratified decision.
  • No mcp__task-master-ai__* invocations. KH adopts the TM JSON shape (§7 of the canonical SDLC doc) but NOT the TM tool. The Orchestrator splices Subtask records into docs/reference/task-list.json via surgical Edit (per workflow-orchestration Promote mode pattern — never round-trip JSON.parse/stringify).
  • Cherry-pick (not merge) parallel branches per CLAUDE.md “Worktree isolation rules” — agents branched from main at launch time; earlier merges make later agents stale. Sequential cherry-pick onto production-readiness track branch + bun run test after each.
  • Knip baseline check after Phase 4 lands: the 5 new .claude/skills/<name>/SKILL.md files + scripts/skills/run-skill.ts
    • .github/workflows/<name>.yml files will register against Knip. Add .claude/skills/** + .github/workflows/** to Knip’s ignore list at end-of-task if not already present (per TECH §Risks row 12).

This PLAN ships when:

  • All seventeen Subtask records below are populated with sibling-only deps
    • load-bearing details fields + concrete testStrategy lines + test file names per TECH Testing-and-validation table.
  • 52/52 PRODUCT invariants transitively covered (verified under §Coverage verification).
  • 25-Subtask soft ceiling respected (21 total Subtasks; reserved buffer for 9.22-9.25 if 9.16 missing-docs sub-slices).
  • 3 new PLAN-level OQs (OQ-PLAN-1/2/3) surfaced with defaults — within the workflow ≤3 ceiling.
  • Sibling-only dependency constraint honoured (forcing-function escalation tripwire NOT hit).
  • Worktree-first-action gate + brief-authoring discipline applied to every Subtask details field.

{9.4} close-out moves status: pendingin_progress (by this Planner) → done (by Checker post-ratification + Orchestrator promotion).


End of PLAN spec {9.4} for Task ID-9.