E2E test backend, wire @cursor/sdk, remove legacy Python scaffold#7
Merged
Conversation
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>
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.
Summary
curlagainst the dev server:/api/health, the streamingPOST /api/runSSE for both seeded scenarios (clean-acme,bec-acme),GET /api/memo/{runId}, andPOST /api/amend.CURSOR_API_KEYis set the demo uses the same agent runtime that powers Cursor's IDE / CLI / Cloud Agents.AGENTS.md, onlybackend/andfront-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.tsnow resolves the narrative LLM in this order:@cursor/sdk—Agent.create()+send()+ stream the assistant text, withlocal: { cwd: process.cwd() }. The prompt explicitly asks for prose only so the agent never invokes file-editing tools. Used whenCURSOR_API_KEYis set andUNDERWRITER_DISABLE_CURSOR_SDK !== "true"./chat/completions— used only whenOPENAI_API_KEY,OPENAI_API_BASE, andOPENAI_MEMO_MODELare all set.Implementation notes:
backend/next.config.tsmarks@cursor/sdkas aserverExternalPackagesentry so Turbopack does not try to bundle the SDK's.LICENSE.txtasset (Next 16 / Turbopack threwUnknown module typeotherwise).backend/scripts/sdk-probe.tsexercises 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_KEYset in this environment:End-to-end through
/api/run→/api/memo, the IC summary now reads as fluent prose generated bycomposer-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:3001withDEMO_FORCE_FIXTURES=true:clean-acmeproceed(6/6 desks pass, conf 0.62)passbec-acmehold(5 pass, 1 block)wireacrne.co(edit distance 2), domain age 6d, DKIM fail, BO mismatchCaptured 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/amenddraftnpm run smokeruns green end-to-end against both fixtures (with and withoutCURSOR_API_KEY).Cleanup
Deleted (unused, superseded by
backend/):app/(already absent),tests/,pyproject.toml,requirements.txt,requirements-dev.txtDockerfile,docker-compose.yml,Makefile, root.env.exampleUpdated to match the actual demo:
README.md— describesbackend/+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— runsnpm ci && npm run typecheckagainstbackend/instead of the deletedpytestsuite.Verification
cd backend && npm run typecheck— cleancd backend && npm run smoke—ALL CHECKS PASSEDcd backend && npx tsx scripts/sdk-probe.ts— returns SDK-generated textcurl /api/health— 200 OK after cleanupOut of scope
front-end/was deliberately untouched.npm run buildfailure on_global-error(Next 16 / React 19) reproduces onmaintoo, so I left build out of CI rather than introduce a flaky check. Worth a separate fix.Slack Thread