Roadmap
Phases are ordered by dependency. Each phase ends with a working, demoable slice and green
pnpm test. The differentiator (research + benchmark) lands first to de-risk the hardest
custom part early.
Epic codes referenced below map to the build order in
product-requirements.md:
FOUND → SET → DATA → RES → CAMP → VCO → OUT → BAN → CON → CLO → CTRL → BI.
Phase 0 — Foundations (Epics FOUND, SET, DATA)
Goal: the skeleton everything hangs off.
- Monorepo (
apps/webNext.js 16 / React 19,apps/apiNestJS, sharedpackages/); pnpm workspaces + Turborepo; the deployment target's environments; CI (lint,tsc --noEmit,pnpm test). - Auth: passwordless magic-link (tokens hashed at rest, single-use, 15-min TTL; invitation links get a longer TTL). Rate-limit by IP + email; no user-enumeration. API via tokens.
- Roles & authorization (role/permission layer, e.g. CASL): Admin / Supervisor / Connect-Agent / Closing-Agent with per-resource checks. Connect-Agent sees only released campaigns; Closing-Agent only their round-robin-assigned targets.
- Base data model + migrations:
User/Role,CampaignAccess,Campaign,Product,AssignmentRule,Target,Contact,Department.Targetbelongs to 0..1 Campaign (may be unassigned; re-assignment supported) —Targetis the prospect company. settingstable (key/value; third-party secrets stored encrypted, set via UI, never in env — except the Anthropic key, an infra credential).- Append-only
audit_logs(immutable — never UPDATE/DELETE) wired for business models. - Redis + BullMQ wired; named queues (
default,research,outreach-mail,connect-sync,webhooks,notifications); scheduler skeleton. /docsroute live (App Router server components renderingdocs/*.mdread-only, env-gated) — docs + roadmap + first design prototypes. See 04-design-workflow.
Done when: a logged-in Supervisor sees an empty dashboard, roles gate access, the queue
workers are up, and pnpm test is green.
Phase 1 — Research + benchmark (the differentiator first) (Epics RES, CAMP)
Goal: "define a campaign → get scored local targets."
- Campaigns CRUD: postal-code region(s) + industry input, budget + warning threshold, daily/per-run limits, assignment rule (threshold or LLM-prompt matching).
- Serper.dev discovery job (Google Maps/Places — primary ID source, parallel); creates
Targetrows directly (no separate deduplicated company master — a Target is the company). - Enrichment jobs, each in its own Nest module behind a mockable interface: Firecrawl.dev website crawl (on demand), Meta Ad Library ad activity (free, parallel), Wayback Machine snapshot age (free, parallel), jobsuche.api.bund.dev job postings (primary, free, parallel; SerpAPI Google Jobs fallback). Free sources run in parallel; paid sources run sequentially, on demand, and are budget-pre-checked.
- Every stored fact lands in
research_data_pointswith provenance (source, retrieved_at, confidence); every external HTTP/LLM call is logged append-only inresearch_api_calls(provider, tokens, cost, duration, status). - An LLM (Claude, schema-validated responses, XML-isolated user content) builds the structured company profile and de-duplicates hiring managers.
- Budget guard: pre-check before any paid call → abort if it would exceed the campaign budget; record actual cost after; 80% → warning email; 100% → auto-pause + escalation. Per-source rate limiting. This path is 100% test-covered.
- Benchmark scoring engine: a versioned 0–100 score across 5 weighted dimensions — (1) Segment fit, (2) Size & hiring pressure, (3) Growth & dynamics, (4) Marketing/sales intent, (5) Contactability & data quality — with a stored breakdown. Computed once per target (no auto-refresh; re-research only when a >60-day-stale target is assigned to a campaign). Re-scoring never rewrites history.
- Campaign assignment: new targets auto-route into a campaign via threshold rule or LLM-prompt rule; handles multi-match and re-assignment of previously "unassigned" targets.
- Target list sortable by benchmark, with the "why it scored" breakdown.
Done when: running a real campaign discovers + enriches + scores local businesses, the target
list sorts by benchmark, and pnpm test is green. This alone is demoable value.
Specs: 01-discovery-target-pipeline · 02-discovery-benchmark · 03-campaigns
Phase 2 — Outreach + Bandit (Epics VCO, OUT, BAN)
Goal: "scored targets get emailed automatically, and the system learns what converts."
- VirtualCompany / VirtualEmployee synthetic sender identities (1..3 employees per company), managed by the platform. Mailboxes via Microsoft Graph / Exchange Online; inbox warmup via Trulyinbox (continuous background).
- AI-generated content with versioned step-versions (each hashed & audited).
- A 3-mail sequence orchestrated in benchmark order; non-responders hand off to Connect.
- Reply / bounce webhooks (signature-verified before any business logic) →
OutreachMessagelifecycle transitions; inbound reply classification. - Bandit (Epic BAN): a multi-armed bandit (Thompson Sampling default, epsilon-greedy
alternative) selects the best
StepVersionat send time and learns from reply outcomes. Success = a genuine reply (not spam/out-of-office); Failure = no reply in the wait window. Outcomes recorded append-only inbandit_events.
Done when: targets flow to virtual-employee mailboxes, the 3-mail sequence sends, replies/bounces
advance state, the bandit picks step-versions and records outcomes, and pnpm test is green.
Prereq / design consideration: ⚠️ legal (GDPR / German UWG) is a design consideration, not a
v1 build item — a full compliance layer is explicitly out of scope for v1. Get a written legal
opinion before Outreach goes live (see 00-overview).
Spec: 04-outreach
Phase 3 — Connect / call center (the standout module) (Epic CON)
Goal: "non-responder targets become worked call queues with full KPIs."
- CloudTalk power-dialer integration: push call lists per shift; auto-advance.
- Supervisors define Connect variants (weekday/time windows) and build Shifts that must fall inside those windows; Connect-Agents are released per-campaign (commission rate per agent).
- Benchmark-driven call Packages: on shift activation, lock top-N unworked targets by score (up to 4 packages per shift).
- Agent cockpit: current target context (enrichment + benchmark + outreach history), script, disposition form, next-call. Realtime via Socket.IO (CloudTalk event → UI in < 500ms; webhook fallback re-broadcast internally).
- 8-stage connect pipeline: Targets → Not reached (follow-up) → Reached (gatekeeper blocked) → Reached (appointment interest) → Appointment scheduled → No interest (follow-up) → Finally rejected → Do not contact. Bandit success = Appointment scheduled.
- KPIs (reach rate, gatekeeper quote, interest rate, appointment rate) + per-agent commissions.
Done when: a Supervisor schedules a shift, the Connect-Agent works a benchmark-ordered queue in
the cockpit, outcomes log through the 8 stages, KPIs + commissions compute, and pnpm test is
green. Worth extra polish — the biggest market gap.
Spec: 05-connect-callcenter
Phase 4 — Closing (Epic CLO)
Goal: "interested targets close."
- Appointments round-robin assigned to Closing-Agents (each sees only their assigned targets).
- 8-stage closing pipeline: New target (validation pre-stage) → Appointment scheduled → Follow-up → First meeting → Follow-up meeting → Sold (end) → Not sold (end) → Unqualified (end).
- Drag-drop Kanban pipeline (React + shared shadcn/ui components): targets across stages.
- Appointments, notes, no-show tracking, warm "call job" handoff — a distinct job type from cold Connect shifts.
- Contract send via SignRequest (e-signature); payment collection via GoCardless.
- Closing-agent commissions.
Done when: an interested target moves through the pipeline to a Sold/Not sold outcome with a
signed contract, payment collection is initiated, commissions compute, and pnpm test is green.
Spec: 06-closing
Phase 5 — Controlling + optimization (Epics CTRL, BI)
Goal: "one cross-team overview + smarter spend."
- Read-model / reporting layer: Outreach, Connect, Closing dashboards into one overview (materialized nightly + on-demand). Read-only BI views (no soft-deletes on reporting tables).
- Cost per stage, yield per source, per-agent performance, budget health.
- Budget allocation optimization across sources/campaigns by observed yield (a separate, later concern from the outreach-content Bandit above).
- Benchmark weighting A/B testing.
Done when: the controlling overview shows the cross-stage funnel + cost + yield, budget
allocation responds to yield, and pnpm test is green.
Spec: 07-controlling
Cross-cutting (continuous)
- Tests + ESLint + Prettier +
tsc --noEmitgreen every phase; integrations tested against faked adapters (external APIs are never called for real in CI). Coverage: ≥70% overall, ≥90% on services/integrations, 100% on auth/permissions/budget enforcement. - Immutable
audit_logsof every lifecycle transition from Phase 1 on — feeds all KPI dashboards. - Seed/demo data so the app (and the
/docsprototypes) are explorable without live APIs. - Provenance is first-class from Phase 1: every stored fact carries source + retrieved_at + confidence.