---
title: "PBI Bulk-Create Spec — Docs-Restructure for AI-Optimized Lookup"
status: done
audience: [ai-agent]
spec_version: 1
spec_type: pbi-bulk-create
generated_at: 2026-05-02
language: en
last_updated: 2026-05-03
notes: |
  Input for a bulk-create executor that calls
    mcp__scrum4me__create_pbi
    mcp__scrum4me__create_story
    mcp__scrum4me__create_task
  in that order. The executor reads the YAML graph at the bottom of this
  file. The prose above the graph is identical to what the executor sends
  as the PBI's `description` field, so any agent that later picks up a
  task gets the full context via mcp__scrum4me__get_claude_context.

  product_id is intentionally left as a placeholder (REPLACE_ME) — fill it
  in before running the executor. priority uses 1 = critical … 5 = trivial.
  sort_order is omitted everywhere; the MCP server auto-assigns last+1
  within the priority group.
---

# PBI Bulk-Create Spec — Docs-Restructure for AI-Optimized Lookup

## 1. Context (this becomes the PBI description)

This PBI executes the docs-restructure plan
([`docs/plans/docs-restructure-ai-lookup.md`](./docs-restructure-ai-lookup.md))
over eight phases, mapped here as eight stories with three to eight tasks
each. The goal is to cut the documentation surface an AI agent has to read
to find the right reference, without breaking existing workflows.

### Why this PBI exists

Today an agent loads `CLAUDE.md` (340 lines) every turn before reading a
single line of code, then has to choose from 35 docs in `docs/` whose
purpose is only inferable from the filename — there is no front-matter,
no index, no machine-readable status. After this PBI, the agent reads
`CLAUDE.md` (≤150 lines) plus `docs/INDEX.md` and knows where to go.

### Going-forward defaults — every task must respect these

- **Language:** all new and touched docs in English. Code comments stay
  English (already the case). UI strings stay Dutch.
- **Front-matter:** every `.md` under `docs/` (and `CLAUDE.md`,
  `AGENTS.md`) carries YAML front-matter with at minimum
  `title`, `status`, `audience`, `language`, `last_updated`. Add
  `related`, `when_to_read`, `do_not_read_for` where useful.
- **Naming:** lowercase kebab-case. No `` prefix. No spaces in
  filenames. No UPPER. Files matching `_*.md` are personal sidecar and
  excluded from the index.
- **Commits:** one commit per logical layer. Use `docs(<story-slug>):`
  as the prefix when no ST-code applies. Reference the matching story
  slug from this spec (e.g. `docs(naming): drop  prefix`).
- **Pushing:** never push without explicit user approval. Local commits
  on the feature branch only. The branch convention is
  `feat/docs-restructure-<phase-slug>` (one branch per story).
- **Cross-references:** when renaming or moving a file, update every
  internal link to it in the same commit. After the link-check story
  (Story 8) is done, run `npm run docs:check-links` before each commit.

### Sequencing

Stories run in numeric order. Story N+1 assumes the changes from Story N
are merged. If you pick up a task and earlier stories aren't done, stop
and surface it — don't try to leapfrog. The exception is Story 6
(ADR-backfill) and Story 7 (glossary): both are content-only and can run
in parallel with Stories 3–5 if you want.

### Out of scope

- Translating Dutch docs that this PBI doesn't otherwise touch — that's
  a separate full-sweep PR.
- Code changes outside `docs/`, `scripts/`, `package.json`, `.gitignore`.
- Pushing branches or opening PRs against `main`.
- Restyling, content rewrites beyond what each task asks for.

### Where to look first

- This file (the PBI context block above).
- [`docs/plans/docs-restructure-ai-lookup.md`](./docs-restructure-ai-lookup.md)
  — the full plan, especially §3 (Goals), §4 (Target structure), §6
  (Front-matter spec), §8 (Phased migration).
- [`docs/adr/README.md`](../adr/README.md) — when writing an ADR in
  Story 6.

### Definition of done for this PBI

- All 8 stories' tasks accepted.
- `docs/INDEX.md` regenerates without errors and lists every doc grouped
  correctly.
- `npm run docs:check-links` passes (after Story 8).
- `CLAUDE.md` ≤ 150 lines.
- Zero docs without front-matter.
- Zero junk files (`docs/patterns/test.md`, `Brainstorm.md` at root,
  `.Plans/` at root) remain.

---

## 2. Resolved decisions (quick reference)

| # | Question | Decision |
|---|---|---|
| 1 | Doc language | English for all new/touched docs |
| 2 | MD3-color + styling | Merge into one `docs/design/styling.md` |
| 3 | `solo-paneel-spec.md` | Merge into `docs/specs/functional.md` |
| 4 | `.Plans/` | Archive under `docs/plans/archive/` |
| 5 | ADR template | Nygard default; MADR for auth, queue, agent integration |
| 6 | Index generator | Node script (`scripts/generate-docs-index.mjs`, already exists) |

---

## 3. What's already done (do not re-do)

These commits on `feat/docs-adr-and-index` already shipped:

- `docs(plans):` the restructure plan itself.
- `docs(adr):` ADR scaffolding — templates, README, meta-ADR (0000).
- `feat(docs):` the docs index generator + initial `docs/INDEX.md`.
- `chore:` `.gitignore` for `.obsidian/` + `_*.md`.

So Story 6 only needs the **content** (the actual ADR-0001 … 0008
files); Story 7 only needs the **glossary + husky hook**, the script
already exists.

---

## 4. Structured graph (executor reads this)

```yaml
pbi:
  product_id: REPLACE_ME
  title: "Docs-restructure for AI-optimized lookup"
  description: |
    See section 1 (Context) above. Every task in this PBI must respect:
    - English for new/touched docs (UI strings stay Dutch).
    - YAML front-matter on every doc (title, status, audience, language,
      last_updated; related/when_to_read/do_not_read_for where useful).
    - kebab-case, lowercase, no  prefix, no spaces.
    - One commit per logical layer (`docs(<story-slug>):` prefix).
    - No pushes without user approval.
    - Update every internal link in the same commit as a rename.
    Read docs/plans/docs-restructure-ai-lookup.md §3, §4, §6, §8 first.
  priority: 2

  stories:

    - slug: junk-cleanup-and-front-matter
      title: "Phase 1 — Junk cleanup + front-matter on every doc"
      description: |
        Lowest-risk first phase. Remove stub/junk files, archive parallel
        plan folder, and add YAML front-matter to every existing .md
        under docs/. No paths change yet — every existing link still
        works after this story.
      acceptance_criteria: |
        - docs/patterns/test.md is deleted.
        - .Plans/ is moved to docs/plans/archive/ and the .gitignore
          entry for .Plans/ is removed.
        - Brainstorm.md at repo root is deleted (or moved to
          docs/scratch/) — it's already gitignored.
        - Every existing .md under docs/ (and CLAUDE.md, AGENTS.md) has
          YAML front-matter with at least title, status, audience,
          language, last_updated.
        - `npm run docs:index` reports 0 docs missing front-matter and
          regenerates docs/INDEX.md cleanly.
      priority: 2
      tasks:

        - title: "Remove docs/patterns/test.md"
          description: "One-word stub file (`test`) committed by accident."
          implementation_plan: |
            git rm docs/patterns/test.md
            grep -rn "patterns/test" docs/ CLAUDE.md AGENTS.md README.md
              # expect no matches
            commit: docs(junk-cleanup): remove stub patterns/test.md
          priority: 3

        - title: "Archive .Plans/ into docs/plans/archive/"
          description: "Three historical plan files at repo root parallel to docs/plans/."
          implementation_plan: |
            mkdir -p docs/plans/archive
            git mv .Plans/2026-04-27-claude-md-workflow-update.md docs/plans/archive/
            git mv .Plans/2026-04-27-insert-milestone-tool.md docs/plans/archive/
            git mv .Plans/2026-04-27-m8-realtime-solo.md docs/plans/archive/
            rmdir .Plans
            # remove the .Plans/ entry from .gitignore (line 55 today)
            commit: docs(junk-cleanup): archive .Plans/ to docs/plans/archive/
          priority: 3

        - title: "Delete root Brainstorm.md"
          description: "Already gitignored; contains stray Prisma + DOM dump with no context."
          implementation_plan: |
            git rm -f Brainstorm.md
            # leave the .gitignore Brainstorm.md entry — harmless if file gone
            commit: docs(junk-cleanup): remove root Brainstorm.md scratch file
          priority: 4

        - title: "Add front-matter to all docs/*.md (root)"
          description: "13 files at docs/ root currently have no front-matter."
          implementation_plan: |
            For each file in docs/*.md (excluding INDEX.md):
              prepend a YAML block:
                ---
                title: <copy from H1>
                status: active
                audience: [maintainer, contributor]
                language: nl   # or en, match the actual file
                last_updated: 2026-05-02
                ---
            Verify: head -1 docs/*.md | grep -c '^==>' should equal
            (count of files), and head -2 docs/*.md should show "---" on
            line 2 of every file.
            commit: docs(front-matter): add YAML front-matter to docs/ root
          priority: 2

        - title: "Add front-matter to docs/patterns/*.md"
          description: "11 patterns get front-matter with audience=ai-agent."
          implementation_plan: |
            For each docs/patterns/*.md:
              ---
              title: <H1 minus 'Patroon: ' prefix>
              status: active
              audience: [ai-agent, contributor]
              language: nl
              last_updated: 2026-05-02
              when_to_read: <one sentence — what triggers reading this>
              ---
            commit: docs(front-matter): add YAML front-matter to patterns/
          priority: 2

        - title: "Add front-matter to docs/plans/*.md and CLAUDE.md/AGENTS.md"
          description: "Plans, the orientation file, and AGENTS.md."
          implementation_plan: |
            Plans (active + archive): include `applies_to: [<milestone>]`
            and `status: <proposal|active|done|deprecated>` based on git
            history of the file.
            CLAUDE.md and AGENTS.md: status: active, audience: ai-agent.
            commit: docs(front-matter): add YAML front-matter to plans + agent files
          priority: 2

        - title: "Verify INDEX.md picks up new metadata"
          description: "Sanity check: status and dates now visible in INDEX.md."
          implementation_plan: |
            npm run docs:index
            grep -c "| — |" docs/INDEX.md
              # expect significantly fewer than before (most rows now
              # show real status/date)
            commit: docs(index): regenerate INDEX.md after front-matter pass
          priority: 3

    - slug: naming-normalization
      title: "Phase 2 — Normalize file naming"
      description: |
        Drop the `` prefix. Lowercase everything. Remove the
        space + em-dash filename. Rename Next.js 16 middleware to proxy.
        After this story all filenames are kebab-case and grep-friendly.
      acceptance_criteria: |
        - No file under docs/ starts with ``.
        - No file under docs/ uses UPPER, snake_case, or contains spaces.
        - docs/patterns/proxy.md is renamed to docs/patterns/proxy.md.
        - Every internal link to renamed files is updated in the same
          commit as the rename.
        - `npm run docs:index` runs cleanly with no missing files.
      priority: 2
      tasks:

        - title: "Rename docs/* (drop prefix)"
          description: "8 spec/backlog/styling files at docs/ root."
          implementation_plan: |
            git mv docs/architecture.md     docs/architecture.md
            git mv docs/backlog/index.md          docs/backlog/index.md
            git mv docs/specs/functional.md  docs/specs/functional.md
            git mv docs/specs/dialogs/pbi.md       docs/specs/dialogs/pbi.md
            git mv docs/specs/personas.md         docs/specs/personas.md
            git mv docs/backlog/product-historical.md  docs/backlog/product-historical.md
            git mv docs/specs/dialogs/story.md     docs/specs/dialogs/story.md
            git mv docs/design/styling.md          docs/design/styling.md
            git mv docs/specs/dialogs/task.md      docs/specs/dialogs/task.md
            git mv docs/qa/api-test-plan.md        docs/qa/api-test-plan.md
            # update every internal link
            grep -rln "" docs/ CLAUDE.md AGENTS.md README.md \
              | xargs sed -i '' 's|||g'
            npm run docs:index
            commit: docs(naming): drop  prefix from doc filenames
          priority: 2

        - title: "Lowercase api.md and MD3 file"
          description: "Two files use non-kebab capitalization."
          implementation_plan: |
            git mv docs/api/rest-contract.md docs/api/rest-contract.md
            git mv docs/design/styling.md docs/design/styling.md
            grep -rln "API\.md\|MD3_Color_Scheme" docs/ CLAUDE.md AGENTS.md README.md \
              | xargs sed -i '' 's|API\.md|api.md|g; s|md3-color-scheme|md3-color-scheme|g'
            npm run docs:index
            commit: docs(naming): lowercase api.md and MD3 filenames
          priority: 2

        - title: "Rename plan file with spaces + em-dash"
          description: "`tweede-claude-agent-planning.md` → kebab-case."
          implementation_plan: |
            git mv "docs/plans/tweede-claude-agent-planning.md" \
                   docs/plans/tweede-claude-agent-planning.md
            grep -rln "Tweede Claude Agent" docs/ CLAUDE.md AGENTS.md README.md \
              | xargs sed -i '' 's|Tweede Claude Agent — Planning Agent\.md|tweede-claude-agent-planning.md|g'
            npm run docs:index
            commit: docs(naming): rename plan file to kebab-case ASCII
          priority: 3

        - title: "Rename middleware.md → proxy.md"
          description: "Next.js 16 renamed middleware.ts to proxy.ts."
          implementation_plan: |
            git mv docs/patterns/proxy.md docs/patterns/proxy.md
            grep -rln "patterns/proxy" docs/ CLAUDE.md AGENTS.md README.md \
              | xargs sed -i '' 's|patterns/proxy|patterns/proxy|g'
            npm run docs:index
            commit: docs(naming): rename middleware.md to proxy.md (next 16)
          priority: 3

        - title: "Update CLAUDE.md doc-index table"
          description: "After renames, CLAUDE.md §Specificatiedocumenten and §Implementatiepatronen tables need a sweep."
          implementation_plan: |
            Manually review CLAUDE.md lines 13–32 (specs table) and
            99–118 (patterns table) — the sed sweeps already updated the
            paths, but column wording may need a quick polish.
            commit: docs(naming): polish CLAUDE.md doc-index after renames
          priority: 3

    - slug: folder-taxonomy
      title: "Phase 3 — Move docs into topical folders"
      description: |
        Create architecture/, specs/, design/, api/, runbooks/,
        decisions/, backlog/, qa/, assets/ folders. Move existing files
        into them. Keep one git mv per group so commits stay readable.
      acceptance_criteria: |
        - docs/ root contains only INDEX.md and (later) glossary.md.
        - All existing docs moved into the right folder per
          docs/plans/docs-restructure-ai-lookup.md §4.
        - Internal links updated in the same commit as each move.
        - `npm run docs:index` shows docs grouped correctly.
      priority: 2
      tasks:

        - title: "Create folder skeleton"
          description: "Empty folders with .gitkeep so structure is visible."
          implementation_plan: |
            for d in architecture specs specs/dialogs design api runbooks decisions backlog qa assets; do
              mkdir -p docs/$d
              touch docs/$d/.gitkeep
            done
            commit: docs(taxonomy): scaffold topical folders under docs/
          priority: 3

        - title: "Move spec files into docs/specs/"
          description: "functional, personas, dialogs/."
          implementation_plan: |
            git mv docs/specs/functional.md      docs/specs/functional.md
            git mv docs/specs/personas.md        docs/specs/personas.md
            git mv docs/specs/dialogs/pbi.md      docs/specs/dialogs/pbi.md
            git mv docs/specs/dialogs/story.md    docs/specs/dialogs/story.md
            git mv docs/specs/dialogs/task.md     docs/specs/dialogs/task.md
            grep -rln "docs/specs/personas\|docs/specs/functional\|docs/.*-dialog" \
              docs/ CLAUDE.md AGENTS.md README.md \
              | xargs sed -i '' \
                -e 's|docs/specs/functional|docs/specs/functional|g' \
                -e 's|docs/specs/personas|docs/specs/personas|g' \
                -e 's|docs/specs/dialogs/pbi|docs/specs/dialogs/pbi|g' \
                -e 's|docs/specs/dialogs/story|docs/specs/dialogs/story|g' \
                -e 's|docs/specs/dialogs/task|docs/specs/dialogs/task|g'
            commit: docs(taxonomy): move spec files into docs/specs/
          priority: 2

        - title: "Move design + api + qa + backlog + assets"
          description: "Bulk move per topic."
          implementation_plan: |
            git mv docs/design/styling.md          docs/design/styling.md
            git mv docs/design/styling.md docs/design/styling.md
            git mv docs/api/rest-contract.md              docs/api/rest-contract.md
            git mv docs/qa/api-test-plan.md        docs/qa/api-test-plan.md
            git mv docs/backlog/index.md          docs/backlog/index.md
            git mv docs/backlog/product-historical.md  docs/backlog/product-historical.md
            git mv docs/assets/erd.svg             docs/assets/erd.svg
            git mv docs/assets/icons.html          docs/assets/icons.html
            # update links — sed sweep
            commit: docs(taxonomy): move design/api/qa/backlog/assets into folders
          priority: 2

        - title: "Move decisions/agent-instructions-history → decisions/ as ADR seed"
          description: "Sets up Story 6 ADR-0008 (will replace this file with a real ADR)."
          implementation_plan: |
            git mv docs/decisions/agent-instructions-history.md docs/decisions/agent-instructions-history.md
            grep -rln "decisions/agent-instructions-history" docs/ CLAUDE.md AGENTS.md README.md \
              | xargs sed -i '' 's|decisions/agent-instructions-history|decisions/agent-instructions-history|g'
            commit: docs(taxonomy): move decisions/agent-instructions-history into decisions/
          priority: 3

    - slug: split-monoliths
      title: "Phase 4 — Split oversized docs"
      description: |
        Four docs exceed 800 lines and conflate multiple topics. Split
        them so an agent can grep for the right section directly.
      acceptance_criteria: |
        - No doc in docs/ exceeds 800 lines.
        - The original location of each split doc still exists as a
          breadcrumb file (≤25 lines) listing the new paths so old links
          fail gracefully.
        - solo-panel content lives inside docs/specs/functional.md as
          its own H2 section.
        - md3-color-scheme.md content is merged into docs/design/styling.md.
      priority: 2
      tasks:

        - title: "Split docs/architecture.md into 6 files under docs/architecture/"
          description: "Current size: 1247 lines."
          implementation_plan: |
            Target split (per plan §4):
              docs/architecture/overview.md             (today §1–§3)
              docs/architecture/data-model.md           (Datamodel + Prisma Schema)
              docs/architecture/auth-and-sessions.md    (Authenticatieflow)
              docs/architecture/qr-pairing.md           (QR-pairing flow)
              docs/architecture/claude-question-channel.md (Q&A kanaal)
              docs/architecture/project-structure.md    (Projectstructuur)
            Replace docs/specs/architecture.md (after Phase 3 it's at
            docs/architecture.md still — adjust path) with a 20-line
            breadcrumb pointing to the six new files.
            Each new file gets fresh front-matter.
            commit: docs(split): break architecture.md into 6 topical files
          priority: 2

        - title: "Merge solo-paneel-spec.md into specs/functional.md"
          description: "Per resolved decision 3."
          implementation_plan: |
            Append solo-paneel-spec.md content as a new H2 section
            "Solo Panel" inside docs/specs/functional.md.
            git rm docs/specs/functional.md#solo-panel
            grep -rln "solo-paneel-spec" docs/ CLAUDE.md AGENTS.md README.md \
              | xargs sed -i '' 's|docs/solo-paneel-spec\.md|docs/specs/functional.md#solo-panel|g'
            commit: docs(split): merge solo-paneel-spec into specs/functional.md
          priority: 3

        - title: "Merge md3-color-scheme.md into design/styling.md"
          description: "Per resolved decision 2."
          implementation_plan: |
            Append md3-color-scheme.md content as H2 sections inside
            docs/design/styling.md. Drop redundant intro paragraphs.
            git rm docs/design/styling.md
            grep -rln "md3-color-scheme" docs/ CLAUDE.md AGENTS.md README.md \
              | xargs sed -i '' 's|docs/design/md3-color-scheme\.md|docs/design/styling.md|g'
            commit: docs(split): merge md3-color-scheme into design/styling
          priority: 3

    - slug: trim-orientation
      title: "Phase 5 — Trim CLAUDE.md and AGENTS.md"
      description: |
        Move conventions, branch/commit rules, MCP details, and deploy
        notes out of CLAUDE.md into runbooks/. Replace AGENTS.md with a
        10-line stub. Goal: CLAUDE.md ≤ 150 lines.
      acceptance_criteria: |
        - CLAUDE.md is at most 150 lines and contains only: scope,
          orientation pointers, hardstop rules, stack one-liner, pattern
          quickref, verification command. (See plan §5 for the
          skeleton.)
        - AGENTS.md is the 10-line stub from plan §7.
        - Removed sections live as their own files under docs/runbooks/.
      priority: 2
      tasks:

        - title: "Extract Branch & Commit strategy → docs/runbooks/branch-and-commit.md"
          description: "CLAUDE.md §Branch & PR Strategy + §Commit Strategy + §Plan Mode."
          implementation_plan: |
            Move CLAUDE.md lines covering Branch & PR Strategy, Plan
            Mode, and Commit Strategy verbatim into
            docs/runbooks/branch-and-commit.md (with front-matter).
            In CLAUDE.md, leave a one-line link.
            commit: docs(trim): extract branch/commit rules into runbook
          priority: 2

        - title: "Extract MCP integration → docs/runbooks/mcp-integration.md"
          description: "CLAUDE.md §MCP-integratie."
          implementation_plan: |
            Move §MCP-integratie verbatim. Replace in CLAUDE.md with a
            link + the bare list of tool names (no schemas).
            commit: docs(trim): extract MCP integration into runbook
          priority: 2

        - title: "Extract Deployment → docs/runbooks/deploy-vercel.md"
          description: "CLAUDE.md §Deployment."
          implementation_plan: |
            Move §Deployment verbatim. Replace in CLAUDE.md with a link.
            commit: docs(trim): extract Vercel deployment into runbook
          priority: 2

        - title: "Rewrite CLAUDE.md skeleton ≤ 150 lines"
          description: "Per plan §5 layout."
          implementation_plan: |
            Following plan §5, rewrite CLAUDE.md as:
              §1 What is Scrum4Me (2 sentences + README link)
              §2 Read first (INDEX, glossary)
              §3 How to find work (compact 2-track summary)
              §4 Hardstop rules (one line each, link to detail)
              §5 Stack one-liner per layer
              §6 Pattern quickref table (≤10 rows)
              §7 Verification command
            Verify: wc -l CLAUDE.md → ≤ 150
            commit: docs(trim): rewrite CLAUDE.md as ≤150-line skeleton
          priority: 2

        - title: "Replace AGENTS.md with stub"
          description: "10-line redirect to CLAUDE.md per plan §7."
          implementation_plan: |
            Overwrite AGENTS.md with the stub from plan §7 (English).
            Verify no other doc references AGENTS.md for content
            (only as a name).
            commit: docs(trim): replace AGENTS.md with redirect stub
          priority: 3

    - slug: adr-backfill
      title: "Phase 6 — Backfill ADRs for implicit decisions"
      description: |
        Write the actual ADR-0001 through ADR-0008 files. Scaffolding
        (templates, README, meta-ADR 0000) already exists from
        feat/docs-adr-and-index. Use Nygard for one-way-door decisions,
        MADR where rejected alternatives matter (auth, agent integration).
      acceptance_criteria: |
        - 8 new ADR files exist under docs/adr/ with correct numbering.
        - Each is status `accepted` and dated.
        - docs/adr/README.md table-of-contents lists all 8.
        - `npm run docs:index` shows them in the ADRs section.
      priority: 3
      tasks:

        - title: "ADR-0001: base-ui-over-radix (Nygard)"
          description: "Why @base-ui/react instead of Radix."
          implementation_plan: |
            Copy docs/adr/templates/nygard.md → docs/adr/0001-base-ui-over-radix.md
            Context: shadcn/ui visually identical to Radix-based components,
              but @base-ui/react uses render-prop composition and TS-correct
              prop API. Radix asChild caused TS errors in our setup.
            Decision: We adopt @base-ui/react and never import from Radix.
            Consequences: positive — TS-clean composition; negative — agent
              must remember the render-prop pattern (not asChild).
            Update docs/adr/README.md TOC.
            commit: docs(adr): add 0001-base-ui-over-radix
          priority: 3

        - title: "ADR-0002: float-sort-order (Nygard)"
          description: "Why float instead of integer for drag-and-drop ordering."
          implementation_plan: |
            See docs/patterns/sort-order.md for the existing pattern.
            Context: drag-and-drop reordering with N items — integer
              positions force a renumber on every reorder.
            Decision: Use float sort_order; insert between two items as
              the midpoint.
            Consequences: positive — O(1) inserts; negative — float
              precision drift requires periodic compaction (document
              when).
            commit: docs(adr): add 0002-float-sort-order
          priority: 3

        - title: "ADR-0003: one-branch-per-milestone (MADR)"
          description: "Why milestones, not stories, get branches — and the cost driver."
          implementation_plan: |
            Use MADR (alternatives matter — Vercel cost driver explicit).
            Considered options: branch-per-story, branch-per-milestone,
              trunk-based.
            Decision: branch-per-milestone, push only after user-test.
            Decision drivers: Vercel Hobby preview-build cost; small team
              size; AI-driven dev flow.
            More information: revisit when Vercel Pro is on.
            commit: docs(adr): add 0003-one-branch-per-milestone
          priority: 3

        - title: "ADR-0004: status-enum-mapping (Nygard)"
          description: "Why DB UPPER_SNAKE and API lowercase, plus the lib/task-status.ts mapper."
          implementation_plan: |
            Context: Prisma uses UPPER_SNAKE for enums; OpenAPI/REST
              clients expect lowercase.
            Decision: DB stays UPPER; API exposes lower; conversion
              exclusively via lib/task-status.ts mappers.
            Consequences: negative — anyone tempted to .toLowerCase()
              elsewhere breaks the contract; mitigated by lint rule.
            commit: docs(adr): add 0004-status-enum-mapping
          priority: 3

        - title: "ADR-0005: iron-session-over-nextauth (MADR)"
          description: "Why iron-session — alternatives weighed."
          implementation_plan: |
            Use MADR.
            Considered options: NextAuth/Auth.js v5, Clerk, Supabase Auth,
              iron-session.
            Decision: iron-session.
            Drivers: full control over cookie shape; demo-user policy
              requires synchronous check; no third-party redirect chain.
            commit: docs(adr): add 0005-iron-session-over-nextauth
          priority: 3

        - title: "ADR-0006: demo-user-three-layer-policy (Nygard)"
          description: "Why the same check exists in proxy + actions + UI."
          implementation_plan: |
            Context: demo-user must never write. Defense-in-depth across
              network, server, and UI layers.
            Decision: enforce in proxy.ts (network), every Server
              Action / Route Handler (server), and disabled buttons +
              DemoTooltip (UI).
            See: docs/architecture/auth-and-sessions.md (after Phase 4
              split) and ST-1110 plan.
            commit: docs(adr): add 0006-demo-user-three-layer-policy
          priority: 3

        - title: "ADR-0007: claude-question-channel-design (MADR)"
          description: "How the agent ↔ user async channel works and why."
          implementation_plan: |
            Use MADR.
            Considered options: synchronous polling only, push via SSE,
              persistent claude_questions table + LISTEN/NOTIFY.
            Decision: persistent table + LISTEN/NOTIFY trigger.
            See: docs/patterns/claude-question-channel.md and M11 plan.
            commit: docs(adr): add 0007-claude-question-channel-design
          priority: 3

        - title: "ADR-0008: agent-instructions-policy (Nygard, supersedes audit doc)"
          description: "Replaces docs/decisions/agent-instructions-history.md as a real ADR."
          implementation_plan: |
            Migrate the conclusions of docs/decisions/agent-instructions-history.md
            into an ADR.
            After accepted: mark history doc as superseded with a
            top-of-file note linking to ADR-0008.
            commit: docs(adr): add 0008-agent-instructions-policy
          priority: 3

    - slug: glossary-and-husky
      title: "Phase 7 — Glossary + pre-commit hook for INDEX.md"
      description: |
        Write a glossary and wire the index generator into husky so
        INDEX.md never goes stale. The script itself already exists.
      acceptance_criteria: |
        - docs/glossary.md exists with entries for PBI, Story, Sprint,
          Solo, Todo, demo-token, MCP-job, agent worker, claude-question.
        - .husky/pre-commit runs `npm run docs:index` only when staged
          changes touch docs/**/*.md, then `git add docs/INDEX.md`.
        - README points to docs/INDEX.md and docs/glossary.md.
      priority: 3
      tasks:

        - title: "Write docs/glossary.md"
          description: "Single-page domain-term reference."
          implementation_plan: |
            Front-matter: status active, audience [ai-agent, contributor],
              language en.
            Terms (alphabetical):
              demo-token, demo-user, MCP-job, PBI, Solo Panel, Sprint,
              Story, Task, Todo, agent worker, claude-question.
            Each term: 1-2 sentences + link to canonical doc.
            commit: docs(glossary): add docs/glossary.md
          priority: 3

        - title: "Wire docs:index into husky pre-commit"
          description: "Avoid stale INDEX.md."
          implementation_plan: |
            Edit .husky/pre-commit:
              if git diff --cached --name-only | grep -q '^docs/.*\.md$'; then
                npm run docs:index
                git add docs/INDEX.md
              fi
            Verify with: stage a doc edit and run git commit --dry-run
            commit: chore(docs): regenerate INDEX.md in pre-commit hook
          priority: 3

        - title: "Add INDEX + glossary pointer to README"
          description: "Mensbezoekers vinden dan ook het orientation-laagje."
          implementation_plan: |
            In README.md add a short section under "Architectuur (kort)":
              ## Documentation
              - docs/INDEX.md — generated index of all docs
              - docs/glossary.md — domain terms
              - CLAUDE.md / AGENTS.md — agent instructions
            commit: docs(readme): link INDEX + glossary + agent instructions
          priority: 4

    - slug: link-check
      title: "Phase 8 — Doc-link health check"
      description: |
        Add a small node script that walks docs/, finds every markdown
        link, and verifies the path (and anchor) exists. Wire into
        npm test or CI so a broken link blocks merge.
      acceptance_criteria: |
        - scripts/check-doc-links.mjs exists, pure Node, no deps.
        - It validates relative .md links and #anchors.
        - It prints a non-zero exit code on failures.
        - `npm run docs:check-links` is wired in package.json.
        - At least one CI step (vitest config or a separate npm script)
          runs it.
        - All current docs pass the check after the renames from
          Stories 2–4.
      priority: 3
      tasks:

        - title: "Write scripts/check-doc-links.mjs"
          description: "Walk docs/, parse markdown links, validate."
          implementation_plan: |
            Pure Node 20.
            For each .md file:
              extract markdown links via regex /\[([^\]]+)\]\(([^)]+)\)/g
              skip http(s):// and mailto: links
              for each relative link:
                resolve against the file's directory
                check the path exists
                if the link includes #anchor:
                  read the target file, check for a heading whose
                    GitHub-style slug matches the anchor
            Print a table of failures; exit 1 if any.
            commit: feat(docs): add doc-link checker script
          priority: 3

        - title: "Wire docs:check-links in package.json"
          description: "Plus a `docs` super-script that runs index + check together."
          implementation_plan: |
            Add to package.json scripts:
              "docs:check-links": "node scripts/check-doc-links.mjs",
              "docs":             "npm run docs:index && npm run docs:check-links"
            commit: chore(docs): wire docs:check-links and docs npm scripts
          priority: 4

        - title: "Add docs check to CI"
          description: "Block merge on broken links."
          implementation_plan: |
            Edit .github/workflows/<existing>.yml:
              after the lint+test step, add:
                - run: npm run docs:check-links
            commit: ci(docs): block merge on broken doc links
          priority: 3

        - title: "Run + fix any reported broken links"
          description: "Final sweep across the whole tree."
          implementation_plan: |
            npm run docs:check-links
            For each reported broken link: fix in a single commit per
            file. If the target was renamed in Stories 2–4 but a link
            slipped through, that's a missed sed sweep — fix and update
            this story's notes.
            commit: docs(links): fix broken cross-references after restructure
          priority: 3
```

---

## 5. Executor notes

The executor reads the YAML graph above and calls, in order:

1. `mcp__scrum4me__create_pbi` with the `pbi.title`, `pbi.description`,
   `pbi.priority`, `pbi.product_id` (substituted from `REPLACE_ME`).
   Capture the returned `pbi_id`.
2. For each story under `pbi.stories`:
   `mcp__scrum4me__create_story` with `pbi_id`, `story.title`,
   `story.description`, `story.acceptance_criteria`, `story.priority`.
   Capture the returned `story_id`.
3. For each task under `story.tasks`:
   `mcp__scrum4me__create_task` with `story_id`, `task.title`,
   `task.description`, `task.implementation_plan`, `task.priority`.

`sort_order` is intentionally omitted everywhere — the MCP server
auto-assigns `last + 1` within the priority group, which gives a stable
order matching this file's reading order.

If any call fails, halt and surface the response — don't retry blindly,
because a partial create leaves the graph half-built.

After a successful run: store the returned PBI/story/task IDs somewhere
the executor can hand back, so a follow-up can verify everything
exists and the totals match (1 PBI, 8 stories, 39 tasks).

---

## 6. Verification

- [x] Spec written.
- [x] YAML graph parses cleanly with PyYAML; story/task counts verified
      (1 PBI, 8 stories, 39 tasks; phase distribution 7/5/4/3/5/8/3/4).
- [ ] Executor runs end-to-end against the docker sandbox.
- [ ] DB shows 1 PBI titled "Docs-restructure for AI-optimized lookup".
- [ ] DB shows 8 stories under it.
- [ ] DB shows 39 tasks across the 8 stories.
- [ ] `mcp__scrum4me__get_claude_context` for the PBI returns the
      context block (section 1) verbatim as the description.
