Investigations — delivery report
Phases 01–07 ofdocs/architecture/investigations/, one commit per phase, on
claude/architecture-investigations-phases-bnaoaz.
SHAs
origin/staging was merged into the branch after Phase 6 (clean, no conflicts),
so the base above is staging’s head at that merge, not the branch point.
Commits by phase
No phase was merged into another, and nothing was merged into
staging.
Migrations and rollback
One migration:libs/db/src/migrations/1715200000150-AddInvestigations.ts —
creates investigations, investigation_events, investigation_candidates,
with unique (investigation_id, candidate_id) and (investigation_id, seq) and
CHECK constraints on the kind/status vocabularies.
workSessionWorkflow, not added. DATABASE_CONNECTION_BUDGET_TOTAL is still 8,
and database-connection-budget.spec.ts fails if that stops being true.
Rollout switches
On by default. A deployment that sets nothing gets the whole surface, for every workspace whose plan includes it. These are KILL SWITCHES — they take something away in a hurry; they are not an enrolment gate.
An enable-gate was rejected deliberately: it makes the shipped path the one
nobody runs, so the feature works in the deployment where it is on and rots in
every other, and the first real user is also the first integration test.
The two ceilings are operational — they refuse to start work. They are not
credits, not entitlements and not pricing: the plan gate
(
entitlements.assertFeature) still runs unchanged in front of every mutation,
and Phase 7 explicitly defers the pricing decision until real cost is measured.
Test totals
Focused suites, this branch, all green:scripts/harness/check.sh: PASS — 19 passed, 0 failed, 3 skipped.
Build and per-package typecheck (14 packages) clean.
Skipped and NOT RUN — exactly what was not verified
The live-staging runner’s credentialed path — booting the Nest context and
driving a real run — has never executed in the authoring environment. It is
delivered unverified and the runner says so in its own output.
Live staging report
NOT RUN. No staging database and no credentials were available.corepack pnpm run evals:investigation-live prints:
null means NOT MEASURED — a zero is only ever a measured zero.
Known limitations
- No live evidence of usefulness. Whether the open web actually yields useful Mexican commercial candidates for the five frozen objectives is unmeasured. The hermetic suites prove the rules; they cannot prove this.
- No integration-test run. Tenant isolation, the compare-and-set affected count and the unique constraints are proven by the database, and the spec that exercises them has not been executed here.
- No firmographics provider, no second web executor. Both are documented
decisions with their contract questions marked NOT DETERMINED — see
docs/architecture/source-expansion-data-rights.md. - The credentialed half of the live runner is unverified.
- Browser-level scenarios (rows arriving progressively, a real deploy
interrupting a real run) are named in
investigation-acceptance.spec.tsrather than proven. - Operational views are unexecuted SQL. Every column they reference is
checked against the entity definitions by
investigation-operations.spec.ts, which is the strongest guarantee available without a database — it is not the same as having run them.
Security and privacy review
- Tenant isolation. Every service read carries the workspace predicate; a cross-workspace id is 404, never 403. The rollout gate uses 404 for the same reason — a workspace outside the rollout cannot learn the feature exists.
- Authorization. Every mutation calls
assertHasIdentityandentitlements.assertFeature(ws, 'assistant'); the architecture guard asserts the counts match the number of@Posthandlers. No new public route.WorkspaceGuardremains the globalAPP_GUARDand is not bypassed. - Credentials. Resolved server-side through the existing encrypted provider-credential path. Never logged, never returned, never in model context. The web adapter now redacts its key from upstream error bodies before they become error messages.
- Personal data. None is collected or stored. The candidate schema has no person, contact, email, phone or title column, and the discovery contract refuses contact vocabulary — including linkedin — as query material.
- Prompt injection. Third-party text stays inside the branded
UntrustedTextfields; the conformance suite asserts at runtime that it never reaches a title, a control field or a structural position. - Curated activity stream. Numbers, booleans and a closed string vocabulary only. Adapter ids and internal costs are dropped by key — a vendor name would make provider choice product-visible and an internal cost would read as a price.
- Supply chain.
minimumReleaseAgeis untouched and no package exclusion was added. No new runtime dependency was introduced by any phase. - Retired shapes stay retired.
WorkSession*,gtm_research_runsand the deleted generic patch reducer are absent, enforced by the architecture guard.
Bundle and database impact
- Bundle. Four new dashboard modules (
Investigations,InvestigationDetail,DataArtifactRenderer,InvestigationPromote) plus a label dictionary and a stylesheet. No new npm dependency; the artifact renderer is local React rather than@assistant-ui/react-generative-ui(decision recorded indocs/architecture/data-artifact-views.md). - Database. Three tables and one pool connection, re-allocated rather than
added. Reads are indexed on
(workspace_id, created_at)and(status, heartbeat_at); candidate and event reads are bounded (500 rows / 200 events) and the API pages them.
Evidence that Chat remained independent
investigations.architecture.spec.ts fails the build on:
- any file under
investigations/importing fromchat/; - any file under
chat/importing frominvestigations/; InvestigationsModuleimportingChatModuleor anything underchat/;- any investigation file reaching
ChatStreamHubor opening an@Ssestream.
agent_runs,
model_usage) — the same seams every other surface uses — and nothing else.
Rollback rehearsal
Proven ininvestigation-rollout.spec.ts, each switch independently:
What must happen before general availability
- Run the integration spec against a real database.
- Run
evals:investigation-liveon staging and attach the report. - Read the measured cost, then make the pricing/credits decision separately — Phase 7 deliberately does not make it.
- Decide retention and support posture.
- If anything looks wrong on the way, pin
INVESTIGATIONS_WORKSPACESor pullINVESTIGATIONS_DISABLED— the feature is on for everyone until told otherwise.
