Skip to content

Align Specter integration with backend/docs/SPECTER_FLOW.md#10

Merged
trenchsheikh merged 2 commits into
mainfrom
cursor/follow-specter-flow-spec-b77b
Apr 30, 2026
Merged

Align Specter integration with backend/docs/SPECTER_FLOW.md#10
trenchsheikh merged 2 commits into
mainfrom
cursor/follow-specter-flow-spec-b77b

Conversation

@trenchsheikh

Copy link
Copy Markdown
Owner

Why

backend/docs/SPECTER_FLOW.md was added in #7 as the spec for how the diligence backend should talk to Specter — endpoints, auth, error semantics, derived fields, cross-step underwriting flags, and the canonical Dex worked example. The implementation in backend/lib/sources/specter.ts was still the original ad-hoc shim (legacy getSpecterCompany / getSpecterCompanyPeople / getSpecterInterestSignals / getSpecterTransactions calls against fixture-only paths). This PR brings the implementation in line with the spec.

What changed

1. backend/lib/sources/specter.ts — full rewrite to follow SPECTER_FLOW.md

  • HTTP layer matching §0: X-API-Key: $SPECTER_API_KEY against https://app.tryspecter.com/api/v1 (override with SPECTER_API_BASE); typed SpecterError for the four documented error families (NOT_FOUND JSON vs WRONG_PATH HTML, NOT_PERMITTED, VALIDATION_ERROR, RATE_LIMIT); x-ratelimit-remaining / x-ratelimit-reset honoured.
  • Endpoints wired: §1 POST /companies, §2 GET /companies/{id}/people, §3 GET /people/{id}, §5 GET /companies/{id}/similar + per-peer GET /companies/{id} fan-out.
  • Snapshot builder that orchestrates the spec exactly: §1 → §2 (founder_info ∪ is_founder merge per §2 caveat) → §3 in parallel → §5 in parallel → §4 cross-step flags.
  • §3b derived fields: prior_exits (regex over experience.description), stealth_history, departed_subject_company (with days_before_close math).
  • §4 cross-step flags: founder_departed_before_close, ex_founder_now_at_investor, funding_outlier_high|low, plus the web_traffic_dip_during_growth informational yellow flag.
  • §7 explicitly NOT WIRED: Investor-Interest endpoint is not called (saved Investor Interest searches required); Desk 03 falls back to funding.investors[] + top_tier_investors / raised_last_month highlights, and the desk's facts say so.
  • Per-runId caching: snapshot memoised by specter_id / website_url / seed for the lifetime of the process.
  • Fixture fallback when no key is present, when DEMO_FORCE_FIXTURES=true, when OFFLINE_MODE=true, or when a live call fails — so the demo continues to run keyless.

The output of buildSpecterSnapshot() is the SpecterSnapshot object specified in §8 of the doc, used as-is by the desks.

2. Snapshot fixtures

  • backend/fixtures/specter/snapshots/dex.json — the canonical worked example from SPECTER_FLOW.md (Dex / meetdex.ai, $5.3M Seed led by Andreessen Horowitz, both founders enriched, Harry Uglow's 2026-04-01 exit 26 days before the 2026-04-27 close, his "a16z speedrun scout" tagline, AgentMail / Coverflow direct-match peers, all three §4 flags pre-computed).
  • backend/fixtures/specter/snapshots/acme.json — backwards-compat snapshot for the existing clean-acme / bec-acme scenarios.
  • The legacy ad-hoc fixtures (acme-company.json, acme-founders.json, sequoia-interest.json, eu-robotics-rounds.json) are removed.

3. Desk refactor — agents/desks/{company,founder,investor,round}.ts

All four Specter-consuming desks now read from ctx.specter.snapshot instead of calling Specter functions individually:

  • Company desk — cites snapshot.company; cross-checks against Companies House when HQ is UK; non-UK HQs soft-skip the registry call (the Dex case).
  • Founder desk — cites snapshot.founders (with the §2 founder_info ∪ is_founder merge already applied); surfaces founder_departed_before_close and ex_founder_now_at_investor from snapshot.flags as REVIEW banners; sanctions / PEP screening still runs against OpenSanctions.
  • Lead Investor desk — explicitly notes the §7 NOT WIRED status; uses funding.investors[], the tier-1 funds list from the mandate, and the raised_last_month / recent_funding recency highlights.
  • Round Dynamics desk — uses snapshot.peers (from §5 /similar); flags funding_outlier_high|low when snapshot.flags reports them; SPA pro-rata math unchanged.

4. Orchestrator + types

  • agents/orchestrator.ts calls buildSpecterSnapshot() once per run (after parsePrompt), then threads SpecterContext { snapshot, cached, mode } into every desk via DeskRunner's ctx. The parsed deal is hydrated with the snapshot's specter_id and domain so downstream evaluators stay consistent.
  • lib/types.ts adds SpecterContext and updates the DeskRunner signature.
  • lib/contract.ts adds dex-meetdex to RunRequest.fixtureSeed.

5. New dex-meetdex demo seed

  • agents/parse-prompt.ts recognises "Dex" / "meetdex.ai" / fixtureSeed: "dex-meetdex" and defaults stage = seed, lead = Andreessen Horowitz, sector = ai_infrastructure, geography = EU.
  • MANDATE.md adds andreessen_horowitz alongside a16z on the tier-1 list so the mandate evaluator matches the long-form name on the Dex round.
  • scripts/smoke.ts runs the Dex scenario after clean / BEC and asserts that both founder_departed_before_close and ex_founder_now_at_investor surface on the Founder desk.

6. README updates (root + backend)

  • Top-level pitch in both READMEs now describes the SPECTER_FLOW alignment in one paragraph and points to the doc.
  • Backend README has a dedicated "Specter source" section that maps the implementation to each section of the spec, including which endpoints are wired vs explicitly NOT WIRED.
  • Demo-scenarios tables in both READMEs add the Dex row alongside clean / BEC; curl smoke sections include a Dex POST.

Evidence

npm run typecheck is clean. npm run smoke passes all three scenarios:

  • clean-acmeproceed (6/6 desks pass, wire queued).
  • bec-acmehold (Wire desk BLOCK on lookalike + young domain + DKIM fail; amendment-PR draft generated).
  • dex-meetdexreview (Founder desk flag with both §4 flags surfaced as REVIEW banners; verdict summary "1 flag(s); 5 pass(es)" — exactly matching the §4 expectation that this should drive Desk 02 to REVIEW without blocking the deal).

Captured live SSE stream and memo for the Dex run via curl:

  • Verdict event: {"type":"verdict","verdict":{"action":"review","confidence":0.45,"summary":"REVIEW — 1 flag(s); 5 pass(es)"}}
  • Founder desk facts include both: founder_departed_before_close: Harry Uglow (Cofounder & CTO) left 2026-04-01, 26 days before Seed close 2026-04-27 and ex_founder_now_at_investor: Harry Uglow's current tagline references "a16z speedrun scout"; a16z and a16z speedrun are listed investors in the closing round.

Artifacts attached:

Risk notes

  • The SPA fixture is shared across scenarios, so the Dex memo's "$18M @ $80M post" headline still references the Acme SPA terms; replacing this with a Dex SPA fixture is out of scope for this PR.
  • §7 Investor-Interest remains unwired by design; the spec says this requires a saved Investor Interest search created via the Specter web UI first.
  • The pre-existing Next 16 / React 19 _not-found prerender error is unchanged on main; not introduced by this PR. Typecheck and smoke are the load-bearing CI gates here.

Slack Thread

Open in Web Open in Cursor 

cursoragent and others added 2 commits April 30, 2026 19:57
Implement the canonical SpecterSnapshot flow exactly as specified in
backend/docs/SPECTER_FLOW.md so the four Specter-consuming desks (Company,
Founder, Lead Investor, Round Dynamics) read from one snapshot per run
instead of ad-hoc legacy fixtures.

backend/lib/sources/specter.ts
- Documented HTTP layer: X-API-Key auth against
  https://app.tryspecter.com/api/v1, the §0 error semantics
  (NOT_FOUND vs WRONG_PATH vs NOT_PERMITTED vs VALIDATION_ERROR vs
  RATE_LIMIT) typed as SpecterError, and rate-limit header backoff.
- Endpoint wrappers for §1 POST /companies, §2 GET /companies/{id}/people,
  §3 GET /people/{id}, §5 GET /companies/{id}/similar (+ per-peer
  GET /companies/{id} fan-out).
- Snapshot builder that follows §1 → §2 (founder_info ∪ is_founder merge)
  → §3 (parallel) → §5 (parallel) → §4 cross-step flags.
- §3b derived fields (prior_exits, stealth_history,
  departed_subject_company) and §4 flags (founder_departed_before_close,
  ex_founder_now_at_investor, funding_outlier_high|low,
  web_traffic_dip_during_growth).
- §7 investor-interest is explicitly NOT WIRED; Desk 03 falls back to
  funding.investors[] + highlight tile (matches the spec).
- Per-runId memoisation by specter_id / website_url / seed (§6.1
  Backend.md / §implementation-notes SPECTER_FLOW).

backend/agents/orchestrator.ts + lib/types.ts
- Build the snapshot once per run and thread it to every desk via
  SpecterContext (snapshot, cached, mode).

backend/agents/desks/{company,founder,investor,round}.ts
- Refactor each desk to consume the snapshot. Citations cite the snapshot
  fields directly; Founder/Round desks surface §4 flags as REVIEW/INFO
  banners. Lead Investor desk explicitly notes the §7 NOT WIRED status
  and uses tier-1 + recency highlights as fallback.

backend/fixtures/specter/snapshots/{dex,acme}.json
- New canonical SpecterSnapshot fixtures. dex.json mirrors the worked
  example in SPECTER_FLOW.md verbatim (Dex / meetdex.ai / a16z Seed,
  Harry Uglow's 26-day pre-close exit + a16z speedrun scout overlap,
  AgentMail/Coverflow direct-match peers, all three §4 flags).
- acme.json provides a backwards-compatible snapshot for the existing
  clean-acme / bec-acme scenarios after the refactor.
- The legacy ad-hoc Specter fixtures (acme-company.json,
  acme-founders.json, sequoia-interest.json, eu-robotics-rounds.json)
  are removed.

backend/agents/parse-prompt.ts
- Add the dex-meetdex seed: prompt-driven recognition of "Dex" /
  "meetdex.ai", correct stage (seed) / sector (ai_infrastructure) /
  geography (EU) / lead (Andreessen Horowitz) defaults.

backend/MANDATE.md
- Add 'andreessen_horowitz' alongside 'a16z' on the tier-1 list so the
  evaluator recognises the long-form name on the Dex round.

backend/scripts/smoke.ts
- Add a third scenario for dex-meetdex; assert the verdict is review or
  hold and that both founder_departed_before_close and
  ex_founder_now_at_investor surface on the Founder desk.

Verified end-to-end: npm run typecheck clean; npm run smoke passes all
three scenarios (clean → proceed, BEC → hold + amendment draft, Dex →
review with both §4 flags surfaced).

Co-authored-by: Mr T <trenchsheikh@users.noreply.github.com>
backend/README.md
- New top-level paragraph + dedicated 'Specter source' section that
  walks through how lib/sources/specter.ts maps onto every section of
  SPECTER_FLOW.md (auth, error semantics, wired vs NOT WIRED endpoints,
  snapshot output, caching, fixture fallback).
- fixtureSeed table now lists clean-acme / bec-acme / dex-meetdex with
  the expected verdict and the SPECTER_FLOW.md flags surfaced for Dex.
- curl reference updated with the Dex POST and a memo/amend example.

README.md (root)
- Lead paragraph mentions the SPECTER_FLOW.md alignment explicitly.
- Demo-scenarios table adds the Dex (meetdex.ai) row alongside Acme
  clean / BEC, with the founder-departure + investor-overlap story.
- Curl smoke section includes a Dex POST.
- Project layout snippet calls out fixtures/specter/snapshots/.

Co-authored-by: Mr T <trenchsheikh@users.noreply.github.com>
@trenchsheikh trenchsheikh marked this pull request as ready for review April 30, 2026 20:00
@trenchsheikh trenchsheikh merged commit d33f583 into main Apr 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants