Sales Proposals Workspace — Implementation Plan (Arm b)
Sales Proposals Workspace — Implementation Plan (Arm b)
Section titled “Sales Proposals Workspace — Implementation Plan (Arm b)”This plan decomposes the §9.2 Sales Proposals workspace spec at
docs/specs/sales-proposals-workspace-spec-arm-b.md into ordered, individually
verifiable tasks. Every spec acceptance criterion (AC-1 to AC-17) is mapped to
one or more tasks; every task carries acceptance criteria, a verification gate,
dependencies, file-touch boundaries, and a size estimate.
The plan is structured as twelve sequential phases with checkpoints between them. Where tasks within a phase have disjoint file ownership, they are flagged for parallel implementation. The dependency graph follows the bottom-up order: foundation (schema, types, workspace registration) before vertical feature slices (intake → components → assembly → review → export → MCP surface → polish).
Overview
Section titled “Overview”The workspace adds a new sales_proposal value to the existing workspace type
set, backed by a new proposals table joined by workspace_id with supporting
tables for sections and pricing line items. A typed ProposalContext captures
deal context at intake. Seven §9.2 components (ROI calculator, case-study
selector, quote picker, pricing configurator, templates, assembly logic, export)
compose into a draft proposal that passes a pre-send review and exports to DOCX,
PDF, and HTML preview. A new MCP App (Account Brief) and three MCP prompts
(account_brief, proposal_shortcut, case_study_assembly) extend the workspace
into the Claude Desktop / Claude.ai client. A cover-email template and a
post-send follow-up workflow complete the lifecycle.
The build draws on substantial existing scaffolding documented in the Stage 1 audit: the proposal-writer skill (rules library), the ai-smb-playbook ROI/feasibility components, the playbook DOCX exporter, brand-review and uk-english enforcers, the markdown-converter for RFP ingest, and the existing review-skill pattern for the pre-send gate. Disposition per asset is recorded in spec §6 and governed by spec §9 (the embedded OPS-26 plugin reuse policy).
Architecture Decisions
Section titled “Architecture Decisions”The following decisions are taken at plan time and frame every downstream task. Each is anchored to a spec section.
- Schema-first persistence (spec §1, §3). A dedicated
proposalstable joined toworkspacesholds proposal records. Sections live inproposal_sections; pricing inproposal_pricing_line_items. Thecontent_itemstable is not extended with aproposalcontent_type. This is settled here against OQ-3 to unblock Phase 1; if reversed, Phase 1 re-scopes. - Vertical slicing through workspace lifecycle, intake, components, assembly, export. Each phase delivers a working slice of the user journey; checkpoints validate the slice end-to-end before the next phase begins. The spec’s seventeen ACs map onto this structure naturally because each AC describes a behaviour visible at the slice boundary.
- Component orthogonality. The four mid-stack components (ROI, case-study
selector, quote picker, pricing configurator) are each owned by their own
subdirectory (
components/proposals/<component>/,lib/proposals/<component>/) so they can be built in parallel after the foundation phase. The assembly orchestrator depends on all four, so it cannot start until they have settled their typed interfaces. - Templates are file-driven (spec §FR-7, §AC-7). Adding a template is a file-system change, not a code change. The orchestrator iterates the template directory at boot. This makes the templates phase parallelisable with the components phase: their interfaces meet only inside the orchestrator, which is built later.
- Brand voice enforcement runs at section save and at export gate (spec §FR-9). It is built as a substrate (Phase 4) before the components that depend on it. Severity model (Critical blocks export; non-Critical warns inline) is set in Phase 4 and consumed everywhere downstream.
- Pre-send review is a checks-driven mirror of the existing review skill (spec
§6.11). Check files in
.claude/checks/proposal-readiness/are read by a thin wrapper around the existing/reviewmachinery. No new review framework is built. - PDF route is deferred to a Phase 9 spike (OQ-2). A short investigation chooses between DOCX-to-PDF server-side conversion and HTML-to-PDF print-rendering before AC-11 acceptance; the choice changes the export pipeline shape but does not affect upstream phases.
- Three MCP prompts ship in two waves (spec §FR-14).
account_briefmay ship first with static Phase 1 grounding (per gap-tracker §D.1 v1.2 disposition);proposal_shortcutandcase_study_assemblyship with the workspace in Phase 10. This split is preserved in the task list.
Task list
Section titled “Task list”Phase 0 — Pre-flight decisions
Section titled “Phase 0 — Pre-flight decisions”Settle the spec’s open questions that block downstream tasks. No code in this phase.
Task 0.1: Resolve OQ-1 (bid-writing reconciliation)
Section titled “Task 0.1: Resolve OQ-1 (bid-writing reconciliation)”Description: Decide the canonical home for RFP/bid response strategy. Either
(a) keep bid-writing as canonical for UK public procurement and scope
proposal-writer/rfp-response-strategy.md to commercial proposals only, (b)
merge into a single skill, or (c) keep both with a clearly bounded delegation.
The decision is captured as a one-paragraph note appended to spec §11.
Acceptance criteria:
- A written decision is recorded against OQ-1 in the spec.
- The decision identifies which skill is canonical for which path.
- If (b) is chosen, a follow-on task is opened to merge.
Verification: Manual — Liam reads and signs off.
Dependencies: None.
Files likely touched: docs/specs/sales-proposals-workspace-spec-arm-b.md
(§11 OQ-1 update).
Estimated scope: XS.
Task 0.2: Resolve OQ-2 (PDF rendering route)
Section titled “Task 0.2: Resolve OQ-2 (PDF rendering route)”Description: Spike a comparison of DOCX-to-PDF server-side conversion versus HTML-to-PDF print-rendering. Produce a one-page comparison covering styling fidelity, server cost, library footprint, and dependency risk. Pick one. The choice settles AC-11 acceptance and §6.7 effort.
Acceptance criteria:
- Comparison written.
- Decision recorded against OQ-2 in the spec.
- Acceptance criteria for AC-11 are updated to reflect the chosen route.
Verification: Manual — Liam reads and signs off.
Dependencies: None.
Files likely touched: docs/specs/sales-proposals-workspace-spec-arm-b.md
(§11 OQ-2 + §AC-11).
Estimated scope: S.
Task 0.3: Resolve OQ-3 through OQ-8
Section titled “Task 0.3: Resolve OQ-3 through OQ-8”Description: Settle the remaining six open questions in spec §11: dedicated table vs content_type (OQ-3, framed by Architecture Decision above as table-first; confirm or reverse), cover-email home (OQ-4), Account Brief data freshness (OQ-5), multi-proposal-per-workspace cardinality (OQ-6), citation provenance rendering (OQ-7), follow-up reminder mechanism (OQ-8). Each gets a short paragraph in the spec.
Acceptance criteria:
- All six OQs are resolved with rationale.
- Where an OQ resolution changes downstream task scope, the affected tasks are flagged in this plan.
Verification: Manual — Liam reads and signs off.
Dependencies: Task 0.2 (PDF route influences OQ-5 if Account Brief ships PDF artefacts).
Files likely touched: docs/specs/sales-proposals-workspace-spec-arm-b.md
(§11 OQ-3 to OQ-8).
Estimated scope: S.
Checkpoint A — Phase 0
Section titled “Checkpoint A — Phase 0”- All eight OQs resolved.
- Plan tasks updated for any scope changes implied by OQ resolutions.
- Liam signoff captured.
Phase 1 — Foundation (schema, types, workspace registration)
Section titled “Phase 1 — Foundation (schema, types, workspace registration)”Task 1.1: Migration — proposals schema
Section titled “Task 1.1: Migration — proposals schema”Description: Author a single migration creating proposals,
proposal_sections, proposal_pricing_line_items. Include foreign keys to
workspaces.id, RLS policies that defer to existing get_user_role() plus
workspace-membership tables, audit columns (created_by, updated_by,
created_at, updated_at, last_exported_at, last_sent_at), and per-table
indexes appropriate to the access pattern. Authored via
supabase migration new; applied via supabase db push. PL/pgSQL helpers
include SET search_path = public, extensions. The migration also extends any
DB-level enum or constraint on workspaces.type to include sales_proposal
(or, if type is plain text, no DDL change but the in-app type list is
extended).
Acceptance criteria:
- Migration applies cleanly to a fresh local DB.
- Three new tables exist with the documented columns and FKs.
- RLS policies enforce workspace membership for read, write, archive, delete.
- No
execute_sqlDDL anywhere; Liam runsdb pushafter author commits the file.
Verification:
-
supabase migration upsucceeds locally. - A short Vitest integration test inserts a
sales_proposalworkspace + one proposal and reads it back as the workspace owner. - An admin advisors run produces no security or performance warnings on the new tables.
Dependencies: Phase 0 complete.
Files likely touched:
supabase/migrations/<timestamp>_proposals_schema.sql__tests__/integration/proposals/schema.integration.test.ts
Estimated scope: M.
Task 1.2: Type definitions
Section titled “Task 1.2: Type definitions”Description: Add types/proposal.ts exporting ProposalContext,
AssembledProposal, ProposalSection, PricingPlan, RoiInputs, RoiOutput,
CoverEmailContext, and any union types referenced by the components. No barrel
re-exports; named exports only. Strict TypeScript, no any.
Acceptance criteria:
- Type file compiles under
tsc --noEmitwith no diagnostics. - Each type’s shape matches the spec (FR-2 for
ProposalContext, FR-6 forPricingPlan, FR-3 for the ROI types). - No type imports from index files.
Verification:
-
bun run lintpasses. -
bunx tsc --noEmitpasses. - A short type-only Vitest spec asserts the discriminated unions in
ProposalContext.dealTypeare exhaustive.
Dependencies: Task 1.1.
Files likely touched: types/proposal.ts,
__tests__/lib/proposals/types.test.ts.
Estimated scope: S.
Task 1.3: Workspace-type registry guard
Section titled “Task 1.3: Workspace-type registry guard”Description: Add a Vitest guard that enumerates every workspaces.type
value the codebase recognises and fails if a runtime type appears in the DB that
the code does not handle. Mitigates spec §R-5 (hard-coded type-string filter
drift). The guard inspects lib/mcp/tools/workspaces.ts, app/workspaces/**,
and any other file pattern-matching on the type string.
Acceptance criteria:
- The guard test exists and currently passes against the four known types
(
bid,intelligence,content,sales_proposal). - Adding an unrecognised string to the test fixture causes the test to fail with a clear message.
Verification:
bun run test __tests__/lib/proposals/workspace-type-guard.test.ts passes.
Dependencies: Task 1.1.
Files likely touched:
__tests__/lib/proposals/workspace-type-guard.test.ts, possibly a single helper
export in lib/workspaces/types.ts.
Estimated scope: S.
Task 1.4: Validation schemas extension (touch-with-care)
Section titled “Task 1.4: Validation schemas extension (touch-with-care)”Description: If Phase 0 OQ-3 is reversed (proposals as content_items
rows), extend lib/validation/schemas.ts to add a proposal content_type. If
OQ-3 stays at table-first, this task is no-op and the file is not touched. The
plan flags this conditionally because the spec §8.2 lists
lib/validation/schemas.ts as touch-with-care.
Acceptance criteria:
- Either no change to
lib/validation/schemas.ts, or one new entry inVALID_CONTENT_TYPESmatched by a single test. - If extended, the validation-sweep guard still passes.
Verification: bun run test __tests__/validation/ passes; bun run lint
passes.
Dependencies: Task 0.3 (OQ-3 resolution).
Files likely touched: lib/validation/schemas.ts (only if OQ-3 reversed).
Estimated scope: XS.
Checkpoint B — Phase 1
Section titled “Checkpoint B — Phase 1”- Schema applied; types compile; workspace-type guard green.
- No raw Tailwind colours introduced.
- No unchecked Supabase calls (ESLint
local/no-unchecked-supabase-errorandlocal/no-silent-promise-catchclean). -
bun run knipreports no orphans.
Phase 2 — Workspace CRUD shell
Section titled “Phase 2 — Workspace CRUD shell”Task 2.1: API routes — proposals CRUD
Section titled “Task 2.1: API routes — proposals CRUD”Description: Implement app/api/proposals/route.ts (POST create, GET list
with workspace filter), app/api/proposals/[id]/route.ts (GET, PATCH, DELETE),
and app/api/proposals/[id]/archive/route.ts (POST archive/unarchive). Every
route uses getAuthorisedClient() + authFailureResponse(auth) for auth
routing. Body parsing via parseBody from @/lib/validation; query parsing via
parseSearchParams. All Supabase calls use sb() or tryQuery().
Acceptance criteria:
- All four routes return correct HTTP for unauthenticated, forbidden, and ok cases.
- Editor-role users can create and update; admin can hard-delete archived; viewer is read-only.
- No raw
fetchcallers; no unchecked Supabase responses.
Verification:
-
bun run test __tests__/api/proposals/passes. - An integration test exercises the full CRUD lifecycle as editor + admin.
Dependencies: Task 1.1, Task 1.2.
Files likely touched:
app/api/proposals/route.tsapp/api/proposals/[id]/route.tsapp/api/proposals/[id]/archive/route.ts__tests__/api/proposals/*.test.ts__tests__/integration/proposals/crud.integration.test.tslib/query/query-keys.ts,lib/query/fetchers.ts(proposal keys + fetchers)
Estimated scope: M.
Task 2.2: Workspace page — list of proposals
Section titled “Task 2.2: Workspace page — list of proposals”Description: Implement app/workspaces/[id]/page.tsx with branching on
workspaces.type. When type is sales_proposal, render the proposals list
view; when type is bid or intelligence, defer to the existing routes. The
list view shows each proposal with status, last edited, and quick-action
buttons. Uses TanStack Query exclusively.
Acceptance criteria:
- The page loads in under 800 ms server-timing on a warm session of 50 proposals (AC-17).
- Type-branching works without breaking existing
bidorintelligenceworkspace renders. - WCAG 2.1 AA passes on the list view (status colour is paired with iconography or text).
- No raw Tailwind colour utilities.
Verification:
-
bun run test __tests__/components/proposals/passes. - A Lighthouse accessibility check on the list page scores ≥95.
- Manual: existing
bidworkspace page still renders correctly.
Dependencies: Task 2.1.
Files likely touched:
app/workspaces/[id]/page.tsx(new dynamic route)app/workspaces/[id]/proposals-list.tsxcomponents/proposals/proposal-card.tsxcomponents/proposals/proposal-list.tsxhooks/proposals/use-proposals-list.ts
Estimated scope: M.
Task 2.3: Create-proposal dialog + create / archive / delete UI
Section titled “Task 2.3: Create-proposal dialog + create / archive / delete UI”Description: Add a CreateProposalDialog invoked from the workspace page
header. Captures the minimal seed (title, prospect handle, deal type) and routes
the user into the intake page on submit. Adds archive and delete affordances on
each card consistent with the existing workspace-archive pattern. Hard-delete is
admin-only and gated behind a confirmation modal.
Acceptance criteria (AC-1):
- An editor can create a proposal from the dialog.
- The new proposal appears in the list with status
draft. - Archive and unarchive work; archived proposals are excluded from the default list.
- An admin can hard-delete an archived proposal; an editor cannot.
Verification:
-
bun run test __tests__/components/proposals/create-proposal-dialog.test.tsxpasses. - An E2E spec at
e2e/tests/proposals/lifecycle.spec.tsexercises create-archive-unarchive-delete across editor and admin roles.
Dependencies: Task 2.2.
Files likely touched:
components/proposals/create-proposal-dialog.tsxcomponents/proposals/proposal-card.tsx(archive/delete affordances)app/workspaces/[id]/proposals-list.tsx(wire dialog)e2e/tests/proposals/lifecycle.spec.ts
Estimated scope: M.
Checkpoint C — Phase 2 (validates AC-1)
Section titled “Checkpoint C — Phase 2 (validates AC-1)”- AC-1 acceptance criteria all green.
- Type-branching does not regress
bidorintelligenceworkspaces. - Lighthouse accessibility ≥95 on workspace and authoring pages.
-
bun run knipclean.
Phase 3 — Intake (ProposalContext, manual + RFP + MCP-prompt entry points)
Section titled “Phase 3 — Intake (ProposalContext, manual + RFP + MCP-prompt entry points)”Task 3.1: ProposalContext intake form (manual entry)
Section titled “Task 3.1: ProposalContext intake form (manual entry)”Description: Build components/proposals/intake-form.tsx capturing the
typed ProposalContext. Fields: prospect identity, sector, deal type, target
outcomes, decision drivers, optional budget signal, optional decision date.
Required fields fail closed; the user cannot leave intake until they are
complete. Persists via the API route at
app/api/proposals/[id]/context/route.ts.
Acceptance criteria (AC-2 partial):
- Required-field validation blocks submission.
- Submitted context is persisted as a typed
ProposalContextagainst the proposal record. - DD/MM/YYYY is enforced on the decision-date field; GBP on the budget-signal field.
Verification:
-
bun run test __tests__/components/proposals/intake-form.test.tsxpasses. - Integration test asserts the persisted shape matches
ProposalContext.
Dependencies: Tasks 2.1, 2.3.
Files likely touched:
components/proposals/intake-form.tsxapp/api/proposals/[id]/context/route.tsapp/workspaces/[id]/proposals/[proposalId]/intake/page.tsxhooks/proposals/use-proposal-context.ts__tests__/components/proposals/intake-form.test.tsx
Estimated scope: M.
Task 3.2: RFP attachment storage + ingest pipeline
Section titled “Task 3.2: RFP attachment storage + ingest pipeline”Description: Add a Supabase Storage bucket proposal-attachments with
signed-URL access only. Implement an ingest route at
app/api/proposals/[id]/rfp/route.ts that accepts a PDF or DOCX upload,
converts to Markdown via the markdown-converter, and stores the converted
Markdown against the proposal record’s rfp_context field. Conversion uses the
documented two-step HTML → Turndown path (with the GFM plugin) so tables survive
(per CLAUDE.md gotcha; spec §R-8). Pipeline runs are recorded via
recordPipelineRun().
Acceptance criteria (AC-2 partial, AC-12):
- PDF and DOCX uploads convert to Markdown with table preservation.
- The converted Markdown is stored against the proposal record and accessible to the assembly logic.
- Raw URLs are never exposed to the UI; signed URLs only.
- A pipeline-run row is written for every ingest.
Verification:
-
bun run test:integration __tests__/integration/proposals/rfp-ingest.integration.test.tsingests a fixture DOCX containing a table and asserts the table survives. -
bun run test __tests__/api/proposals/rfp.test.tscovers auth and validation paths.
Dependencies: Task 1.1 (storage bucket), Task 2.1.
Files likely touched:
app/api/proposals/[id]/rfp/route.tslib/proposals/rfp-ingest.ts__tests__/integration/proposals/rfp-ingest.integration.test.ts__tests__/api/proposals/rfp.test.ts- A DOCX fixture under
__tests__/fixtures/rfp/ supabase/migrations/<timestamp>_proposal_attachments_bucket.sql
Estimated scope: M.
Task 3.3: Account-brief MCP prompt — Phase 1 static grounding (parallelisable with 3.1, 3.2)
Section titled “Task 3.3: Account-brief MCP prompt — Phase 1 static grounding (parallelisable with 3.1, 3.2)”Description: Register the first of the three MCP prompts: account_brief.
Per gap-tracker §D.1 v1.2 and spec §FR-14, this prompt may ship first with
static Phase 1 Company Profile grounding while proposal_shortcut and
case_study_assembly wait for Phase 10. The prompt produces a structured
AccountSnapshot consumable by an intake-form pre-fill button.
Acceptance criteria (AC-14 partial, AC-2 partial):
- The prompt registers in the MCP prompt list.
- Invoking the prompt with a prospect handle returns a grounded snapshot.
- The intake form has a “pre-fill from account brief” affordance that consumes the snapshot.
Verification:
- MCP eval Layer 1 passes for the new prompt.
- Functional-correctness eval (Layer 4) asserts citations resolve.
Dependencies: Task 1.2 (types), Task 2.1.
Files likely touched:
lib/mcp/prompts/account-brief.tslib/mcp/index.ts(registration entry)components/proposals/intake-form.tsx(pre-fill button)__tests__/mcp/prompts/account-brief.test.ts
Estimated scope: M.
Checkpoint D — Phase 3 (validates AC-2 and AC-12)
Section titled “Checkpoint D — Phase 3 (validates AC-2 and AC-12)”- All three intake entry points populate the same
ProposalContextschema. - RFP ingest preserves tables.
- Account-brief prompt grounded against the static Company Profile.
-
bun run test:mcp-evalLayers 1 and 4 pass foraccount_brief.
Phase 4 — Brand voice + UK English enforcement substrate (validates AC-9)
Section titled “Phase 4 — Brand voice + UK English enforcement substrate (validates AC-9)”Task 4.1: Configure brand-review enforcer with KH brand voice
Section titled “Task 4.1: Configure brand-review enforcer with KH brand voice”Description: Connect the brand-review skill to the KH brand voice document
as the single source. Author or reuse the brand voice document. Add a
lib/proposals/qa/brand-review.ts adapter that exposes
runBrandReview(content): Promise<Findings> for callers.
Acceptance criteria:
- The KH brand voice document exists and is referenced as the only source for brand-review.
- The adapter returns structured findings with severity (
critical|warning|info).
Verification:
-
bun run test __tests__/lib/proposals/qa/brand-review.test.tspasses.
Dependencies: Phase 0.
Files likely touched:
lib/proposals/qa/brand-review.tsdocs/reference/kh-brand-voice.md(if not present)__tests__/lib/proposals/qa/brand-review.test.ts
Estimated scope: S.
Task 4.2: UK-English enforcer hook
Section titled “Task 4.2: UK-English enforcer hook”Description: Add lib/proposals/qa/uk-english.ts wrapping the existing
uk-english skill so it returns the same structured-findings shape as 4.1.
Acceptance criteria:
- The adapter returns structured findings with severity.
- Test fixtures cover at least three UK/US deviations (
color,optimize,MM/DD/YYYY).
Verification: bun run test __tests__/lib/proposals/qa/uk-english.test.ts
passes.
Dependencies: Phase 0.
Files likely touched:
lib/proposals/qa/uk-english.ts__tests__/lib/proposals/qa/uk-english.test.ts
Estimated scope: S.
Task 4.3: Section-save + export-gate hooks
Section titled “Task 4.3: Section-save + export-gate hooks”Description: Wire 4.1 and 4.2 into lib/proposals/sections.ts so every
section save runs both passes. Critical findings block export (set a flag on the
proposal record); warnings surface as inline UI annotations. The export endpoint
reads the flag and refuses to export when Critical findings remain unresolved.
Acceptance criteria (AC-9):
- Section save triggers both passes.
- Critical findings block export; non-critical findings produce inline warnings.
- The KH brand voice document is the only configured source for brand-review.
Verification:
-
bun run test:integration __tests__/integration/proposals/qa-gate.integration.test.tsexercises the section-save → export-block path with seeded Critical findings. - An E2E spec asserts the warnings render in the authoring UI.
Dependencies: Tasks 4.1, 4.2; Task 1.1 (proposal record).
Files likely touched:
lib/proposals/sections.tslib/proposals/qa/run-gates.tsapp/api/proposals/[id]/sections/[sectionId]/route.ts__tests__/integration/proposals/qa-gate.integration.test.ts
Estimated scope: M.
Checkpoint E — Phase 4 (validates AC-9)
Section titled “Checkpoint E — Phase 4 (validates AC-9)”- AC-9 acceptance criteria green.
- No silent error swallow in the QA gates.
Phase 5 — Components (parallel)
Section titled “Phase 5 — Components (parallel)”The four components below have disjoint file ownership and may run as parallel
agents. Their typed interfaces are declared in types/proposal.ts (Task 1.2)
and consumed by the assembly orchestrator in Phase 7.
Task 5.1: ROI calculator component
Section titled “Task 5.1: ROI calculator component”Description: Implement components/proposals/roi-calculator.tsx and
lib/proposals/roi/calculator.ts. Inputs: current state, target state, value
drivers, risk-adjusted-return parameters. Output: a templated section conforming
to the proposal-writer pricing-roi-business-case.md framework. Live preview
re-renders within 200 ms of an input change. Three sector-scenario tests draw on
existing KB case-study data.
Acceptance criteria (AC-3):
- Inputs accepted; output structure matches the framework.
- GBP and UK English throughout.
- Editing an input updates the section preview within 200 ms (measured).
- Three sector-scenario unit tests pass.
Verification:
-
bun run test __tests__/components/proposals/roi-calculator.test.tsxpasses. -
bun run test __tests__/lib/proposals/roi/calculator.test.tspasses.
Dependencies: Tasks 1.2, 4.3.
Files likely touched:
components/proposals/roi-calculator.tsxlib/proposals/roi/calculator.tslib/proposals/roi/render.tshooks/proposals/use-roi-preview.ts
Estimated scope: M.
Task 5.2: Case-study selector
Section titled “Task 5.2: Case-study selector”Description: Implement components/proposals/case-study-selector.tsx and
lib/proposals/case-study/select.ts. The selector queries KB content_type
case_study with sector + use-case + decision-driver match scoring and returns
up to N candidates (default 3). The salesperson picks which to include. Selected
case studies render as templated sections with KB-backed citations resolving to
source records.
Acceptance criteria (AC-4):
- A query with sector + use-case returns up to N ranked candidates.
- Selected case studies render with citations that resolve.
- No selection still allows the assembly to proceed (empty section permitted).
Verification:
-
bun run test __tests__/components/proposals/case-study-selector.test.tsxpasses. - An integration test asserts citation resolution against a seeded KB.
Dependencies: Tasks 1.2, 4.3.
Files likely touched:
components/proposals/case-study-selector.tsxlib/proposals/case-study/select.tslib/proposals/case-study/rank.tslib/proposals/case-study/render.tshooks/proposals/use-case-study-candidates.ts
Estimated scope: M.
Task 5.3: Quote picker
Section titled “Task 5.3: Quote picker”Description: Implement components/proposals/quote-picker.tsx and
lib/proposals/quote/select.ts. The picker filters quotes from q_a_pair,
policy, methodology, and capability content by sector / use-case / topic
and renders selected quotes inline with attribution. Citation orphans must
report zero on the rendered draft.
Acceptance criteria (AC-5):
- Filters surface matches from the four supported content_types.
- Selected quotes render with attribution; citations resolve.
- No orphaned citations.
Verification:
-
bun run test __tests__/components/proposals/quote-picker.test.tsxpasses. - The citation-orphans hook reports zero on a rendered draft fixture.
Dependencies: Tasks 1.2, 4.3.
Files likely touched:
components/proposals/quote-picker.tsxlib/proposals/quote/select.tslib/proposals/quote/render.tshooks/proposals/use-quote-candidates.ts
Estimated scope: S.
Task 5.4: Pricing configurator
Section titled “Task 5.4: Pricing configurator”Description: Implement components/proposals/pricing-configurator.tsx and
lib/proposals/pricing/configure.ts. Line-item table (description, unit, unit
price, quantity, discount); totals re-compute live. Optional good/better/best
packaging. The renderer encodes the proposal-writer pricing-presentation.md
rule: pricing section position is locked to after value-establishing sections
(the orchestrator enforces order; the renderer refuses to emit pricing if the
consumer requests it before value sections). Currency is GBP.
Acceptance criteria (AC-6):
- Line items add / edit / reorder / remove; totals re-compute live.
- Good/better/best packaging supported where configured.
- Pricing-section position is locked to after value sections.
- GBP throughout.
Verification:
-
bun run test __tests__/components/proposals/pricing-configurator.test.tsxpasses. - An integration test asserts the position-lock rule fires when the orchestrator is asked to render pricing first.
Dependencies: Tasks 1.2, 4.3.
Files likely touched:
components/proposals/pricing-configurator.tsxlib/proposals/pricing/configure.tslib/proposals/pricing/render.tshooks/proposals/use-pricing-plan.ts
Estimated scope: M.
Checkpoint F — Phase 5 (validates AC-3, AC-4, AC-5, AC-6)
Section titled “Checkpoint F — Phase 5 (validates AC-3, AC-4, AC-5, AC-6)”- All four components have green Vitest coverage and are wired through the QA gates.
- Citation-orphans report zero on a rendered draft.
- No raw Tailwind colour utilities.
Phase 6 — Templates registry (validates AC-7) — parallel with Phase 5
Section titled “Phase 6 — Templates registry (validates AC-7) — parallel with Phase 5”Task 6.1: Template frontmatter schema
Section titled “Task 6.1: Template frontmatter schema”Description: Define the frontmatter shape every proposal-section template
must declare (id, rule_reference, section_kind, page_budget_target,
required_context_fields, optional_context_fields). Persist as
lib/proposals/templates/schema.ts.
Acceptance criteria:
- Schema parses every existing proposal-writer rule into a synthetic frontmatter for testing.
- An invalid template fails parse with a typed error.
Verification:
bun run test __tests__/lib/proposals/templates/schema.test.ts passes.
Dependencies: Task 1.2.
Files likely touched: lib/proposals/templates/schema.ts,
__tests__/lib/proposals/templates/schema.test.ts.
Estimated scope: S.
Task 6.2: Template registry + per-rule templates
Section titled “Task 6.2: Template registry + per-rule templates”Description: Implement lib/proposals/templates/registry.ts reading every
.md file under lib/proposals/templates/ at boot. Author one template per
proposal-writer rule listed in spec §FR-7 (architecture, executive-summary,
pricing-presentation, pricing-roi-business-case, sow, terms-conditions,
design-formatting, executive-stakeholder-alignment,
strategy-competitive-differentiation, strategy-followup, plus rfp-response per
OQ-1 outcome).
Acceptance criteria (AC-7 partial):
- At least one template exists per rule listed in §FR-7.
- Each template’s frontmatter parses.
- Adding a new template file is picked up without code change.
Verification:
-
bun run test __tests__/lib/proposals/templates/registry.test.tspasses. - A fixture-sync guard test enumerates all template files and asserts each has a frontmatter entry the schema accepts.
Dependencies: Task 6.1.
Files likely touched:
lib/proposals/templates/registry.tslib/proposals/templates/<rule-id>.md(one per rule)__tests__/lib/proposals/templates/registry.test.ts__tests__/lib/proposals/templates/fixture-sync.test.ts
Estimated scope: M.
Task 6.3: Adapt feasibility-study + delivery-email templates
Section titled “Task 6.3: Adapt feasibility-study + delivery-email templates”Description: Adapt the two highest-fit reusable templates from the Stage 1
audit: the feasibility-study template (annex slot for proposals) and the two
delivery-email variants (cover-email pattern). Each lands as a
registry-conformant template file with adapted placeholders pointing at
ProposalContext fields.
Acceptance criteria (AC-7 partial):
- Both adapted templates parse under the registry.
- Cover-email variants exist for advisory / project / retainer engagement types.
Verification: Same fixture-sync guard from Task 6.2 covers these.
Dependencies: Task 6.2.
Files likely touched:
lib/proposals/templates/feasibility-study.mdlib/proposals/templates/cover-email-advisory.mdlib/proposals/templates/cover-email-project.mdlib/proposals/templates/cover-email-retainer.md
Estimated scope: S.
Checkpoint G — Phase 6 (validates AC-7)
Section titled “Checkpoint G — Phase 6 (validates AC-7)”- AC-7 acceptance criteria green.
- Fixture-sync guard passes.
Phase 7 — Assembly orchestrator (validates AC-8)
Section titled “Phase 7 — Assembly orchestrator (validates AC-8)”Task 7.1: Assembly orchestrator core
Section titled “Task 7.1: Assembly orchestrator core”Description: Implement lib/proposals/assembly.ts. Inputs:
ProposalContext + selected components’ state (ROI inputs, selected case
studies, selected quotes, pricing plan). Output: a typed AssembledProposal
with sections in the order defined by the proposal-writer
structure-proposal-architecture.md rule (Executive Summary → Solution →
Investment → Proof) and within the rule’s page-budget targets. The orchestrator
selects templates from the registry and renders each section.
Acceptance criteria (AC-8 partial):
- Assembling a draft from a populated context produces sections matching the rule’s architecture and page-budget targets.
- Pricing-section position is locked after value sections (spec §R-7 mitigation).
- LLM calls within the orchestrator are scoped to section-level rendering with retrieval-grounded context (spec §R-2 mitigation).
Verification:
-
bun run test __tests__/lib/proposals/assembly.test.tspasses. - An integration test asserts the section ordering and page-budget caps under a seeded context.
Dependencies: Tasks 5.1–5.4, 6.2.
Files likely touched:
lib/proposals/assembly.tslib/proposals/assemble-section.ts__tests__/lib/proposals/assembly.test.ts__tests__/integration/proposals/assembly.integration.test.ts
Estimated scope: L.
Task 7.2: Section regeneration with manual-edit preservation
Section titled “Task 7.2: Section regeneration with manual-edit preservation”Description: Implement single-section regeneration. The orchestrator accepts a section id and regenerates only that section, preserving manual edits in other sections. A user opting to overwrite the section’s manual edits is supported as an explicit flag.
Acceptance criteria (AC-8 partial):
- Regenerating one section preserves manual edits in the other sections.
- Manual edits to the regenerated section survive unless the user opts to overwrite.
Verification:
bun run test __tests__/lib/proposals/regenerate-section.test.ts passes.
Dependencies: Task 7.1.
Files likely touched:
lib/proposals/regenerate-section.ts__tests__/lib/proposals/regenerate-section.test.ts
Estimated scope: M.
Task 7.3: Authoring page UI — assembled draft preview
Section titled “Task 7.3: Authoring page UI — assembled draft preview”Description: Implement app/workspaces/[id]/proposals/[proposalId]/page.tsx
showing the assembled draft. Editable section-by-section; each section carries a
regenerate button and a manual-edit indicator. Initial render under 1.5 s on a
50-proposal workspace (spec §AC-17).
Acceptance criteria:
- The authoring page renders the assembled draft.
- Section regeneration triggers via the section’s regenerate button.
- Manual edits are visually flagged.
Verification:
-
bun run test __tests__/components/proposals/section-editor.test.tsxpasses. - An E2E spec exercises edit-regenerate-edit on three sections.
Dependencies: Tasks 7.1, 7.2.
Files likely touched:
app/workspaces/[id]/proposals/[proposalId]/page.tsxcomponents/proposals/section-editor.tsxcomponents/proposals/section-list.tsxhooks/proposals/use-section-state.ts
Estimated scope: M.
Checkpoint H — Phase 7 (validates AC-8)
Section titled “Checkpoint H — Phase 7 (validates AC-8)”- AC-8 acceptance criteria green.
- Section regeneration under 4 s, streaming where LLM-bound (spec §AC-17).
- Pricing position-lock rule firing in integration test.
Phase 8 — Pre-send review (validates AC-10)
Section titled “Phase 8 — Pre-send review (validates AC-10)”Task 8.1: Author proposal-readiness checks
Section titled “Task 8.1: Author proposal-readiness checks”Description: Author check files under .claude/checks/proposal-readiness/:
legal-clauses.md, pricing-set.md, citations-resolved.md,
brand-review-pass.md, uk-english-pass.md, executive-summary-present.md,
signoffs-captured.md. Each defines a single binary check evaluable by the
existing review-skill machinery.
Acceptance criteria:
- All seven check files exist and parse.
- Each check has a specific, machine-evaluable assertion.
Verification:
bun run test __tests__/lib/proposals/proposal-readiness-checks.test.ts parses
all check files.
Dependencies: Phase 4.
Files likely touched: .claude/checks/proposal-readiness/*.md,
__tests__/lib/proposals/proposal-readiness-checks.test.ts.
Estimated scope: S.
Task 8.2: Pre-send review wrapper + report
Section titled “Task 8.2: Pre-send review wrapper + report”Description: Implement lib/proposals/review/run-readiness.ts invoking the
existing review machinery against the check directory, producing a structured
report. Wire to an API route at app/api/proposals/[id]/readiness/route.ts. The
route returns pass/fail plus per-check pointers. Failing checks block export.
Acceptance criteria (AC-10):
- All seven checks are exercised by an integration test.
- A failing check blocks export; a passing report sets a green-state flag on the proposal.
- The schema-drift guard test (spec §R-9) fails when a check references a field no longer in the schema.
Verification:
-
bun run test:integration __tests__/integration/proposals/readiness.integration.test.tspasses. - A schema-drift fixture asserts the guard fires when a renamed column is referenced.
Dependencies: Tasks 8.1, 1.1.
Files likely touched:
lib/proposals/review/run-readiness.tsapp/api/proposals/[id]/readiness/route.ts__tests__/integration/proposals/readiness.integration.test.ts__tests__/lib/proposals/proposal-readiness-schema-drift.test.ts
Estimated scope: M.
Checkpoint I — Phase 8 (validates AC-10)
Section titled “Checkpoint I — Phase 8 (validates AC-10)”- AC-10 acceptance criteria green.
- Schema-drift guard armed.
Phase 9 — Export (validates AC-11)
Section titled “Phase 9 — Export (validates AC-11)”Task 9.1: DOCX exporter extension
Section titled “Task 9.1: DOCX exporter extension”Description: Adapt app/src/lib/docx-export.ts from the playbook into
lib/proposals/export/docx.ts. Extend with cover page, headers/footers, page
breaks, table support, image embed, and branded heading styles. The exporter
consumes AssembledProposal. Branded heading styles encode the proposal-writer
design-formatting.md rule.
Acceptance criteria (AC-11 partial):
- DOCX export produces a file that opens cleanly in Microsoft Word and Google Docs.
- DOCX export of a 30-page proposal completes in under 6 s server-side.
Verification:
-
bun run test __tests__/lib/proposals/export/docx.test.tscovers cover page, headers/footers, page breaks, tables, images, branded headings. - A 30-page fixture proposal exports under 6 s in CI.
Dependencies: Task 7.1.
Files likely touched:
lib/proposals/export/docx.tslib/proposals/export/docx-styles.ts__tests__/lib/proposals/export/docx.test.ts
Estimated scope: L.
Task 9.2: PDF + HTML preview pipeline (route per OQ-2)
Section titled “Task 9.2: PDF + HTML preview pipeline (route per OQ-2)”Description: Implement the PDF route chosen in Task 0.2. Either DOCX-to-PDF server-side conversion (one library; one CLI step downstream of 9.1) or HTML-to-PDF print-rendering (duplicate styling layer; print stylesheet). Implement HTML preview as the in-app live view consumed by the authoring page.
Acceptance criteria (AC-11 partial):
- PDF export produces a file that renders correctly in the two most common readers.
- HTML preview matches the DOCX layout within the documented styling-fidelity tolerance.
- Export endpoint refuses to emit when Critical brand-review or UK-English findings remain (spec §FR-9, §FR-10 gate consumed here).
Verification:
-
bun run test __tests__/lib/proposals/export/pdf.test.tscovers the chosen pipeline. - An E2E spec at
e2e/tests/proposals/export.spec.tsexercises DOCX + PDF + HTML preview from the assembled draft.
Dependencies: Tasks 0.2, 9.1.
Files likely touched:
lib/proposals/export/pdf.tslib/proposals/export/html-preview.tsapp/api/proposals/[id]/export/route.tse2e/tests/proposals/export.spec.ts
Estimated scope: M.
Task 9.3: Export endpoint + observability
Section titled “Task 9.3: Export endpoint + observability”Description: Wire DOCX, PDF, and HTML preview behind a single
app/api/proposals/[id]/export/route.ts that selects format from a query param.
The endpoint records last_exported_at on the proposal, writes a pipeline-run
row, and surfaces export errors via the Sentry path. No silent catches.
Acceptance criteria:
- All three formats produced from the same canonical source.
-
last_exported_atupdates on every successful export. - Pipeline-run row written.
Verification: bun run test __tests__/api/proposals/export.test.ts passes.
Dependencies: Tasks 9.1, 9.2.
Files likely touched: app/api/proposals/[id]/export/route.ts,
__tests__/api/proposals/export.test.ts.
Estimated scope: S.
Checkpoint J — Phase 9 (validates AC-11)
Section titled “Checkpoint J — Phase 9 (validates AC-11)”- AC-11 acceptance criteria green.
- DOCX export under 6 s for 30-page proposal.
- No silent error swallow in the export pipeline.
Phase 10 — MCP App + remaining prompts (validates AC-13, AC-14)
Section titled “Phase 10 — MCP App + remaining prompts (validates AC-13, AC-14)”Task 10.1: Account Brief MCP App
Section titled “Task 10.1: Account Brief MCP App”Description: Scaffold mcp-apps/account-brief/ as a sibling of the four
existing MCP Apps (bid-dashboard, coverage-matrix, intelligence-feed,
reorient-me) using the same Vite single-file build. The App shows company
snapshot, sector signals, recent KB hits, and a suggested intake form pre-fill.
Registered as an MCP UI resource.
Acceptance criteria (AC-13):
- The App appears alongside the existing four with the same Vite build.
- Invoking
/account-brieffrom a Claude.ai client launches the App with prospect intelligence. - The App’s “open in workspace” action seeds an intake-form pre-fill.
Verification:
-
bun run build:mcp-appsproduces the new bundle. - Manual smoke test from a Claude.ai client.
Dependencies: Task 3.3.
Files likely touched:
mcp-apps/account-brief/**(Vite config, source, build)lib/mcp/resources/account-brief.ts(UI resource registration)
Estimated scope: M.
Task 10.2: proposal_shortcut MCP prompt
Section titled “Task 10.2: proposal_shortcut MCP prompt”Description: Register the proposal_shortcut prompt. Given a
ProposalContext summary, returns a draft skeleton with section recommendations
and ROI / pricing inputs pre-filled where derivable from KB content.
Acceptance criteria (AC-14 partial):
- Prompt registers and is discoverable.
- Output is grounded with resolvable citations.
Verification: MCP eval Layers 1, 3, 4 pass for the prompt.
Dependencies: Tasks 3.3, 7.1.
Files likely touched:
lib/mcp/prompts/proposal-shortcut.tslib/mcp/index.ts__tests__/mcp/prompts/proposal-shortcut.test.ts
Estimated scope: M.
Task 10.3: case_study_assembly MCP prompt
Section titled “Task 10.3: case_study_assembly MCP prompt”Description: Register the case_study_assembly prompt. Given a
ProposalContext, returns a ranked candidate set for the case-study selector
with brief justifications.
Acceptance criteria (AC-14 partial):
- Prompt registers and is discoverable.
- Output is grounded with resolvable citations.
Verification: MCP eval Layers 1, 3, 4 pass for the prompt.
Dependencies: Tasks 3.3, 5.2.
Files likely touched:
lib/mcp/prompts/case-study-assembly.tslib/mcp/index.ts__tests__/mcp/prompts/case-study-assembly.test.ts
Estimated scope: M.
Checkpoint K — Phase 10 (validates AC-13, AC-14)
Section titled “Checkpoint K — Phase 10 (validates AC-13, AC-14)”- AC-13 and AC-14 acceptance criteria green.
- All three prompts ground against KB content; citations resolve.
- MCP inventory regenerated via
bun run generate:mcp-inventory.
Phase 11 — Cover email + follow-up (validates AC-15, AC-16) — parallel inside this phase
Section titled “Phase 11 — Cover email + follow-up (validates AC-15, AC-16) — parallel inside this phase”Task 11.1: Cover-email templating at send time
Section titled “Task 11.1: Cover-email templating at send time”Description: Implement lib/proposals/cover-email/render.ts selecting from
the three engagement-type variants in
lib/proposals/templates/cover-email-*.md. The rendered email references the
proposal record by ID and embeds the export filename. Surfaced from the
authoring page’s “send” menu.
Acceptance criteria (AC-16):
- At send time, a cover email is templated for the proposal type.
- The email references the proposal record by ID and embeds the export filename.
Verification: bun run test __tests__/lib/proposals/cover-email.test.ts
passes.
Dependencies: Task 6.3.
Files likely touched:
lib/proposals/cover-email/render.tscomponents/proposals/send-menu.tsx__tests__/lib/proposals/cover-email.test.ts
Estimated scope: S.
Task 11.2: Follow-up reminder surface + draft-outreach integration
Section titled “Task 11.2: Follow-up reminder surface + draft-outreach integration”Description: Implement the follow-up surface in the authoring page sidebar.
After a proposal is sent, reminders surface at the cadence the proposal-writer
strategy-followup.md rule defines. The user can invoke the Anthropic Sales
plugin’s draft-outreach skill with the proposal context flowing in. Reminder
mechanism per OQ-8 resolution (in-app only, or in-app + notifications hook).
Acceptance criteria (AC-15):
- After a proposal is sent, follow-up reminders surface at the documented cadence.
- Invoking
draft-outreachfrom inside the workspace flows the proposal context into the outreach skill and returns a personalised draft.
Verification:
-
bun run test __tests__/components/proposals/follow-up-panel.test.tsxpasses. - An E2E spec at
e2e/tests/proposals/follow-up.spec.tsexercises the post-send reminder flow.
Dependencies: Tasks 0.3 (OQ-8), 9.3.
Files likely touched:
components/proposals/follow-up-panel.tsxlib/proposals/follow-up/schedule.tslib/proposals/follow-up/draft-outreach-bridge.tse2e/tests/proposals/follow-up.spec.ts
Estimated scope: M.
Checkpoint L — Phase 11 (validates AC-15, AC-16)
Section titled “Checkpoint L — Phase 11 (validates AC-15, AC-16)”- AC-15 and AC-16 acceptance criteria green.
Phase 12 — Non-functional gates + golden path (validates AC-17)
Section titled “Phase 12 — Non-functional gates + golden path (validates AC-17)”Task 12.1: Performance budget tests
Section titled “Task 12.1: Performance budget tests”Description: Add timing assertions to the workspace-list, authoring-page-render, DOCX-export, and section-regeneration paths matching the budgets in spec §5.3 and §AC-17. CI fails on regression.
Acceptance criteria (AC-17 partial):
- Workspace list under 800 ms warm.
- Authoring page initial render under 1.5 s on a 50-proposal workspace.
- DOCX export under 6 s for 30-page proposal.
- Section regeneration under 4 s, streaming where LLM-bound.
Verification: Custom CI check at
__tests__/integration/proposals/performance.integration.test.ts.
Dependencies: Phases 2, 7, 9.
Files likely touched:
__tests__/integration/proposals/performance.integration.test.ts.
Estimated scope: S.
Task 12.2: WCAG audit
Section titled “Task 12.2: WCAG audit”Description: Run an accessibility audit against the workspace-list and authoring pages. WCAG 2.1 AA target. Fix any colour-only signals (status colour pairs with iconography or text).
Acceptance criteria (AC-17 partial):
- Lighthouse accessibility score ≥95 on the two pages.
- No raw Tailwind colour utilities introduced (lint guard fires).
- All status states present an iconographic or textual signal alongside colour.
Verification: bun run test __tests__/lib/proposals/accessibility.test.ts;
manual Lighthouse audit.
Dependencies: Phases 2, 7.
Files likely touched: Components under components/proposals/ may receive
iconography/text additions.
Estimated scope: S.
Task 12.3: Lint + ESLint guards
Section titled “Task 12.3: Lint + ESLint guards”Description: Confirm all new code passes the existing guards:
local/no-unchecked-supabase-error, local/no-silent-promise-catch, the
validation-sweep guard (any route reading request.nextUrl.searchParams or
request.json() imports parseBody / parseSearchParams), the
no-raw-Tailwind-colour guard, the integration-test-location guard.
Acceptance criteria (AC-17 partial):
-
bun run lintclean. - All ESLint custom rules pass.
- No new
*.integration.test.{ts,tsx}outside__tests__/integration/.
Verification: CI runs bun run lint; integration-location guard test
passes.
Dependencies: All prior phases.
Files likely touched: Any with cleanup needed.
Estimated scope: XS.
Task 12.4: Golden-path E2E + knip + stats regen
Section titled “Task 12.4: Golden-path E2E + knip + stats regen”Description: Author the golden-path E2E spec at
e2e/tests/proposals/golden-path.spec.ts exercising create → intake → assemble
→ export end-to-end. Multi-role variants (admin / editor / viewer) cover the
permission boundaries. Run bun run knip to catch orphans. Regenerate
docs/generated/codebase-stats.md and docs/generated/mcp-inventory.md
end-of-session.
Acceptance criteria:
- Golden-path E2E spec passes for editor; viewer is read-only; admin can hard-delete.
-
bun run knipreports no new orphans. - Generated stats and MCP inventory regenerated.
Verification:
-
bun run test:e2e e2e/tests/proposals/passes. -
bun run knipclean.
Dependencies: Phases 2, 3, 7, 8, 9.
Files likely touched: e2e/tests/proposals/golden-path.spec.ts,
docs/generated/codebase-stats.md, docs/generated/mcp-inventory.md.
Estimated scope: M.
Checkpoint M — Phase 12 (validates AC-17)
Section titled “Checkpoint M — Phase 12 (validates AC-17)”- AC-17 acceptance criteria green.
- Golden-path E2E spec green for all three roles.
-
bun run knip,bun run lint,bun run test,bun run test:e2e,bun run test:mcp-evalall green. - Generated docs refreshed.
Phase 13 — Documentation
Section titled “Phase 13 — Documentation”Task 13.1: Update roadmap + state-of-the-product
Section titled “Task 13.1: Update roadmap + state-of-the-product”Description: Add the §9.2 implementation entry to
docs/reference/product-roadmap.md referencing this spec. After merge, add a
sales-proposals capability section to docs/reference/state-of-the-product.md.
Acceptance criteria:
- Roadmap entry exists with cross-reference to the spec and the plan.
- State-of-the-product is updated post-merge (not pre-merge per the canonical-discipline rule).
Verification: Manual review.
Dependencies: Phase 12 complete and merged.
Files likely touched: docs/reference/product-roadmap.md,
docs/reference/state-of-the-product.md.
Estimated scope: XS.
AC → task coverage matrix
Section titled “AC → task coverage matrix”Every spec AC is addressed by at least one task. Tasks marked with multiple ACs deliver the criteria jointly.
| AC | Title | Tasks |
|---|---|---|
| AC-1 | Workspace lifecycle | 2.1, 2.2, 2.3 |
| AC-2 | ProposalContext intake | 3.1, 3.2, 3.3 |
| AC-3 | ROI calculator | 5.1 |
| AC-4 | Case-study selector | 5.2 |
| AC-5 | Quote picker | 5.3 |
| AC-6 | Pricing configurator | 5.4 |
| AC-7 | Templates | 6.1, 6.2, 6.3 |
| AC-8 | Assembly logic | 7.1, 7.2, 7.3 |
| AC-9 | Brand voice + UK English | 4.1, 4.2, 4.3 |
| AC-10 | Pre-send review | 8.1, 8.2 |
| AC-11 | Export | 9.1, 9.2, 9.3 |
| AC-12 | RFP ingest | 3.2 |
| AC-13 | Account Brief MCP App | 10.1 |
| AC-14 | Three MCP prompts | 3.3, 10.2, 10.3 |
| AC-15 | Follow-up workflow | 11.2 |
| AC-16 | Cover email | 11.1 |
| AC-17 | Non-functional gates | 12.1, 12.2, 12.3, 12.4 |
Parallelisation analysis
Section titled “Parallelisation analysis”Tasks below have disjoint file ownership and may run as parallel agents under
the existing isolation: "worktree" pattern. Each parallel group has a
coordination point (a checkpoint) where the parent thread merges branches
sequentially.
- Group P1 — Phase 5 components. Tasks 5.1, 5.2, 5.3, 5.4 own separate
subdirectories under
components/proposals/<x>/andlib/proposals/<x>/; their interfaces are pre-declared intypes/proposal.ts(Task 1.2). Run as four parallel agents. Coordination: Checkpoint F. - Group P2 — Phase 6 templates. Task 6.2’s per-rule template authoring may be split across two agents (architecture + executive + pricing rules to one; SOW + RFP + design + strategy rules to another). Coordination: Checkpoint G.
- Group P3 — Phase 5 + Phase 6 cross-phase. Phase 5 components and Phase 6 templates have disjoint file ownership and interface only inside the assembly orchestrator (Phase 7). Both phases may run in parallel after Phase 4 completes. Coordination: Checkpoints F and G before Phase 7 begins.
- Group P4 — Phase 10 prompts. Tasks 10.2 and 10.3 are independent prompt registrations. Run as two parallel agents after Task 10.1 completes. Coordination: Checkpoint K.
- Group P5 — Phase 11. Tasks 11.1 and 11.2 touch disjoint files and may run in parallel. Coordination: Checkpoint L.
Tasks below must run sequentially because they share state or sit on the dependency chain:
- Sequential — Phase 1. Task 1.1 (migration) before Task 1.2 (types referencing the schema) before Task 1.3 (guard).
- Sequential — Phase 4. Tasks 4.1 + 4.2 before Task 4.3 (Task 4.3 wires both into the section-save hook).
- Sequential — Phase 7. Task 7.1 before 7.2 before 7.3 (each builds on the prior).
- Sequential — Phase 9. Task 9.1 before 9.2 (PDF route may depend on DOCX output) before 9.3 (endpoint wires both).
- Sequential — Phase 12. Performance tests after the relevant phases land; golden-path E2E last because it exercises everything.
Risks and mitigations
Section titled “Risks and mitigations”The risks and mitigations are inherited from spec §10 and reflected in the plan as follows.
| Risk | Mitigation in plan |
|---|---|
| R-1 — bid-writing duplication | Task 0.1 forces resolution before any template authoring. |
| R-2 — orchestrator hallucination | Task 7.1 acceptance constrains LLM calls to section-level rendering with retrieval-grounded context. |
| R-3 — DOCX styling fidelity | Task 0.2 spike + Task 9.1 + Task 9.2 split ownership between DOCX and PDF/HTML. |
| R-4 — brand-review noise | Task 4.3 codifies the severity model (Critical blocks, non-Critical warns). |
| R-5 — workspace-type filter drift | Task 1.3 adds a guard. |
| R-6 — refactor pressure for shared workspace abstraction | Plan does not introduce a workspace abstraction; defers per spec §R-6. |
| R-7 — pricing-section ordering vs orchestrator order | Task 7.1 acceptance encodes the rule’s order; Task 5.4’s renderer enforces. |
| R-8 — RFP table loss | Task 3.2 mandates the documented two-step HTML → Turndown path with a fixture test. |
| R-9 — pre-send check schema drift | Task 8.2 adds a schema-drift guard. |
| R-10 — MCP prompt grounding regression | Task 3.3 pins to a versioned grounding source; Phase-2 grounding is out of scope. |
Open questions
Section titled “Open questions”The plan inherits spec §11’s open questions and surfaces them as Phase 0 tasks. No additional plan-level questions are introduced.
Cross-references
Section titled “Cross-references”The plan resolves to the following on-disk artefacts.
- Input spec —
docs/specs/sales-proposals-workspace-spec-arm-b.md(§1 to §13). - Input research —
docs/research/sales-proposals-reuse-audit-arm-b.md(Bucket assessments inform Phase 5 component dispositions and Phase 6 template adaptations). - Knowledge Hub conventions —
CLAUDE.md(commands, gotchas, design system, sandbox, parallel tracks). Used throughout the file-touch boundaries (spec §8) and the verification gates.
Workflow notes
Section titled “Workflow notes”- The decomposition was almost entirely a function of the spec quality, not the planning effort. Spec §6 (component dispositions) and §7 (acceptance criteria, one per FR) gave a near-finished task graph; the plan’s job was to order them, identify the parallel groups, and bolt verification gates onto each. The longest single deliberation in the planning pass was deciding whether to split Phase 5 and Phase 6 or run them in parallel — the disjoint file ownership made that decision easy once the directory layout was sketched.
- Phase 0 (resolve open questions) was added explicitly because three of the eight OQs change downstream task scope: OQ-1 changes whether RFP-response templates exist (Task 6.2), OQ-2 changes the entire shape of Task 9.2, and OQ-3 turns Task 1.4 from a no-op into a schema extension. Treating these as code-blocking is the cheapest risk reduction available.
- The component phase (Phase 5) is the natural parallelisation prize: four
tasks, four agents, four directories. Naming the per-component subdirectories
(
components/proposals/roi-calculator/,lib/proposals/roi/and so on) up front in this plan removes the ambiguity that usually causes parallel-agent worktree collisions later. - Testing discipline tracks the AC structure verbatim: every AC bullet maps to a Vitest or Playwright assertion, and every task’s verification line names a runnable command. This is heavier than the planning skill’s minimal template asks for, but the spec’s CLAUDE.md gotcha density (vector serialisation, generated columns, sandboxed Bash, gitignored env files, validation-sweep guard, etc.) makes implicit verification dangerous — naming the command at task time is cheaper than rediscovering the right invocation under time pressure during impl.
- The plan deliberately defers a workspace abstraction. Three workspace types is the smallest sample size from which to refactor, and spec §R-6 says wait for the fourth. Phase 13 Documentation flags the deferral so the next planner knows what was on the table and what was not.