flow-next ships three second-model review backends today — rp (RepoPrompt),
codex (OpenAI Codex CLI), copilot (GitHub Copilot CLI) — selected via the
BACKEND_REGISTRY in plugins/flow-next/scripts/flowctl.py and consumed by
/flow-next:impl-review, /flow-next:plan-review, /flow-next:spec-completion-review.
There is no cursor backend. Cursor is already supported as a primary host
driver (the CURSOR_AGENT/install-cursor.sh path in flow-next-setup) — a
different integration point, out of scope here.
Add cursor as a first-class review backend that shells out to the cursor-agent
CLI (installed locally, v2026.06). It unlocks Cursor-billed review (the user's
existing Cursor subscription, no separate API key) and Cursor reviewer models the
others can't reach in one place: gpt-5.5-high (1M ctx, the default), the
gpt-5.3-codex family, composer-2.5, claude-opus-4-8-thinking-high.
Parity port of the most-recent backend (copilot, fn-28) — no new review features,
no new architecture. The headless contract was verified live and the spec was then
dogfooded through a cursor-agent gpt-5.5-high plan-review of itself (see
Decision Context), which corrected the session/repo-scope/triage contracts below.
Doc-drift this closes: the GrowthFactors cross-model-review spec
(~/work/code-factory-package/spec/05-cross-model-review.md) already advertises
"Cursor via its cursor-agent headless CLI" as a supported review backend. That
claim is currently false. fn-74 makes the already-published claim true.
Mirror the copilot backend end-to-end. Paths in
plugins/flow-next/scripts/flowctl.py unless noted.
Verified cursor-agent contract (probed live + dogfood plan-review):
- Invocation:
cursor-agent -p --output-format json --trust --mode ask --model <model> [--resume <session_id>] "<prompt>", run withcwd=repo_root(Cursor scopes to the workspace dir; without it a review launched from a subdir reads the wrong tree — copilot's--add-dir <repo_root>analog). --mode ask= read-only Q&A; the CLI refuses to edit in this mode (verified). Reviewer never mutates the tree.--trustis mandatory headless or the CLI blocks on a "Workspace Trust Required" prompt and hangs.- Result JSON:
{"type":"result","subtype":"success","is_error":false,"result":"<text>","session_id":"<uuid>","usage":{...}}. Parse.result,.session_id,.is_error. - Session model = resume-only (like copilot's Windows/stdin path, NOT its POSIX create-or-resume). First call: omit
--resume, let Cursor generatesession_id, capture it from the result, store in the receipt. Continuation: pass--resume <stored_session_id>. Verified: a generated id resumes prior history non-interactively under-p. Never pass a caller-fabricated uuid as--resumeon the first call. - Auth: stored login creds OR
CURSOR_API_KEY.--list-modelsis the source of truth for model strings;cursor-agent --version→2026.06.xx-<hash>forcheck.
Components to add (copilot is the template):
-
Registry entry —
BACKEND_REGISTRY(~L3449). NEW shape: model accepted, effort folded into the model name (Cursor convention) soefforts: None:"cursor": { "models": {"auto", "gpt-5.5-high", "gpt-5.4-high", "gpt-5.3-codex", "gpt-5.3-codex-high", "gpt-5.3-codex-xhigh", "gpt-5.2", "composer-2.5", "claude-opus-4-8-thinking-high", "claude-opus-4-7-thinking-high"}, "efforts": None, # Cursor bakes reasoning effort into the model name "default_model": "gpt-5.5-high", },
VALID_BACKENDS(~L3510) derives → free. Verified: existingBackendSpec.parse/.resolve+parse_backend_spec_lenienthandle this model-yes/effort-no shape with no parser edits. -
Helpers (mirror
require_copilot/get_copilot_version/run_copilot_exec~L3786-3967):require_cursor()/get_cursor_version().run_cursor_exec(prompt, session_id=None, *, spec, repo_root) -> (result_text, returned_session_id, exit_code, stderr)—session_idis optional input (None on first call → omit--resume; non-None →--resume <id>), and the returned session id (parsed from.resultJSON) is what the caller persists. Run withcwd=repo_root,--trust --mode ask,timeout=600; non-zero onis_error/timeout/CLI failure. Reuse copilot's argv-vs-temp prompt threshold (POSIX argv handles 60KB — verified).
-
CLI subcommands (mirror the
copilotparser block ~L25968): acursorsubparser withcheck,impl-review,plan-review,completion-review,validate,deep-pass— same args as copilot (incl.check --skip-probe). -
Command handlers (mirror
cmd_copilot_*~L22405+, and shared dispatchers_run_validator_pass/deep-pass at L19245 / L19902 / L23606): addelif backend == "cursor":branches +cmd_cursor_*. Receipts must match the copilot field set —mode:"cursor",spec:"cursor:<model>",model:<model>, noeffortkey (effort is invalid for cursor), plus the same confidence/classification rubric injection, suppressed-count, introduced-vs-pre_existing, unaddressed-R-ID, and protected-path handling copilot already does. -
Resolution plumbing —
resolve_review_spec(~L3691) is backend-generic. Env fill:FLOW_CURSOR_MODEL(noFLOW_CURSOR_EFFORT). Thereview-backendresolver already flows from the registry (verified:config set review.backendstores without a separate allowlist; resolution parses via the registry) — config/env/per-task/spec-form acceptcursorautomatically once registered. -
Skill wiring:
flow-next-impl-review: newworkflow-cursor.md(mirrorworkflow-copilot.md); add thecursorrow to the Phase-0 dispatch table inworkflow-common.md.flow-next-plan-review: add acursorsection toworkflow.md.flow-next-spec-completion-review: addcursorto itsworkflow-common.md.- All three SKILL.md + their
commands/flow-next/*.md:--review=rp|codex|copilot|cursor|none.
-
Setup:
flow-next-setupreview.backendconfig prompt/validation acceptscursorand spec formcursor:gpt-5.5-high. -
Triage LLM judge stays
codex|copilot(--backend choices=["codex","copilot"], L25558 — the opt-in judge for ambiguous diffs, default-off behindFLOW_TRIAGE_LLM). Do NOT add cursor there. Precise truth: with the LLM judge off (the default) cursor reviews use the deterministic whitelist — zero extra dependency. A cursor user who opts intoFLOW_TRIAGE_LLM=1gets thecodexjudge and therefore needs codex/copilot present — document this, do not auto-wire a cursor judge. (Keeping cursor out is the lean choice; the judge is a cheap separate concern.) -
Codex mirror: regenerate via
scripts/sync-codex.sh(never hand-editplugins/flow-next/codex/**); install/sync parity tests stay green.
run_cursor_exec(prompt: str, session_id: Optional[str]=None, *, spec: BackendSpec|None, repo_root: Path) -> tuple[str, str, int, str]→(result_text, returned_session_id, exit_code, stderr);session_id=None⇒ first call (no--resume); non-zero exit onis_error/CLI-failure/600s timeout; always invoked withcwd=repo_root.flowctl cursor check [--json] [--skip-probe]→{available, version, authed}(schema aligned to copilot'scheck).flowctl cursor impl-review <task> --base <ref> --receipt <path> [--spec cursor:<model>] [--json]flowctl cursor plan-review <spec> [--files ...] --receipt <path> [--json]flowctl cursor completion-review <spec> --receipt <path> [--json]flowctl cursor validate --findings-file <jsonl> --receipt <path> [--json]flowctl cursor deep-pass --pass <name> --primary-findings <jsonl> --receipt <path> [--json]- Receipt (impl):
{"type":"impl_review","id":"<id>","mode":"cursor","verdict":"SHIP|NEEDS_WORK|MAJOR_RETHINK","session_id":"<uuid>","model":"<model>","spec":"cursor:<model>","timestamp":"..."}— noeffortkey; same additive validator/deep/walkthrough blocks + rigor fields as copilot. - Spec grammar (verified):
cursor|cursor:<model>valid;cursor:<model>:<effort>→ ValueError ("does not accept an effort"); unknown model → ValueError listing valid models.
- NEW registry shape (model-yes / effort-no) — VERIFIED OK. Existing parser raises on effort, resolves
default_modelwith effortNone, no KeyError. Lock with tests. - Session = resume-only — VERIFIED. Caller must not fabricate a first-call
--resumeid; capture and persist Cursor's returnedsession_id, resume with it only when the receipt at the path hasmode == "cursor"(cross-backend → fresh). Mirrors copilot's Windows path, not its POSIX path. - Repo scoping — REQUIRED.
run_cursor_execruns withcwd=repo_root; add a test that invokes from a subdirectory and confirms the correct tree is reviewed. --trustmandatory headless or the CLI hangs on a trust prompt.- Read-only — VERIFIED.
--mode askrefused a "create a file" instruction; tree stayed clean. R8 assertsgit statusunchanged across a review. - Oversized prompts — VERIFIED on POSIX (60KB positional argv). cursor-agent takes the prompt as a positional argument (not stdin). Up to the threshold, pass it positionally. Above the threshold there is no safe path yet: copilot's temp-file step just reads the file back into argv (it does NOT bypass any cap), and cursor-agent stdin support is unconfirmed →
run_cursor_execmust raise an explicit "prompt too large" error above the threshold (with a test), NOT silently reuse the read-back-into-argv trick. Implement a stdin path only if cursor-agent confirms stdin input. (The WindowsCreateProcessWcap is where this bites first.) - Triage precision — see Architecture §8: deterministic by default; opt-in LLM judge stays codex/copilot and is a documented dependency for cursor users who enable it.
- Auth not configured →
checkand runners surface a clear error pointing atcursor-agentlogin /CURSOR_API_KEY(never a silent empty review). .resultempty /is_error:true→ backend failure (non-zero exit + stderr), never a false SHIP.- Effort must not leak — copying copilot receipt code literally risks writing
effort:"high"; cursor receipts must omiteffort(assert in tests). - Model-list drift — Cursor ships model strings without changelog (and auto-updates the CLI); document "keep synced with
cursor-agent --list-models", copilot-style note. - Not the host driver. Independent of the
CURSOR_AGENThost-platform path; works on any host withcursor-agentinstalled.
- R1:
cursoris inBACKEND_REGISTRYandVALID_BACKENDS;flowctl review-backendreportscursorfrom.flow/config.json+FLOW_REVIEW_BACKEND(its only two sources); per-taskdefault_reviewand--spec cursor:<model>resolve viaresolve_review_spec/ the review commands (NOTreview-backend). - R2:
BackendSpec.parse("cursor")/parse("cursor:gpt-5.5-high")succeed;parse("cursor:gpt-5.5-high:high")raises (effort rejected);parse("cursor:bogus")raises listing valid models;.resolve()fillsgpt-5.5-high, effortNone. - R3:
run_cursor_execshellscursor-agent -p --output-format json --trust --mode ask --model <m>withcwd=repo_root; on a first call it omits--resumeand returns Cursor's generatedsession_id; on continuation it passes--resume <session_id>; parses.result/.session_id/.is_error; returns non-zero on a 600s timeout. - R4:
flowctl cursor check [--skip-probe]reports availability + version + auth (authed) in text and--json, schema-aligned to copilot'scheck. - R5:
flowctl cursor impl-review <task> --base <b> --receipt <r>writes amode:"cursor"receipt (noeffortkey) and printsVERDICT=.... - R6:
cursor plan-review,completion-review,validate,deep-passdispatch throughrun_cursor_execand write the same additive receipt shapes as codex/copilot (mode:"cursor"). - R7: Re-review with an existing
mode=="cursor"receipt resumes via--resume <session_id>(using the persisted returned id); a cross-backend receipt starts fresh. - R8: A cursor review leaves the working tree unchanged. Unit-level:
run_cursor_execis asserted to pass--mode ask(read-only) and never an edit/write flag. Integration-level: an optional live smoke test gated oncursor-agentavailability runs a realcursor impl-reviewagainst a temp git repo and assertsgit statusis identical before/after (skipped when the CLI is absent — never a mocked clean-tree claim). - R9:
/flow-next:impl-reviewroutesBACKEND=="cursor"toworkflow-cursor.md;/flow-next:plan-reviewand/flow-next:spec-completion-reviewhandlecursor; every user-facing--review=rp|codex|copilot|nonestring includescursor. - R10:
flow-next-setupreview.backendconfig acceptscursorand spec formcursor:gpt-5.5-high. - R11: Tests:
test_cursor_run_exec.py(mock subprocess: success /is_error/ timeout / first-call-omits-resume / resume-passes-id / cwd=repo_root / mode-ask-flag / prompt-too-large),test_backend_spec.pycursor cases (model-yes/effort-no). Receipt-schemamode:"cursor"+ theeffort-absent assertion are the review-command tests (R14, task .2). Full Python suite passes. - R12:
scripts/sync-codex.shregenerated;cursorsurfaces in the codex mirror; install/sync parity tests pass. - R13: Docs chain updated at the concrete targets below; no version bump (batched), entries under
## Unreleased:- Repo:
plugins/flow-next/docs/flowctl.md(cmd list L14 + new cursor backend section),README.md(L44 / L253 / L290 backend lists),GLOSSARY.md(L29 "Backends:" list), rootCHANGELOG.md## Unreleased. - flow-next.dev:
src/content/docs/review/workflow.mdx(flip the live "coming next release" Cursor row → shipped) +review/receipts.mdx+install.mdxbackend enumeration +releases/changelog.mdx. NoFLOW_NEXT_VERSION/package.jsonbump in this spec — the docs-site version bump is release-only (batched), same rule as the plugin. No new page → navbars unchanged. Runpnpm build. - AI-x-SDLC:
guides/flow-next.md(L65 "(RepoPrompt, OpenAI Codex, GitHub Copilot)" → add Cursor),guides/code-review-tools-changelog.md. - GrowthFactors:
spec/05-cross-model-review.md(claim already lists Cursor — verify/tighten), re-renderdist/gf.html(+shd/shopfully/flooid) and the bundled~/work/AI-x-SDLC-Starter-Kit/resources/assets/code-factory-onboarding.html. - Obsidian vault: the cross-model-review / Skills Catalog / Release Timeline note(s).
- Repo:
- R14: Cursor
impl-review/completion-reviewreceipts carry the same rigor fields as copilot — confidence-rubric anchors, suppressed-finding counts, introduced-vs-pre_existing classification, unaddressed-R-ID surfacing, protected-path filtering — asserted by a parity test scoped to those rigor fields only, which also assertseffortis absent (cursor must never write it; effort is not a cursor field).
- No new host platform (Cursor-as-primary-driver already exists).
- No behavior change to
rp/codex/copilot/none, or to the trivial-diff triage judge (stayscodex|copilot). - CLI only. No Cursor MCP/API/HTTP —
cursor-agentsubprocess only. - No new review features. Pure parity port — same phases, receipt schema, verdict grammar.
- No new flow-next.dev page → both navbars untouched.
- No version bump / release (staged under
## Unreleased). - RP-style window/session UI not applicable — cursor is headless like codex/copilot.
Cursor is the obvious fourth backend: cursor-agent is installed, its headless
-p --output-format json contract is clean (.result + .session_id), it exposes
reviewer models the others can't reach together (gpt-5.5-high 1M, the
gpt-5.3-codex family, composer-2.5, Opus-4.8-thinking), billed against the
Cursor subscription, and the GF cross-model-review spec already advertises it.
Chosen approach: mirror copilot (fn-28) exactly. Closest structural match —
both headless CLIs with -p, JSON result, session UUID, --resume. The only new
wrinkle is the model-yes/effort-no registry shape, which the existing parser
already handles, so it costs a test not new code.
Rejected: (a) Cursor MCP/HTTP — heavier, no upside, inconsistent; (b) reusing
codex since both run GPT-5.5 — different CLI/auth/billing/strings, no
Composer/Opus-via-Cursor; (c) effort-translation layer — needless; Cursor's own
strings are canonical, stored verbatim.
- JSON contract parses (
type:result, is_error:false, result, session_id). - Real review on a planted diff (
a+b→a-b, missing zero-guard) found both bugs,VERDICT=NEEDS_WORK. - Read-only
--mode askrefused a file-write; tree clean. --resume <sid>recalled prior context headless (continuity confirmed).- 60KB argv prompt round-tripped on POSIX.
- Registry-only monkeypatch made
parse/resolve/lenient acceptcursor/cursor:<model>, reject effort, list models — zero parser edits.
Ran a cursor-agent gpt-5.5-high read-only plan-review of fn-74 against the
live repo (228s, ~102K input / 662K cache-read tokens). It verified the cited code
anchors and returned VERDICT=NEEDS_WORK with 4 valid corrections, now folded in:
(a) session is resume-only — capture Cursor's generated id, don't fabricate a
first-call --resume [R3/R7]; (b) cwd=repo_root required for repo scoping
[R3]; (c) triage "deterministic whitelist" was imprecise — true only with the
judge off; opt-in judge stays codex/copilot and is a documented cursor-user
dependency [§8]; (d) receipt parity — omit effort, carry copilot's rigor
fields [R14, R5, R11]. Proves the backend works end-to-end on a real spec.
Natural task seams: (1) flowctl core (registry + helpers + subcommands + handlers + dispatch + unit tests), (2) skill/setup wiring + codex-mirror regen, (3) docs + downstream chain.
Decomposed into 4 sequential tasks (a parity port is inherently code → wire → document); the flowctl core is split into proof + commands so each fits one /flow-next:work iteration.
.1— flowctl cursor foundation (M, no deps · early proof) — registry entry +require_cursor/get_cursor_version/run_cursor_exec+cursor check+ parser/run-exec tests. → R1, R2, R3, R4, R11.2— cursor review commands (M, deps .1) — 5 subcommands +cmd_cursor_*handlers + validator/deep dispatch + own-modemode:"cursor"receipts (resume-guard, rigor parity, clean-tree live test). → R5, R6, R7, R8, R11, R14.3— skill + setup wiring + codex mirror (M–L, deps .2) —workflow-cursor.md×2 + plan-review section +--reviewliterals (8 files) + setup config +sync-codex.shregen. → R9, R10, R12.4— docs + downstream chain (M, deps .3) — repo docs + flow-next.dev (flip the already-live "coming" Cursor row → shipped) + AI×SDLC + GF + vault. No version bump. → R13
Task .1 proves the cursor-agent contract end-to-end (run_cursor_exec + check + BackendSpec parse/resolve). Already de-risked by the spec's live smoke-tests + dogfood; if .1 nonetheless fails, re-examine the cursor-agent CLI contract before .2+.
- Cross-model review — adds a fourth reviewer backend (Cursor: gpt-5.5-high / codex / composer / opus), widening the disagreement surface and letting teams bill review to an existing Cursor subscription.
- Host agent IS the intelligence / lean flowctl — pure parity port: a ~6-line registry entry + mirrored helpers; no new architecture, no new skill/command, no second-LLM-spawn-from-flowctl.
| Req | Task(s) |
|---|---|
| R1 registry / resolve | .1 |
| R2 spec grammar (model-yes/effort-no) | .1 |
| R3 run_cursor_exec | .1 |
| R4 cursor check | .1 |
| R5 impl-review receipt mode:cursor | .2 |
| R6 plan/completion/validate/deep dispatch | .2 |
| R7 session-resume guard | .2 |
| R8 read-only / clean tree | .2 (live test) · .1 (--mode ask flag) |
| R9 skill routing + --review literals | .3 |
| R10 setup config | .3 |
| R11 tests | .1, .2 |
| R12 codex mirror | .3 |
| R13 docs chain | .4 |
| R14 receipt rigor parity | .2 |
fn-54 (eval-driven prompt optimization, 0 tasks) also edits the review workflow*.md files — coordinate on those edits if fn-54 activates concurrently. Not a hard dependency (spec-scout: standalone).