fix(cursor): repair crashing attribution suppression and register cursor for crew-dispatch - #10
Merged
Merged
Conversation
…ister cursor for crew-dispatch The freshly-landed cursor-agent adapter (PR #9) crashed at launch and could not be routed via crew-dispatch. Two cursor-scoped, additive/corrective fixes: Defect 1 (fatal): fm-spawn wrote a project .cursor/cli.json carrying `{"version":1,"attribution":{...}}`. cursor-agent validates that project config against a strict schema that accepts only `permissions`, so it rejected `version`/`attribution` with "Unrecognized key(s)" and dropped the pane to a bash prompt; the worker never started (the `attribution` block is only valid in the GLOBAL ~/.cursor/cli-config.json, which cursor rewrites at runtime and shares across workers). There is no CLI flag or env var to disable attribution. Replace it with a per-task git commit-msg hook that strips cursor's `Co-authored-by: Cursor <cursoragent@cursor.com>` trailer, reached only by the cursor worker through an env-injected core.hooksPath (git resolves a linked worktree's hooks from the shared common dir, so a per-worktree hooks dir would not fire). The hook lives under state/, touches no cursor config, never races a concurrent worker, preserves human co-authors, and is removed at teardown. Defect 2 (minor): add cursor to the crew-dispatch verified-harness set in fm-bootstrap so a config/crew-dispatch.json routing work to cursor validates clean, and treat cursor like opencode/kimi in effort validation (it has no effort flag). Scoped to crewmate/scout-facing lists only; the remote-secondmate lists and secondmate-liveness gate correctly continue to omit cursor, which was verified only as a local crewmate. Tests: rework the cursor-harness attribution tests to cover the commit-msg hook (trailer stripped, human co-authors and clean messages preserved) and the core.hooksPath env wiring, and to assert the crash-inducing .cursor/cli.json is no longer written; add crew-dispatch cases for cursor. Docs: correct the attribution mechanism in harness-adapters and record the live crash/fix proof.
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.
Intent
Fix two defects in the freshly-merged cursor-agent crew harness adapter (Quidge/firstmate PR #9), which is non-functional because cursor crashes at launch. Scope is strictly these two defects plus their tests/docs; explicitly NOT adding context7/MCP wiring (that is a separate task). No behavior change for any existing harness - changes are cursor-scoped and additive/corrective.
Defect 1 (fatal): fm-spawn wrote a per-worktree project .cursor/cli.json of {"version":1,"attribution":{...}} to suppress cursor's default commit/PR agent-attribution trailer (Co-authored-by: Cursor cursoragent@cursor.com). cursor-agent validates that PROJECT config against a strict schema that accepts ONLY
permissions, so it rejects version/attribution with "Unrecognized key(s)" and drops the pane to bash; the worker never starts. The attribution block is valid only in the GLOBAL ~/.cursor/cli-config.json, which cursor rewrites at runtime and shares across concurrent workers, so a global edit is unsafe; and there is no CLI flag or env var to disable attribution (verified empirically against cursor-agent 2026.07.23-e383d2b's bundled zod schema). Chosen fix: a per-task git commit-msg hook under state/.cursor-git-hooks/ that strips the Cursor co-author trailer, reached ONLY by the cursor worker via env-injected core.hooksPath (GIT_CONFIG_* exported before launch on the same channel as GOTMPDIR). This choice is deliberate because git resolves a linked worktree's hooks from the shared common .git/hooks dir (empirically proven), so a per-worktree hooks dir would not fire, whereas an env-injected core.hooksPath does. Deliberate constraints, all met: does not crash the launch; touches NO cursor config; makes no destructive or racy global-config edit; installed by fm-spawn and removed at teardown; strips only Co-authored-by trailers in cursor's agent namespace (@cursor.com/@cursor.sh) so it never interferes with legitimate commit messages or human co-authors. Mandatory live proof was performed against a real cursor-agent worker in a throwaway git repo (interactive launch in a separate tmux window, since a crewmate cannot launch the cursor TUI in its own pane): the old .cursor/cli.json reproducibly crashes the launch ("Unrecognized key(s)", pane drops to bash), and the new mechanism launches clean (pane_current_command=cursor-agent) while the worker's OWN autonomousgit commit --trailer "Co-authored-by: Cursor <cursoragent@cursor.com>"lands a commit whose body has NO trailer - proving the hook is the sole reason it is absent. Evidence recorded in docs/verification/runtime-backends.md. A unit test alone is intentionally treated as necessary-but-not-sufficient here because the trailer is server-driven and only a real worker emits the --trailer commit.Defect 2 (minor): cursor was missing from the crew-dispatch verified-harness set in fm-bootstrap.sh, so a valid config/crew-dispatch.json routing work to cursor was wrongly rejected as "unverified harness: cursor". Added cursor to that verified set, and (for validator correctness) to the no-effort branch of the dispatch effort check, since cursor has no effort flag - exactly like opencode/kimi - so a cursor profile carrying an effort is correctly rejected. Deliberate scoping decision: cursor is intentionally NOT added to the remote-secondmate lists (fm-remote-secondmate-control.sh, fm-remote-doctor.sh) or the secondmate-liveness gate in fm-bootstrap.sh, because cursor was verified only as a LOCAL crewmate, not for remote-secondmate use; those omissions are correct and preserved.
Tests/docs: reworked the cursor-harness attribution tests to cover the commit-msg hook behavior (strips the Cursor trailer, preserves human co-authors and clean messages byte-for-byte) and the core.hooksPath env wiring, and to assert the crash-inducing .cursor/cli.json is no longer written; added crew-dispatch cursor validation cases; corrected the attribution mechanism description in harness-adapters SKILL.md; recorded the live crash/fix proof in docs/verification/runtime-backends.md. All colocated tests, shellcheck 0.11.0, and the doc-audience check pass.
What Changed
.cursor/cli.jsonattribution config — which cursor-agent rejects against its project-config schema and crashes the launch on — with a per-taskcommit-msghook understate/<id>.cursor-git-hooks/that strips only cursor-agent'sCo-authored-by: <…@cursor.com/.sh>trailer;fm-spawn.shwrites and activates it via env-injectedGIT_CONFIG_*/core.hooksPath(gated to non-secondmate cursor workers), andfm-teardown.shremoves the hook dir and drops all.cursor/cli.jsoncleanup.cursorto the crew-dispatch verified-harness set infm-bootstrap.sh, and to the no-effort branch of the dispatch effort check (alongsideopencode/kimi) so a cursor profile carrying an effort flag is correctly rejected.core.hooksPathwiring, assert.cursor/cli.jsonis no longer written, add crew-dispatch cursor validation cases, and update the attribution-mechanism description in the harness-adapters SKILL plus the live crash/fix proof in the runtime-backends doc.Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ **Rebase** - passed
✅ **Review** - completed
✅ **Test** - passed
✅ **Document** - passed
✅ **Lint** - passed
✅ **Push** - passed