Skip to content

Register remind-ums-on-scrutiny.py after #2262 - #2265

Merged
d-morrison merged 10 commits into
mainfrom
cursor/register-ums-scrutiny-hook-32a3
Aug 26, 2026
Merged

Register remind-ums-on-scrutiny.py after #2262#2265
d-morrison merged 10 commits into
mainfrom
cursor/register-ums-scrutiny-hook-32a3

Conversation

@dem-extra1

@dem-extra1 dem-extra1 commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Closes #2263.

#2262 authored hooks/remind-ums-on-scrutiny.py and left it in KNOWN_UNREGISTERED per README's activation gate. This follow-up binds it:

  • add the UserPromptSubmit inject entry to hooks/hooks.json
  • drop it from KNOWN_UNREGISTERED
  • drop not registered from the README catalog row
  • replace the "stays unregistered until its authoring PR merges" sentence in shared/workflow/run-ums-proactively.md with the live plugin / --fix activation sentence

Local verification on fee256c6: check-hook-catalog.py reports 42 registered and 1 known-unregistered; test_check_hook_catalog.py 11/11; hook suite 45/45; check-links.py clean; markdownlint 0 errors.

install-hooks.py --fix cannot bind this hook until this PR merges.

Refs #2261 / #2262.

Open in Web Open in Cursor 

cursoragent and others added 2 commits August 26, 2026 04:00
Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
README's activation gate forbade binding the hook in its authoring PR.
#2262 left it in KNOWN_UNREGISTERED. This follow-up adds the
UserPromptSubmit inject entry, drops the allowlist row, and updates the
catalog and fragment so they describe a live guard.

Closes #2263.

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 04:25
@github-actions

This comment has been minimized.

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

Fallback self-review after claude-review skipped (quota/credential) on earlier HEADs of this PR. Inspected origin/main...49d818d5 (feature commit fee256c6 plus merge of #2226 memories).

This PR registers hooks/remind-ums-on-scrutiny.py in hooks/hooks.json (UserPromptSubmit, inject-only), drops it from KNOWN_UNREGISTERED, drops not registered from the README catalog row, and replaces the fragment sentence that said the hook stayed unregistered with the live plugin / --fix activation sentence. Matcher logic is untouched.

Local verification: check-hook-catalog.py 42 registered / 1 known-unregistered; test_check_hook_catalog.py 11/11; hook suite 45/45; check-links.py clean; markdownlint 0 errors.

Findings

No actionable findings identified.

Catalog, README row, and hooks.json agree on event (UserPromptSubmit, no matcher). The why / _note claims match hooks/remind-ums-on-scrutiny.py. The activation sentence matches README's plugin vs --fix model.

Verdict: Ready for merge

Reviewed-Commit: 49d818d

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

Three commits on cursor/register-ums-scrutiny-* flip hooks/remind-ums-on-scrutiny.py (authored and merged separately, in #2262) from documented-but-inert to bound, plus one merge of origin/main.
The diff is four files, 21 insertions and 3 deletions:

  • hooks/hooks.json gains a UserPromptSubmit entry for the hook (timeout: 10, script, why, and a _note_not_a_stop_hook block), inserted after remind-learn-from-review.py.
  • scripts/check-hook-catalog.py drops "remind-ums-on-scrutiny.py": 2261 from KNOWN_UNREGISTERED, leaving one entry.
  • README.md's hook row loses its (not registered -- see ai-config#2261) parenthetical.
  • shared/workflow/run-ums-proactively.md replaces It stays unregistered until its authoring PR merges, per README. with a sentence describing the activation model.

Verification I ran in the worktree: scripts/check-hook-catalog.py passes non-vacuously (42 hooks registered ... 42 compared for event and matcher, one known-unregistered NOTE for no-incomplete-check-enumeration.py); scripts/test_check_hook_catalog.py 11/11; scripts/test_hooks.py 43/43 suites including test-remind-ums-on-scrutiny.py 45/45; check-links.py, validate-skills.py, and markdownlint-cli2@0.22.1 clean; no non-ASCII in any added line; semantic-line-breaks.py reports 0 paragraphs would change.
The four touched paths are byte-identical between the stale local origin/main (13b581f7) and the true remote tip (ad49f6fb, read via gh api .../contents?ref=), so the stale base does not distort this review, and git merge-tree --write-tree reports zero conflicts.
Deleted lines carry no logic or test: dropping the allowlist entry strengthens rather than weakens the checker, since the hook now falls into the event/matcher comparison instead of the marker-only branch.

Findings

  1. [Factual Error] hooks/hooks.json:112-113 --- the added note claims the hook "fills the hole those two leave -- a review-read before Address, and a closed Q&A that never said 'I was wrong'." The code beside it does not draw that line. hooks/remind-ums-on-scrutiny.py:176 makes _is_correction return True whenever the sibling's own ADMISSION regex matches, so an explicit admission following a question is a trigger, not an excluded case. Measured against a two-record transcript (are you sure about that?, then I was wrong -- the figure is 12, not 9 as I said.), all three hooks print: remind-ums-on-scrutiny ("questioned and then corrected"), remind-ums-after-error ("admitted an error"), and no-mistake-without-a-hook. The failure this produces is twofold. A reviewer reading the manifest to judge what registering the hook adds is told the two are complementary when they overlap on the corpus's commonest shape. And the user gets two reminders for one lesson whose discharge conditions differ --- remind-ums-after-error clears on a memory/skill write, while this one clears only on an explicit UMS/memorize/record-learnings action --- so writing the memory silences one and not the other. Either narrow _is_correction to exclude ADMISSION, or reword the note to say the questioned-wrong path deliberately overlaps the admission sibling.

  2. [Convention] shared/workflow/run-ums-proactively.md:193 --- the replacement sentence never answers the question the sentence it replaced answered. It stays unregistered until its authoring PR merges, per README. stated the hook's state; Activation follows the README model: the plugin loads it from hooks/hooks.json, and install-hooks.py --fix binds the non-plugin path. states a repo-wide mechanism and leaves a reader unable to tell whether this hook is bound. That mechanism is already stated twice at greater length --- README.md:543-550 and README.md:560-580 --- and a third time in the _note this same diff adds to hooks/hooks.json:116-118, so the fragment sentence carries no hook-specific fact. It is not free: check-context-closure.py reports the always-loaded closure at 275,836 bytes against a 200,000-byte budget (OVER BUDGET by 75,836 bytes), and this fragment is a d1 import at 21,977 bytes. The present tense compounds it --- "install-hooks.py --fix binds the non-plugin path" reads as done, while README.md:625-627 says explicitly "Don't: read the merge as the activation on the non-plugin path --- there, merging places a file and merges a manifest entry, and only a binding in settings.json makes it fire." Deleting the sentence outright leaves the fragment accurate and shorter; if a state claim is wanted, say the hook is bound in hooks/hooks.json and stop.

  3. [Convention] hooks/hooks.json:109-110 --- "for the same reason as the two UMS reminders above" has no resolvable referent. Four hooks precede this entry in the group, and only remind-ums-after-error.py's why names UMS; remind-learn-from-review.py is described in both its why and its README row as wanting "a recorded learning or mechanism", never as a UMS reminder. The sibling entry it was patterned on says "the two reminders above" without the qualifier (hooks/hooks.json:88), which is unambiguous in a way the copy is not. Name the two scripts.

  4. [Convention] scripts/check-hook-catalog.py:58-65 --- removing the second allowlist entry leaves a one-entry dict under a comment that explains a plural keying rationale: "Keyed per entry rather than sharing one issue number, because the entries are unregistered for different reasons and a reader of the printed NOTE would otherwise be sent to the wrong tracker. Two merged hooks were never registered, so they are inert: no-handrolled-verdict-parse.py and remind-brief-premises.py #1505 covers two hooks ... Guard a quoted phrase attributed to a corpus file that does not contain it #1527's hook is inert BY THE GATE". Neither Two merged hooks were never registered, so they are inert: no-handrolled-verdict-parse.py and remind-brief-premises.py #1505 nor Guard a quoted phrase attributed to a corpus file that does not contain it #1527 is in the dict. The stale issue numbers predate this branch, so that half is not this diff's doing; what this diff adds is that the plural framing now describes a set of one, and the diff edits that exact block. The failure is a future reader adding an entry and following the comment to trackers describing hooks that left the list.

Non-diff note, per the assignment-premise check: the brief names scripts/check-new-line-breaks.py, which does not exist in this tree. The checker is scripts/semantic-line-breaks.py, and it does not implement the rule the brief attributes to it --- run on the fragment it prints "Note: This tool does not implement the CI clause-break rule (NLB_CLAUSE_BREAKS). A clean run here may still fail in CI if a line >=80 chars contains a mid-line semicolon." The rule itself is enforced elsewhere in CI; grep finds NLB_CLAUSE_BREAKS nowhere in the repo but that advisory string. Either way the added fragment line (137 characters) carries no semicolon, so the rule is satisfied.

Verdict: Needs more work

Reviewed-Commit: 49d818d

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

cursoragent and others added 2 commits August 26, 2026 05:30
Reword the scrutiny-hook note to name the sibling scripts and to say
admission overlap is deliberate. State that this hook is bound in
hooks.json. Refresh the remaining allowlist comment. Note that --fix
binds only the manifest.

Refs #2263.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
Drop the fragment binding-status sentence. Trim the duplicated
allowlist header. Break the README allowlist sentence at the clause.

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

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Addressed the Claude adversarial-reviewer findings on 8bf265e7: named the sibling scripts, stated admission overlap is deliberate, dropped the fragment binding-status sentence, trimmed the allowlist header, and noted that --fix binds only the manifest. Timeout-on-huge-transcript is a class property of the three scanners, not unique to this registration. The stale CLAUDE.md sentence for remind-learn-from-review.py is the subject of #2266.

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

cursor Bot pushed a commit that referenced this pull request Aug 26, 2026
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>
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@cursor

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

#2294 merged to main at 6b7790fe (2026-08-26T10:18:51Z) and this PR is now CONFLICTING.

The collision is scripts/check-hook-catalog.py (KNOWN_UNREGISTERED): both PRs drop a different allowlist row from the same dict. README.md and hooks/hooks.json auto-merged. git merge-tree --write-tree origin/main origin/cursor/register-ums-scrutiny-hook-32a3 reports the conflict on that catalog file only.

This session will not push to cursor/register-ums-scrutiny-hook-32a3. Fetch origin/main and drop the remaining remind-ums-on-scrutiny.py row (the #1717 row is already gone on main).

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

@dem-extra1

Copy link
Copy Markdown
Collaborator Author

ARDI round dispositions for this round (adversarial subagent reviews of f327801, tree carried to ecd7602 by main-sync only):

Deferred: fetch-pattern over-fire (a Grep/Read whose arguments name a comment-fetch counts as a review-read) - declared deliberate in the hook docstring, predates this PR (#2262); sentinel-file accumulation in the shared tempdir - bounded per session, same shape as the sibling reminder hooks.

Resolved: branch staleness behind main - synced; the paired hook suite was re-run green (45/45) after the sync, and check-hook-catalog stays consistent (42 registered / 43 documented / 1 remaining allowlist entry, no-incomplete-check-enumeration.py, untouched by this PR).

The dispatched review verdict on f327801 was Ready for merge; no PR-owned file changed since. Merge remains blocked on a clean automated claude-review verdict for the current head (runs currently 429 on the account weekly limit); human review requested.

Posted by opencode (AI agent) --- not written by a human.

@dem-extra1
dem-extra1 requested a review from d-morrison August 26, 2026 10:28
cursor Bot pushed a commit that referenced this pull request Aug 26, 2026
The allowlist mapped unregistered hooks to a tracker issue but never
checked that the issue was still open. That is how #1717 stayed
allowlisted after it closed. Fail on a closed mapped issue so a closed
activation tracker cannot keep a hook silently inert.

When the issue cannot be fetched, print SKIP and do not fail -- that
is the documented offline path, not a silent pass. Tests inject states
via HOOK_CATALOG_ISSUE_STATES so they never hit the network.

Retarget remind-ums-on-scrutiny.py from closed #2261 to open #2265
(the registration follow-up) so the live catalog stays green without
registering the hook in this PR.

Closes #2302.

Co-authored-by: dem-extra1 <dem-extra1@users.noreply.github.com>
…crutiny-hook-32a3

# Conflicts:
#	scripts/check-hook-catalog.py
@github-actions
github-actions Bot removed the request for review from d-morrison August 26, 2026 17:22
@github-actions

This comment has been minimized.

@github-actions
github-actions Bot requested a review from d-morrison August 26, 2026 17:23
cursor Bot pushed a commit that referenced this pull request Aug 26, 2026
The injected `closed` token never parses JSON, and production #2265 is
open, so a regression that mapped a 200 `closed` body to None would
keep the suite green and SKIP after that tracker closed.

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

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Cursor Grok 4.6 is working on this --- resolving the KNOWN_UNREGISTERED conflict from #2294. Please hold off on pushing to this branch until I'm done.

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

The merge of origin/main into this branch conflicted on the allowlist
dict: this PR drops remind-ums-on-scrutiny.py, and #2294 already dropped
no-incomplete-check-enumeration.py. The merge kept the #1717 row, which
is now registered on main, so check-hook-catalog.py failed. Restore
main's keyed-per-entry comment and leave the dict empty. Keep this PR's
hooks.json registration of remind-ums-on-scrutiny.py.

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

Copy link
Copy Markdown
Collaborator

fix validation

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

cursor Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Fallback adversarial self-review after Claude review skipped (quota/credential) on this PR. Inspected origin/main...HEAD.

Summary of Changes

This branch registers remind-ums-on-scrutiny.py as a live UserPromptSubmit hook. It adds the binding to hooks/hooks.json (same command/timeout/script shape as the neighbouring UMS reminders), drops the script from KNOWN_UNREGISTERED, removes the README table's "not registered" marker, and deletes the matching "stays unregistered until its authoring PR merges" sentence from shared/workflow/run-ums-proactively.md. README also states that install-hooks.py --fix only binds entries already in hooks/hooks.json, so an allowlisted hook still needs its registration PR before post-merge step 3.75 can bind it.

The merge of origin/main after #2294 conflicted on scripts/check-hook-catalog.py (KNOWN_UNREGISTERED). Both PRs dropped a different allowlist row. The resolution empties the dict: this PR drops remind-ums-on-scrutiny.py, and #2294 already dropped no-incomplete-check-enumeration.py. The hooks.json registration of remind-ums-on-scrutiny.py is kept.

Findings

No actionable findings identified.

Catalog, event, and matcher now agree: python3 scripts/check-hook-catalog.py reports 43 registered / 43 documented / 0 known unregistered, and python3 scripts/test_check_hook_catalog.py is 11/11 including the live-repo case. Emptying KNOWN_UNREGISTERED does not vacate the allowlist checks; the suite still injects a synthetic allowlist. The hook itself still never emits "decision" and exits 0 (python3 hooks/test-remind-ums-on-scrutiny.py hooks/remind-ums-on-scrutiny.py: 45/45).

Verdict: Ready for merge

Reviewed-Commit: 5cadd82

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

Adversarial review of origin/main...HEAD.

Summary of Changes

This branch registers remind-ums-on-scrutiny.py as a live UserPromptSubmit inject hook after its authoring PR merged. It adds a hooks/hooks.json entry (same shape as remind-ums-after-error.py / remind-learn-from-review.py), drops the script from KNOWN_UNREGISTERED, removes the README catalog's "not registered" marker, deletes the fragment sentence that said the hook stayed inert until its authoring PR merged, and adds three README lines stating that install-hooks.py --fix only binds what is already in hooks.json.

Findings

No actionable findings identified.

Checks that survived inspection:

  • Catalog and binding match: python3 scripts/check-hook-catalog.py reports 43 registered, 43 documented, 0 known unregistered. The hook is bound once, on UserPromptSubmit, with no matcher.
  • Allowlist hygiene still runs with an empty production dict: python3 scripts/test_check_hook_catalog.py is 11/11, including the synthetic-allowlist cases.
  • Output shape: python3 scripts/check-hook-output-shape.py is clean. The new entry prints to stdout and returns 0; it never emits reason without decision.
  • Hook tests: python3 hooks/test-remind-ums-on-scrutiny.py hooks/remind-ums-on-scrutiny.py is 45/45.
  • --fix claim matches scripts/install-hooks.py: that script reads only hooks/hooks.json. A KNOWN_UNREGISTERED row is README-only, so 3.75 cannot bind it until a registration PR puts the script in the manifest.
  • _note_not_a_stop_hook overlap claim matches the scanner: _is_correction() treats an ADMISSION hit as a correction, so a questioned claim answered with "I was wrong" fires both this hook and remind-ums-after-error.py.
  • Deleted lines are the inert-state markers, not load-bearing tests or matcher logic. Cursor needs no extra catalog row; .cursor/hooks.json dispatches through the Claude manifest.

Verdict: Ready for merge

Reviewed-Commit: 5cadd82

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 for the adversarial review of 5cadd82: no findings. Nothing to Address, Rebut, or Defer.

Validate on that HEAD is pass (Ezra's "fix validation": the leftover KNOWN_UNREGISTERED row is gone).

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

dem-extra1 added a commit that referenced this pull request Aug 26, 2026
…2272)

* start: Cursor Task Claude adversarial-reviewer routing (closes #2270)

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

* cai: Cursor Task dispatches adversarial-reviewer; prefer Claude

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>

* Address Claude review of Cursor Task routing

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>

* Address remaining review findings on Cursor Task routing

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>

* Hedge Cursor Task routing claims the re-review falsified

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>

* Separate self-review dispatch from a cross-vendor second reviewer

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>

* Check HEAD around the Cursor Task child, not git status

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>

* Date Cursor Task measurements in Pacific and sweep sibling "only" claims

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>

* Retrieve Reviewed-Commit from the child report, not the Task JSON

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>

* Fail closed when Reviewed-Commit cannot be retrieved

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>

* Require Ready for merge and includeTranscripts on the fetch

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>

* Scope the skipped pre-push guard to Cursor Cloud, not any Task tool

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>

* Fail closed on a Cursor Task miss and a HEAD mismatch

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>

* Fail closed on an unclosed fence and name the hand comparison

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>

* State nested-fence close rules and drop the incomplete refuse list

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>

* Resolve shipped refs with dry-run and scope the skip to Cloud

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>

* Fail closed on a dry-run miss and drop the Cloud-only skip

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>

* Blank the fingerprint search and compare the dry-run source ref

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>

* Restore the override list and record the branch name

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>

* Make the transcript route the push gate

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>

* Break the Cursor Cloud override sentence after the semicolon

PR-event new-line-breaks failed on a 81-character added line in
skills/push/SKILL.md that packed two clauses around a mid-line
semicolon.

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

* Align the Do-bullet dry-run clause with the no-sha carve-outs

The summary bullet refused any dry-run that did not print the
fingerprint sha, which is the first push of a new branch and an
Everything up-to-date retry. Name the hand comparison the
transcript route discharges, and qualify the mechanism section
as Claude Code.

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

* fix: match Cursor Task review recipe to VERDICT_LINE and adapter scope

Address the Claude Opus Task child of ea38ed0:
allow an optional ATX prefix on the hand-parsed Verdict line,
treat the transcript as the source of the comparison rather than
a discharge of it, scope the inert ALLOW_UNREVIEWED_PUSH prefix
to wherever the adapter skips the guard, and qualify the pre-push
claim on CLAUDE.md and both persona copies.

Defer a parse_report CLI wrapper to #2299.

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

* Address adversarial-review findings on the Cursor Task route

# Conflicts:
#	memories/cursor.md
#	skills/push/SKILL.md

* fix: pin Verdict emphasis position and name the adapter in fragments

Address the Claude Opus Task child of 1004f34:
optional ** on a Verdict line is only between the colon and the value,
an unrecognized final verdict fails closed,
the transcluded fragment names Morrison-Lab/ai-config,
the push-skill pronoun names the guard,
and the Copilot contrast no longer repeats the billing blurb.

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

* fix: restore two-space indent on the Task-route Do-bullet

The parallel Address commit left four continuation lines at three
spaces, which nested them under the bullet rather than continuing it.

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

* Widen the no-override scope to Cursor desktop as well as Cloud

* fix: qualify the Cursor prefix-inert claim as Cloud-only

Address the Claude Opus Task child of 2c0ed03:
the adapter skip makes ALLOW_UNREVIEWED_PUSH inert on Cloud,
but desktop third-party Claude hooks still run the native guard,
so that prefix is the escape there.
Pin Reviewed-Commit to 7-40 hex, read dry-run stderr,
put the transcript subagent first, and restore dispatch-pairing scope.

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

* fix: compare only the new tip on a Cursor Task dry-run

Git prints old..new on a fast-forward. Treating every displayed sha
as shipped would reject a normal push. Compare only the right-hand tip.

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

* fix: handle git-push `...` dry-run ranges and #2241 provenance

The d8d5bc3 Claude child found the dry-run gate split on `..`
inside a forced-update `...` summary, skipped lowercasing the
fingerprint, treated an unrecognized Verdict: line ambiguously,
and left the adapter-skip claim undated at four sites.

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

* fix: key the prefix on the hook system and call parse_report

The 0ae0db8 Claude child found Cloud home Claude settings after
bootstrap, so "no home settings" was a false mechanism, and the
hand-specified VERDICT_LINE recipe duplicated parse_report().

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

* fix: require HEAD to still be the recorded sha after the child

The 852aaf9 Claude child found the fingerprint gate's "or HEAD"
reading admitted a stale pre-dispatch sha, cited _rev_parse for
a check that lives in verify_review, and left pr-on-claim with
no action once the prefix was withheld.

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

* fix: require a clean HEAD-matching parse_report on compact copies

The 51aa928 Claude child found AGENTS.md and skills/push treating
parse_report() as enough, a stale "Cloud has no ~/.claude" line,
and an exclusive "the one running" split that both-sources falsifies.

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

* fix: name install-hooks as Cloud settings writer

Address the Claude Opus child of 9488dac (bc-1ddb6849):
stop attributing Cloud ~/.claude/settings.json to bootstrap.sh,
qualify the adapter prefix as for the adapter's sake, split
parse_report into decoder and verbatim-subagent routes, drop
restore/again for #2241, phrase the persona call as required,
name the last heading-bearing assistant text, and keep the
parse_report gate once in skills/push. Rebut 40-55 char wraps
(suggestion-weight; check-new-line-breaks is clean).

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

* fix: carve out empty pr-on-claim and qualify Cloud settings provenance

Address the Claude Opus child of f22a0f5 (bc-e67d9844):
authorize the empty pr-on-claim push when there is no report,
require both parse_report routes to produce the report body,
scope the import as the Cursor Cloud recovery instrument and
name #2255 pre-push-review.py / #2309, separate the Cloud
settings.json measurement from how that file got there, add a
Do-Confirm refusal-gate checklist, and name the adapter checkout
in both personas. Rebut restating the parse_report gate across
compact copies (required by the prior child of 9488dac).

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

* fix: make the pr-on-claim carve-out decidable and scoped

Address the Claude Opus child of 2da6c8c (bc-e24f4da3):
drop the false claim that provenance lives in #2299, decide
the empty-branch carve-out with git diff ...HEAD and require
disclosure, scope that carve-out in AGENTS.md and keep the
Claude Code prefix, name Morrison-Lab/ai-config's adapter in
AGENTS.md, and state adapter inertness unconditionally.
Filed #2310 for the remaining git-decidable gates.
Rebut mid-phrase wrapping (suggestion-weight; the blocking
new-line-breaks gate is clean).

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

* fix: scope Cursor review gates to the push checkout

Address the Claude Opus child of 751875a (bc-5f5b3190):
run all six refusal gates in the checkout whose push follows,
recover the report through a file, name the adapter checkout
in the push skill, add checklist pause points and killer items,
and treat per-ref up-to-date and ref-deletion dry-run forms
as not this procedure.

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

* fix: correct deletion claim and tighten Cursor review gates

Address the Claude Opus child of 3466ef7 (bc-d5e046e3):
drop the false verify_review-allows-deletion claim,
state carve-out exemptions on every vacated gate,
relabel the gate list Read-Do with inline killer items,
require the verdict-line form on Cursor as well as Claude Code,
default ALLOW_UNREVIEWED_PUSH off until a native deny,
name tree-equality vs net-zero other commits,
record the #2241 landing sweep, and decode transcript.json once.

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

* fix: grade Cursor reviews only from transcript.json

Address the Claude Opus child of 92be0ac (bc-63006d82):
parse_report always runs on route (a)'s transcript file,
split :branch vs --delete handling, drop intra-passage
native-deny restatements, and name parse_report as the
fingerprint reader in both persona copies.

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

* fix: decide the pr-on-claim carve-out with two git commands

A Cursor Task child of f55e60c showed `_argv_push` excludes
`--delete` rather than ignoring it, that the transcript is not
the source for dry-run gates, and that the empty-branch carve-out
had no positive test. Import parse_report from the worktree hook.

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

* fix: import parse_report from the worktree, not ~/.claude

A Cursor Task child of 95b55f4 showed ~/.claude/hooks is a
directory symlink into the primary checkout, not a copy, and that
writing the recovered report inside the push checkout trips the
empty-status gate. Keep compact copies; drop parent-obligation
lines from the reviewer persona.

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

* fix: scope parse_report import to an ai-config worktree

A Cursor Task child of b39eaac showed the worktree-hook import
is unfollowable outside ai-config, that one matching dry-run line
was enough to pass gates 5-6, and that skills/push dropped the
missing-fingerprint refusal. Fetch only an adversarial-reviewer
child. Add CLAUDE.md to the #2241 sweep.

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

* fix: fail-closed empty-commit carve-out and scoped hook import

Address Cursor Task child bc-74f98435 of a0124f7.
Drop the undefined Route (a) label.
Import ~/.claude/hooks only from a non-ai-config checkout.
Test the parse_report script, not the hooks/ directory.
Require both carve-out git commands to succeed.
Put provenance on gate 2.
Name the dry-run and source-ref checks.
Scope "all six" to the git commands.
Rebut collapsing AGENTS.md compact copies.

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

* fix: last-assistant report selector and disclosure on post

Address Cursor Task child bc-16017d04 of dbf359d.
Return the structured report as the call's own message.
Post the recovered file then the disclosure marker.
Import ~/.claude/hooks only when that file exists
on a non-ai-config checkout; otherwise CLI review.
Add pr-on-claim.md to the #2241 sweep.
Take the last assistant text; do not scan backward.
Drop the circular step-0 link.
Name the file pair for the inode measurement.
Narrow the gate-list ordering claim.

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

* fix: unify last-nonempty assistant selector and name messages

Address Cursor Task child bc-7e680d49 of 6d665f7.
Take the last non-empty assistant text; empty thinking and
tool_calls records are not candidates.
Iterate json.load's messages list.
Fix the pr-on-claim ALLOW_UNREVIEWED_PUSH=1 cause
(reviewer-call gate, not shipped-commit).
Gate 3 consumes gate 2's tuple.
Name the verdict-line form as parse_report's referent.
Say the recovered file is both the parse_report input
and the posted comment body.

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

* fix: post recovered file only; quiet empty-commit carve-out

Address Cursor Task child bc-497f3009 of 882ed05.
Always recover the transcript file; a harness paste may
corroborate and is not the posted body.
Drop the ~/.claude/hooks import fallback (unfresh copy).
Compact copies name the transcript recovery and the
always-true reason not to import that path.
Use git diff --quiet HEAD^ HEAD for the empty-commit carve-out.
Drop the adjacent tuple-is-the-push-gate duplicate.

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

* fix: name parse_report's accepted verdict forms

Address Cursor Task child bc-a728241f of 8be8093.
parse_report accepts Needs work, an optional heading, and
spaces around the colon; wrapping the whole verdict line
is no verdict.
Call parse_report from the worktree hook on the recovered
report. On a failed dispatch, write the CLI review to /tmp
and parse that file. Anchor the settings.json measurement
in docs/cursor-hook-mapping.md. Scope the push-skill
recovery to Cursor Cloud Task.

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

* fix: require .get on transcript text and a bare fingerprint

Name that thinking records usually omit text, parse origin/main's
parse_report when the diff touches the hook, show Reviewed-Commit
as a bare line, and label the refusal-gate checklist as Read-Do.

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

* fix: prefix empty-claim push and close parse_report's else

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>

* fix: move claim-push prefix out of the shared block

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>

* fix: name the -u dry-run upstream line and decoder heading check

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>

---------

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

Copy link
Copy Markdown
Contributor

Claude finished reviewView run


Code review

This is a small, mechanical follow-up PR that binds hooks/remind-ums-on-scrutiny.py (authored in #2262) into the active hook set now that its registration PR (this one) is itself merging. Four coordinated edits:

  1. README.md: drops "(not registered — see ai-config#2261)" from the hook's catalog row.
  2. hooks/hooks.json: adds the UserPromptSubmit entry for the hook, matching the schema/structure of sibling hooks exactly (type, command, timeout, script, why, _note_not_a_stop_hook).
  3. scripts/check-hook-catalog.py: empties KNOWN_UNREGISTERED (was {"remind-ums-on-scrutiny.py": 2261}).
  4. shared/workflow/run-ums-proactively.md: drops the now-false "It stays unregistered until its authoring PR merges" sentence.

Verification performed:

  • python3 scripts/check-hook-catalog.py at HEAD: 43 hooks registered in hooks.json; 43 documented in README (0 known unregistered); 43 compared for event and matcher — consistent, no drift.
  • python3 scripts/test_check_hook_catalog.py: 11/11 passed.
  • python3 hooks/test-remind-ums-on-scrutiny.py hooks/remind-ums-on-scrutiny.py: 45/45 correct.
  • python3 scripts/check-links.py: 2453 links checked, no broken links.
  • npx markdownlint-cli2 on the two changed .md files: 0 issues.
  • python3 -m py_compile hooks/remind-ums-on-scrutiny.py: compiles cleanly (pre-existing file, unchanged by this PR).
  • Confirmed hooks/hooks.json's new entry matches every sibling hook's schema.
  • Confirmed the new README.md prose (--fix binds only what is already in hooks/hooks.json...) accurately describes skills/post-merge/SKILL.md's step 3.75, which exists as described.
  • Grepped the whole repo for remind-ums-on-scrutiny — every reference (README, hooks.json, the hook file, its test, and the workflow doc) is now internally consistent with the "registered" state.
  • No em-dashes or non-ASCII punctuation introduced (repo's ASCII-punctuation-in-source rule).

I noted one pre-existing stale comment in scripts/check-hook-catalog.py (a block comment above KNOWN_UNREGISTERED still references specific past entries #1505/#1527 that are no longer in the dict), but git log -p confirms that comment predates this PR and was already stale before this diff — out of scope per the pre-existing-issues exclusion.

No issues found. Checked for bugs and CLAUDE.md/lab-manual compliance.

Verdict

Ready for merge

Reviewed commit: 18628be

@github-actions

Copy link
Copy Markdown
Contributor

💰 Cost: $1.8607 (review) — run

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.

Register remind-ums-on-scrutiny.py after #2262

3 participants