Skip to content

feat: Cursor host adapter, skill versioning, and release 0.5.0 - #15

Merged
windaddict merged 6 commits into
mainfrom
feat/cursor-host-adapter
Aug 23, 2026
Merged

feat: Cursor host adapter, skill versioning, and release 0.5.0#15
windaddict merged 6 commits into
mainfrom
feat/cursor-host-adapter

Conversation

@windaddict

Copy link
Copy Markdown
Owner

Brings main up 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

  • Cursor host adapter — the review path already ran under Cursor; what needed care was the independence claim. Cursor's model is operator-chosen and unattributable, so a session is undetermined unless 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.
  • grok and composer as 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.
  • Skill versioning + v0.5.0VERSION is the single source of truth, surfaced in SKILL.md (which hosts load into context, so no command is needed) and on every machine surface. A gate asserts the surfaces agree.
  • The runner owns 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.
  • Artifact-selection guidance — relational claims need both sides; an analysis you could do yourself is work; and send the evidence, not your conclusions.
  • Four README inaccuracies found by an independent review of the README against the code.

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.0 points at 49d3684 on this branch; squashing would rewrite it onto a new SHA and leave the release tag pointing at a commit unreachable from main. main is 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.md still 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

windaddict and others added 6 commits August 20, 2026 21:35
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
@windaddict
windaddict merged commit e94a092 into main Aug 23, 2026
2 checks passed
@windaddict
windaddict deleted the feat/cursor-host-adapter branch August 23, 2026 03:41
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.

1 participant