PR3: Path B + agent swarm + MVI router (mocks)#4
Open
Regantih wants to merge 7 commits into
Open
Conversation
Owner
Author
|
| This PR's content | Status in PR #7 |
|---|---|
lib/storage.ts (StorageClient interface) |
✅ Ported |
lib/storage.mock.ts (MockStorageClient) |
✅ Ported + hardened prod guard |
lib/llm.ts (ModelRouter interface) |
✅ Ported + updated model IDs (claude-sonnet-4-20250514) |
lib/llm.mock.ts (MockModelRouter) |
✅ Ported + hardened prod guard |
lib/swarm/ (all 5 agents + orchestrator) |
✅ Ported — now wired to real AnthropicModelRouter |
api/ingest-link.ts |
✅ Refactored to dependency-inject the queue |
api/ingest-queue.mock.ts |
✅ Ported + hardened prod guard |
Path B UI in submit.html |
✅ Carried through |
Additionally, PR #7 adds what this PR deferred to "PR#5": a real Anthropic LLM adapter (AnthropicModelRouter), a real Supabase-backed jobs queue (SupabaseJobsQueue), and 4 database migrations.
Recommended action
This PR will be auto-closed when PR #7 merges to main. No manual action needed — the merge order is: PR #8 (docs) first, then PR #7 (everything else).
If you wish to close this PR now, use "Close pull request" below.
12 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR3: Path B + Agent Swarm + MVI Router (mocks)\n\nImplements the full scaffolding for data-room link ingest, the five-agent swarm, and the MVI cost-aware model router. No real API keys are used. Every live service is hidden behind an interface and substituted with a clearly-labeled mock that is guard-gated against production use.\n\n---\n\n## What's in this PR\n\n### 1. Storage abstraction (
lib/)\n-lib/storage.ts—StorageClientinterface:putFile,getSignedUrl,listDealFiles\n-lib/storage.mock.ts—MockStorageClient: writes to/tmp/deallenz-mock-storage/{deal_id}/, returnsfile://signed URLs. Throws at import time inNODE_ENV=productionwithoutUSE_MOCKS=true.\n\n### 2. MVI Model Router (lib/)\n-lib/llm.ts—ModelRouterinterface +CostEntry/CostLedgertypes +resolveTier()+estimateUsd()pure helpers.\n - Tier mapping:cheap(Haiku/4o-mini) →mid(Sonnet/4o) →deep(Opus/o1)\n - Downgrade ladder: ifcost_budget_usdis set and the estimated cost exceeds it, the router steps down one tier (deep→mid→cheap) until under budget.\n-lib/llm.mock.ts—MockModelRouter: returns deterministic[MOCK]-prefixed stub responses, realistic token counts, andestimateUsd()-computed costs so the cost-transparency UI renders with plausible numbers.\n\n### 3. Agent swarm (lib/swarm/)\n-lib/swarm/agents/researcher.ts—ResearcherAgent: web + doc retrieval (researchtask type)\n-lib/swarm/agents/analyst.ts—AnalystAgent: financials, unit economics, market sizing (classify+analyze). Computes Rule of 40 deterministically fromMoMwhen available.\n-lib/swarm/agents/risk.ts—RiskAgent: risk register + red-flag summary (analyze)\n-lib/swarm/agents/writer.ts—WriterAgent: 14-chapter memo, 3 chapters per parallel batch (write)\n-lib/swarm/agents/critic.ts—CriticAgent: 14-point QA rubric, 6 blocking items,approvedflag (critique)\n-lib/swarm/orchestrator.ts—SwarmOrchestrator: plan → dispatch (parallel) → gather → compose → critique → finalize. Emits granularProgressEvents. AggregatesCostLedgeracross all agents and attaches to returnedDealRecord.\n\n### 4. Path B — link ingest (api/)\n-api/ingest-link.ts— Framework-agnostic handler. Accepts{ url, deal_id }, validates (HTTPS only, deal_id format, URL parseable), classifies source type (Google Drive folder/file, Dropbox folder, Notion page, generic webpage), enqueues job. Returns{ ok, job_id, source_type }or structured error.\n-api/ingest-queue.mock.ts—MockIngestQueue: in-memory queue with realistic status transitions (queued → processing → done) and simulated per-source-type delays. Result always contains{ _mock: true }to make mock nature unmistakable.\n\n### 5.submit.html— Path B UI\n- New "Path B — Data room link" section in the sidebar.\n- Input field + Ingest button (disabled until a company name exists in the live deal record).\n- Live job cards: show source type badge, status (Queued / Processing / Done / Failed), per-status note.\n- Honest error states: if the backend isn't running (404/405), the UI explains exactly why and where the code lives — no fake success.\n- Polling loop for job status updates.\n\n### 6.CostLedgerJSON shape (for PR#4 UI)\nDocumented indocs/ARCHITECTURE.md. Shape is:\njson\n{\n \"cost_ledger\": {\n \"deal_id\": \"pqc-bank\",\n \"entries\": [ { \"call_id\", \"agent\", \"task_type\", \"model\", \"tokens_in\", \"tokens_out\", \"usd_cost\", \"duration_ms\", \"timestamp\" } ],\n \"total_usd\": 0.412,\n \"total_tokens_in\": 18400,\n \"total_tokens_out\": 5500\n }\n}\n\nThe cost-transparency UI in PR#4 readsdeal.cost_ledgerfrom the deal JSON.\n\n### 7.docs/ARCHITECTURE.md\nFull architecture reference covering: storage abstraction, MVI router tiers + pricing, orchestrator phases, agent contracts, critic rubric, Path B sources + job lifecycle, mock guards, environment variables, and file map.\n\n### 8. Supporting files\n-tsconfig.json— strict TypeScript + NodeNext module resolution\n-.env.example— all variables documented, real secrets never committed\n-docs/DECISIONS.md— D-021 through D-026 appended\n\n---\n\n## No fake data / no placeholder URLs\n- Mock classes are gated: throw in production unlessUSE_MOCKS=true\n- All stub responses are prefixed[MOCK]and include a note explaining what real integration is needed\n-MockIngestQueueresult always sets_mock: trueinextracted_fields\n- Path B UI shows real error messages when the backend is absent — never fakes a success toast\n\n---\n\n## Test notes\n\n### TypeScript compilation\nbash\nnpm install typescript @types/node\nnpx tsc --noEmit\n\nExpect zero errors. All files compile clean with strict mode.\n\n### Path B UI (static HTML)\n1. Opensubmit.htmlin a browser.\n2. Type a company name in chat (e.g. "We're looking at Acme Finance").\n3. Observe the Ingest button becomes active once a name is extracted.\n4. Pastehttps://drive.google.com/drive/folders/exampleand click Ingest.\n5. Observe the honest error: "The /api/ingest-link endpoint is not running in this environment" (expected — no backend running).\n6. Paste a non-HTTPS URL → see the client-side validation error before any network call.\n\n### MockModelRouter\ntypescript\nimport { MockModelRouter } from './lib/llm.mock';\nconst router = new MockModelRouter('test-deal');\nconst resp = await router.route({ deal_id: 'test-deal', agent: 'researcher', task_type: 'research', prompt: 'test' });\nconsole.log(resp.content); // starts with [MOCK]\nconsole.log(router.getCostLedger().total_usd); // realistic number\n\n\n### MockIngestQueue\ntypescript\nimport { MockIngestQueue } from './api/ingest-queue.mock';\nconst q = new MockIngestQueue();\nconst job = { id: 'j1', deal_id: 'd1', url: 'https://example.com', source_type: 'generic_webpage', status: 'queued', queued_at: new Date().toISOString(), attempts: 0 };\nawait q.enqueue(job);\nq.onJobUpdate('j1', j => console.log(j.status)); // logs: processing, then done\n\n\n---\n\n## Acceptance checklist\n\n- [x]lib/storage.ts—StorageClientinterface withputFile,getSignedUrl,listDealFiles\n- [x]lib/storage.mock.ts—MockStorageClientwriting to/tmp, guard for production\n- [x]lib/llm.ts—ModelRouterinterface,CostEntry,CostLedger,resolveTier(),estimateUsd(), tier catalogue\n- [x]lib/llm.mock.ts—MockModelRouterwith deterministic stubs, realistic costs, simulated latency, production guard\n- [x]lib/swarm/agents/researcher.ts—ResearcherAgentwith typed output\n- [x]lib/swarm/agents/analyst.ts—AnalystAgentwith deterministic Rule-of-40 computation\n- [x]lib/swarm/agents/risk.ts—RiskAgentwith risk register + red flags\n- [x]lib/swarm/agents/writer.ts—WriterAgentwith 14-chapter manifest + parallel batching\n- [x]lib/swarm/agents/critic.ts—CriticAgentwith 14-point rubric (6 blocking)\n- [x]lib/swarm/orchestrator.ts—SwarmOrchestratorplan/dispatch/gather/compose/critique/finalize +ProgressEmitter\n- [x]api/ingest-link.ts— validated handler, source classifier, enqueue\n- [x]api/ingest-queue.mock.ts—MockIngestQueuewith status transitions + listeners\n- [x]submit.html— Path B section with link field, job cards, honest error states\n- [x]CostLedgerJSON shape documented for PR#4 UI consumption\n- [x]docs/ARCHITECTURE.md— swarm, MVI, CostLedger, storage, Path B all documented\n- [x] No real API keys in any file\n- [x] No fake data shown to end users\n- [x] No placeholder URLs or "Awaiting enrichment" copy\n- [x] All mocks gated behindNODE_ENV !== 'production' OR USE_MOCKS=true\n- [x]tsconfig.jsonstrict mode added\n- [x].env.exampledocuments all variables\n- [x]docs/DECISIONS.mdupdated D-021 through D-026\n\n---\n\n## What lands next\n- PR#2 — Real SupabaseStorageClientimplementation\n- PR#4 — Cost-transparency UI ondeal.html(readscost_ledgerJSON shape defined here)\n- PR#5 — Real LLM adapters (lib/llm.anthropic.ts,lib/llm.openai.ts) + real data-room connectors (Drive API, Dropbox SDK, Notion API, Firecrawl)\n