feat: Cursor host adapter, skill versioning, and release 0.5.0 - #15
Merged
Conversation
Records how Impasse could run under Cursor Agent (Desktop + CLI) without overclaiming independence. Explicitly marked "design proposal — NOT built" in the first line, per the repo's rule against describing planned capability in the present tense. Scope: a Cursor host adapter in SKILL.md / install docs; an independence workaround for Cursor's mixed-model host with assertion provenance always disclosed; and optional later backends (notably xAI Grok) so a Cursor session has a rival reviewer that is neither OpenAI nor Anthropic. The verify → reconcile → escalate protocol is unchanged. Revised after an Impasse review (impasse-cursor-host-adapter-review-001, --backend claude, 2026-08-20). Evidence for the limitations comes from Cursor's public skill docs (fetched 2026-08-20), Impasse's existing host-detection code, and a live probe in a Cursor session. Committed to its own branch so the plan is durable in git; it asserts no code change and nothing on main depends on it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBJxgqjWtXmstng2dGz7SG
…ases A+B)
Cursor implements the Agent Skills standard, so Impasse's scripts already run there.
What did not work was the INDEPENDENCE CLAIM. Cursor's model picker spans Anthropic,
OpenAI, Google, xAI and its own Composer family, and no environment marker reveals
which is driving a session, so every Cursor review reported `undetermined`.
CURSOR_AGENT=1 identifies the IDE, not the lab.
The route to a positive tier is the operator naming the model driving THIS session
via IMPASSE_HOST. That already worked. What was missing was DISCLOSURE.
- A cross_provider tier resting on confidence=="asserted" now carries a soft
independence_notice, parallel to the existing heuristic one: the label was taken
on the operator's word, Impasse verified nothing, and it goes stale silently if
they switch models mid-session. Success for an asserted tier is explicitly NOT
"notice is null" — it is "the tier is honest AND the operator can see it was
asserted." BEHAVIOR CHANGE: three tests asserted independence_notice is None for
an asserted cross_provider tier; updated to pin the new behavior while still
protecting what they originally did (a real DOWNGRADE notice can never be lost).
- `grok` is nameable as a host (_HOST_PROVIDERS["grok"] = "xAI"). No marker, never
auto-detected — assertion is the only way in — but naming it lets a Grok-driven
session label a Codex/Claude reviewer as genuinely cross-provider.
- scripts/install-cursor.sh: symlink-only, refuses to clobber a real directory,
idempotent, and tells the operator at install time that they must assert the host.
- Docs: a Cursor host adapter section in SKILL.md (skill-root resolution with no
CLAUDE_SKILL_DIR equivalent, the per-invocation assertion rule, consent without
AskUserQuestion, provisional timeout guidance), plus README install, environments,
host-detection, and a glossary entry for "asserted host".
Fixes from the cross-provider review of this diff (8 findings, all verified, all
fixed; reconciliation converged, 0 escalated):
- F001 the timeout recovery path printed a bare "that backend is cross_provider"
with no provenance caveat. Predates this work (the codex heuristic had the same
gap) but Cursor makes it reachable every session. _recovery_options now takes the
host confidence and names the basis.
- F002 `ln -s -- SRC DEST` into an existing directory does NOT fail — it silently
links INSIDE it and exits 0, contradicting the installer's own comment. Verified
on macOS. install-codex.sh had the identical defect; both now post-verify the end
state and fail loudly, and the absolute no-clobber claim is replaced with the exact
one plus the residual race stated openly.
- F003/F004 defects in the NEW TESTS: the "exhaustive" host matrix hardcoded its
override list and silently stopped covering grok (128 -> 144 cells, now derived
from KNOWN_HOSTS); the conflict check accepted the unsafe {codex, asserted}
outcome it claimed to reject; a missing installer took a skip branch and recorded
a PASS, so deleting the production file left the suite green.
- F005 docs claimed more than the probe established. Every Cursor claim is now
scoped to what was observed, discovery paths are attributed to Cursor's docs
rather than asserted, and "no full review has been completed from Cursor" is
stated plainly.
- F006 this change made the heuristic notice's own advice ("set IMPASSE_HOST to
confirm it") point at a different warning instead of silence. Reworded.
- F007 the comment claimed the backend side "can only ever be" OpenAI or Anthropic
— false about the future. xAI is still deliberately out of _KNOWN_PROVIDERS (no
backend ships; matches the Google precedent), but the limitation is now stated
exactly and the fail-safe direction is pinned by a test.
- F008 SKILL.md Guardrails carried a stale IMPASSE_HOST allowlist without grok.
NOT DOGFOODED. Nothing here has been run end to end from inside Cursor — this was
built from Cursor's published docs plus a probe of the scripts in a Cursor shell.
SKILL.md still lists only Claude Code and Codex as TESTED hosts, every Cursor claim
is marked provisional, and the proposal's dogfood checklist stays open (rollout step
2 marked OUTSTANDING). Phase C (a grok reviewer backend) is deferred by design.
Three gates green (443 checks). New-behavior tests verified to FAIL with the
production change surgically reverted, then pass restored.
Reconciliation: runs/cursor-host-adapter-review-002/reconciliation-result.json
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LBJxgqjWtXmstng2dGz7SG
… host
Three changes from operator feedback after the first real Cursor session, plus an
operator ruling on Composer, plus the fixes from a cross-provider review of all of it.
WHAT THE OPERATOR HIT
- Asked to "review the README against the code and make a plan to fix defects", a
Cursor-hosted run sent the README ALONE to the reviewer. Two distinct defects: it
reviewed the source material instead of doing the work and reviewing its own
output, and a RELATIONAL claim ("README vs code") was sent with only one side, so
the reviewer could not check the correspondence at all — yet would still return
confident, well-anchored findings. SKILL.md gains a "Choosing the artifact"
section stating both rules and a four-step preflight (write the question down;
list every thing it names and locate each in the bundle; confirm your own output
is present; state an ambiguous reading before spending the review).
- The session reported `undetermined` under Cursor's Auto. Investigated: Auto picks
a model PER REQUEST, and its pool contains BOTH reviewer providers. So asserting a
lab under Auto could label a same-provider reviewer as independent — the exact
overclaim this tool exists to prevent. SKILL.md, README and environments.md now
LEAD with "turn off Auto, pick a named model", with real model-ID prefixes.
COMPOSER — OPERATOR RULING
`composer` is now an attributable host (Anysphere), so a Codex/Claude reviewer scores
cross_provider against it instead of collapsing to `undetermined`. The reviewer argued
(critical) that this converts an acknowledged provenance uncertainty into a positive
claim, since Composer's base model is not fully public. The operator ruled that
Composer is a different lab and asked that the uncertainty be documented. Both were
honored: the tier stands, AND the caveat now rides on the notice the operator actually
reads — _HOST_TIER_CAVEATS attaches it inside independence_notice, so a caveated host
owes a disclosure even on a basis that would otherwise owe none. A prose caveat is the
wrong instrument for a claim made in code. Escalation recorded in the reconciliation.
`composer` (a model) and `cursor` (the Auto router) are deliberately separate hosts;
end-to-end tests through host_detection pin that Auto can never reach the composer
mapping.
ALSO: docs/proposals/cursor-agent-backend.md (NOT built) answers the operator's
question about reviewing on Cursor's own models. Feasible as a supervised
`cursor-agent -p` subprocess — NOT the in-IDE Task anti-pattern — with two
merge-blocking empirical prerequisites: plain `-p` has write+shell access so a
read-only mode must be pinned AND proven (--help claims it; that is not evidence),
and the tier must rest on the model that actually ran, not the one requested.
REVIEW FIXES (8 findings, all verified, all resolved)
- F002 the composer/Auto boundary was correct but only tested via literal strings;
end-to-end checks through host_detection added.
- F003/F004/F005 the backend proposal made resolved-model handling non-blocking,
labeled `--mode ask` "Verified" read-only while conceding elsewhere that --help
cannot establish it, and asserted a two-recipient data flow that --help cannot
source. All three corrected.
- F006 the artifact guidance was unenforced admonition; it now has a preflight.
- F007 one observed compat load was written up as "confirmed working" in four files;
all now scoped to Cursor Desktop / macOS / 2026-08-21 and explicitly not a
cross-build guarantee.
- F008 two new checks passed with production reverted; they are invariant guards and
are labeled as such, and the coupled end-to-end checks now stand behind the claim.
Three gates green (453 checks).
Reconciliation: runs/impasse-cursor-followup-independent-review-20260821/
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LBJxgqjWtXmstng2dGz7SG
Answers "which Impasse is running?" WITHOUT an obscure command, by putting the version where a reader already looks. The motivating failure was observed, not hypothetical: two install paths (~/.claude/skills/impasse and a Cursor-native symlink) served different code, a review ran against the stale one, and nothing said so. - VERSION at the skill root is the single source of truth. - Surfaced free: the SKILL.md header line (hosts that load the skill body have it in context) and frontmatter `metadata.version` — chosen over a bare `version:` key, which is unattested across all 31 skills installed on this machine, while Cursor's own skills already use `metadata:`. - SKILL.md instructs the host to STATE its version when a review begins, unprompted. - impasse_version on every machine surface: `mode` (run first, before any review), `estimate`, every result including failures, every metrics row, and a sibling run-meta.json beside each run record — kept records should be able to say which code produced them. A sibling file because both schemas are additionalProperties: false and host provenance is not the reviewer's output. - A +<commit> suffix when running from this skill's OWN git checkout. - CLAUDE.md gains a release procedure; CHANGELOG gains the three-independent-contracts note (skill / schemas / on-disk formats are versioned separately). The redundancy is safe only because it is gated: the suite asserts VERSION, the header line and the frontmatter agree, verified to fail on the exact release mistake it exists to catch. CI runs that gate on the committed tree. REVIEW FIXES (8 findings, all verified, all resolved) - F001 (the sharpest) the gate searched the whole frontmatter for /^version:/ and took the first match, so a top-level key could satisfy it while metadata.version disagreed. A gate satisfiable by the wrong line is not a gate. Now scoped to the metadata block, plus a check that `version` appears exactly once. - F003 `git -C` searches PARENT directories, so a skill copied into an unrelated checkout reported that repo's commit as its own — not a corner case, since ~/.claude is itself a repo. Reproduced, then fixed: provenance is refused unless the repo top level IS the skill root and VERSION is tracked in it. False provenance is worse than none. - F005 a non-UTF-8 VERSION raised UnicodeDecodeError out of a function called from the FAILURE path, where a traceback would replace the diagnosis. Now degrades to "unknown"; reads 256 bytes so trailing junk is rejected rather than truncated away; numeric components bounded. - F006 five production lines were unpinned — allowlist membership proves a field is permitted, not written. mode/estimate/failed-review are now driven for real. - F002/F004/F007 overstated claims, all narrowed: the gate covers the working tree and (via CI) the committed tree, not a copied install; announcing a version says WHICH COPY ANSWERED and does not compare installs, so catching a stale one still needs a reader who knows what to expect; hosts differ in when they load SKILL.md body text. - F008 the bare `except Exception` was already removed mid-review (it violated this repo's own rule about constructs that discard errors); the timeout claim is now exact — 2s per git call, cached, so a one-off first-lookup delay, not every call. Three gates green (468 checks). Reconciliation: runs/review-impasse-versioning-050-20260821/ Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBJxgqjWtXmstng2dGz7SG
Three host-error fixes prompted by watching a real Cursor-hosted run, plus the six
findings from a cross-provider review of them.
- THE RUNNER STAMPS artifact.revision. SKILL.md asked the HOST to set it from the
consent digest and nothing enforced that, so a host that forgot left the reviewer's
INVENTED value in the permanent record — the observed run stored
{"algorithm":"other","value":"caller-provided-bundle-2026-08-21"} and patched the
file by hand afterwards. That field is what stops findings being reconciled against
changed content, so a fabricated value defeats it silently. `kind` is stamped the
same way: the operator sets it, the reviewer only echoes it.
Bounded precisely: the runner corrects what the reviewer CANNOT KNOW; it never
invents what the reviewer never sent. A response missing `artifact`, or with a
non-object there, is left as received — `artifact` is schema-required while the
shape-check does not demand it, so filling it in would turn a response that must
fail validation into one that passes, inside data whose premise is that it is
untrusted. (Self-caught mid-review; the submitted diff still synthesized it.)
- lib.revision_from_digest() converts a manifest digest to {algorithm, value},
validating length PER ALGORITHM. Hosts were observed guessing three key names and
then recomputing the hash from a temp file.
- GUIDANCE: an analysis you could perform yourself is work too — with the ORDER that
makes it independent.
REVIEW FIXES (6 findings, all verified, all resolved)
- F001 (high, the serious one) my first attempt told the host to send its findings and
ask the reviewer to challenge them. That is ANCHORING: it discloses the hypotheses
before the reviewer forms its own view, so what returns critiques the framing rather
than looking independently — forfeiting the exact property Impasse provides. It also
describes how THIS review was requested. Replaced with an order: form your view,
send the EVIDENCE not your conclusions, compare afterwards; an adversarial pass on
your reasoning is a legitimate SECOND review, reported as anchored. The "no
disagreement means only one analysis happened" heuristic is deliberately NOT shipped
— two genuine analyses can agree, and treating agreement as suspicious would push a
host to manufacture disagreement.
- F002 `sha256:aaaaaaa` parsed as a SHA-256 digest, as did a 128-char value. An
abbreviation is the one thing an immutable identity must not be. Now exactly 64 hex
for sha256; 40 or 64 for git.
- F003 `revision` was corrected while `kind` was trusted, though both are caller-owned.
- F004 success and failure derived the identity from different sources while a comment
claimed they agreed. Computed once, passed to every failure envelope.
- F005 no test covered a missing/non-object artifact, a conflicting kind, or digest
boundaries — the paths where normalization can do harm. Three new fake modes and
four boundary checks.
- F006 the changelog cited an exact fabricated value and a 4-of-4 result with no
durable evidence in the repo, and repeated it in a production comment. Now scoped to
"one observed local run, reported by the operator", and no longer used to support
any general claim.
Three gates green (483 checks). Two revision checks verified to fail with the stamping
block removed; the reviewer independently confirmed that count.
Reconciliation: runs/impasse-independent-20260822-01/
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LBJxgqjWtXmstng2dGz7SG
All four were raised by a Cursor-hosted Impasse review of the README against the codebase, and re-verified against the live files before fixing. - Requirements named only Claude Code and Codex as hosts while Install documented Cursor and shipped install-cursor.sh — the README contradicted itself about whether Cursor is supported. Now lists all three, marking Claude Code and Codex as TESTED, which is the distinction that was actually intended. - The independence-ladder diagram showed three rungs where INDEPENDENCE_TIERS has four, so it described an ordering the code does not implement. `undetermined` now appears in its real position — second, ABOVE same-provider — with the reason: it means unknown, and an unknown pairing may well be cross-provider, whereas same-provider is a known correlation. It is also the rung a Cursor session sits on until the operator asserts a host. - The Audit trail section listed six reporting subcommands but omitted the two that carry the protocol itself: save-reconciliation (without which a run stores only the reviewer's raw findings, never what you decided) and escalations (which refuses to let you be asked to rule on a question stripped of its context). - The install comments claimed fixed ~/.codex / ~/.cursor destinations; both installers detect the root, may pick ~/.agents/skills, honor CODEX_HOME/--root, and refuse when the choice is ambiguous. Three gates green (483 checks). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBJxgqjWtXmstng2dGz7SG
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.
Brings
mainup to v0.5.0 — the repo's first numbered release — plus the Cursor host adapter and the host-error fixes that came out of running it for real.What's in it
undeterminedunless the operator asserts a host. That assertion now carries a soft notice saying the label was taken on their word and goes stale silently if they switch models.grokandcomposeras attributable hosts — neither is auto-detected.composer(Anysphere) carries a recorded caveat in the notice itself, not just the docs: its base-model provenance isn't fully public.v0.5.0—VERSIONis the single source of truth, surfaced inSKILL.md(which hosts load into context, so no command is needed) and on every machine surface. A gate asserts the surfaces agree.artifact.revision— the reviewer can't know the digest of the bytes it was sent, so anything it writes there is fiction. A real run stored exactly that.Review
Every substantive change here went through a cross-provider Impasse review and reconciliation: 8 findings on the adapter, 8 on the follow-up, 8 on versioning, 6 on the revision work, all verified against the code and resolved. One item was escalated and decided by the operator (whether Composer counts as a different lab).
Merge method
Fast-forward, not squash.
v0.5.0points at49d3684on this branch; squashing would rewrite it onto a new SHA and leave the release tag pointing at a commit unreachable frommain.mainis 0 behind, so a fast-forward is clean and keeps history linear.Not done
Cursor has not been dogfooded end to end — no full review has completed from inside it, so
SKILL.mdstill lists only Claude Code and Codex as tested hosts and the Cursor timeout guidance stays provisional.🤖 Generated with Claude Code
https://claude.ai/code/session_01LBJxgqjWtXmstng2dGz7SG