Skip to content

Cursor Cloud: dispatch adversarial-reviewer via Task; prefer Claude - #2272

Merged
dem-extra1 merged 56 commits into
mainfrom
cursor/cursor-claude-adv-review-32a3
Aug 26, 2026
Merged

Cursor Cloud: dispatch adversarial-reviewer via Task; prefer Claude#2272
dem-extra1 merged 56 commits into
mainfrom
cursor/cursor-claude-adv-review-32a3

Conversation

@dem-extra1

Copy link
Copy Markdown
Collaborator

Closes #2270.

Cursor Cloud already exposes Task with subagent_type: adversarial-reviewer.
A non-Claude conductor that treats that route as unavailable, and writes an
author-assembled fallback, skips a reachable reviewer.

GitHub claude-review skipping for missing CLAUDE_CODE_OAUTH_TOKEN / quota
is a different channel from Cursor's listed Claude models on Task.

This PR records:

  • Dispatch Task adversarial-reviewer (foreground, read-only) in a Cursor session.
  • When the conductor is not Claude and a Claude model is listed, pass that Claude model.
  • Post the child's structured report as the fallback comment, not an author wrap.

Out of scope: sequential all-provider quorum (#2256);
enumerating providers at session start (#2253).

Open in Web Open in Cursor 

cursoragent and others added 4 commits August 26, 2026 05:06
Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
…adv-review-32a3

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
A skipped GitHub claude-review is a different channel from Cursor Task.
When the conductor is not Claude, pass a listed Claude model so the
review is cross-vendor on blind spot as well as independent of intent.

Closes #2270.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
Hedge that Cursor does not filter the persona tools list. Name the
Task model parameter. Cite self-review-fallback for the cross-vendor
half. Scope the dispatch to a repo that ships the persona. Move the
fragment pointer below the CLI pre-push-guard paragraph.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
@dem-extra1
dem-extra1 marked this pull request as ready for review August 26, 2026 06:00
@github-actions

This comment has been minimized.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary of Changes

Four files, 66 insertions, 2 deletions, on top of origin/main at commit 85840b82.

memories/cursor.md gains a section, "Cursor Cloud Task dispatches adversarial-reviewer" (lines 88-135): a Cursor Cloud session rooted in a repo shipping .claude/agents/adversarial-reviewer.md can dispatch that persona through Task; a non-Claude conductor should pass a listed Claude slug on model; the persona's tools: frontmatter is instruction-level on Cursor Cloud rather than a harness filter; a skipped GitHub claude-review is a different channel; a measured case on PRs #2265/#2266; and a five-item Do/Don't pair.
memories/MEMORY.md extends the cursor.md index row to name the new content.
AGENTS.md adds an "Adversarial review" bullet (lines 390-396) to the Cursor Cloud caveats list.
shared/workflow/adversarial-self-review.md adds a paragraph (lines 52-58) naming Cursor Cloud Task as the subagent dispatch and pointing at memories/cursor.md, and disambiguates one existing sentence ("Note what that CLI fallback does to the pre-push guard").
No tests, hooks, scripts, or manifests change.

Verification run: check-links.py (2400 links, clean), validate-skills.py (clean), check-memory-file-size.py (clean), check-stale-records.py (clean), markdownlint-cli2 0.22.1 (0 errors), check-context-closure.py (the touched fragment is not in the always-loaded closure). Added lines are ASCII-only. The pre-push-guard claim checks out: SKIP_WITHOUT_TOOL_RESULT in .cursor/hooks/adapt-claude-hooks.py does contain no-push-without-self-review.py. The cited artifacts check out: issue #2270 is open with the quoted done-criteria, PRs #2265 and #2266 both carry author-assembled "Fallback self-review" comments from cursor[bot], and PR #2272's only comment is the claude-review skip notice naming CLAUDE_CODE_OAUTH_TOKEN. Per this repo's claude-review.yml review-scope addendum, cosmetic raw-source line wrapping is out of scope and is not raised below, although scripts/semantic-line-breaks.py --base origin/main would reformat every changed paragraph in all three prose files.

Findings

  1. [Defect] shared/workflow/self-review-fallback.md lines 170-176 are left stating "the pairing above is now Copilot and delegate-to-codex, and nothing else" and "delegate-to-codex is the only cross-vendor reviewer this corpus can dispatch itself", while memories/cursor.md lines 108-110 assert that a Claude child on a Grok diff "buys independence of vendor blind spot, which is the cross-vendor half of [self-review-fallback]" --- citing as authority the one fragment whose exclusivity claim this diff falsifies. A non-Claude Cursor conductor reading that fragment concludes the only self-dispatchable cross-vendor reviewer is codex and skips the Claude Task route, which is exactly the behaviour issue Cursor Cloud: dispatch adversarial-reviewer via Task; prefer Claude when the conductor is not Claude #2270 was filed to correct. rg -n "Grok|conductor is not Claude|non-Claude" shared/ returns only the new line in adversarial-self-review.md, so nothing anywhere in shared/ qualifies the "only" for a non-Claude conductor.

  2. [Defect] The route the diff endorses cannot hold the property the endorsing fragment requires of it, and the diff records the mismatch without resolving it anywhere a reader of either artifact will hit it. shared/workflow/adversarial-self-review.md line 38-40 requires "Read-only. ... A reviewer that can edit turns a finding into a silent fix", and .claude/agents/adversarial-reviewer.md states "with no Edit or Write access, so it can never alter code" (line 3) and "You have no Edit or Write access" (line 63). memories/cursor.md lines 97-99 measure the opposite on this route --- the child "still received Write schemas" --- and this dispatch confirms it: I hold Write, StrReplace, Delete, and EditNotebook schemas right now. The new fragment paragraph (lines 52-58) nonetheless presents Cursor Task as "the subagent dispatch" and enumerates only the pre-push-guard deviation in its pointer, and the memory's five-item Do/Don't pair says nothing about write capability. Concrete failure: a Cursor Task reviewer can edit the worktree it is reviewing, turning a finding into a silent fix, and a child that reads a false sentence about its own tool list has grounds to treat that sentence as stale. Either correct the persona's two false self-descriptions, or add a Do/Don't that makes read-only a briefed and verified constraint on this route (for example, state it in the brief and check git status after the dispatch).

  3. [Edge Case] The dispatch recipe omits the foreground requirement. shared/workflow/adversarial-self-review.md lines 34-36 require "Foreground, not background ... A background dispatch returns an agent id rather than a report", and issue Cursor Cloud: dispatch adversarial-reviewer via Task; prefer Claude when the conductor is not Claude #2270's done-criteria ask the memory to state the dispatch is "(foreground, read-only)". The new memory section enumerates subagent_type and model, ends with "That is the dispatch", and never names foreground or the parameter that controls it; the new fragment paragraph does the same. The section is careful to flag one unmeasured default ("the dispatch default when model is omitted was not separately measured") and silent about the background default. Concrete failure: a background dispatch yields the identity-only tool_result documented in the very next section of the same file (lines 137-147), which is the input to the author-composed fallback comment this diff's own Don't bullet forbids.

  4. [Convention] One rule is stated four times inside 45 lines of memories/cursor.md: lines 94-95 ("Pass model from the listed Claude slugs when the conductor is not Claude"), lines 104-105 ("When the conductor is not Claude and a Claude model is listed for Task, pass that Claude model via model"), the Do bullet at lines 127-128, and the Don't bullet at lines 131-132. Lines 104-105 are a pure restatement of lines 94-95 --- the new content in that paragraph is the intent-versus-blind-spot rationale that follows --- so a later edit that revises one statement leaves three stale, and the repetition buries the section's one genuinely novel measurement (the Write schemas). shared/workflow/challenge-redundant-content.md governs; the Do/Don't pair itself is required by convention and is not the redundancy at issue.

  5. [Convention] Ambiguous pronoun in two places: AGENTS.md lines 394-395 and the memories/cursor.md Do bullet at lines 127-128 both read "when ... a Claude model is listed for Task, pass it on model", where the nearest grammatical antecedent of "it" is Task rather than the intended Claude model. This is the exact pattern shared/writing/ambiguous-reference.md names, and the remedy is already written in the same file at line 105 ("pass that Claude model via model").

  6. [Convention] Forward reference: the last Don't bullet (memories/cursor.md lines 133-135) points at "Cursor Cloud Task tool_result is identity-only", a section that begins at line 137 --- after the pointer. shared/writing/forward-references.md states the test is positional rather than textual and prefers reordering, then a precise working anchor link; a bare quoted section title is also inconsistent with the linking convention the same section uses for self-review-fallback at line 110 and with the AGENTS.md "File formatting & links" rule. Placing the new section after the tool_result section resolves it and puts the referenced mechanics ahead of the rule that depends on them.

  7. [Factual Error] The resolution mechanism is stated with more precision than the cited measurement can support. memories/cursor.md lines 90-93 attribute the reviewer's availability specifically to a repo that ships .claude/agents/adversarial-reviewer.md, but this tree also ships .opencode/agents/adversarial-reviewer.md (find . -name "adversarial-reviewer*" returns both), so a single observation in this repo cannot isolate which path Cursor Cloud read. Neither plugin manifest declares an agents field (.cursor-plugin/plugin.json, .claude-plugin/plugin.json), and this environment has no ~/.claude/agents or ~/.cursor/agents and no persona copy under ~/.cursor/plugins, so the repo-rooted attribution is plausible --- but the specific filename is not what was measured. The consequence is a wrong prediction for a repo that ships only one of the two directories, which is the situation ai-config#1921 is about; the adjacent unmeasured item on line 120-122 is hedged, and this one is not.

Verdict: Needs more work

Reviewed-Commit: 85840b8

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

cursoragent and others added 3 commits August 26, 2026 06:16
Qualify the self-review-fallback exclusivity claim to the CLI axis so a
non-Claude Cursor conductor is not told that codex is the only
self-dispatchable cross-vendor reviewer. Name foreground dispatch, hedge
that Cursor Task still grants Write schemas, and drop the restated
pass-model paragraph plus the forward pointer at the tool_result section.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
Drop the omit-model vendor assertion the same section called unmeasured,
stop citing #1921 for a which-path question that issue does not track,
and stop calling codex the only self-dispatchable CLI: opencode is
another. Name the 2026-08-25 dispatch instead of "this session", and
state that this conductor's Task schema listed run_in_background and
did not list isolation.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
A Claude Task child of a Grok conductor is independent of the author,
not of a GitHub claude-review primary, so it does not belong in the
Copilot/codex pairing. State that Cursor's adapter skips the pre-push
guard, name the Task-to-Agent mapping that trips the worktree warning,
and keep the dispatch recipe in memories/cursor.md rather than
restating it in the always-loaded fragments.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
cursoragent and others added 4 commits August 26, 2026 06:53
git status is clean over unpushed commits, so it cannot show a child
that committed. Record HEAD before the dispatch and compare it after.
Qualify AGENTS.md: Cursor's adapter skips the pre-push guard. Name
opencode as a CLI whose skill excludes this work, not as "only"'s
exception. File #2276 for the unmarkable isolation warning.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
Use 2026-08-25 PDT for every measurement this branch records, matching
the wraps on #2265/#2266. Retire the leftover "only cross-vendor
reviewer" sentences in the retired Antigravity skills. Name opencode as
outside the Copilot/codex pairing, with its OpenRouter caveat. Drop the
forward "below" pointer. Justify passing Claude as vendor independence
from the author, not as the intent-independence floor.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
The Task tool_result is identity-only, so a HEAD comparison that names
Reviewed-Commit has to say how to get that line: a harness paste of
the report, or batch-fetch-details. Compare the push refspec when it
is not HEAD. Hedge the Desktop guard skip: only the project adapter
path omits it. Drop the tools: causal claim the two persona copies
cannot support.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
The posted PR comment is a record, not a gate. If the harness paste
and batch-fetch-details both lack Reviewed-Commit, do not push.
Hedge the AGENTS.md Task claim on the conductor listing Task. Keep
git status as the dirty-tree check beside the HEAD comparison.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
cursoragent and others added 2 commits August 26, 2026 07:31
A Needs more work report whose fingerprint matches HEAD is not a
push. batch-fetch-details needs includeTranscripts true or it writes
no transcript. File #2281 for the persona Write-schema leak. Unify
the Task-lists-adversarial-reviewer precondition.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
A Claude Code session whose subagent tool is Task still has the
guard. Name Cursor Cloud in the sentences. Enabling Desktop
third-party Claude hooks beside the project adapter runs the
native guard and denies every push. Drop "and nothing else" from
the Copilot/codex pairing.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

ARD of the Claude child report on fa4fbbc4 (HEAD is now db383b28):

  1. Address --- named Cursor Cloud in the sentences, not only the heading.
  2. Address --- replaced "On that surface" with "On Cursor Cloud".
  3. Address --- Desktop: enabling both runs the native guard, which denies every push (dated 2026-08-25 PDT).
  4. Address --- dropped "and nothing else" from the Copilot/codex pairing sentence.
  5. Rebut --- the Do/Don't pair is required; the identity-only section stays the retrieval mechanics.
  6. Rebut --- the recipe names the refspec gap; Cursor adapter: synthesize tool_result from postToolUse.tool_output #2241 tracks retiring the hand procedure.
  7. Rebut --- the self-review section already points at memories/cursor.md; the caveats bullet is the compact env note.
  8. Rebut --- suggestion weight; CI new-line-breaks is clean.

No Claude Ready-for-merge verdict evaluates db383b28. Blocked on review. Not mergeable.

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary of Changes

The branch documents a Cursor Cloud route for the mandatory adversarial self-review and adjusts three sites that described delegate-to-codex as the sole dispatchable cross-vendor reviewer. Seven files, +145/-10.

  • memories/cursor.md gains a 102-line section, "Cursor Cloud Task dispatches adversarial-reviewer", covering the foreground dispatch, the flag-unassigned-worktree.py warning, a hand procedure for obtaining and comparing Reviewed-Commit, and a model rule for a non-Claude conductor, plus Do/Don't bullets. A second hunk records a recurrence of the author-wrap failure on two PRs.
  • memories/MEMORY.md updates that file's index row.
  • AGENTS.md narrows the pre-push-guard sentence to Claude Code, adds the Cursor adapter skip plus Desktop hook-pairing advice, and appends an "Adversarial review" bullet to the Cursor Cloud caveats list.
  • shared/workflow/adversarial-self-review.md adds a "Cursor Cloud has a subagent dispatch" block and disambiguates one pronoun in the preceding paragraph.
  • shared/workflow/self-review-fallback.md adds a two-line Cursor Cloud pointer and rewords the delegate-to-codex description.
  • skills/agy-review-workflow/SKILL.md and skills/antigravity-review-workflow/SKILL.md carry the same reword.

Repo gates all pass at this head: validate-skills.py, check-links.py (2404 links), markdownlint-cli2 (575 files, 0 errors), check-memory-file-size.py, and the semantic-line-break gate's two rules checked by hand against the added lines. The four cited issues (#2241, #2270, #2276, #2281) all exist and are open with matching titles. Deleted lines carry no load-bearing content beyond the reworded claims discussed below. The .claude/agents/ tools: field, the .opencode/ permission: edit: deny, SKIP_WITHOUT_TOOL_RESULT, the Task-to-Agent mapping, and READ_ONLY = {"Explore", "Plan"} were each verified against source and are stated correctly.

Findings

  1. [Defect] shared/workflow/adversarial-self-review.md:52-61 --- the new block's entry conditions are keyed on the tool being named Task, not on the session being Cursor, while the block asserts "On that surface the pre-push guard never runs." A Claude Code session whose subagent tool is Task satisfies the stated condition and is precisely what the guard covers: hooks/no-push-without-self-review.py:130 sets AGENT_TOOLS = {"agent", "task", "invoke_subagent"}, and read_latest_review admits a verdict from a Task call's tool_result. Only the bold lead-in "Cursor Cloud has a subagent dispatch" scopes the passage, and a lead-in is not a condition. The concrete failure: such a session reads that its guard does not run, and then reads "Do not prefix ALLOW_UNREVIEWED_PUSH=1 after a Task dispatch just ran" --- which contradicts the paragraph five lines above (lines 46-50), where the override is explicitly reserved for "a push whose verdict the guard cannot check, not only a push with nothing to check", the stale-persona-definition case included. Put the Cursor condition in the sentences rather than in the heading.

  2. [Defect] shared/workflow/adversarial-self-review.md:55 --- "On that surface" has "a Grok conductor" as its nearest grammatical antecedent, not Cursor Cloud. This is the fluent-wrong-reading case shared/writing/ambiguous-reference.md describes: it reads perfectly and yields a narrower fact than intended (the guard's absence is a property of the Cursor adapter, not of the conductor's model). The remedy that fragment prescribes is to name the referent rather than reword around the demonstrative.

  3. [Factual Error] AGENTS.md:265-267 --- "pairing both sources is not a second check" is contradicted by this repo's own record, and the correction runs the dangerous way. scripts/install-hooks.py registers the catalog into ~/.claude/settings.json; hooks/hooks.json:341 carries no-push-without-self-review.py on PreToolUse; and .cursor/hooks/adapt-claude-hooks.py:59-66 states the reason the adapter skips it --- "These scripts fail closed or loop until they see one, so running them on Cursor is a lockout rather than a no-op." So on Desktop with third-party Claude hooks enabled the guard does run natively, and the recorded outcome is a session-wide lockout on git push, not an absent check. "Not a second check" reads as harmless-but-useless and so understates the consequence the sentence exists to prevent. The sentence also carries no vintage while the clause immediately before it does, which shared/writing/timestamp-volatile-claims.md treats as a finding in its own right for a harness-behaviour claim.

  4. [Factual Error] shared/workflow/self-review-fallback.md:177-178 --- the diff removes the exclusivity claim from one sentence and leaves the equivalent claim standing two lines above it, at line 172: "So the pairing above is now Copilot and delegate-to-codex, and nothing else." If exclusivity was false, it is false there too: shared/workflow/adversarial-self-review.md:43 names delegate-to-opencode as "the same move and a stronger one" alongside codex, and skills/delegate-to-opencode/SKILL.md:308-309 calls an opencode model "a cheap cross-family second reader" whose agreement "is governed by [self-review-fallback]'s cross-vendor section" --- a direct back-reference to the passage that now says nothing else exists. The commit message reports sweeping the sibling claims; rg "only cross-vendor" returns zero hits across the tree, which is exactly the failure shared/workflow/grep-is-not-coverage.md names --- the surviving claim is spelled differently, and a phrase grep matches strings while coverage is a claim about ideas.

  5. [Convention] memories/cursor.md --- the new section restates content that already lives beside it, measured rather than eyeballed per challenge-redundant-content.md's instrument rule. A normalized 6-gram comparison of the new section (729 words) against the adjacent "Cursor Cloud Task tool_result is identity-only" section (307 words) returns 4 overlapping runs: already carries summary / findings / verdict, cursor cloud batch fetch details with, adapter skips no push without self review.py, and a harness paste of the child s report. A 5-gram comparison of the new section's own prose (520 words) against its Do/Don't block (203 words) returns 7 runs, restating the whole record-HEAD, git status --short, obtain-Reviewed-Commit, compare-and-re-check procedure rather than summarizing it. Applying the litmus test, the cross-section copies look consolidatable to one statement plus a cross-reference with nothing lost; the intra-section duplication is the weaker of the two.

  6. [Edge Case] memories/cursor.md:121-124 --- the hand comparison is offered as what stands in for the skipped guard, and it names only the refspec gap. The guard refuses several other classes a sha comparison cannot see: --all, --branches, --mirror, --tags, --follow-tags (PUSH_OPTS_INDETERMINATE), push.default=matching, a configured remote.<name>.push, remote.<name>.mirror, --recurse-submodules=on-demand|only, --config-env, and --git-dir/--work-tree/GIT_DIR redirects. A conductor that follows the recipe exactly, on a bare git push under a long-lived push.default=matching, compares one matching sha and ships branches the reviewer never read --- and nothing in the procedure reports that it examined only one ref. Relatedly, the recipe is written as a standing procedure with no note that it is interim; the same file already cites open issue Cursor adapter: synthesize tool_result from postToolUse.tool_output #2241 ("Cursor adapter: synthesize tool_result from postToolUse.tool_output") at line 69 as the change that would retire it.

  7. [Convention] AGENTS.md:397-404 --- the "Adversarial review" bullet is appended to the Cursor Cloud section's "Non-obvious caveats worth knowing" list, whose other six entries (Lint, Test, Build, Run, Submodule, pre-commit) are all build and tooling environment quirks. A dispatch instruction is a different kind of item, and it now sits roughly 130 lines from AGENTS.md's own "Every self-review is an adversarial review by a separate subagent" section, which this same diff edits and which never mentions that a Task route exists. The failure that produces: a Cursor Cloud session reading the self-review section learns only that its pre-push guard is skipped, and has no reason to scroll to an environment-caveats list to discover the dispatch it is required to make.

  8. [Convention] Semantic line breaks, raised as a suggestion rather than a blocker, per shared/writing/semantic-line-breaks.md's own instruction to reviewers. The CI gate is clean --- I confirmed no added line packs two sentences and no added line reaches 80 markup-stripped characters with a mid-line semicolon --- so this is about the 60-to-80 clause-boundary guidance only. Several added lines wrap around 50 characters and break mid-phrase: AGENTS.md splits "leave third-party Claude hooks off while this / project adapter is enabled" and "can dispatch that persona / through Task"; memories/cursor.md splits "proof the child did / not commit" and "for every self-review in a Cursor / session".

Verdict: Needs more work

Reviewed-Commit: fa4fbbc

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

cursoragent and others added 7 commits August 26, 2026 07:59
The Desktop-lockout sentence was an unverified claim: native Claude
hooks key on Bash, and Cursor's Shell path is not that adapter.
Strip it from AGENTS.md. Commit before dispatching, parse the last
line-start Verdict then the first Reviewed-Commit after it, and treat
a child error as the CLI-fallback case rather than as a forbidden
override.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
A truncated report with an open fence is no verdict to the guard and
was a matching Ready under the hand recipe. State that rule, drop
the "instead" in AGENTS.md, and stop forbidding the override for a
reason the fragment already rejects.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
A nested fence of different lengths is the shape the guard's scanner
exists to catch. Pairing by count reads Needs more work as Ready.
Name the close rule, and treat any push that is not a single named
ref as uncovered rather than enumerating a subset of the guard.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
A matching HEAD sha does not cover tags or extra branches a config
flag would add. git push --dry-run is the resolution step the guard
exempts from review. Scope the adapter skip to Cursor Cloud so
"active hook path" cannot be read as covering a paired Desktop
native path.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
The adapter skip is a property of the adapter, not of Cloud.
A dry-run must use the same argv as the push, and an empty or
failed dry-run is not coverage. On Cursor Cloud the override
prefix is inert even after a Task error.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
A fenced example sha that names HEAD is the hole the guard already
measured. Search verdict and fingerprint on the same blanked text.
A new-branch dry-run has no sha; the source ref, left of the arrow,
is what ships.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
The Cursor Cloud inert-prefix sentence had stolen the override
case list. Put it after the list. Record the branch name so a
new-branch dry-run whose source is HEAD is covered by the sha,
and require a paste to be the child's own message.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

ARD of the review of fa4fbbc4 (and the later Cursor Task children of db383b28 through 9ca5b967). HEAD is now 4ba85089.

# Disposition Note
1 Defect (Task vs Cursor) Address Cursor Cloud is named in the sentences, not only the heading.
2 Defect ("On that surface") Address Named Cursor Cloud.
3 Factual Error (Desktop lockout) Address Dropped the unverified lockout. Skip is the adapter's, not Cloud-only.
4 Factual Error (exclusivity) Address Pairing is Copilot and delegate-to-codex; no "nothing else".
5 Convention (redundancy) Rebut Dispatch section holds the procedure; identity-only holds retrieval.
6 Edge (refspec) Address Same-argv git push --dry-run; fail closed on empty/fail; source ref left of ->.
7 Convention (caveats vs self-review) Address Dispatch lives in the self-review section; caveats bullet dropped.
8 Convention (SemBr) Rebut CI new-line-breaks is clean.

Later children of db383b28+ added fail-closed holes the first review did not: unclosed and nested fences, fingerprint search on blanked text, commit-first, HEAD mismatch, dirty tree, Needs work, provenance of a paste, override list attachment, recorded branch name. Those are in 4ba85089.

Rebutted: expanding always-loaded CLAUDE.md for the same skip (context budget); naming delegate-to-opencode in the Copilot pairing (that skill screens judgment work out).

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

A paste of an author-composed Summary/Findings/Verdict block
is the wrap this file already records. batch-fetch-details
discharges the check. Prefix-match the fingerprint, skip a
trailing Approved, and treat Everything up-to-date as shipping
nothing rather than as a mismatch.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary of Changes

The branch documents a Cursor Cloud route for the mandatory adversarial self-review and adjusts four sites that previously assumed the Claude Code pre-push guard.

Claims I checked and found true of this tree: SKIP_WITHOUT_TOOL_RESULT in .cursor/hooks/adapt-claude-hooks.py contains no-push-without-self-review.py and the skip is unconditional on both the preToolUse and stop paths; .cursor/hooks.json binds all four events to the adapter, so the guard never runs on Cursor Cloud and ALLOW_UNREVIEWED_PUSH=1 (read only by that one script) is genuinely inert; the adapter maps Task to Agent unless subagent_type is explore/plan/shell, flag-unassigned-worktree.py is registered with matcher Agent and its READ_ONLY set is {Explore, Plan}, so the warning does fire on every such dispatch; parse_report blanks fences before both the verdict and the fingerprint searches and treats an unclosed fence as no verdict; FENCE/_blank_fences closes only on the same character at least as long, scanning rather than pairing by count; VERDICT_LINE is line-anchored, optionally a heading, and accepts Ready for merge, Needs more work, and Needs work; the sibling _argv_push exempts --dry-run/-n, and no-clobbering-push.py also exempts dry-run, so the same-argv dry-run is runnable; .claude/agents/adversarial-reviewer.md carries tools: while .opencode/agents/adversarial-reviewer.md uses permission: edit: deny, and this dispatch did receive Write schemas (2026-08-26), corroborating #2281; bcIds and includeTranscripts are real parameters and cloudAgentBcId is documented on Task results; issues #2241, #2270, #2276, #2281 exist with matching subjects and #2265/#2266 carry parent-posted self-review wraps. check-links.py, validate-skills.py, and markdownlint-cli2 are clean, added lines are ASCII, and check-context-closure.py does not count AGENTS.md. No deleted line lost content that is not restated nearby.

Findings

  1. [Defect] memories/cursor.md, the paste route as a push gate ("from a harness paste of the child's own assistant message ... An author-composed block with those headings is not a paste. If the paste is not clearly the child's, use the transcript route"). Every other step in this procedure fails closed on a condition the author can check mechanically (HEAD equality, empty git status --short, a dry-run sha, an unclosed fence). This one turns on a judgment the author applies to their own output, at the moment the answer decides whether they may push, and it is the exact failure the same diff records recurring twice on 2026-08-25 (Register remind-ums-on-scrutiny.py after #2262 #2265/ums: bank #2262 merge-lifecycle lessons #2266). Two concrete consequences: an author summary carrying the three headings satisfies the recipe as written, and because nothing requires stating which route produced the verdict, no later reader of the reply or the PR comment can tell a transcript-derived verdict from a self-composed one. The CLI fallback three paragraphs away in shared/workflow/adversarial-self-review.md does require naming the reviewer and why the subagent route was unavailable, so the weaker branch is the newer one. batch-fetch-details is always available in Cloud, so making the transcript route the default (and the paste only corroboration), or requiring the reply to name the route used, costs nothing.

  2. [Defect] memories/cursor.md, the verdict-extraction procedure restates parse_report() in prose instead of invoking it, and already diverges from it. hooks/no-push-without-self-review.py exposes a tested parse_report(text) (suite: hooks/test-no-push-without-self-review.py) that does precisely what these paragraphs ask a human to do by hand, and nothing ties the prose to the code, so a change to VERDICT_LINE or REVIEWED_COMMIT staleifies the memory silently — the divergence the guard's own docstring warns about for its push detector ("would diverge silently (ai-config#1920)"). Three divergences are already present, measured against the module in this tree: (a) REVIEWED_COMMIT accepts a 7-to-40-char sha and the guard prefix-matches it (parse_report("...Reviewed-Commit: 4ba8508") returns 4ba8508, which startswith-matches HEAD), while the prose says only "Compare that sha to the recorded sha and to git rev-parse HEAD. If they differ, do not push" and reserves prefix-matching for the dry-run output; (b) the guard takes the last matching verdict line and ignores a trailing non-matching one (a report ending Verdict: Approved after ### Verdict: Ready for merge still parses clean), while "The last Verdict: line must match ...; a heading such as Approved is not a verdict" reads equally as "refuse" or as "skip it", and the two readings give opposite answers; (c) the fence-blanking and line-anchoring rules presume decoded markdown, but the transcript route yields transcript.json, where newlines are \n escapes — the decode step is only implicit in the cross-referenced section's "quote the last assistant text". Both shared/principles/deterministic-tools.md ("use the instrument that exists") and the DRW rule ("a hand-rolled equivalent of functionality that already exists is a review finding") point the same way: call the function (or a thin scripts/ wrapper around it) and keep the prose to intent.

  3. [Edge Case] memories/cursor.md, the dry-run output enumeration omits Everything up-to-date. The section enumerates the shapes an author must read — a sha range, [new branch] with no sha, HEAD versus a branch name on the left of -> — and then says "If that command fails, or you cannot tell from its output which commits would ship, or those commits are not the compared sha ... do not push." An up-to-date branch exits 0 with Everything up-to-date and no ref line at all, so the middle clause fires and the recipe forbids the push. That state is not exotic here: it is what a retry after an ambiguously-failed push produces (both skills/push/SKILL.md and the Cloud task instructions prescribe a retry loop), what git push -u on an already-pushed branch produces when the point is to set upstream, and what a child-side push produces — the very case the section's last Don't bullet is watching for. The direction is safe, but one clause saying an Everything up-to-date dry-run means the push would ship nothing, and that this is not a fingerprint mismatch, would close it.

Verdict: Needs more work

Reviewed-Commit: 4ba8508

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@d-morrison

Copy link
Copy Markdown
Collaborator

needs more work

@d-morrison
d-morrison removed their request for review August 26, 2026 17:34
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Review complete. Five findings, two of them substantive; the report follows.

Summary of Changes

The diff documents a Cursor Cloud route for the adversarial self-review and re-scopes the pre-push guard's claims to Claude Code.

  • memories/cursor.md gains a ~480-line section, "Cursor Cloud Task dispatches adversarial-reviewer": a dispatch recipe (commit first, record HEAD/branch/git status in the pushing checkout, foreground Task, recover the child's report from batch-fetch-details with includeTranscripts: true, decode the last non-empty assistant text, write it under /tmp, call parse_report() imported from the pushing checkout's hooks/no-push-without-self-review.py), a six-item Read-Do refusal checklist, an empty-pr-on-claim carve-out with a two-command positive test, and dry-run / source-ref rules. The existing "Task tool_result is identity-only" section is tightened so a harness paste can corroborate but never be posted.
  • Both adversarial-reviewer persona copies (.claude/agents/, .opencode/agents/) move the Reviewed-Commit: template out of a text fence and add a description of what parse_report() accepts and rejects.
  • AGENTS.md, CLAUDE.md, skills/push/SKILL.md, and shared/workflow/adversarial-self-review.md qualify the guard as gating "on Claude Code", carry compact copies of the Cursor recipe, and state that ALLOW_UNREVIEWED_PUSH=1 is inert on the adapter path.
  • shared/workflow/pr-on-claim.md adds a paragraph saying the empty-commit push still needs ALLOW_UNREVIEWED_PUSH=1 on Claude Code.
  • shared/workflow/self-review-fallback.md plus the agy/antigravity review-workflow skills drop the "only cross-vendor reviewer this corpus can dispatch" claim about delegate-to-codex; docs/cursor-hook-mapping.md replaces "Cursor Cloud has no ~/.claude" with a hedged, dated measurement; memories/MEMORY.md updates the index row.

I verified the parser claims by executing parse_report from the worktree copy against constructed reports, verified _argv_push's --dry-run/--delete exclusions and verify_review's c.startswith(reviewed_commit) and if not commits branches in source, verified SKIP_WITHOUT_TOOL_RESULT and the Task-to-Agent mapping in .cursor/hooks/adapt-claude-hooks.py, verified flag-unassigned-worktree.py's READ_ONLY = {"Explore", "Plan"}, verified the three carve-out exit codes on real commits in this branch (empty commit 0, non-empty 1, root 128, and rev-list --count of 1 for 8e697f16), confirmed ~/.claude/settings.json exists on this VM and binds the guard under PreToolUse with ~/.claude/hooks -> /workspace/hooks, and ran check-links.py, validate-skills.py, check-hook-catalog.py, check-context-closure.py, markdownlint (0 errors), and hooks/test-no-push-without-self-review.py (169 cases pass).

Findings

  1. [Defect] shared/workflow/pr-on-claim.md lines 22-37: the new paragraph says the push needs ALLOW_UNREVIEWED_PUSH=1, and the copy-paste block immediately above it still shows the unprefixed push. The Mechanics block ends with git push -u origin HEAD, and lines 32-37 then state that on Claude Code the guard "still requires ALLOW_UNREVIEWED_PUSH=1 on that git push". I confirmed the refusal path in hooks/no-push-without-self-review.py: verify_review returns on saw_reviewer_call being false before it ever reaches shipped_commits, and the --allow-empty commit is a shipped commit, so the if not commits allow branch is unreachable. A reader who copies the block verbatim, which is the block's only purpose, gets a PreToolUse deny on the very command the paragraph below it just described. No snippet anywhere in the repo shows the prefixed form (grep -rn ALLOW_UNREVIEWED_PUSH --include=*.md returns only prose sites). Either prefix the command in the block or annotate that line; note that doing so puts Claude-specific framing inside a lab-manual-shared fragment, which the paragraph you added already does.

  2. [Defect] .claude/agents/adversarial-reviewer.md line 61 and .opencode/agents/adversarial-reviewer.md line 63: a general fail-closed clause was deleted and replaced with an incomplete enumeration of rejected shapes. The removed sentence ended "the pre-push guard reads your call's result for it, and treats anything else as no verdict". The replacement names four rejections: whole-line emphasis, fenced content, an unclosed fence, and a fenced-only fingerprint. Executing parse_report from hooks/no-push-without-self-review.py against other natural shapes returns (None, None) for all of them, and none is named: a blockquoted verdict, a list-item verdict, and a four-space-indented verdict line, since VERDICT_LINE's prefix class is [ \t]{0,3} with no > or list marker. The concrete failure is a reviewer that formats its verdict as a callout or a bullet: the report reads as complete, the guard reports "no verdict came back", and the persona no longer contains the sentence that would have told the reviewer why. Restore the closed statement alongside the specifics rather than leaving the list to imply exhaustiveness.

  3. [Convention] AGENTS.md line 267, skills/push/SKILL.md line 50, shared/workflow/adversarial-self-review.md line 153: "when that file exists" attaches to the wrong nearest antecedent. All three compact copies read "call parse_report() from the worktree's hooks/no-push-without-self-review.py on the report recovered from the child's transcript / when that file exists", where the nearest noun is the transcript and the intended referent is the hook script. memories/cursor.md line 209 gets this right ("when that file exists in the pushing checkout"). This is the failure mode shared/writing/ambiguous-reference.md names: the wrong referent reads perfectly well, so a reader conditions the parse on the transcript's existence and never reaches the "if the worktree script is missing, obtain a CLI review" branch. Replace the demonstrative with the noun in all three compact copies.

  4. [Factual Error] memories/cursor.md lines 404-409: the stated Read-Do ordering constraint is stronger than the checklist's actual dependencies. The text says "items 1 through 4 must run in that order", then immediately gives the two real dependencies: item 1's pre-dispatch half must precede the dispatch, and gate 3 consumes gate 2's tuple. Nothing makes item 4 (HEAD is still the recorded sha) order-dependent with items 2 or 3, and item 1's second half (status still empty after) is independent of both. shared/workflow/skill-checklists.md makes the Do-Confirm/Read-Do choice turn precisely on whether reordering changes the answer, so an overstated dependency in the passage that declares the type is a defect in the instrument's own specification. State the two dependencies as the constraint instead of the 1-through-4 chain.

  5. [Edge Case] memories/cursor.md lines 235 and 246: a blocking verdict leaves the ARD step with no defined input. The recipe says "Do not read the transcript file into the conductor's context" and, on a non-clean verdict, only "do not push" plus re-dispatch on a new HEAD. parse_report returns (verdict, reviewed_commit) and no findings text, so on needs_work the conductor holds a tuple, a file it is told not to read, and a recovered /tmp report whose readability the section never states, while skills/ard and shared/workflow/adversarial-self-review.md ("Its findings are findings") require every finding to be Addressed, Rebutted, or Deferred in writing. Say explicitly that the recovered report file is what the author reads to disposition findings, so the prohibition on the transcript is not read as covering it.

Two smaller items I checked and am not filing as findings, recorded so the disposition is informed: "the module loads with no side effects" (line 208) is loose, since import executes _load_sibling() and can write hooks/__pycache__, but the sibling load is wrapped in try/except, parse_report does not touch _SIBLING, and __pycache__/ is gitignored, so gate 1 cannot trip on it; and "call parse_report() on that file" (gate 2, and the errored-dispatch instructions) is imprecise for a function that takes text rather than a path, but passing a path yields (None, None) and refuses, which fails closed.

Verdict: Needs more work

Reviewed-Commit: dfdb692

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

Put ALLOW_UNREVIEWED_PUSH=1 on the pr-on-claim copy-paste push,
restore the persona fail-closed else, name the worktree hook
script in compact copies, state the two Read-Do dependencies,
and say the recovered report file is the ARD input.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

ARD of the Cursor Task child of dfdb692f (bc-9972ca59-5f84-5938-ad58-716606da02d5). HEAD is now 4744c35f after Addressing findings 1-5.

# Disposition Note
1 Defect (pr-on-claim copy-paste push unprefixed) Address The Mechanics block now runs ALLOW_UNREVIEWED_PUSH=1 git push -u origin HEAD. The prefix is inert on the Cursor adapter.
2 Defect (persona dropped the fail-closed else) Address Personas now end the accepted-forms list with "Anything else is no verdict."
3 Convention ("when that file exists" attaches to the transcript) Address Compact copies now say "when the worktree hook script exists".
4 Factual Error (Read-Do claimed items 1-4 must run in order) Address The checklist now names the two real dependencies: item 1's pre-dispatch recording before dispatch, and gate 3 consuming gate 2's tuple.
5 Edge Case (blocking verdict left ARD with no input) Address The recovered report file under /tmp is what the author reads to Address, Rebut, or Defer. The transcript prohibition does not cover that file.

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

I inspected the branch diff, re-derived every tool-behaviour claim from the guard's source, the Cursor adapter, git's own source and documentation, and the live Cloud VM, and ran the repo's gates. Report follows.

Summary of Changes

The branch qualifies "the pre-push guard blocks an unreviewed push" as a Claude Code fact, and documents a Cursor Cloud replacement path in its place.
memories/cursor.md gains a 468-line section: dispatch adversarial-reviewer through Cursor Cloud's Task tool, recover the child's report from batch-fetch-details with includeTranscripts: true, decode the last non-empty assistant text from transcript.json, write it under /tmp, and call parse_report() on it by importing the pushing worktree's own hooks/no-push-without-self-review.py; then six numbered refusal gates (git status, report parse, verdict plus fingerprint, HEAD unchanged, same-argv --dry-run tip comparison, source-ref check) with a carve-out for the empty pr-on-claim --allow-empty branch.
Condensed copies of that procedure are added to AGENTS.md, skills/push/SKILL.md, shared/workflow/adversarial-self-review.md, and shared/workflow/pr-on-claim.md.
Both adversarial-reviewer persona copies now spell out which verdict spellings parse_report() accepts and rejects.
docs/cursor-hook-mapping.md and the adapter docstring replace "Cursor Cloud has no ~/.claude" with "Cloud agents can still have ~/.claude/settings.json", and self-review-fallback.md plus two review-workflow skills drop the claim that delegate-to-codex is the only cross-vendor reviewer this corpus can dispatch.

Claims I checked and found accurate: every parse_report() tolerance stated in the persona files (verified by executing parse_report against bolded-label, blockquote, four-space, Needs work, ** after colon, fingerprint-before-verdict, unclosed-fence and emphasised-fingerprint inputs); c.startswith(reviewed_commit) in verify_review; the lowercasing of the fingerprint; _argv_push's exclusion of --dry-run/--delete/-d and the :branch docstring case; SKIP_WITHOUT_TOOL_RESULT containing no-push-without-self-review.py; the adapter mapping Task to Agent outside explore/plan/shell and flag-unassigned-worktree.py's READ_ONLY = {"Explore", "Plan"}; the guard module importing with no side effects; bcIds/includeTranscripts/cloudAgentBcId against the live MCP schema; transcript.json being a dict with messages, records carrying role and text, and a user record carrying the same headings; all nine referenced issue/PR number types; and every git claim, against git/git v2.43.0 transport.c print_ref_status directly (porcelain to stdout with tab-separated from:to and no ->, non-porcelain to stderr with from -> to, [deleted] passing from = NULL, [new branch] with no sha, ... for a forced update). check-links.py, check-memory-file-size.py, check-context-closure.py, check-hook-catalog.py, validate-skills.py, markdownlint-cli2, test_cursor_hook_adapter.py and test_hooks.py all exit 0, and the added lines are ASCII throughout.

Findings

  1. [Defect] memories/cursor.md:392-417 --- the numbered refusal-gate checklist depends on a recording step that is not one of its items.
    The preamble at line 393 says "item 1's pre-dispatch recording must precede the dispatch, or item 4 has nothing to compare against", and designates the gates as the pause-point instrument ("Pause points: before the Task dispatch (item 1's first half)").
    Item 1 (line 412) records nothing: it is only git status --short empty before and after.
    Gate 4 ("Confirm HEAD is still the recorded sha") and gate 6 ("every source ref is HEAD or the recorded branch") therefore reference values no numbered gate ever captures; the capture lives only in the procedure prose at line 132 and the Do-bullet at line 496.
    A session working the six gates as written reaches gate 4 with nothing recorded, and the available repair is to read HEAD after the child returned --- which makes gate 4 compare a value to itself and passes exactly the child-committed case the gate exists to catch, with the killer-item marking on gate 1 pointing at the wrong half of the problem.
    Related wording in the same block: line 406 exempts "item 3's verdict/fingerprint clause", but item 3 has no other clause.

  2. [Defect] skills/push/SKILL.md:84-85 --- the carve-out test loses the checkout scoping the other three copies carry.
    AGENTS.md:281-283 and shared/workflow/adversarial-self-review.md:164-166 both end the test with "in the checkout whose push follows", and memories/cursor.md:152 states it as "two commands in that checkout"; the push copy stops at "exit 0" with no scoping at all.
    That copy is the one a pushing session reads at its pre-push step.
    Concretely: a conductor holding two worktrees --- an empty pr-on-claim claim branch and an implementation branch --- runs the two commands in whichever checkout its shell happens to sit in, gets count == 1 and git diff --quiet HEAD^ HEAD exit 0 from the claim worktree, and grants the no-review carve-out to a git -C <other-worktree> push that ships reviewed-by-nobody commits.
    This is the wrong-repository shape the same branch names as load-bearing at memories/cursor.md:126-130 (ai-config#1977, iter_pushes), and the scoping clause is the only thing that closes it.

  3. [Convention] AGENTS.md:259-289, skills/push/SKILL.md:40-96, shared/workflow/adversarial-self-review.md:139-176, memories/cursor.md:96-470 and its Do-bullet at 493-511 --- the same operative recipe is written out five times, against challenge-redundant-content, and thirty lines of it land in the file AGENTS.md's own "Instruction layering" section calls "the compact, unconditional cross-agent contract".
    What lands there is harness-specific procedure down to git exit-code trivia ("Exit 1 means a diff; exit 128 means the command failed"), loaded unconditionally by every agent in every repo session, while memories/cursor.md is the on-demand file the "Context budget" section prefers for exactly this.
    Nothing gates it: check-context-closure.py measures CLAUDE.md's closure and never reads AGENTS.md, so the cost is invisible to CI.
    The diff's own mitigation is an instruction to hand-sweep nine sites when Cursor adapter: synthesize tool_result from postToolUse.tool_output #2241 lands (memories/cursor.md:376-390), and finding 2 is that sweep already failing inside a single commit series.
    One authoritative copy in memories/cursor.md with one-sentence pointers elsewhere would remove both the load and the drift surface.

  4. [Factual Error] docs/cursor-hook-mapping.md:76-81 and .cursor/hooks/adapt-claude-hooks.py:19-21 --- "Cloud agents can still have ~/.claude/settings.json (measured 2026-08-26 PDT)" replaces a statement of the default with a possibility, and states it as a platform property.
    Measured by me on the Cursor Cloud VM that holds this worktree, on that same date: /home/ubuntu/.claude does not exist at all (ls -la /home/ubuntu), and find / -maxdepth 4 -name .claude -type d returns only /workspace/.claude, which is this repo's own tracked project settings file rather than home settings.
    The alternative explanation the prose does not consider at these two sites is that the observed instance was created by the measuring session itself: the in-tree writer of that path is scripts/install-hooks.py --fix (its module docstring says bootstrap is "a pure symlinker" that deliberately does not touch it), and the companion measurement at memories/cursor.md:121-127 describes ~/.claude/hooks -> /workspace/hooks, which is what bootstrap.sh creates --- so the VM in question had this repo's installers run on it.
    memories/cursor.md:271-272 does carry that qualification; docs/cursor-hook-mapping.md and the adapter docstring do not, and the paragraph that now hosts the claim is the one telling the reader not to run install-hooks.py --fix.
    The concrete failure: a reader on a fresh Cloud VM cannot tell whether an absent ~/.claude is normal or a broken install, because the sentence that stated the default was deleted rather than corrected.

  5. [Convention] AGENTS.md:265-269, skills/push/SKILL.md:48-52, shared/workflow/adversarial-self-review.md:151-155 --- "Call parse_report() on the report recovered from the child's transcript from the worktree's hooks/no-push-without-self-review.py" stacks two from phrases, and the nearer attachment ("the child's transcript from the worktree's hook script") is not the intended one.
    A reader following any of the three condensed copies looks for the transcript in the hook path, or imports parse_report from wherever the transcript came from --- the ~/.claude/hooks import the next line forbids.
    memories/cursor.md:115-120 already has the unambiguous ordering ("Call parse_report() from the worktree's ... on the file contents"); the three condensed copies should use it.

Verdict: Needs more work

Reviewed-Commit: 765553d323697edf96c48b44e62356037a8e4b1b

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

ARD of the Cursor Task child of 765553d3 (bc-1e798253-606e-59d0-b374-19eeea334736). HEAD is now 5eeb04bf after Addressing findings 1-5.

# Disposition Note
1 Defect (gate 1 recorded nothing) Address Item 1 now records HEAD and the branch name before dispatch. Killer item names gates 4 and 6. Carve-out says "item 3", not "item 3's verdict/fingerprint clause".
2 Defect (skills/push carve-out unscoped) Address Two-command test and the empty three-dot diff now say "in the checkout whose push follows".
3 Convention (recipe written five times, 30 lines in AGENTS.md) Address AGENTS.md is now a pointer at memories/cursor.md. On-demand copies in skills/push and adversarial-self-review stay; the #2241 sweep still lists them.
4 Factual Error (Cloud ~/.claude as platform property) Address Docs and adapter now split installer-present vs fresh-VM-absent, both dated 2026-08-26 PDT.
5 Convention (stacked from phrases) Address Condensed copies now call parse_report() from the worktree hook script on the recovered transcript, when that hook script exists in the pushing checkout.

Independent follow-ups already in flight: #2276, #2281, #2299, #2310.

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

I reviewed the branch diff against origin/main in that checkout, verified every tool-behaviour claim against the hook sources (including running parse_report directly), the git-push v2.43.0 OUTPUT documentation, the Cursor adapter, and the cited issues/PR, and ran the repo's own gates.

Summary of Changes

The diff documents a Cursor Cloud route for the mandatory adversarial self-review and re-scopes the existing pre-push-guard claims to Claude Code.

  • memories/cursor.md gains a ~465-line section, "Cursor Cloud Task dispatches adversarial-reviewer": how to dispatch the persona through Task, recover the child's report from batch-fetch-details with includeTranscripts: true, decode the last non-empty assistant text from transcript.json, call parse_report() from the pushing worktree's own hooks/no-push-without-self-review.py, and six numbered refusal gates before git push, plus a --allow-empty pr-on-claim carve-out and a Do/Don't pair. Its sibling section drops the "quote a harness paste" route in favour of posting the recovered file.
  • Both adversarial-reviewer persona copies (.claude/agents/, .opencode/agents/) narrow the pre-push-guard sentence to Claude Code and add an explicit statement of which verdict spellings parse_report() accepts and rejects.
  • AGENTS.md, CLAUDE.md, shared/workflow/adversarial-self-review.md, shared/workflow/self-review-fallback.md, shared/workflow/pr-on-claim.md, and skills/push/SKILL.md add "on Claude Code" scoping, the adapter-skip note pinned to issue Cursor adapter: synthesize tool_result from postToolUse.tool_output #2241, the parse_report() call, and the carve-out.
  • docs/cursor-hook-mapping.md and the .cursor/hooks/adapt-claude-hooks.py docstring replace the flat claim "Cursor Cloud has no ~/.claude" with dated presence measurements. No adapter code changes.
  • skills/agy-review-workflow/SKILL.md and skills/antigravity-review-workflow/SKILL.md drop the "only cross-vendor reviewer this corpus can dispatch itself" description of delegate-to-codex; memories/MEMORY.md updates the cursor.md index row.

Verified clean: validate-skills.py (Codex wrappers in sync), check-links.py (2451 links), markdownlint-cli2@0.22.1 (0 errors), check-context-closure.py (CLAUDE.md at 78.2% of the harness cap), check-hook-catalog.py, scripts/test_cursor_hook_adapter.py (149 passed), hooks/test-no-push-without-self-review.py (169 passed). No added markdown line trips the line-break gate's sentence or clause rules once the gate's own table/heading/fence exclusions are applied, and no added line carries non-ASCII. Every cited reference resolves and says what the diff says it says: #2241's acceptance criteria include "the three scripts are unskipped", #2255 merged 2026-08-26 and its scripts/pre-push-review.py does carry a separate parse_review_verdict contract, and #2270/#2276/#2281/#2299/#2309/#2310 exist with matching titles. All eight parse_report behaviour claims (heading optional, ** after the colon, Needs work synonym, bolded label rejected, blockquote rejected, four-space indent rejected, fingerprint lowercased, unclosed fence yielding no verdict) reproduce exactly against the module.

Findings

  1. [Factual Error] docs/cursor-hook-mapping.md:76-78 and .cursor/hooks/adapt-claude-hooks.py:19-23 state a cause the measurement does not establish, and the same PR's memories/cursor.md:355-359 explicitly declines to state it. The docs sentence reads "A Cloud VM can have ~/.claude/settings.json when this repo's installers have run (measured 2026-08-26 PDT on a session whose ~/.claude/hooks was a symlink into /workspace/hooks)" — the evidence offered is a symlink at a different path, which is bootstrap.sh's artifact and says nothing about who wrote settings.json; the adapter docstring asserts the same causal clause with only "(measured 2026-08-26 PDT)" attached, which reads as though the causation was measured. memories/cursor.md:358 says of the same day's reading, "That measurement does not say how the Cloud VM's copy got there." Other explanations are present in this tree: ~/.claude/settings.json is Claude Code's own user settings file, .cursor/install.sh (the Cloud install command in .cursor/environment.json) runs neither bootstrap.sh nor install-hooks.py, and bootstrap.sh:9-10 records that "cloud/web sessions pre-populate ~/.claude/skills" independently of this repo. Concrete failure: a reader takes the contrapositive — a Cloud VM where this repo's installers have not run cannot have ~/.claude/settings.json, so no native PreToolUse guard can be bound there — which is exactly the inference memories/cursor.md:361-363 ("Whether Claude Code's native hook runner also fires on Cloud is unmeasured") exists to block. Three sites in one diff give one measurement three different strengths.

  2. [Defect] memories/cursor.md:405-408 exempts the recording that gate 6 at :448 depends on, while keeping gate 6 in force. The carve-out block says the --allow-empty pr-on-claim case "exempts item 1's first half, item 2, item 3, and item 4 ... It does not exempt item 1's second half, item 5, or item 6." Item 1's first half (:412-413) is where git rev-parse --abbrev-ref HEAD is recorded, and item 1's own killer item (:416-418) says in so many words that skipping it leaves "gates 4 and 6 [with] no recorded sha or branch to compare." Gate 4 duly gets an explicit carve-out at :440 ("no sha was recorded before a dispatch"); gate 6, which requires "every source ref is HEAD or the recorded branch," gets none. Concrete failure: an agent taking the carve-out has no recorded branch, so gate 6 is either unsatisfiable — refusing the very pr-on-claim push the carve-out exists to permit — or it is satisfied against a branch name read at push time, most naturally off the push command itself, which makes the check circular and lets git push -u origin some-other-branch pass a gate whose whole purpose is to catch that. Gate 5 survives the carve-out because it compares against a live HEAD read; gate 6 is the only one of the six whose comparand exists solely in the exempted half. The same gap is in the Do-bullet: :524 requires the recorded branch and :527-534 grants the carve-out without addressing it.

  3. [Convention] memories/cursor.md:390, "Compact copies stay until that landing," uses a term defined nowhere in the file or the corpus (case-insensitive grep for compact cop across *.md returns this one line). The preceding sentence (:378-389) enumerates ten sites to sweep when Cursor adapter: synthesize tool_result from postToolUse.tool_output #2241 lands, so "compact copies" could mean those abbreviated restatements, the two persona copies, the generated codex-skills/ wrappers, or something else. Concrete failure: a future session doing the Cursor adapter: synthesize tool_result from postToolUse.tool_output #2241 sweep cannot tell what this sentence forbids removing, so it either deletes a restatement the sentence meant to protect or leaves one the sweep should have updated — and the sentence is the only thing standing between the two outcomes. Naming the referent ("the abbreviated restatements in the sites listed above") costs one clause.

Verdict: Needs more work

Reviewed-Commit: 5eeb04bf53a0c0673530f68cc71f866482c83104

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

ARD of the Cursor Task child of 5eeb04bf (bc-c3492351-48e7-58b7-80e1-c1f51519de13). HEAD is now 52fcd0af after Addressing findings 1-3.

# Disposition Note
1 Factual Error (installer cause for settings.json) Address Docs and adapter now report presence only. Both say the measurement does not say how the copy got there, matching memories/cursor.md.
2 Defect (carve-out kept gate 6 in force) Address Carve-out now exempts item 6. Gate 6 has an explicit skip. Do-bullet skips the recorded-branch source-ref check on the --allow-empty case.
3 Convention ("compact copies" undefined) Address Replaced with "the abbreviated restatements in the sites listed above".

Independent follow-ups already in flight: #2276, #2281, #2299, #2310.

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

I inspected the diff, verified every checkable claim against the actual code and against git's own source, and ran the repo's gates. Here is the report.

Summary of Changes

The branch documents a Cursor-route self-review procedure and re-scopes the pre-push guard's claims to Claude Code.

  • Both adversarial-reviewer persona copies (.claude/agents/, .opencode/agents/) drop the fenced Reviewed-Commit: example in favour of a bare line, add parse_report()'s accepted verdict forms, and require the report to be the call's own message rather than a pointer to a file.
  • memories/cursor.md gains a ~490-line section: dispatching adversarial-reviewer through Cursor Cloud Task, recovering the child's report from batch-fetch-details transcripts, calling the worktree copy of parse_report() on it, six ordered refusal gates as a Read-Do checklist, an --allow-empty pr-on-claim carve-out decided by two git commands, and Do/Don't pairs.
  • AGENTS.md, CLAUDE.md, skills/push/SKILL.md, shared/workflow/adversarial-self-review.md, and shared/workflow/self-review-fallback.md carry compact copies of that rule and qualify "the pre-push guard gates this" with "on Claude Code".
  • shared/workflow/pr-on-claim.md adds ALLOW_UNREVIEWED_PUSH=1 to the claim-push recipe.
  • docs/cursor-hook-mapping.md replaces the false "Cursor Cloud has no ~/.claude" with a dated measurement; self-review-fallback.md and the two review-workflow skills drop the "only cross-vendor reviewer" claim.

Gates run clean: check-links.py, validate-skills.py, markdownlint-cli2@0.22.1, check-vendored-drift.py, check-hook-catalog.py, check-memory-file-size.py, check-context-closure.py. No non-ASCII in added lines, and semantic line breaks hold throughout. I fact-checked the technical claims and found no false ones: parse_report's tolerances (bare Needs work, optional heading, spaces around the colon, whole-line emphasis rejected, fences blanked before both searches, unclosed fence yielding no verdict, a fenced fingerprint yielding none, lowercasing) all reproduce exactly when the module is imported and exercised; verify_review's c.startswith(reviewed_commit), _argv_push's exclusion of --delete/-d, the adapter's SKIP_WITHOUT_TOOL_RESULT entry and its Task-to-Agent mapping, flag-unassigned-worktree.py's READ_ONLY = {"Explore", "Plan"}, install-hooks.py as the sole in-tree writer of ~/.claude/settings.json, and the module's absence of import-time side effects all check out. The git claims check out against git v2.43.0 transport.c print_ref_status: porcelain goes to stdout as flag\tfrom:to\tsummary with no -> on any line, non-porcelain summaries go to stderr with from -> to, .. marks a fast-forward and ... a forced update, and - [deleted] carries no source ref. The VM measurements reproduce here too: ~/.claude/settings.json binds no-push-without-self-review under PreToolUse, ~/.claude/hooks -> /workspace/hooks, the guard file is inode-shared with /workspace/hooks/, and /workspace is main at 21a2e2aa. The sweeps for the two retired claims return zero remaining sites.

Findings

  1. [Defect] shared/workflow/pr-on-claim.md:26 contradicts the Cursor-adapter rule this same diff introduces. The recipe block is agent-neutral and is the copy-paste surface for gi, gii, gip, and st, and it now hard-codes ALLOW_UNREVIEWED_PUSH=1 git push -u origin HEAD. The same diff writes the opposite instruction for a Cursor session in two places: skills/push/SKILL.md:72-73 ("On a session whose pushes go through Morrison-Lab/ai-config's Cursor adapter, default: do not prefix") and the memories/cursor.md Don't bullet ("Don't: prefix ALLOW_UNREVIEWED_PUSH=1 on a Cursor-adapter push by default"). The block's own follow-up prose at lines 32-37 scopes the requirement to Claude Code, so the block and the paragraph under it disagree about scope. Concrete failure: a Cursor session claiming an issue copies the block, uses the override, and then must either state in its reply that it used an override it did not need or say nothing and leave an unexplained override in the shell history. shared/ fragments are also transcluded by the UCD-SERG lab manual, so the recipe now ships a Claude-Code-only environment variable to readers with no such guard. Putting the prefix in the Claude-Code paragraph rather than in the shared block resolves both.

  2. [Edge Case] The stale-persona rollout case has no route on the Cursor-adapter path, and it is live on this very branch. skills/push/SKILL.md:69 lists "a session where the reviewer agent is unregistered or registered from a stale definition" as an override case. Lines 72-77 of that same skill then declare the override inert on the adapter, and the new gate that replaces it is a flat refusal: "If the verdict is not clean, or there is no fingerprint, or the fingerprint does not prefix-match HEAD, do not push". The authorization to fall back to a CLI review is keyed only on a missing worktree script, a missing default-branch copy, or a dispatch that "errored or produced no report". A stale-registered persona is none of those, and it produces exactly the failure this diff exists to fix: the previous persona revision shows the fingerprint inside a text fence, and a child that imitates it yields a clean verdict with no fingerprint. As written, the recipe's outcome for that state is a permanent refusal with no named exit. One sentence closes it, either by extending "produced no report" to a report whose fingerprint cannot be recovered, or by naming a stale-registered persona as a CLI-review case on this path.

  3. [Edge Case] The decoder requires the report to be the child's last non-empty assistant message, and neither persona copy tells the child that. memories/cursor.md is emphatic: take the last assistant record whose text is non-empty, "Do not skip a later non-empty assistant text to reach an earlier matching one", and "If that last non-empty text lacks those headings, there is no report". The persona files only say to end the report with the fingerprint and to return the report as the call's own message — nothing forbids a trailing sign-off, a closing note, or a follow-up message after it. On Claude Code this is invisible because the tool result carries the final message, but on the Cursor route a fully compliant reviewer that appends one line is graded as having produced no report. It fails closed rather than open, so it is not a safety hole, but the fix belongs in the same diff that rewrote that paragraph: tell the child to emit nothing after the fingerprint.

  4. [Convention] .claude/agents/adversarial-reviewer.md:71 and .opencode/agents/adversarial-reviewer.md:73: "Anything else is no verdict." has the wrong nearest referent. It follows immediately after "A fingerprint only inside a fence is no fingerprint", so its nearest antecedent is fingerprint forms while its intent is verdict-line forms. Naming the referent ("a verdict line in any other form is no verdict") restores it.

  5. [Convention] skills/push/SKILL.md:86-91 states the carve-out commands with no checkout scoping, unlike every sibling copy. memories/cursor.md, AGENTS.md, and shared/workflow/adversarial-self-review.md all qualify the two-command test with "in the checkout whose push follows". The push skill is the surface actually read at push time, and it is the Cursor case — where the conductor's cwd is deliberately not the pushing worktree — so a reader who runs those commands in the conductor's cwd decides the carve-out against the wrong repository.

Verdict: Needs more work

Reviewed-Commit: 4744c35

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

Keep the agent-neutral git push in the pr-on-claim recipe, show the
Claude Code prefix beside it, treat a missing fingerprint as a
CLI-review case, tell the reviewer to emit nothing after the
fingerprint, and scope the push-skill carve-out to the pushing
checkout.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

ARD of the Cursor Task child of 4744c35f (bc-1c217d3f-8597-5b93-b412-73f89242334c). HEAD is now 57b53607 after Addressing findings 1-5.

# Disposition Note
1 Defect (shared pr-on-claim block hard-coded the Claude prefix) Address The recipe block is again the unprefixed git push. The Claude Code paragraph now shows ALLOW_UNREVIEWED_PUSH=1 git push -u origin HEAD as its own snippet.
2 Edge Case (stale persona has no Cursor-path exit) Address A report whose fingerprint cannot be recovered, including a stale-registered persona, is a CLI-review case. Write that reviewer's report under /tmp and call parse_report() on it.
3 Edge Case (persona never forbids a trailing message) Address Personas now say "Emit nothing after the fingerprint."
4 Convention ("Anything else is no verdict" attaches to the fingerprint) Address Personas now say "A verdict line in any other form is no verdict."
5 Convention (skills/push carve-out had no checkout scope) Address The two-command test is now "in the checkout whose push follows".

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Summary of Changes

The branch documents a Cursor Cloud self-review route: dispatch the adversarial-reviewer persona through Cursor's Task tool, recover the child's report from a batch-fetch-details transcript, gate the push on parse_report() imported from the pushing checkout's own hooks/no-push-without-self-review.py, and post the recovered report verbatim.

  • memories/cursor.md: a new ~475-line section ("Cursor Cloud Task dispatches adversarial-reviewer") carrying the dispatch preconditions, transcript-decoding rules, git push --dry-run output interpretation, an --allow-empty pr-on-claim carve-out, a six-item refusal-gate checklist, and Do/Don't pairs; the existing "identity-only" section is tightened so a harness paste may only corroborate, never be posted.
  • Abbreviated restatements land in AGENTS.md, CLAUDE.md, skills/push/SKILL.md, shared/workflow/adversarial-self-review.md, shared/workflow/pr-on-claim.md, and shared/workflow/self-review-fallback.md, most of them scoping the pre-push guard claim to "on Claude Code" and naming the adapter skip until Cursor adapter: synthesize tool_result from postToolUse.tool_output #2241.
  • Both adversarial-reviewer persona copies gain an explicit statement of the verdict forms parse_report() accepts and rejects.
  • .cursor/hooks/adapt-claude-hooks.py and docs/cursor-hook-mapping.md replace the flat claim "Cloud agents have no home Claude settings" with dated, hedged measurements.
  • skills/agy-review-workflow and skills/antigravity-review-workflow drop the "only cross-vendor reviewer" phrasing.

Verification I ran: parse_report exercised against 13 verdict shapes; verify_review, VERDICT_LINE, REVIEWED_COMMIT, iter_pushes, _argv_push, SKIP_WITHOUT_TOOL_RESULT, the TaskAgent mapping and flag-unassigned-worktree.py's READ_ONLY read directly; git v2.43.0 transport.c print_ref_status and the git-push OUTPUT docs checked for the porcelain/stderr/../.../[deleted]/[new branch] claims; all twelve cited issue and PR numbers resolved and 2265/2266 confirmed to be PRs; three real transcript.json files inspected; check-links.py, validate-skills.py, check-hook-catalog.py, markdownlint-cli2, check-context-closure.py, test-no-push-without-self-review.py (169 cases) and test_cursor_hook_adapter.py (149 cases) all pass. The great majority of the tool-behaviour claims in this diff check out exactly as written.

Findings

  1. [Defect] memories/cursor.md:405-410 and :450-451 — the --allow-empty carve-out exempts the only gate that ties the push's refspec to the reviewed branch, and the exemption is stated two incompatible ways. The gate list exempts "item 1's first half, item 2, item 3, item 4, and item 6" in full, so gate 6 ("Confirm every source ref is HEAD or the recorded branch", whose procedure text at :330-333 also refuses a tag, FETCH_HEAD, or a raw sha) does not run. The Do-bullet at :527-528 and :539-541 instead exempts only the recorded-branch comparison. Under the gate-list reading the carve-out path admits git push -u origin <a-different-new-branch>: gate 5 explicitly "does not confirm the shipped tip" for a first push of a new branch (:310-314, which the file notes is the cursor/<name> case by construction), the two-command positive test measures HEAD rather than the refspec, and gate 6 is skipped — so that branch's commits ship with nothing having compared them to anything. That is precisely the hole hooks/no-push-without-self-review.py's docstring says the refspec resolution exists to close. The stated justification does not hold either: "no branch was recorded before a dispatch" cannot license skipping the source-ref-is-HEAD half, and the branch name is one git rev-parse --abbrev-ref HEAD in the same checkout where item 1's second half already runs on the carve-out. Contrast gate 4, where the justification is sound because a recorded sha has nothing to be compared against without a dispatch. Note this is the gate set's logic rather than its mechanization, so Instrument the Cursor Task pre-push refusal gates that git already decides #2310 would inherit the hole rather than resolve it.

  2. [Factual Error] memories/cursor.md:161-162 (restated at :426 and :509) — "Thinking and tool_calls records have empty or null text" is contradicted by the transcripts on this platform. In the three transcript.json files under /tmp/cursor/cloud-agent-transcripts/ on this Cursor Cloud VM (fetched 2026-08-26, the same platform and date as the section's other measurements), the text key is absent on 138 of 141, 137 of 140, and 149 of 152 records; zero records carry a present-but-null or present-but-empty text. The concrete failure is in the artifact this section exists to specify: a decoder written from that sentence as m["text"], or as if m["text"] is None, raises KeyError on nearly every record. The prescriptive line ("whose text is a non-empty string") is safe as written; the description beside it is not, and it is what a reader implements from. The measured shape is "no text key at all", which is worth stating because it also confirms the sibling structural claims (dict with messages, role present on every record, the last non-empty assistant text carrying the four headings, and the user brief at index 0 carrying them too).

  3. [Defect] memories/cursor.md:128-131 — an unqualified guard-coverage claim inside the section whose premise is that the guard does not run. "A git -C on the push that names a different directory than the gates is the wrong-repository bypass iter_pushes already grades" is true of Claude Code (I confirmed the chained -C, cd/pushd, and REDIRECTED handling and the ai-config#1977 attribution), but this same file states 200 lines later (:338-341) that the Cursor adapter skips that script entirely. A reader on the Cursor path can take the wrong-repository case as already covered and skip the manual discipline the sentence is introducing. The diff adds "on Claude Code" at every other guard-coverage site it touches (AGENTS.md:259, CLAUDE.md:660, skills/push/SKILL.md:42 and :59, shared/workflow/adversarial-self-review.md:266) and omits it here.

  4. [Edge Case] .claude/agents/adversarial-reviewer.md:63-73 and .opencode/agents/adversarial-reviewer.md:65-75 — a fail-closed catch-all was replaced by an incomplete enumeration. The deleted sentence said the guard "treats anything else as no verdict". The replacement lists three rejected shapes (bolded label, blockquote prefix, four-space indent) — all three of which I confirmed against VERDICT_LINE — but a list-item verdict is also rejected and is not named: I measured parse_report returning (None, None) for a hyphen-bulleted verdict line, for a bulleted heading form, and for a numbered-list form, all of which are natural Markdown for a reviewer writing a summary list. The failure direction is fail-closed rather than unsafe: a genuinely clean review is read as no verdict and the push is refused, costing a round. Keeping the "anything else is no verdict" sentence alongside the enumeration closes it.

  5. [Convention] shared/workflow/self-review-fallback.md:183-184 — "the same-session self-review dispatch" invites exactly the reading this fragment forbids. Nine lines above, the same fragment says the authoring session is "the one party who cannot" review the diff, and memories/cursor.md:464 describes the Task child as "a separate context". "Same-session" reads most naturally as "performed inside the authoring session", i.e. the inline pass the corpus rules out, so the sentence meant to distinguish the self-review dispatch from the second-reviewer pairing can be read as licensing an inline pass. "The self-review step's own dispatch, to a separate context" carries the intended contrast without the misreading.

  6. [Factual Error] memories/cursor.md:349-350 — "measured" is attached to a claim that was derived, by this file's own standard. The prefix's inertness follows from SKIP_WITHOUT_TOOL_RESULT in .cursor/hooks/adapt-claude-hooks.py, which I verified; what a Cloud session can observe is that an unprefixed push was not denied, and that observation is equally consistent with the adapter skipping the script, a native runner not firing, and a hook that fired and passed. The file draws this exact distinction fourteen lines later ("Settings existing is not the measurement that it fired"), so the label is inconsistent with the standard the section sets for itself. Attribute the claim to the code read, naming the constant and dating the read.

  7. [Convention] memories/cursor.md:393 — the refusal-gate checklist does not state its type. shared/workflow/skill-checklists.md says plainly: "state which kind a checklist is, in the heading or its first line". This list is Read-Do by that fragment's own tell — item 1's recording must precede the dispatch and gate 3 consumes the tuple gate 2 produces — and its preamble says "in order" without naming Read-Do, so a reader may work ahead and lose the pre-dispatch recording, which is the list's own killer item.

  8. [Convention] The carve-out recipe is triplicated with no consolidation scheduled. The two-command test, the "Exit 1 means a diff; exit 128 means the command failed" gloss, and the net-zero-tree caveat appear at memories/cursor.md:239-251, shared/workflow/adversarial-self-review.md:164-172, and skills/push/SKILL.md:84-91. The sweep note at memories/cursor.md:376-391 is scoped to "the adapter-skip claim", so nothing schedules the carve-out text itself — meaning the correction in finding 1 has to be made in three places, and only one of them is covered by the Cursor adapter: synthesize tool_result from postToolUse.tool_output #2241 sweep.

  9. [Convention, non-blocking] Added prose breaks below clause level. Across the 640 added non-blank Markdown lines the median length is 50 characters and 172 are under 40, with breaks landing after prepositional phrases ("in that checkout", "before the dispatch,", "on the file contents") rather than at clause boundaries; shared/writing/semantic-line-breaks.md asks for roughly 60 to 80 characters, one clause per line. CI's actual rule (one sentence per line, plus the length-plus-semicolon clause rule) passes: I found no added line at or over 80 characters carrying a mid-line semicolon. Per that fragment's own instruction to reviewers this is a suggestion rather than a blocker, and it is not what drives the verdict below.

Verdict: Needs more work

Reviewed-Commit: 52fcd0af1f3473e39a58427066c5f5b4aa840a93

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

I inspected the diff, ran the repo's own gates, and fact-checked the guard/git claims against source. Report follows.

Summary of Changes

The branch documents a Cursor Cloud route for the mandated adversarial self-review and re-scopes existing pre-push claims from "the guard" to "the guard on Claude Code."

  • memories/cursor.md gains a ~490-line section, "Cursor Cloud Task dispatches adversarial-reviewer": commit-first discipline, recording HEAD/branch/git status in the pushing checkout, recovering the child's report from batch-fetch-details transcript.json, selecting the last non-empty assistant text, writing it under /tmp, calling parse_report() imported from the worktree's hooks/no-push-without-self-review.py, a same-argv git push --dry-run tip/source-ref comparison, an --allow-empty pr-on-claim carve-out, and a six-item Read-Do refusal checklist with pause points and killer items.
  • Compact restatements land in AGENTS.md, skills/push/SKILL.md, shared/workflow/adversarial-self-review.md, and shared/workflow/self-review-fallback.md; CLAUDE.md and adversarial-self-review.md qualify "gates the pre-push case" with "on Claude Code."
  • Both adversarial-reviewer persona copies (.claude/agents/, .opencode/agents/) unfence the Reviewed-Commit: example and add explicit parse_report() acceptance rules (Needs work, optional heading, spaces around the colon, fence blanking, unclosed fence, whole-line emphasis).
  • shared/workflow/pr-on-claim.md adds a Claude-Code ALLOW_UNREVIEWED_PUSH=1 prefix for the claim push; docs/cursor-hook-mapping.md replaces "Cursor Cloud has no ~/.claude" with a dated measurement; skills/agy-review-workflow, skills/antigravity-review-workflow, and self-review-fallback.md drop the "only cross-vendor reviewer" over-claim; memories/MEMORY.md updates the index row.

Repo gates I ran all pass: check-links.py, validate-skills.py, check-memory-file-size.py (652 lines, under 1200), check-vendored-drift.py, check-hook-catalog.py, markdownlint-cli2@0.22.1 (0 errors), and check-context-closure.py (exit 0; its over-budget line is advisory and pre-existing). No non-ASCII characters are added. Source claims I verified against code and match: parse_report returns (verdict, reviewed_commit) with clean/needs_work/(None, None), lowercases the fingerprint, blanks fences before both searches, and refuses an unclosed fence; verify_review compares with c.startswith(reviewed_commit) and requires a reviewer call before reaching shipped_commits; _argv_push excludes --dry-run/-n/--delete/-d; SKIP_WITHOUT_TOOL_RESULT contains no-push-without-self-review.py; the adapter maps Task to Agent unless subagent_type is explore/plan/shell; flag-unassigned-worktree.py's READ_ONLY is {"Explore", "Plan"}; install-hooks.py writes ~/.claude/settings.json; /home/ubuntu/.claude/settings.json exists here and binds no-push-without-self-review under PreToolUse, with ~/.claude/hooks -> /workspace/hooks; and the module imports with no side effects beyond a sibling load that fails soft.

Findings

  • [Convention] Semantic line breaks are broken in every prose file this branch touches. The added text hard-wraps mid-clause rather than at sentence or clause boundaries. python3 scripts/semantic-line-breaks.py (preview mode) reports reformat suggestions per file. Negative control: the same tool on the origin/main copies of those same files reports 0 for each. So every one of these files was conformant before this branch and none is now.

  • [Edge Case] The dry-run output taxonomy omits the one line this recipe's own push form always emits. A same-argv --dry-run of a -u push also prints Would set upstream of '<branch>' to '<branch>' of 'origin' on stdout. Checklist item 5 refuses when "the dry-run listed other refs", and item 6 teaches that a line with no -> is a deletion. A line naming two branch refs, carrying no -> and no sha, is covered by neither rule.

  • [Edge Case] The four-heading requirement is asserted as a gate but no instrument decides it. parse_report() matches only VERDICT_LINE and REVIEWED_COMMIT, and returns ("clean", <sha>) for a body containing nothing but ### Verdict: Ready for merge and a Reviewed-Commit: line. A decoder that follows the checklist mechanically satisfies gates 2 and 3 while the heading requirement passes vacuously.

  • [Defect] "Do not pair the project adapter with native Claude hooks" is stated flatly against a state this same diff measures as already true on Cloud, with no remediation. A Cloud session reading these lines finds itself in the forbidden configuration by default. Either scope the prohibition to the desktop case the evidence covers, or state the Cloud remediation.

  • [Convention] Ambiguous demonstrative in the carve-out passage. "That is the --allow-empty pr-on-claim commit." The nearest antecedent of "That" is "Neither"/the two failing exit codes, while the intended referent is the pair of passing conditions two sentences earlier. Name the referent: "Both conditions passing is the --allow-empty pr-on-claim commit".

Verdict: Needs more work

Reviewed-Commit: 57b5360

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

Treat Would set upstream as neither a mismatch nor other refs.
The decoder, not parse_report, decides the four headings.
Scope adapter-plus-native pairing to desktop.
Name both-conditions-passing as the empty-claim carve-out.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

ARD of the Cursor Task child of 57b53607 (bc-d69b374f-fcea-5ed7-9e1c-c598800bb9b1). HEAD is now 1cb6840d after Addressing findings 2-5 and Rebutting finding 1.

# Disposition Note
1 Convention (semantic line breaks via scripts/semantic-line-breaks.py) Rebut The blocking CI gate is Morrison-Lab/gha/check-new-line-breaks@fdaeccc4. That check passed on prior HEADs of this branch. The preview reformatter is not that gate. Mid-phrase wraps at suggestion weight stay.
2 Edge Case (Would set upstream unnamed) Address A -u dry-run's Would set upstream of ... line on stdout is not a mismatch and is not "other refs". This push's own dry-run emitted that line.
3 Edge Case (four headings not checked by parse_report) Address The decoder decides the four headings. parse_report matches only the verdict line and the fingerprint. Do not call parse_report on a body that failed the heading check.
4 Defect (adapter-plus-native pairing forbidden on Cloud by default) Address Desktop: leave one path enabled. Cloud: both can be present; a native deny of the unprefixed push is the observable that the native runner fired.
5 Convention ("That is the --allow-empty commit") Address Compact copies and the canonical now say "Both conditions passing is the --allow-empty pr-on-claim commit."

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.

2026-08-26 20:01 UTC

@github-actions

Copy link
Copy Markdown
Contributor

Claude finished reviewView run


Code Review: #2272

Summary of changes

This PR is a documentation-only change to the ai-config corpus (no executable code touched). It:

  1. Reworks the adversarial-reviewer persona's fingerprinting instructions (both .claude/agents/ and .opencode/agents/ copies) to require the Reviewed-Commit: line as a bare, non-fenced line, and adds precise rules distinguishing what counts as "no verdict" (unclosed fence, fingerprint only inside a fence, emphasis wrapping the whole verdict line, etc.).
  2. Adds a large new section to memories/cursor.md documenting a manual recovery procedure for verifying/dispatching adversarial-reviewer self-reviews on Cursor Cloud (where the native pre-push guard is currently skipped), including a numbered "refusal gates" checklist and an empty-commit carve-out.
  3. Threads "on Claude Code" qualifiers through AGENTS.md, CLAUDE.md, shared/workflow/adversarial-self-review.md, and skills/push/SKILL.md wherever they previously stated the pre-push guard's behavior unconditionally.
  4. Adds an explicit ALLOW_UNREVIEWED_PUSH=1 prefix example to shared/workflow/pr-on-claim.md for the initial empty-commit PR push.
  5. Fixes an ambiguous "the only cross-vendor reviewer" claim (now stale, per the corpus's own Antigravity-retirement note) in three files: shared/workflow/self-review-fallback.md, skills/agy-review-workflow/SKILL.md, skills/antigravity-review-workflow/SKILL.md.
  6. Clarifies docs/cursor-hook-mapping.md's claim that "Cursor Cloud has no ~/.claude" (measured false on at least one VM) with appropriately hedged language.

Verification performed

Given this diff makes many precise, checkable claims about tool/code behavior, I verified rather than took them on faith:

I found no hallucinated APIs, functions, file paths, or fabricated tool behavior — every checkable technical claim in this diff held up against the actual code, git's own documentation, or the live issue tracker.

Findings

No blocking findings. Two minor, non-blocking notes:

  1. Environment artifact, not a PR defect.claude/agents/adversarial-reviewer.md and CLAUDE.md currently have uncommitted local reversions in this review sandbox's working tree (visible in git status --short at session start: M .claude/agents/adversarial-reviewer.md, M CLAUDE.md), which silently restore the pre-PR text on disk even though the PR's commit (HEAD) contains the correct new content. This tripped me up briefly (a direct Read of the working-tree file showed stale content until I cross-checked with git show HEAD:<path>). This is a harness/checkout artifact unrelated to the PR's authorship — flagging only so it isn't mistaken for a real regression by a future reviewer relying on plain file reads instead of git show HEAD:.
  2. Unverifiable internal citation (memories/cursor.md) — the attribution git 2.43.0 \set_upstreams()`for the "pretend branch"-u dry-run message could not be independently confirmed (the installed git binary is stripped, and I had no network access to git's source). The *observable behavior* it describes (Would set upstream of ... printed on stdout even when upstream is already set`) is confirmed accurate from the binary's embedded strings; only the specific C function name is unverified. Low risk, since it's a citation detail rather than an operational instruction.

Both are informational only; neither affects correctness of the guidance this PR ships.

Verdict

Ready for merge

Reviewed-Commit: 9dbc640

Reviewed commit: cb6ac0a

@github-actions

Copy link
Copy Markdown
Contributor

💰 Cost: $7.4264 (review) — run

@dem-extra1
dem-extra1 merged commit ff43c6c into main Aug 26, 2026
11 checks passed
@dem-extra1
dem-extra1 deleted the cursor/cursor-claude-adv-review-32a3 branch August 26, 2026 20:01
@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

I've finished the review. Here is the report.

Summary of Changes

The branch documents a Cursor Cloud route for the mandatory adversarial self-review and adjusts the surrounding corpus to match.

memories/cursor.md gains a 514-line section, "Cursor Cloud Task dispatches adversarial-reviewer", covering: foreground dispatch through Task; recording HEAD, branch, and git status --short in the pushing checkout before dispatch; recovering the child's report via cursor-cloud batch-fetch-details with includeTranscripts: true; decoding the last non-empty assistant text from transcript.json and requiring it to carry Summary / Findings / Verdict / Reviewed-Commit; calling parse_report() imported from the worktree's hooks/no-push-without-self-review.py (never ~/.claude/hooks/); a two-command positive test for the empty pr-on-claim --allow-empty carve-out; dry-run tip and source-ref gates; and a six-item Read-Do checklist plus a Do/Don't block.

Condensed copies of that recipe are added to AGENTS.md (+37 lines), shared/workflow/adversarial-self-review.md (+49), and skills/push/SKILL.md (+34). shared/workflow/pr-on-claim.md gains the ALLOW_UNREVIEWED_PUSH=1 prefix for the empty claim push on Claude Code. shared/workflow/self-review-fallback.md points the Cursor case at the new recipe and reworks the delegate-to-codex "only cross-vendor reviewer" phrasing (mirrored in agy-review-workflow and antigravity-review-workflow). Both adversarial-reviewer persona copies drop the ```text fence around Reviewed-Commit:, require the report as the call's own message, and enumerate `parse_report()`'s accepted forms. `docs/cursor-hook-mapping.md` replaces "Cursor Cloud has no `~/.claude`" with a measured correction. `CLAUDE.md` and `memories/MEMORY.md` get one-line updates.

Verification I ran: check-links.py, validate-skills.py, markdownlint-cli2@0.22.1, check-memory-file-size.py, check-hook-catalog.py, check-hook-output-shape.py, check-stale-records.py, check-vendored-drift.py, check-jules-review-workflow.py, check-tui-alloc-readme.py, check-harness-ignores.py, and the test_hooks, test_cursor_hook_adapter, test_pre_push_review, test_check_context_closure, test_validate_skills, test_check_pr_fully_clean, test_slb, test_check_memory_file_size, test_cursor_rules_sync, test_check_hook_catalog, test_check_hook_output_shape suites — all pass. check-context-closure.py reports the always-loaded closure over its advisory budget by 81,791 bytes, which is a pre-existing condition this branch adds to.

I also verified the parser claims directly by importing parse_report and exercising it: Needs work, an optional heading, and spaces around the colon are accepted; emphasis wrapping the whole verdict line yields (None, None); a fingerprint only inside a fence yields no fingerprint; an unclosed fence yields no verdict; the fingerprint is lowercased. verify_review's c.startswith(reviewed_commit), _argv_push's --delete exclusion, SKIP_WITHOUT_TOOL_RESULT, flag-unassigned-worktree.py's READ_ONLY = {"Explore", "Plan"}, install-hooks.py as the only in-tree writer of ~/.claude/settings.json, and pre-push-review.py's separate parse_review_verdict contract all check out. Against git v2.43.0's transport.c I confirmed old..new / old...new, [new branch] with no sha, - [deleted] with no ->, porcelain writing to stdout with : rather than ->, and set_upstreams() printing "Would set upstream of ..." to stdout with no already-set check. includeTranscripts is a real batch-fetch-details parameter writing <bcId>/transcript.json. On this Cloud VM, ~/.claude/settings.json exists and binds no-push-without-self-review, and ~/.claude/hooks -> /workspace/hooks, so both the corrected claim and the "different revision from the branch under review" rule are accurate.

Findings

  1. [Defect] docs/cursor-hook-mapping.md lines 86-90 (and the same text at memories/cursor.md lines 391-396) narrow a safety rule to desktop and leave Cloud with no rule, on a premise the same passage calls unmeasured. The deleted line was the unqualified "Leave one path enabled: this project file, or Claude settings, not both", justified two lines earlier by "the adapter's tick sentinel does not collapse adapter-plus-native". The replacement scopes that to "On a desktop session" and offers, for Cloud, only the observation "On Cursor Cloud both can be present". Lines 79-81 of the same passage state that whether Claude Code's native hook runner fires on Cloud is "unmeasured as of 2026-08-26 PDT". If it does fire, adapter-plus-native double execution applies on Cloud exactly as on desktop, and it applies to every hook bound in settings.json, not only to the push guard. I confirmed on this Cloud VM that ~/.claude/settings.json is present and binds no-push-without-self-review, so this is the live configuration rather than a hypothetical. The change relaxes a fail-closed rule on an admittedly unmeasured condition and supplies no replacement instruction: the only guidance offered is that a native deny of the unprefixed push tells you afterwards that the runner fired, which detects the condition only for that one hook and only after it has already double-run everything else. Either keep the rule for Cloud until the runner question is measured, or state explicitly why the rule is unactionable there (for instance, that the VM image writes settings.json and the session cannot disable it) — the reason is not in the diff.

  2. [Factual Error] shared/workflow/adversarial-self-review.md lines 145-150 state without qualification that the adapter skip makes "ALLOW_UNREVIEWED_PUSH=1 ... inert on that adapter path under any reviewer". Lines 185-187 of the same block then contradict that: "If Claude Code's native guard is also running, the prefix is that guard's escape even when the adapter skip makes it inert for the adapter." The prefix is inert for the adapter, not for the push, and skills/push/SKILL.md line 102 states it correctly ("The adapter skip makes the prefix inert for the adapter only"). The unqualified form is the one that carries the operative instruction ("default: do not prefix") and sits 36 lines ahead of its own correction, in the fragment that AGENTS.md and CLAUDE.md both name as the full rule. Given finding 1's measurement — a Cloud VM where the native binding is present — the unqualified sentence is the reading most likely to be acted on and it is false on that configuration. Qualify it at line 148 the way skills/push/SKILL.md already does.

  3. [Defect] memories/cursor.md line 427 asserts "Reordering 5 with 6 does not change the answer", but item 6 consumes item 5's output. Item 5 is "Run the same-argv dry-run; confirm every reported new tip prefix-matches HEAD"; item 6 is "Confirm every source ref is HEAD or the recorded branch", and the source ref is read from that same dry-run output (the text left of ->). Run before item 5, item 6 has nothing to read. The surrounding lines take ordering dependencies seriously and name two of them explicitly — "Item 1's pre-dispatch recording must precede the dispatch" and "Gate 3 consumes the tuple gate 2 produces" — so a Read-Do checklist that then declares independence where a third dependency exists teaches the reader the wrong thing about its own structure. Either move the dry-run invocation into a shared preamble both items read, or say that 6 depends on 5's output the way line 426 says 3 depends on 2's.

  4. [Convention] The parse_report/carve-out recipe is duplicated near-verbatim across four files, and one of them already carried a pointer delegating precisely that content elsewhere. Roughly 25 lines — "Do not import ~/.claude/hooks/ ...", "When the three-dot diff includes hooks/no-push-without-self-review.py ...", "The carve-out is git rev-list --count ... equal to 1 and git diff --quiet HEAD^ HEAD exit 0 ...", "Exit 1 means a diff; exit 128 means the command failed.", "A net-zero tree of other commits is not the carve-out." — appear identically in AGENTS.md lines 260-296, shared/workflow/adversarial-self-review.md lines 151-178, and skills/push/SKILL.md lines 46-97, on top of the source in memories/cursor.md (which itself restates the same procedure three times: prose, refusal checklist, Do/Don't block). adversarial-self-review.md already said, at lines 261-262 and 267-268, "How Cursor Cloud obtains the child's structured report is in [memories/cursor.md]" — the new inline block duplicates the very content those two pointers exist to avoid carrying. AGENTS.md describes itself as "the compact, unconditional cross-agent contract" and elsewhere reduces comparable material to a one-line pointer ("See [shared/workflow/check-before-pushing.md]"); 37 lines of exit-code semantics is not that. The diff concedes the hazard at memories/cursor.md lines 407-420, which schedules a nine-site sweep for when Cursor adapter: synthesize tool_result from postToolUse.tool_output #2241 lands and says "Compact copies stay until that landing" — but the copies are not compact, and a sweep list is a plan to fix drift rather than a reason to create it. Reduce the three secondary sites to the decision each audience actually needs plus a pointer, and keep the exit-code and two-command detail in memories/cursor.md only.

  5. [Edge Case] The transcript decoder's two rules — take the last non-empty assistant text, and require it to carry Summary / Findings / Verdict / Reviewed-Commit — cannot distinguish a completed report from a final assistant message that restates the brief's required shape (memories/cursor.md lines 160-178, gate 2 at lines 449-467). The passage names the sibling hole with care: an unfiltered decoder "grades the brief when the child produced no report", and one that skips a later text "grades a draft when the child errored after quoting the shape". The case it does not name is the child whose last message is itself such a shape restatement — a plan or an apology that reproduces the four headings the brief specifies. The role filter does not exclude it. The last-text rule selects it, and the heading check passes. What actually saves the gate is that REVIEWED_COMMIT requires 7-40 hex characters, so a literal <full sha ...> placeholder yields no fingerprint and gate 3 refuses. That is a real backstop but an incidental one, and the passage reasons about every neighbouring case explicitly. Name it, and say that the fingerprint regex is what closes it.

Verdict: Needs more work

Reviewed-Commit: cb6ac0a

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

ARD of the Cursor Task child of cb6ac0a7 (bc-37882a1b-2b7e-5901-b33a-4c2db262157e). This PR squash-merged as ff43c6c6 at 2026-08-26T20:01:09Z before the Address could push. GitHub Claude on that HEAD (19:56Z) was Ready for merge (informational notes only). The Task child was Needs more work. Leftover Address is #2339 / #2340. Did not recreate this deleted branch.

# Disposition Note
1 Defect (Cloud pairing has no replacement rule) Address Follow-up #2340: VM image already writes settings.json; desktop leave-one-path is unfollowable on Cloud.
2 Factual error (prefix inert on adapter path) Address Follow-up #2340: inert for the adapter only.
3 Defect (reordering 5 with 6) Address Follow-up #2340: item 6 consumes item 5's dry-run output.
4 Convention (compact copies) Rebut Compact copies stay until #2241.
5 Edge case (last message restates report shape) Address Follow-up #2340: heading check passes; fingerprint regex refuses a placeholder.

Posted by Cursor Grok 4.6 (AI agent) --- not written by a human.

d-morrison added a commit that referenced this pull request Aug 27, 2026
* start: qualify adversarial-reviewer Write-schema hedge (closes #2281)

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* Qualify adversarial-reviewer Write-schema claim.

The persona stated harness-enforced "no Edit or Write access" /
"can never alter code". Cursor Cloud Task still granted Write schemas
to that child (measured 2026-08-25 PDT). Hedge both copies and pin
the hedge with a test that fails the old absolute.

Independent of #2272: parent-side brief+HEAD checks stay there.
Does not claim Task can strip Write schemas.

Closes #2281.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* Address adversarial-reviewer hedge review findings.

Qualify agents.qmd so the published page no longer asserts universal
harness-enforced Write denial. Word the OpenCode copy around
permission: edit: deny rather than a tools: allowlist it does not
declare. Give each predicate clause a synthetic that can fail, derive
persona paths by glob, and cite ai-config#NNNN in the persona files.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* Restore Bash-discipline attribution and pin the qmd absolute.

Keep "each Bash-keeping agent file says so" in agents.qmd, and name
adversarial-reviewer as the Write-schema hedge. Date the Claude Code
allowlist claim. Unscope the OpenCode copy's discipline sentence.
Drop the redundant strip sentence. Give "can never call those tools"
its own synthetic. Sibling personas remain at ai-config#2326.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* Break semicolon clauses and isolate each forbidden needle.

The new-line-breaks gate failed on three added persona lines.
Give each FORBIDDEN_ABSOLUTES needle its own synthetic so dropping
one still reddens the suite. Collapse the duplicated Claude Code
versus other-harness restatement in agents.qmd and cite the
upstream sub-agent docs beside ai-config#341.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* Hedge the leftover caller-only-writes claim and generalize the tool ban.

agents.qmd still said only the calling session can write, three lines
after the hedge. The Claude persona enumerated four write-tool names
and then bound "those tools" to that list. Match the OpenCode copy's
general "edit or Write tools if they are present" ban.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* Use a category write-tool ban and drop unsupported OpenCode claims.

Name any write tool, not a Cursor-specific list. Stop asserting that a
harness loading the OpenCode copy grants Write; keep the un-isolated
copy as a separate sentence. Restore the user-go-ahead clause. The
opencode mirrors differ on bash, not on edit.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* Date the CI comment and pin the declared restriction.

Stop attributing the Cursor Cloud miss to the Claude tools: field.
Extend the category ban to posts and pushes. Pin that the Claude
copy omits Edit/Write and the OpenCode copy denies edit. Split the
packed agents.qmd sentence and name the Bash restriction.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* style: merge the two near-verbatim Write-schema sentences (review nit)

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
Co-authored-by: Douglas Ezra Morrison <demorrison@ucdavis.edu>
d-morrison pushed a commit that referenced this pull request Aug 27, 2026
* fix: name why Cloud pairing is unfollowable and close decoder shape restatement

State that the VM image writes settings.json so desktop leave-one-path
is unfollowable on Cloud. Qualify the adapter-skip prefix as inert for
the adapter only. Record that checklist item 6 consumes item 5. Name
that a last-message shape restatement is closed by the fingerprint regex.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* fix: drop unverified VM-image cause for Cloud settings.json

GitHub Claude on #2340 found the new causal claim contradicted the
adjacent unmeasured-origin sentence in the same paragraph. Soften both
copies: this VM's copy predates the session and its origin is
unmeasured; keep the instruction not to delete settings to clear pairing.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* fix: stop overclaiming Cloud pairing and decoder closure

Address Task child bc-a66c522f of 373b790: drop predates/unfollowable
on settings.json; state the decoder regex refuses a placeholder only
(ai-config#2343); disambiguate adapter inertness from the native guard.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* fix: drop redundant Cloud pairing restatement

Address Task child bc-4e9a147c of ffd5fc9: keep only the new
instruction (do not delete settings until native-runner firing is
measured); drop "that file" / "until both"; attribute the fingerprint
regex to parse_report; drop the fragment's native-guard capability claim.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

* fix: compact pairing hold names the file and the release

Address Task child bc-1fe50da0 of 134fd1d: Do/Don't names
settings.json and "until the native runner's firing is measured";
a restatement of the brief is not a report (refuse it); mapping doc
drops "unprefixed push".

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
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.

Cursor Cloud: dispatch adversarial-reviewer via Task; prefer Claude when the conductor is not Claude

3 participants