Skip to content

Sales Proposals Workspace — Implementation Plan (Arm a)

Sales Proposals Workspace — Implementation Plan (Arm a)

Section titled “Sales Proposals Workspace — Implementation Plan (Arm a)”

Stage 3 deliverable. Decomposes the Stage 2 spec (docs/specs/sales-proposals-workspace-spec-arm-a.md) into ordered, verifiable tasks. Every spec acceptance criterion (AC-1 through AC-41) maps to at least one task. Tasks are sized S/M; any L candidate is split before landing.

Build a Knowledge Hub-native sales-proposals workspace covering the seven §9.2 components (ROI calculator, case-study selector, quote picker, pricing configurator, templates, assembly logic, export), the pre-send QA gate, the Account Brief MCP App, three sales-persona prompts, and the OPS-26 plugin- reuse policy. Phasing follows spec §13: foundation → templates+content → pricing+ROI → assembly+editor → export+QA → Account Brief+prompts → hardening → optional PDF.

§2 Architecture decisions (locked from spec)

Section titled “§2 Architecture decisions (locked from spec)”
  • Single-Supabase-project tenancy scoped via client_id; no multi-tenant RLS row sharing (spec Assumption 1).
  • DB-first storage — 7 tables + JSON templates on disk; reject the JSON-on-disk runtime model (spec Assumption 2).
  • Tiptap canonical, Markdown serialised on readblock_data stores the Tiptap JSON; round-trip stability enforced by AC-16 (spec FR-6.5).
  • DOCX primary, PDF secondary — DOCX always v1.0; PDF v1.0 if effort allows, else v1.5 (spec Assumption 4 + Phasing v0.5/v1.5).
  • OPS-26 reuse modes — Wrap / Compose / Adapt / Build native; documented verdict per reused asset (spec §10).
  • proposal-writer doctrine canonical — assembly, exec summary, pricing, ROI, structure rules defer to .claude/skills/proposal-writer/rules/* (spec Assumption 10).

§3 Open questions to resolve before kickoff

Section titled “§3 Open questions to resolve before kickoff”

These are spec §17 questions Liam must answer before Phase 1 starts. Phase 0 captures the resolutions; without them, downstream tasks are blocked or scoped ambiguously.

#QuestionBlocks
Q1§C.3 case-study tab dependency: ship before v0.2, or workspace ships with empty-state?T7 (case-study selector)
Q2PDF in v1.0 or v1.5?T22 / T38
Q3sales_author role granularity (single role vs author+reviewer split)T1 (migration), T4 (auth gating)
Q4Multi-client tenancy model — confirm one Supabase project per clientT1 (RLS)
Q5Templates: locked v1 / extensible v2 / extensible v1T6 (template loader)
Q6T&Cs source — bundled UK SMB library or per-client suppliedT6 (template defaults), T34 (docs)
Q7Handover surface — live workspace + starter zip, or live onlyT35 (handover pack)
Q8Cover image storage — per-proposal Supabase Storage or shared brand bucketT1 (storage paths), T21 (DOCX)
Q9QA gate numerics tolerance — ±0.5% confirmed or pilot-tunableT23 (QA rules)
Q10proposal_shortcut grounding — wait for P1-15 Phase 2 or ship staticT17 (prompt)

Description: Liam dispositions Q1–Q10 from spec §17. Update spec with canonical answers; mark §17 status resolved. No code changes.

Acceptance criteria:

  • Each of Q1–Q10 has a recorded answer in spec §17.
  • Spec frontmatter status flips from draft to resolved-questions.

Verification:

  • Spec diff shows §17 status change + per-question answer block.
  • Plan §3 table updated to “resolved” with answer summary.

Dependencies: None.

Files likely touched:

  • docs/specs/sales-proposals-workspace-spec-arm-a.md (§17 only)

Estimated scope: S (1 file).

ACs covered: none directly (unblocks all).


Phase 1 — Foundation (v0.1, M, mostly sequential)

Section titled “Phase 1 — Foundation (v0.1, M, mostly sequential)”

Goal: data layer + minimal workspace shell + 3 stub MCP tools. End state = listing renders and a draft proposal can be created with empty sections.

T1 — DB migration (7 tables + RLS + new role)

Section titled “T1 — DB migration (7 tables + RLS + new role)”

Description: Create one Supabase migration adding proposals, proposal_sections, proposal_revisions, proposal_pricing_tiers, proposal_roi_inputs, proposal_assets, proposal_qa_gate_runs. Add sales_author role; extend get_user_role(). RLS per spec §6.3. All new PL/pgSQL functions SET search_path = public, extensions. Storage bucket provisioned for proposals/<id>/... paths.

Acceptance criteria:

  • Migration applies cleanly via the Supabase CLI on a shadow project.
  • RLS verified: sales_author can write own draft; viewer reads only sent/won/lost; admin reads all.
  • Storage path policy created with signed-URL TTL per spec §9.1.

Verification:

  • supabase db push succeeds against shadow project.
  • Integration test (added in T5) covers RLS matrix.
  • AC-34 (RLS) and AC-35 (search_path) verified.

Dependencies: T0.

Files likely touched:

  • supabase/migrations/<yyyymmdd>_proposals.sql (new)
  • supabase/types/database.types.ts (regenerated at the deliberate reconciliation point only — not mid-session).

Estimated scope: M (1 large SQL file + types regen).

ACs covered: AC-34, AC-35.


Description: Author types/sales-proposals.ts with all spec §6 row types, ROIInputs / ROIOutputs, template definition schema, embed-ref discriminated union, QA-gate finding schema. Zod schemas mirror DB enums. No barrel re-exports per CLAUDE.md.

Acceptance criteria:

  • TS compiles against regenerated database.types.ts.
  • Zod schemas reject invalid enum values + non-negative numerics.
  • Direct file import path documented (no index.ts re-export).

Verification:

  • bun run test __tests__/lib/sales-proposals/types.test.ts passes (Zod schema round-trip).
  • bun lint clean.

Dependencies: T1.

Files likely touched:

  • types/sales-proposals.ts (new)
  • __tests__/lib/sales-proposals/types.test.ts (new)

Estimated scope: S (2 files).

ACs covered: none directly (foundation for many).


T3 — MCP tool stubs (proposal.create, proposal.update, proposal.add_section)

Section titled “T3 — MCP tool stubs (proposal.create, proposal.update, proposal.add_section)”

Description: Register three foundational MCP tools under lib/mcp/tools/sales-proposals/. Tools accept Zod-validated inputs and write to the new tables via getAuthorisedClient(); check auth.success and use authFailureResponse(auth) per CLAUDE.md. Empty block_data seeded.

Acceptance criteria:

  • All three tools registered in MCP server inventory.
  • Layer 1 protocol-compliance check passes for the three tool names.
  • Layer 4 functional-correctness asserts a created proposal has the correct template’s section list seeded.

Verification:

  • bun run test:mcp-eval Layer 1 + Layer 4 pass for the new tools.
  • bun run generate:mcp-inventory reflects the additions.

Dependencies: T2.

Files likely touched:

  • lib/mcp/tools/sales-proposals/create.ts (new)
  • lib/mcp/tools/sales-proposals/update.ts (new)
  • lib/mcp/tools/sales-proposals/add-section.ts (new)
  • lib/mcp/tools/sales-proposals/index.ts (registration only — direct re-imports per CLAUDE.md no-barrel rule)
  • __tests__/integration/sales-proposals/mcp-create.test.ts (new)

Estimated scope: M (5 files).

ACs covered: partial AC-2 (proposals row + sections seeded).


T4 — Workspace shell + listing + new-proposal modal

Section titled “T4 — Workspace shell + listing + new-proposal modal”

Description: Build app/sales-proposals/page.tsx (listing) and app/sales-proposals/[id]/page.tsx (empty edit page with section navigator skeleton). New-proposal modal posts to proposal.create. Auth gating: unauthenticated → /login; viewer sees only sent/won/lost. TanStack Query for listing with key ['sales-proposals', clientId, filters].

Acceptance criteria:

  • AC-1: /sales-proposals listing renders for sales_author; viewer filtered; unauthenticated redirected.
  • AC-2: New-proposal flow creates row + sections; navigates to [id].
  • Listing card shows: title, target entity, deal-stage type, status, last- edited timestamp; recommended pricing tier and ROI% slots present (filled in later phases).

Verification:

  • Component test: listing role-matrix + filter tests.
  • Manual: bun dev, sign in as sales_author, run the create flow.
  • bun run knip clean for the new files.

Dependencies: T3.

Files likely touched:

  • app/sales-proposals/page.tsx (new)
  • app/sales-proposals/[id]/page.tsx (new)
  • app/sales-proposals/new/page.tsx (new modal route)
  • components/sales-proposals/ProposalListing.tsx (new)
  • components/sales-proposals/NewProposalModal.tsx (new)
  • components/sales-proposals/SectionNavigator.tsx (skeleton)
  • lib/query/query-keys.ts (extend)
  • lib/query/fetchers.ts (extend)

Estimated scope: M (5 files + 2 extensions).

ACs covered: AC-1, AC-2.


T5 — Foundation tests (CRUD round-trip + auth gating + RLS matrix)

Section titled “T5 — Foundation tests (CRUD round-trip + auth gating + RLS matrix)”

Description: Integration tests under __tests__/integration/sales- proposals/ covering: proposal CRUD via MCP tools; RLS matrix (admin/sales_author/viewer/anon); empty-state listing.

Acceptance criteria:

  • bun run test:integration __tests__/integration/sales-proposals/ passes.
  • RLS write-denied for unauthenticated requests asserted.

Verification:

  • Run with dangerouslyDisableSandbox: true per CLAUDE.md (Bun fetch + 204).
  • Coverage of lib/sales-proposals/ ≥ 50% at this phase milestone.

Dependencies: T1–T4.

Files likely touched:

  • __tests__/integration/sales-proposals/crud-roundtrip.test.ts (new)
  • __tests__/integration/sales-proposals/rls-matrix.test.ts (new)

Estimated scope: S (2 files).

ACs covered: AC-34 verified.


  • bun run test green.
  • bun build green.
  • Manual: create + list a proposal end-to-end.
  • AC-1, AC-2, AC-34, AC-35 verified.
  • Liam sign-off before Phase 2.

Phase 2 — Templates + content selection (v0.2, M, parallelisable)

Section titled “Phase 2 — Templates + content selection (v0.2, M, parallelisable)”

Goal: templates load real section lists; case-study selector + quote picker populate embedded_block_refs. End state = author can configure a draft with selected case studies and quotes, but no editing yet.

T6 — Five template JSON definitions + loader

Section titled “T6 — Five template JSON definitions + loader”

Description: Author 5 templates in lib/sales-proposals/templates/*.json per spec §8.5 table. Each defines section list, required flags, default block content (placeholders to proposal-writer doctrine), recommended length per deal_size_band. Build a typed loader; template-swap logic preserves overlapping sections, archives orphans (display_order = NULL), seeds new sections empty.

Acceptance criteria:

  • AC-14: All 5 JSON files exist and parse.
  • AC-15: Swap from full_proposalsolution_brief preserves Cover, Exec Summary, Understanding, Solution; orphans archived; new sections empty.
  • Soft-target word counts per section keyed by deal_size_band.

Verification:

  • bun run test __tests__/lib/sales-proposals/templates.test.ts passes (loader + swap matrix).

Dependencies: T2 (types).

Files likely touched:

  • lib/sales-proposals/templates/one-pager.json
  • lib/sales-proposals/templates/solution-brief.json
  • lib/sales-proposals/templates/full-proposal.json
  • lib/sales-proposals/templates/rfp-response.json
  • lib/sales-proposals/templates/sow.json
  • lib/sales-proposals/templates/loader.ts
  • lib/sales-proposals/templates/swap.ts
  • __tests__/lib/sales-proposals/templates.test.ts

Estimated scope: M (8 files).

ACs covered: AC-14, AC-15.


T7 — Case-study selector UI + relevance scoring

Section titled “T7 — Case-study selector UI + relevance scoring”

Description: Build components/sales-proposals/CaseStudySelector.tsx. Query content_items where content_type = 'case_study' AND client_id matches. Rank by 0.5 × sector_match + 0.5 × use_case_tag_overlap. Render top 10 cards. Selection appends embedded_block_refs entry. Empty-state copy per FR-2.5. Filters: free-text, sector, tag chips.

Acceptance criteria:

  • AC-6: 5 case studies (3 sector-match, 2 not) → 3 matches in top 3.
  • AC-7: Empty state when 0 indexed.
  • AC-8: Selection appends ref + section navigator increments count.

Verification:

  • Component test: relevance ordering + empty state + selection.
  • Manual: open a draft, select 2 case studies.
  • Radix Select shims via installRadixPointerShims() per CLAUDE.md.

Dependencies: T6 (templates), T2 (types). Phase 0 Q1 resolution governs empty-state expectation.

Files likely touched:

  • components/sales-proposals/CaseStudySelector.tsx (new)
  • components/sales-proposals/CaseStudyCard.tsx (new)
  • lib/sales-proposals/relevance.ts (new — scoring fn)
  • __tests__/components/sales-proposals/CaseStudySelector.test.tsx (new)
  • __tests__/lib/sales-proposals/relevance.test.ts (new)

Estimated scope: M (5 files).

ACs covered: AC-6, AC-7, AC-8.


Description: Build components/sales-proposals/QuotePicker.tsx. Queries q_a_pairs, content_items where content_type IN ('certification', 'evidence'), and entity_mentions for holder/supplier metadata. Filters: source type, tag, relevance vs active section. Selection inserts a structured quote block; per-line justification field optional.

Acceptance criteria:

  • AC-9: source_type = certification returns only those rows.
  • AC-10: Selecting a Q&A pair embeds question + answer + source link in block_data.
  • Sort options: relevance / recency / alphabetical.

Verification:

  • Component test: filter + sort + selection.
  • Manual: select a cert + a Q&A pair into a draft.

Dependencies: T6, T2.

Files likely touched:

  • components/sales-proposals/QuotePicker.tsx (new)
  • components/sales-proposals/QuoteCard.tsx (new)
  • __tests__/components/sales-proposals/QuotePicker.test.tsx (new)

Estimated scope: M (3 files).

ACs covered: AC-9, AC-10.


T9 — Selector MCP tools (proposal.select_case_studies, proposal.select_quotes)

Section titled “T9 — Selector MCP tools (proposal.select_case_studies, proposal.select_quotes)”

Description: Register two MCP tools that accept proposal_id, section_id, and a list of refs. Validate refs exist, append to embedded_block_refs, write a revision with change_reason = manual_edit.

Acceptance criteria:

  • Both tools registered; Layer 1 + Layer 4 pass.
  • Citation integrity warning fires when a ref does not resolve.

Verification:

  • bun run test:mcp-eval:fc passes for both tools.
  • Integration test asserts revision row created with the canonical change_reason value.

Dependencies: T7, T8.

Files likely touched:

  • lib/mcp/tools/sales-proposals/select-case-studies.ts (new)
  • lib/mcp/tools/sales-proposals/select-quotes.ts (new)
  • __tests__/integration/sales-proposals/select-tools.test.ts (new)

Estimated scope: S (3 files).

ACs covered: none net-new (supports AC-8, AC-10 via API surface).


  • AC-6 through AC-10 + AC-14, AC-15 verified.
  • All 5 templates load.
  • Two selectors operational.
  • bun run test green; bun run test:mcp-eval green.

Phase 3 — Pricing + ROI (v0.3, M, parallelisable)

Section titled “Phase 3 — Pricing + ROI (v0.3, M, parallelisable)”

Goal: pricing tiers + ROI calculator with hand-computed reference fixtures. End state = pricing and ROI panels persist and recompute live.

T11 — Pricing configurator UI + DB writes + constraint enforcement

Section titled “T11 — Pricing configurator UI + DB writes + constraint enforcement”

Description: Build components/sales-proposals/PricingConfigurator.tsx with 2–3 tier cards, recommended-flag uniqueness, GBP formatting, inclusions list, payment terms, value-summary slot, anchor-strategy slot, discount-trade matrix, objection-prevention slot. DB constraint (partial unique index) enforces ≤1 recommended tier per proposal.

Acceptance criteria:

  • AC-11: Marking tier 2 unchecks any other recommended; DB rejects two- recommended states.
  • AC-12: Prices render as £24,000.00 (UK formatting, two decimals).
  • AC-13: Inclusions list 0–20 rows; over-20 soft warning.

Verification:

  • Component test: recommended-uniqueness + GBP formatting.
  • Integration test asserts DB constraint rejects duplicate is_recommended.

Dependencies: T2 (types).

Files likely touched:

  • components/sales-proposals/PricingConfigurator.tsx (new)
  • components/sales-proposals/PricingTierCard.tsx (new)
  • lib/sales-proposals/pricing/format.ts (new — GBP formatter)
  • __tests__/components/sales-proposals/PricingConfigurator.test.tsx (new)
  • __tests__/integration/sales-proposals/pricing-constraint.test.ts (new)

Estimated scope: M (5 files).

ACs covered: AC-11, AC-12, AC-13.


T12 — ROI math (lib/sales-proposals/roi/compute.ts) + reference fixtures

Section titled “T12 — ROI math (lib/sales-proposals/roi/compute.ts) + reference fixtures”

Description: Implement computeROI per spec §5.3 example. Pure function; Zod-validated inputs; scenario weights 0.6 / 0.85 / 1.0; outputs grossValueGBP, netValueGBP, paybackMonths, roiPct, costOfInactionGBP. Fixture file roi-references.json stores hand-computed truth (AC-3 reference).

Acceptance criteria:

  • AC-3: investment=24000, revenue=60000, cost=30000, others=0, scenario=moderategross=76500, net=52500, payback≈3.76, roi≈218.75.
  • Edge cases: zero investment, all-zero drivers, conservative scenario.

Verification:

  • bun run test __tests__/lib/sales-proposals/roi/compute.test.ts passes with exact reference fixtures.

Dependencies: T2.

Files likely touched:

  • lib/sales-proposals/roi/compute.ts (new)
  • __tests__/lib/sales-proposals/fixtures/roi-references.json (new)
  • __tests__/lib/sales-proposals/roi/compute.test.ts (new)

Estimated scope: S (3 files).

ACs covered: AC-3.


T13 — ROI panel UI + scenario toggle + persistence

Section titled “T13 — ROI panel UI + scenario toggle + persistence”

Description: Build components/sales-proposals/ROIPanel.tsx. Five value-driver inputs, investment input, cost-of-inaction input, scenario selector (default moderate). Real-time output recomputation ≤100ms debounced. Narrative notes ≤2000 chars. Outputs render: investment table, value-drivers table, sensitivity matrix, payback period, ROI%, cost-of- inaction summary. Persists proposal_roi_inputs on debounced edit.

Acceptance criteria:

  • AC-4: Switching scenario recomputes in ≤100ms.
  • AC-5: Save persists row; reload restores all field values exactly.
  • Layout follows proposal-writer/rules/pricing-roi-business-case.md shapes.

Verification:

  • Component test: scenario toggle + save/load round-trip.
  • Manual: enter inputs, toggle scenarios, refresh page, confirm restore.

Dependencies: T12.

Files likely touched:

  • components/sales-proposals/ROIPanel.tsx (new)
  • components/sales-proposals/ROITable.tsx (new)
  • components/sales-proposals/SensitivityMatrix.tsx (new)
  • __tests__/components/sales-proposals/ROIPanel.test.tsx (new)

Estimated scope: M (4 files).

ACs covered: AC-4, AC-5.


T14 — Pricing + ROI MCP tools (proposal.configure_pricing, proposal.compute_roi)

Section titled “T14 — Pricing + ROI MCP tools (proposal.configure_pricing, proposal.compute_roi)”

Description: Register two MCP tools. configure_pricing writes tier rows (atomic transaction enforcing recommended uniqueness). compute_roi runs computeROI server-side and persists proposal_roi_inputs.

Acceptance criteria:

  • Both tools registered; Layer 1 + Layer 4 pass.
  • AC-31 (GBP formatting on substituted strings) groundwork present.

Verification:

  • bun run test:mcp-eval:fc passes.
  • Integration test asserts DB state after tool invocations.

Dependencies: T11, T12.

Files likely touched:

  • lib/mcp/tools/sales-proposals/configure-pricing.ts (new)
  • lib/mcp/tools/sales-proposals/compute-roi.ts (new)
  • __tests__/integration/sales-proposals/pricing-roi-tools.test.ts (new)

Estimated scope: S (3 files).

ACs covered: none net-new (API surface).


  • AC-3, AC-4, AC-5, AC-11, AC-12, AC-13 verified.
  • ROI hand-computed reference fixture green.
  • Pricing constraint enforced at DB layer.

Phase 4 — Assembly + editor (v0.4, M, partially parallelisable)

Section titled “Phase 4 — Assembly + editor (v0.4, M, partially parallelisable)”

Goal: Tiptap editor wired; assembly prompt produces drafts; round-trip stable. End state = author edits inline and re-assembles per section.

T16 — Tiptap block editor + section navigator wiring

Section titled “T16 — Tiptap block editor + section navigator wiring”

Description: Tiptap editor in components/sales-proposals/SectionEditor.tsx, bound to proposal_sections.block_data. Use @tiptap/markdown per the CLAUDE.md note (editor.getMarkdown(), setContent with { contentType: 'markdown' }). Section navigator drives editor target. Save creates a revision with change_reason = manual_edit. Reset local state via key prop on section switch (no setState in effect).

Acceptance criteria:

  • Editor mounts per section; switch preserves draft via block_data write.
  • Inline edits create revision rows.

Verification:

  • Component test: switch sections + persist edits.
  • Manual: edit Solution section → switch to Investment → return → content present.

Dependencies: T2.

Files likely touched:

  • components/sales-proposals/SectionEditor.tsx (new)
  • components/sales-proposals/SectionNavigator.tsx (extend skeleton from T4)
  • __tests__/components/sales-proposals/SectionEditor.test.tsx (new)

Estimated scope: M (3 files).

ACs covered: none directly (foundation for AC-16/17/18).


T17 — proposal_shortcut prompt registration + Zod IO schema

Section titled “T17 — proposal_shortcut prompt registration + Zod IO schema”

Description: Register prompt at lib/mcp/prompts/sales-proposals/proposal-shortcut.ts. Inputs: deal-stage type, target entity profile, embedded blocks (compact refs), pricing summary, ROI summary, doctrine excerpts. Output: per-section Markdown with placeholders ({{block:case_study:<id>}}, {{roi.payback_months}}, etc.). UK English + GBP enforced. Output validated by Zod before persistence.

Acceptance criteria:

  • AC-29 partial: prompt listed under sales-proposals namespace.
  • AC-30 partial: Zod rejects malformed output.
  • AC-31: GBP-formatted substitutions emitted.

Verification:

  • bun run generate:mcp-inventory lists the prompt.
  • Unit test: malformed-output rejection + GBP formatting.

Dependencies: T2 (types). Phase 0 Q10 resolution determines grounding (static P1-15 Phase 1 only, or dynamic P1-15 Phase 2).

Files likely touched:

  • lib/mcp/prompts/sales-proposals/proposal-shortcut.ts (new)
  • lib/mcp/prompts/sales-proposals/index.ts (registration)
  • __tests__/lib/sales-proposals/prompts/proposal-shortcut.test.ts (new)

Estimated scope: S (3 files).

ACs covered: AC-29 partial, AC-30 partial, AC-31.


T19 — Assembly parser (Markdown ↔ Tiptap JSON, block-placeholder substitution)

Section titled “T19 — Assembly parser (Markdown ↔ Tiptap JSON, block-placeholder substitution)”

Description: Implement lib/sales-proposals/assembly/parser.ts. Convert prompt-output Markdown to Tiptap JSON; substitute placeholders with referenced content (case studies, quotes, pricing tier blocks, ROI symbolic references). Preserve Tiptap node types per spec §8.6. Use @tiptap/markdown official API only.

Acceptance criteria:

  • AC-16: Round-trip: assemble → export-to-Markdown → reassemble → emitted Tiptap JSON matches modulo timestamps.
  • AC-18: Substituted block-ref content present at placeholder positions.

Verification:

  • bun run test __tests__/lib/sales-proposals/assembly/parser.test.ts passes (round-trip golden fixtures).

Dependencies: T2.

Files likely touched:

  • lib/sales-proposals/assembly/parser.ts (new)
  • lib/sales-proposals/assembly/placeholders.ts (new — placeholder regex + substitutor)
  • __tests__/lib/sales-proposals/assembly/parser.test.ts (new)
  • __tests__/lib/sales-proposals/assembly/fixtures/ (golden Markdown + JSON pairs)

Estimated scope: M (4 files).

ACs covered: AC-16, AC-18.


T18 — proposal.assemble_draft MCP tool + section-level granularity

Section titled “T18 — proposal.assemble_draft MCP tool + section-level granularity”

Description: Register MCP tool. Pulls section list, embedded refs, pricing tiers, ROI outputs, target entity profile. Invokes the prompt. Parses output via T19. Writes per-section block_data; sets last_assembled_at; records revision with change_reason = assembled_draft. Section-level granularity: re-assembling one section does not modify siblings.

Acceptance criteria:

  • AC-17: Re-assembling one section leaves siblings’ block_data and last_edited_at unchanged.
  • Layer 1 + Layer 4 pass for the tool.

Verification:

  • Integration test: full-proposal assemble → mutate one section → re-assemble that section only → siblings unchanged (timestamps + content).

Dependencies: T17, T19.

Files likely touched:

  • lib/mcp/tools/sales-proposals/assemble-draft.ts (new)
  • __tests__/integration/sales-proposals/assemble-draft.test.ts (new)

Estimated scope: S (2 files).

ACs covered: AC-17.


  • AC-16, AC-17, AC-18, AC-31 verified.
  • AC-29 / AC-30 partial (one of three prompts registered).
  • Round-trip stability proven on golden fixtures.

Phase 5 — Export + QA gate (v0.5, L → split, parallelisable)

Section titled “Phase 5 — Export + QA gate (v0.5, L → split, parallelisable)”

Goal: DOCX export production-ready; PDF export shipped or deferred per Q2; QA gate operational. End state = Liam exports a buyer-ready .docx and runs the QA gate.

T21 — DOCX export adapter + asset persistence

Section titled “T21 — DOCX export adapter + asset persistence”

Description: Adapt ai-smb-playbook/app/src/lib/docx-export.ts into lib/sales-proposals/export/docx.ts. Apache-2.0 notice preserved. Block-type coverage extended per FR-7.1: cover, headings H1–H4, paragraph, bullet/ordered list, separator, table (pricing + ROI), embedded image, footer with page numbers. Persist to Supabase Storage at proposals/<id>/export_docx-<rev>.docx; row in proposal_assets.

Acceptance criteria:

  • AC-19: Full proposal .docx < 2 MB; opens in LibreOffice 7 (CI).
  • AC-20: TOC, page numbers, pricing/ROI tables match live values.
  • AC-22: Asset row has correct mime_type, size_bytes, signed-URL.

Verification:

  • CI step: LibreOffice headless conversion check.
  • Integration test: byte-stability with golden file (timestamp tolerance).
  • Manual: open the export in Microsoft Word 2021 (Liam pre-v1.0 sign-off).

Dependencies: T11 (pricing), T13 (ROI), T19 (parser).

Files likely touched:

  • lib/sales-proposals/export/docx.ts (new)
  • lib/sales-proposals/export/docx-blocks.ts (block renderers)
  • lib/sales-proposals/export/asset-store.ts (Storage upload + asset row)
  • __tests__/integration/sales-proposals/docx-export.test.ts (new)

Estimated scope: M (4 files).

ACs covered: AC-19, AC-20, AC-22.


T22 — PDF export adapter (conditional on Q2)

Section titled “T22 — PDF export adapter (conditional on Q2)”

Description: If Q2 = v1.0: build lib/sales-proposals/export/pdf.ts using Playwright print over app/sales-proposals/[id]/print/page.tsx (print-optimised render route). Otherwise: skip; defer to T38 in v1.5.

Acceptance criteria:

  • AC-21 (conditional): PDF content matches DOCX numerics; file ≤ 2 MB.

Verification:

  • Integration test: PDF render + numerics-cross-check.

Dependencies: T21 (shared block model).

Files likely touched:

  • lib/sales-proposals/export/pdf.ts (new — if v1.0)
  • app/sales-proposals/[id]/print/page.tsx (new — print route)
  • __tests__/integration/sales-proposals/pdf-export.test.ts (new)

Estimated scope: M (3 files).

ACs covered: AC-21 (conditional).


Description: Implement each rule under lib/sales-proposals/qa-gate/rules/*.ts: numerics consistency, client name spelling, ROI sanity, brand voice, completeness, UK English, currency consistency, date format, citation integrity, length. Each rule returns {rule, severity, findings[]}. Dispatcher composes verdict per FR-8.2. Pattern adapted from playbook-review skill harness.

Acceptance criteria:

  • AC-23: Acme Ltd vs “Acme Limited” → Fail on client-name-spelling.
  • AC-24: Pricing 24000 vs “£24,500” → Fail on numerics consistency.
  • AC-25: “color” → Fail on UK English; “colour” passes.
  • Citation integrity warns when ref missing.

Verification:

  • bun run test __tests__/lib/sales-proposals/qa-gate/rules.test.ts passes; one fixture per rule.

Dependencies: T11, T12, T19. Phase 0 Q9 sets numerics tolerance.

Files likely touched:

  • lib/sales-proposals/qa-gate/rules/numerics-consistency.ts
  • lib/sales-proposals/qa-gate/rules/client-name-spelling.ts
  • lib/sales-proposals/qa-gate/rules/roi-sanity.ts
  • lib/sales-proposals/qa-gate/rules/brand-voice.ts
  • lib/sales-proposals/qa-gate/rules/completeness.ts
  • lib/sales-proposals/qa-gate/rules/uk-english.ts
  • lib/sales-proposals/qa-gate/rules/currency-consistency.ts
  • lib/sales-proposals/qa-gate/rules/date-format.ts
  • lib/sales-proposals/qa-gate/rules/citation-integrity.ts
  • lib/sales-proposals/qa-gate/rules/length.ts
  • lib/sales-proposals/qa-gate/dispatcher.ts
  • __tests__/lib/sales-proposals/qa-gate/rules.test.ts

Estimated scope: L → split if needed (12 files; rule executors independent so split at file granularity is trivial — author 3 sub-tasks T23a/T23b/T23c if a single agent runs over budget).

ACs covered: AC-23, AC-24, AC-25.


T24 — QA gate UI panel + run history persistence + MCP tool

Section titled “T24 — QA gate UI panel + run history persistence + MCP tool”

Description: Build components/sales-proposals/QAGatePanel.tsx. Renders findings checklist; each finding deep-links to the offending block. Register proposal.run_qa_gate MCP tool. Persist runs in proposal_qa_gate_runs keyed to a revision snapshot.

Acceptance criteria:

  • AC-26: Run history persists with verdict + findings JSON.
  • Findings checklist UI renders per FR-8.3.

Verification:

  • Component test: findings render + deep-link target.
  • Integration test: run inserts row.

Dependencies: T23.

Files likely touched:

  • components/sales-proposals/QAGatePanel.tsx (new)
  • lib/mcp/tools/sales-proposals/run-qa-gate.ts (new)
  • __tests__/integration/sales-proposals/qa-gate-run.test.ts (new)

Estimated scope: S (3 files).

ACs covered: AC-26.


T25 — Export MCP tool (proposal.export) + LibreOffice CI step

Section titled “T25 — Export MCP tool (proposal.export) + LibreOffice CI step”

Description: Register proposal.export MCP tool that wraps T21 + T22. CI workflow step runs LibreOffice headless conversion against a fixture proposal export to verify rendering integrity.

Acceptance criteria:

  • Tool registered; Layer 1 + Layer 4 pass.
  • CI step runs on every push touching lib/sales-proposals/export/**.

Verification:

  • bun run test:mcp-eval:fc green.
  • CI run on a sample PR shows the LibreOffice step passing.

Dependencies: T21, T22.

Files likely touched:

  • lib/mcp/tools/sales-proposals/export.ts (new)
  • .github/workflows/<existing>.yml (extend with LibreOffice step)
  • __tests__/integration/sales-proposals/export-tool.test.ts (new)

Estimated scope: S (3 files).

ACs covered: none net-new (wraps T21/T22).


  • AC-19, AC-20, AC-22, AC-23, AC-24, AC-25, AC-26 verified.
  • AC-21 verified or deferred to v1.5.
  • DOCX CI gate live.

Phase 6 — Account Brief MCP App + remaining prompts (v0.6, S, parallelisable)

Section titled “Phase 6 — Account Brief MCP App + remaining prompts (v0.6, S, parallelisable)”

Goal: Account Brief MCP App ships inline + standalone; two remaining prompts registered. End state = AC-27, AC-28, AC-29 (full), AC-30 (full) green.

T27 — Account Brief MCP App (Vite single-file build)

Section titled “T27 — Account Brief MCP App (Vite single-file build)”

Description: Create mcp-apps/account-brief/. Vite single-file build per existing pattern; built via bun run build:mcp-apps. Renders entity profile, recent KB activity (last 10 referenced content_items), last contact touchpoints, prior proposals snapshot. Inline panel inside KH; standalone for Claude Desktop / Claude.ai plugin route.

Acceptance criteria:

  • AC-27: Sub-2s LCP for entity with ≤50 referenced content_items.
  • AC-28: Standalone build < 500 KB minified; renders same data.

Verification:

  • Lighthouse-equivalent on inline panel; manual standalone load test.
  • bun run build:mcp-apps produces the artefact.

Dependencies: T2 (types); P1-15 Phase 1 Company Profile (existing).

Files likely touched:

  • mcp-apps/account-brief/index.html
  • mcp-apps/account-brief/src/main.tsx
  • mcp-apps/account-brief/src/AccountBrief.tsx
  • mcp-apps/account-brief/vite.config.ts
  • lib/mcp/inline-bundle/account-brief.ts (regen by build script)

Estimated scope: M (5 files).

ACs covered: AC-27, AC-28.


Description: Register account_brief prompt at lib/mcp/prompts/sales-proposals/account-brief.ts. Inputs: target entity ID; outputs: structured Markdown brief. UK English. Wired to T27 panel.

Acceptance criteria:

  • AC-29 (full): prompt listed under namespace.
  • AC-30 (full): malformed output rejected.

Verification:

  • bun run generate:mcp-inventory lists; unit test for Zod validation.

Dependencies: T2.

Files likely touched:

  • lib/mcp/prompts/sales-proposals/account-brief.ts (new)
  • __tests__/lib/sales-proposals/prompts/account-brief.test.ts (new)

Estimated scope: S (2 files).

ACs covered: AC-29 progressed.


T29 — case_study_assembly prompt registration

Section titled “T29 — case_study_assembly prompt registration”

Description: Register prompt at lib/mcp/prompts/sales-proposals/case-study-assembly.ts. Inputs: case-study ref + deal context; outputs: Markdown insertion narrative with relevance- justification framing.

Acceptance criteria:

  • AC-29 (full): all three prompts listed.
  • AC-30 (full): all three Zod-validated.

Verification:

  • bun run generate:mcp-inventory shows all three.

Dependencies: T2.

Files likely touched:

  • lib/mcp/prompts/sales-proposals/case-study-assembly.ts (new)
  • __tests__/lib/sales-proposals/prompts/case-study-assembly.test.ts (new)

Estimated scope: S (2 files).

ACs covered: AC-29, AC-30.


T30 — Inline workspace panel for Account Brief

Section titled “T30 — Inline workspace panel for Account Brief”

Description: Mount the Account Brief MCP App inline in /sales-proposals/[id] alongside the section navigator.

Acceptance criteria:

  • Panel renders inline; deal context loads on page mount.

Verification:

  • E2E covers the inline render path (later in Phase 7 Journey A).

Dependencies: T27.

Files likely touched:

  • app/sales-proposals/[id]/page.tsx (extend)
  • components/sales-proposals/AccountBriefPanel.tsx (new)

Estimated scope: S (2 files).

ACs covered: AC-27 partial.


  • AC-27, AC-28, AC-29, AC-30 verified.
  • All three prompts live; inline panel rendering.

Phase 7 — Hardening + handover (v1.0, M, parallelisable)

Section titled “Phase 7 — Hardening + handover (v1.0, M, parallelisable)”

Goal: full E2E green; documentation complete; cross-cutting ACs verified; first-client handover pack assembled. End state = v1.0 ready for sign-off.

Description: Cover Journey A (full proposal end-to-end) per spec §4.2. Open new full-proposal → set deal context → review Account Brief panel → load template → select 2–3 case studies → select 4–6 quotes → configure 3 pricing tiers → enter ROI inputs → assemble draft → run QA gate → export DOCX. No conditional if (visible) fallbacks per CLAUDE.md.

Acceptance criteria:

  • AC-39: Journey A passes locally and in CI.

Verification:

  • bun run test:e2e e2e/tests/sales-proposals/journey-a.spec.ts green.

Dependencies: T1–T30.

Files likely touched:

  • e2e/tests/sales-proposals/journey-a.spec.ts (new)
  • e2e/fixtures/sales-proposals.ts (test data setup)

Estimated scope: M (2 files but heavy logic).

ACs covered: AC-39.


T32 — Playwright E2E Journey C (one-pager)

Section titled “T32 — Playwright E2E Journey C (one-pager)”

Description: Compressed authoring flow: cover + solution + pricing + single case study. Authoring time target ~15 minutes ⇒ test runs the path without the longer-tail steps.

Acceptance criteria:

  • E2E path completes; .docx export downloads.

Verification:

  • bun run test:e2e e2e/tests/sales-proposals/journey-c.spec.ts green.

Dependencies: T1–T30.

Files likely touched:

  • e2e/tests/sales-proposals/journey-c.spec.ts (new)

Estimated scope: S (1 file).

ACs covered: none net-new (operational coverage).


T33 — MCP eval Layer 4 + Layer 3 updates (10 new tools, 3 new prompts)

Section titled “T33 — MCP eval Layer 4 + Layer 3 updates (10 new tools, 3 new prompts)”

Description: Extend Layer 4 (functional correctness) with one check per new tool (10 tools: create, update, add_section, select_case_studies, select_quotes, configure_pricing, compute_roi, assemble_draft, run_qa_gate, export). Extend Layer 3 (response quality) with prompt-output checks.

Acceptance criteria:

  • AC-40: Layer 4 passes for all 10 new tools.
  • Layer 3 quality checks for the three prompts pass.

Verification:

  • bun run test:mcp-eval (Layer 1) + :rq + :fc all green.

Dependencies: T3, T9, T14, T18, T24, T25, T28, T29.

Files likely touched:

  • __tests__/mcp-eval/sales-proposals.fc.ts (new)
  • __tests__/mcp-eval/sales-proposals.rq.ts (new)

Estimated scope: M (2 files but 13 checks).

ACs covered: AC-40.


Description: Author docs/product-functionality/sales-proposals/: overview.md, authoring-guide.md, template-reference.md, roi-methodology.md. UK English; DD/MM/YYYY any dates; Warm Meridian- compatible diagrams.

Acceptance criteria:

  • All four pages exist and link from docs/reference/documentation- inventory.md.

Verification:

  • Manual review by Liam; doc-freshness guard test passes.

Dependencies: T31, T32 (so screenshots and walkthroughs reflect final UI).

Files likely touched:

  • docs/product-functionality/sales-proposals/overview.md (new)
  • docs/product-functionality/sales-proposals/authoring-guide.md (new)
  • docs/product-functionality/sales-proposals/template-reference.md (new)
  • docs/product-functionality/sales-proposals/roi-methodology.md (new)
  • docs/reference/documentation-inventory.md (extend)

Estimated scope: M (5 files).

ACs covered: none net-new (documentation gate).


T35 — Roadmap + state-of-product + handover pack

Section titled “T35 — Roadmap + state-of-product + handover pack”

Description: Update docs/reference/product-roadmap.md §9.2 entry to “shipped”; docs/reference/state-of-the-product.md entry on first-client handover; assemble first-client onboarding pack per Phase 0 Q7 disposition. Sentry observability check (assembly + export breadcrumbs).

Acceptance criteria:

  • Roadmap §9.2 status = “shipped”; SoTP capability folded in (no Phase-N block per CLAUDE.md feedback).
  • Handover pack present (live workspace + zip if Q7 = both).

Verification:

  • Doc diff review.
  • Sentry breadcrumb visible in a smoke run.

Dependencies: T31, T34.

Files likely touched:

  • docs/reference/product-roadmap.md (extend)
  • docs/reference/state-of-the-product.md (extend)
  • docs/handover/first-client-sales-proposals.md (new — if Q7 = both)

Estimated scope: S (3 files).

ACs covered: none net-new.


Description: Document the 7 new tables in docs/reference/SCHEMA-QUICK-REFERENCE.md.

Acceptance criteria:

  • Each table has a row with FK list + RLS summary.

Verification:

  • Manual review.

Dependencies: T1.

Files likely touched:

  • docs/reference/SCHEMA-QUICK-REFERENCE.md (extend)

Estimated scope: S (1 file).

ACs covered: none net-new.


T37 — Cross-cutting verification (lint, knip, coverage, UK English ESLint, regen artefacts)

Section titled “T37 — Cross-cutting verification (lint, knip, coverage, UK English ESLint, regen artefacts)”

Description: Run bun run knip, bun lint, bun run test:coverage, bun run generate:mcp-inventory, bun run build:plugin, bun run sync:taxonomy (if any taxonomy touched), bun run stats. Fix findings inline. Verify no raw Tailwind colour classes (lint rule); confirm UK English ESLint allowlist gates author-visible strings; confirm coverage ≥ 80% on lib/sales-proposals/.

Acceptance criteria:

  • AC-36: No raw Tailwind colour classes.
  • AC-37: ESLint blocks US spellings.
  • AC-38: Coverage ≥ 80% on lib/sales-proposals/.
  • AC-41: bun run knip zero unused exports introduced.
  • AC-32, AC-33: spec §10 + §11 verdicts present (already in spec; verify no drift after impl).

Verification:

  • All commands above run green.

Dependencies: All prior tasks.

Files likely touched:

  • docs/generated/codebase-stats.md (regen)
  • docs/generated/mcp-inventory.md (regen)
  • lib/mcp/plugin-bundle.ts (regen)

Estimated scope: S (artefact regen only; fix-time depends on findings).

ACs covered: AC-32, AC-33, AC-36, AC-37, AC-38, AC-41.


  • All 41 ACs green except AC-21 (if Q2 deferred to v1.5).
  • E2E suites green in CI.
  • MCP eval all layers green.
  • Knip + coverage + lint clean.
  • Liam manual sign-off on 3 exported .docx in Microsoft Word 2021.

Phase 8 — PDF deferral (v1.5, conditional, S)

Section titled “Phase 8 — PDF deferral (v1.5, conditional, S)”

T38 — PDF export adapter (deferred from T22)

Section titled “T38 — PDF export adapter (deferred from T22)”

Description: Run only if Q2 = v1.5. Implement Playwright print over /sales-proposals/[id]/print route.

Acceptance criteria:

  • AC-21: PDF content matches DOCX numerics; file ≤ 2 MB.

Verification:

  • Integration test green.

Dependencies: T21.

Files likely touched:

  • lib/sales-proposals/export/pdf.ts (new)
  • app/sales-proposals/[id]/print/page.tsx (new)
  • __tests__/integration/sales-proposals/pdf-export.test.ts (new)

Estimated scope: S (3 files).

ACs covered: AC-21.


T0
└── T1 (migration)
└── T2 (types)
├── T3 (3 stub MCP tools)
│ └── T4 (workspace shell)
│ └── T5 (foundation tests) ──┐
│ │
├── T6 (templates) ──┐ │
│ ├── T7 (case-study selector) ─┐
│ └── T8 (quote picker) ────────┤
│ └── T9 (selector tools)
│ ├──────────────┐
├── T11 (pricing) ──┐ │ │
│ └── T13 (ROI panel) ←── T12 (ROI math) │ │
│ │ │ │
│ └── T14 (pricing+ROI tools) │
│ │
├── T16 (Tiptap editor) ──┐ │
├── T17 (proposal_shortcut prompt) ──┐ │
│ │ │
└── T19 (assembly parser) ────────────┴── T18 (assemble_draft tool) │
│ │
└── T21 (DOCX) ──┐ │
│ │
T22 (PDF cond) │ │
│ │
T23 (QA rules) ──── T24 (QA panel + tool) │
│ │
T25 (export tool) ──┐ │
│ │
T27 (MCP App) ─┐ │ │
T28 (account_brief prompt)│
T29 (case_study_assembly) │
T30 (inline panel) ───────┤
T31 (E2E A) ──────────────┤
T32 (E2E C) ──────────────┤
T33 (MCP eval) ───────────┤
T34 (docs) ────────────────┤
T35 (roadmap+SoTP) ───────┤
T36 (schema ref) ─────────┤
T37 (cross-cutting verify) ┘
Conditional: T38 (PDF v1.5 if T22 deferred)

Tasks in the same group below can run as parallel agents with disjoint file ownership. Each group is followed by its own checkpoint before launching the next.

TaskFiles (disjoint)
T7components/sales-proposals/CaseStudy* + lib/sales-proposals/relevance.ts
T8components/sales-proposals/Quote*

T9 sequential (depends on both).

Group B — Phase 3 pricing+ROI (after Phase 1)

Section titled “Group B — Phase 3 pricing+ROI (after Phase 1)”
TaskFiles (disjoint)
T11components/sales-proposals/Pricing* + lib/sales-proposals/pricing/*
T12lib/sales-proposals/roi/*

T13 depends on T12; T14 depends on T11+T12 (sequential after group).

TaskFiles (disjoint)
T16components/sales-proposals/SectionEditor.tsx + SectionNavigator.tsx
T17lib/mcp/prompts/sales-proposals/proposal-shortcut.ts
T19lib/sales-proposals/assembly/*

T18 depends on T17+T19; T16 independent.

Group D — Phase 5 export+QA (after Phase 4)

Section titled “Group D — Phase 5 export+QA (after Phase 4)”
TaskFiles (disjoint)
T21lib/sales-proposals/export/docx* + asset-store.ts
T22lib/sales-proposals/export/pdf.ts + print/page.tsx (conditional)
T23lib/sales-proposals/qa-gate/rules/*

T24, T25 sequential after the group.

T23 itself splittable into T23a/T23b/T23c (3-4 rules each) if a single agent runs over budget — rule executors are independent.

Group E — Phase 6 prompts + MCP App (after Phase 5)

Section titled “Group E — Phase 6 prompts + MCP App (after Phase 5)”
TaskFiles (disjoint)
T27mcp-apps/account-brief/*
T28lib/mcp/prompts/sales-proposals/account-brief.ts
T29lib/mcp/prompts/sales-proposals/case-study-assembly.ts

T30 depends on T27.

Group F — Phase 7 hardening (after Phase 6)

Section titled “Group F — Phase 7 hardening (after Phase 6)”
TaskFiles (disjoint)
T31e2e/tests/sales-proposals/journey-a.spec.ts + fixtures
T32e2e/tests/sales-proposals/journey-c.spec.ts
T33__tests__/mcp-eval/sales-proposals.*.ts
T34docs/product-functionality/sales-proposals/*
T36docs/reference/SCHEMA-QUICK-REFERENCE.md

T35 depends on T31 + T34; T37 depends on all.

  • T1 must complete before any other task (DB foundation).
  • T2 must complete before any task touching types.
  • T6 must complete before T7/T8 (template-derived section schema).
  • T19 must complete before T18 (parser feeds assembly tool).
  • T21 must complete before T22 and T25 (shared block model + tool wrapper).
  • T31/T32 must complete before T34/T35 (docs reflect shipped UI).
  • T37 last (verifies the whole).

Per CLAUDE.md: parallel agent branches must cherry-pick (not merge) onto main; agents must git reset --hard main as their first action; verify file content after merging worktree branches from later waves; check git status on main before each cherry-pick. Defensive cd <main-repo-path> && prefix on git operations after any Read on worktree files.

  • Every task: per-task verification block above.
  • Every phase: phase checkpoint listed.
  • After every parallel group: bun run test + bun run knip + git status on main + cherry-pick each agent branch sequentially.
  • Pre-merge per phase: bun run test:integration + relevant E2E specs.
  • Pre-v1.0: full bun run test, bun run test:e2e, all three MCP eval layers, bun run build, bun run knip, manual DOCX review.

§8 Risks and mitigations (plan-level addendum)

Section titled “§8 Risks and mitigations (plan-level addendum)”

These extend spec §16 with task-execution risks specific to this plan.

RiskImpactMitigation
T0 question dispositions delayed — Liam not available for §17 answersBlocks Phase 1Plan §3 lists all 10 questions upfront; capture answers async via spec edit.
T1 migration overrun — 7 tables + RLS + role + storage = larger than typical migrationPhase 1 slipPre-author the SQL in a draft; review separately before applying; shadow project first.
T19 assembly parser drift — Tiptap ↔ Markdown round-trip subtletiesAC-16 failStrict golden fixtures; per-block-type round-trip tests; reference feedback_tiptap_markdown_api.md.
T21 DOCX byte-stability — golden-file noise from docx library version bumpsCI flakyTolerance band on Last-Modified metadata only; pin docx version; document the pin.
T23 rule explosion — 10 rule executors at once oversizes a single agentAgent context overrunSplit T23 into T23a/T23b/T23c as needed; rule executors are independent.
T27 MCP App standalone build > 500 KBAC-28 failExisting MCP App pattern keeps single-file builds tight; tree-shaking enabled; budget alarm in build script.
T31 E2E flakiness — 13+ steps in Journey ACI redWorker-scoped fixtures + multi-role auth; hard expect() assertions only (no conditional fallbacks per CLAUDE.md).
T37 coverage shortfall on QA-gate rulesAC-38 failPer-rule fixture in T23 already covers; verify lib/sales-proposals/ aggregate ≥ 80%.
Cherry-pick conflicts across parallel groupsPhase slipSequence groups (A → B → C → D → E → F); never run two groups concurrently; verify git status clean on main before each cherry-pick.
bun fetch 204 hang in testsIntegration test redAlways run integration tests with dangerouslyDisableSandbox: true per CLAUDE.md.
ACTask(s)
AC-1T4
AC-2T3 + T4
AC-3T12
AC-4T13
AC-5T11 + T13
AC-6T7
AC-7T7
AC-8T7
AC-9T8
AC-10T8
AC-11T11
AC-12T11
AC-13T11
AC-14T6
AC-15T6
AC-16T19
AC-17T18
AC-18T19
AC-19T21
AC-20T21
AC-21T22 (v1.0) or T38 (v1.5)
AC-22T21
AC-23T23
AC-24T23
AC-25T23
AC-26T24
AC-27T27 + T30
AC-28T27
AC-29T17 + T28 + T29
AC-30T17 + T28 + T29
AC-31T17
AC-32T37 (verifies §10)
AC-33T37 (verifies §11)
AC-34T1 + T5
AC-35T1
AC-36T37
AC-37T37
AC-38T37
AC-39T31
AC-40T33
AC-41T37

Every AC has at least one task. AC-21 is conditional on Q2.

  • Input spec: docs/specs/sales-proposals-workspace-spec-arm-a.md (Stage 2).
  • Input research: docs/research/sales-proposals-reuse-audit-arm-a.md (Stage 1).
  • Spec §13 phasing drives plan Phase 1–8 mapping.
  • Spec §15 file-touch boundaries govern every task’s “Files likely touched” list; deviations flagged in commit messages.
  • Spec §17 open questions mapped to plan §3 + Phase 0 Task T0.
  • CLAUDE.md feedback memories flagged at relevant tasks: Tiptap (T19), E2E discipline (T31, T32), no-mid-session type regen (T1), barrel re-exports (T2, T3, T9, etc.), worktree cherry-pick discipline (Group parallelisation).
  • Phase 5 is the natural place for scope pressure — DOCX + PDF + QA gate + CI step all in one phase. The plan keeps T22 (PDF) explicitly conditional on Q2 and pre-stages T38 in v1.5; the CI assertion (T25) attaches to the DOCX path which is non-negotiable. Splitting T23 by rule executor is cheap and worth doing pre-emptively if any agent shows context-budget warnings — rules are mutually independent.
  • The dependency graph has one structural pinch point: T6 (templates) gates both T7 (case-study selector) and T8 (quote picker). It is the only reason Group A is not larger; if T6 ships fast (the JSON files are mostly transcription), Group A scales out cleanly.
  • The plan deliberately mirrors spec phasing v0.1 → v1.5 rather than proposing a different decomposition. Re-slicing would invite drift between spec milestones and impl tasks; the cost of that drift across a 6–8 week Phase 2 dominates any micro-optimisation.
  • AC-32 and AC-33 are documentation ACs; they verify spec §10/§11 still match the implementation’s reused assets list. T37 owns this — without a verification task, a renamed file or a swapped reuse mode would silently break alignment.
  • Worktree discipline applies hardest to Phase 7 because that is where the most parallelism converges (Group F: T31, T32, T33, T34, T36). The sequencing constraint (T35 after T31+T34, T37 last) reduces concurrent branches in flight at any one moment to four — well within the cherry-pick + verify-after-each-merge cadence the project has been using.