Skip to content

feat(cursor): the gate reaches Cursor at preToolUse and stop, from the live witness in agentseam 0.3.3 - #159

Merged
jothimani-rajendran merged 5 commits into
mainfrom
claude/cursor-gate
Sep 23, 2026
Merged

jothimani-rajendran merged 5 commits into
mainfrom
claude/cursor-gate

Conversation

@jothimani-rajendran

Copy link
Copy Markdown
Collaborator

What

Stacked on #158 (plugin gate). agentseam 0.3.3 records what a live probe of Cursor 3.21.18 showed: the generic preToolUse event fires for Write with the file's path and full content and honours a deny, and stop honours a followup_message that sends the agent back into the turn (a silent stop ends it, so that surface fails open). With the pin bumped, both the packaged gate and the repository-side sync reach Cursor at both surfaces; nothing about Cursor's reach is typed here, gate_reach("cursor") flips to ("Write", True) from agentseam's records.

  • Plugin package (gate_package): a vendor whose hook entry is the flat cursor shape gets cursor_entry documents under Cursor's version: 1 envelope, with no matcher and no failClosed. The package posture states the turn is not held: a refusal there is a follow-up message, once, and a hook that fails to answer lets the turn end.
  • Repository sync (in_agent, in_agent_merged): chock sync compiles a Cursor write fragment (pre-tool-use/cursor-write-hooks.json) and a Cursor stop fragment (stop/cursor-hooks.json) in that flat shape, rooted like its shell entries, and merges both into .cursor/hooks.json beside the shell guard under their own event keys. Cursor's row gains the stop column.
  • Runtime (write_gate): a stop that already re-entered once is not judged again; Cursor spells that loop_count, Claude Code stop_hook_active.
  • Pin: agentseam==0.3.3 in pyproject.toml and the hashed requirements/brand-assets.txt (hashes of the wheel and sdist PyPI serves). Runtime goldens, this repo's compiled tree and hook files resynced.

Tests: the Cursor package's hooks file shape; an end-to-end run of the bundled adapter against payloads shaped like the witnessed ones (BOM included): deny on a forbidden Write, allow on a clean one, followup_message naming the leaked file at stop, silence when loop_count is 1; Cursor's stop surface in test_stop_surface; the reach pin in test_plugin_gate_stores updated.

Definition of done

  • chock check → 0 errors, 0 warnings (pre-existing infos only)
  • chock check --only matrix passes; the matrix is unchanged (32 invariants present)
  • chock sync --repo . --check clean
  • chock check --only verify clean
  • Registry rescanned; no stale entries (no manifests touched)
  • pytest -q green: 1450 passed, 6 skipped
  • pytest acceptance/ -c acceptance/pytest.ini --rootdir=acceptance green (run against the 0.3.3 wheel; see note)
  • Existing artifacts: this repo's .cursor/hooks.json gains a preToolUse and a stop entry; guard entries unchanged
  • Touched manifests: none
  • ruff check . and ruff format --check . clean

Claims

  • No surface is described as enforcing more than it installs. surfaces.py now credits Cursor with stop (best-effort, from the matrix), docs/enforcement-surfaces.md marks the cell and says why it is a follow-up rather than a hold, and docs/agent-plugins.md states the package's reach in the same words.

Note: at the time of opening, PyPI's simple index had not yet propagated 0.3.3 (the JSON API and the files had). If the first CI run fails to resolve agentseam==0.3.3, it is that lag; a re-run resolves it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CzNYfzP8ymU3r4JB9Sz8Ha


Generated by Claude Code

agentseam 0.3.3 records what a live probe of Cursor 3.21.18 showed:
the generic preToolUse event fires for Write with the file's path and
full content and honours a deny, and stop honours a followup_message
that sends the agent back into the turn. Both the packaged gate and
the repository-side sync now reach Cursor at both surfaces.

- gate_package: a vendor whose hook entry is the flat cursor shape
  gets cursor_entry documents under its own envelope, with no matcher
- in_agent: Cursor's write and stop fragments in that flat shape,
  rooted like its shell entries; in_agent_merged wires both into
  .cursor/hooks.json under their own event keys
- write_gate: a stop that re-entered once (loop_count) is not judged
  again, the way stop_hook_active already guards Claude Code
- cursor plugin posture states the turn is not held, only followed up
- pin agentseam==0.3.3; runtime goldens, this repo's compiled tree and
  hook files resynced; docs, tables and changelog updated
- tests: the Cursor package's hooks file shape, an end-to-end run of
  the bundled adapter against the witnessed payloads (deny, follow-up,
  silent on re-entry), and Cursor's stop surface

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Claude <noreply@anthropic.com>
Hashes are those of the wheel and sdist PyPI serves for 0.3.3.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Claude <noreply@anthropic.com>

jothimani-rajendran commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator Author

Status: green and mergeable.

The first CI runs were red for a reason outside this PR: every job that installs the package failed with No matching distribution found for agentseam==0.3.3 while PyPI's simple index lagged the published release by about forty minutes (PyPI was also returning 503s on the project page in that window). Once pip resolved 0.3.3 I re-ran the failed jobs.

One real finding came out of that re-run: figures drifted, because the surfaces fan-out counts the agents that reach the turn's end and Cursor makes seven. Regenerated with docs/figures/make_*.py and pushed in f69d0f9 (merged on top of the branch update from main).

  • Definition-of-done checks pass locally, including the acceptance suite against the 0.3.3 wheel
  • PyPI resolves agentseam==0.3.3; failed jobs re-run
  • figures drift fixed (seven stop agents)
  • Full CI green on the current head (e3928b1); no open review threads

Generated by Claude Code

@jothimani-rajendran
jothimani-rajendran marked this pull request as ready for review September 23, 2026 11:00
@jothimani-rajendran
jothimani-rajendran changed the base branch from claude/plugin-gate to main September 23, 2026 11:00
jothimani-rajendran and others added 3 commits September 23, 2026 07:00
Cursor joins the stop surface, so the derived count in the fan-out
figure moves from six to seven, as CI's drift check requires.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Claude <noreply@anthropic.com>
@jothimani-rajendran
jothimani-rajendran merged commit a7f5e89 into main Sep 23, 2026
19 checks passed
@jothimani-rajendran jothimani-rajendran mentioned this pull request Sep 23, 2026
11 tasks
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.

2 participants