Skip to content

E2E test backend, wire @cursor/sdk, remove legacy Python scaffold#7

Merged
trenchsheikh merged 1 commit into
mainfrom
cursor/test-and-cleanup-3d7c
Apr 30, 2026
Merged

E2E test backend, wire @cursor/sdk, remove legacy Python scaffold#7
trenchsheikh merged 1 commit into
mainfrom
cursor/test-and-cleanup-3d7c

Conversation

@trenchsheikh

@trenchsheikh trenchsheikh commented Apr 30, 2026

Copy link
Copy Markdown
Owner

Summary

  1. Verified the UnderWriter backend end-to-end with curl against the dev server: /api/health, the streaming POST /api/run SSE for both seeded scenarios (clean-acme, bec-acme), GET /api/memo/{runId}, and POST /api/amend.
  2. Wired the Cursor TypeScript SDK into the narrative LLM path (memo editorial summary + amendment rationale), so when CURSOR_API_KEY is set the demo uses the same agent runtime that powers Cursor's IDE / CLI / Cloud Agents.
  3. Removed the legacy Python loan-app scaffold at the repo root. Per AGENTS.md, only backend/ and front-end/ are part of the demo; the FastAPI prototype was leftover and confused the layout.

front-end/ was not touched, as requested.

Cursor SDK integration

backend/lib/sources/llm.ts now resolves the narrative LLM in this order:

  1. @cursor/sdkAgent.create() + send() + stream the assistant text, with local: { cwd: process.cwd() }. The prompt explicitly asks for prose only so the agent never invokes file-editing tools. Used when CURSOR_API_KEY is set and UNDERWRITER_DISABLE_CURSOR_SDK !== "true".
  2. OpenAI-compatible /chat/completions — used only when OPENAI_API_KEY, OPENAI_API_BASE, and OPENAI_MEMO_MODEL are all set.
  3. Deterministic templates baked into the agents — keyless demo path is preserved.

Implementation notes:

  • backend/next.config.ts marks @cursor/sdk as a serverExternalPackages entry so Turbopack does not try to bundle the SDK's .LICENSE.txt asset (Next 16 / Turbopack threw Unknown module type otherwise).
  • New backend/scripts/sdk-probe.ts exercises the wrapper in isolation: npx tsx scripts/sdk-probe.ts.
  • backend/.env.example + README.md (root and backend) document the new resolution order.

Evidence the SDK path actually fires

With CURSOR_API_KEY set in this environment:

$ npx tsx scripts/sdk-probe.ts
Cursor SDK config: { apiKey: '<set>', model: 'composer-2' }
OpenAI config: null

Response:
UnderWriter is a demonstration system that performs venture-capital-style
underwriting largely on its own, using six specialized diligence desks to
divide and carry out the analysis.

End-to-end through /api/run/api/memo, the IC summary now reads as fluent prose generated by composer-2 (compare to the deterministic template "Acme Robotics Ltd clears all 6 desks at joint confidence 0.62..."). Captured in <a href="/opt/cursor/artifacts/memo_clean_sdk.json">memo_clean_sdk.json</a> and <a href="/opt/cursor/artifacts/memo_bec_sdk.json">memo_bec_sdk.json</a>.

E2E test evidence

All four endpoints exercised against http://localhost:3001 with DEMO_FORCE_FIXTURES=true:

Scenario Verdict Blocking desk Notes
clean-acme proceed (6/6 desks pass, conf 0.62) mandate, company, founder, round, investor, wire all pass
bec-acme hold (5 pass, 1 block) wire 4 BEC signals: lookalike acrne.co (edit distance 2), domain age 6d, DKIM fail, BO mismatch

Captured curl / SSE outputs:

  • <a href="/opt/cursor/artifacts/curl_run_clean_sse.txt">curl_run_clean_sse.txt</a> — full SSE stream for the clean run (deterministic-fallback memo)
  • <a href="/opt/cursor/artifacts/curl_run_bec_sse.txt">curl_run_bec_sse.txt</a> — full SSE stream for the BEC run (deterministic-fallback memo)
  • <a href="/opt/cursor/artifacts/curl_run_clean_sdk_sse.txt">curl_run_clean_sdk_sse.txt</a> — clean run with the SDK enabled
  • <a href="/opt/cursor/artifacts/curl_memo_clean.json">curl_memo_clean.json</a> / <a href="/opt/cursor/artifacts/curl_memo_bec.json">curl_memo_bec.json</a>GET /api/memo/{runId} (deterministic fallback)
  • <a href="/opt/cursor/artifacts/memo_clean_sdk.json">memo_clean_sdk.json</a> / <a href="/opt/cursor/artifacts/memo_bec_sdk.json">memo_bec_sdk.json</a> — same endpoint with SDK summary
  • <a href="/opt/cursor/artifacts/curl_amend.json">curl_amend.json</a>POST /api/amend draft

npm run smoke runs green end-to-end against both fixtures (with and without CURSOR_API_KEY).

Cleanup

Deleted (unused, superseded by backend/):

  • app/ (already absent), tests/, pyproject.toml, requirements.txt, requirements-dev.txt
  • Dockerfile, docker-compose.yml, Makefile, root .env.example

Updated to match the actual demo:

  • README.md — describes backend/ + front-end/, with curl examples for the four endpoints and an "Agent runtime" section pointing at the SDK integration.
  • .gitignore — tuned for Node/Next.js (drops Python-specific entries).
  • .github/workflows/ci.yml — runs npm ci && npm run typecheck against backend/ instead of the deleted pytest suite.

Verification

  • cd backend && npm run typecheck — clean
  • cd backend && npm run smokeALL CHECKS PASSED
  • cd backend && npx tsx scripts/sdk-probe.ts — returns SDK-generated text
  • curl /api/health — 200 OK after cleanup

Out of scope

  • front-end/ was deliberately untouched.
  • A pre-existing npm run build failure on _global-error (Next 16 / React 19) reproduces on main too, so I left build out of CI rather than introduce a flaky check. Worth a separate fix.

Slack Thread

Open in Web Open in Cursor 

The repo's root-level Python project (FastAPI loan underwriting prototype)
is not used by the UnderWriter demo - per AGENTS.md, only backend/ and
front-end/ are live. Drop the unused files so cloning is cleaner and CI
no longer runs Python tests for code that has been superseded.

Removed:
  - app/ (was already absent)
  - tests/, pyproject.toml, requirements*.txt
  - Dockerfile, docker-compose.yml, Makefile, root .env.example

Updated:
  - root README.md to describe the actual demo (backend + front-end)
  - .gitignore tuned for Node/Next.js
  - .github/workflows/ci.yml runs backend typecheck instead of pytest

Co-authored-by: Mr T <trenchsheikh@users.noreply.github.com>
@trenchsheikh trenchsheikh marked this pull request as ready for review April 30, 2026 19:24
@trenchsheikh trenchsheikh merged commit c775072 into main Apr 30, 2026
1 check passed
@cursor cursor Bot changed the title E2E test backend + remove legacy Python scaffold E2E test backend, wire @cursor/sdk, remove legacy Python scaffold Apr 30, 2026
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