Skip to content

merge queue: checking #1336 on main (2745ccd), stacked on 4 pull requests ahead - #1347

Closed
mergify[bot] wants to merge 30 commits into
mainfrom
mergify/merge-queue/8ce367170e
Closed

mergify[bot] wants to merge 30 commits into
mainfrom
mergify/merge-queue/8ce367170e

Conversation

@mergify

@mergify mergify Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

✨ Pull requests batch (#1332, #1314, #1309) which was ahead in the queue failed. The pull request #1336 has been requeued. ✨

#1336 is queued for merge on branch main (2745ccd).

Stacked behind 4 pull requests queued ahead of this batch, not part of it. These checks run on a tip that also carries their commits, so a failure here can come from them as much as from #1336.

Queued ahead of this batch:

This pull request has been created by Mergify to speculatively check the mergeability of #1336.
You don't need to do anything. Mergify will close this pull request automatically when it is complete.

Required conditions of queue rule admin-bypass for merge:

  • check-success = test
  • check-success = lint
  • check-success = validate

Required conditions to stay in the queue:

---
all_scopes: false
checking_base_sha: 08fcc580dd377dea897f150b46c5dad7f68121e9
previous_check_retries: []
previous_failed_batches: []
pull_requests:
  - number: 1336
    scopes: []
scopes: []
...

EdbertChan and others added 30 commits October 8, 2026 06:55
Agents kept narrating by-model health and patching charts before splitting volume, fill, resolve, and filter — lock that check into standing defaults.

Co-authored-by: Cursor <cursoragent@cursor.com>
Change-Id: I8efc336daf9878751865cf3c4bac4d55cd50733f
Phrase-judge rejected leads that named only the trigger phrase; state the split and the stop-first catch as the lesson, with the triggers as examples.

Co-authored-by: Cursor <cursoragent@cursor.com>
Change-Id: I7dad9e54f9d280bb4d8f41ac06662293e39c9e05
…mple phrasing.

Co-authored-by: Cursor <cursoragent@cursor.com>
Change-Id: Idebc0f0ba74e47864bf479446a8e27b0574cdcde
…lesson.

Co-authored-by: Cursor <cursoragent@cursor.com>
Change-Id: Iaa84683fcf5a66e8f70a0dbf99ebcf19acc1d7a7
The dashboard-health defaults name that audit flag in backticks; the
skill-existence check must treat it as a process token, not a skill path.

Co-authored-by: Cursor <cursoragent@cursor.com>
Change-Id: I1afa1d44a91d2886300ab5f17843b8e583dbda0c
Rule-scope rejected a lead that named automate-mandate mid thrash; keep
named flags only as examples after the same-type-catch rule.

Co-authored-by: Cursor <cursoragent@cursor.com>
Change-Id: Ieedc8823a35a6be02d6b392d5c704f1b817d7ea1
Co-authored-by: Cursor <cursoragent@cursor.com>
tests/test_install.py and engine/hooks/_runner/tests/test_wrap_installed.py
asserted one settings entry per hook, so every per-hook guarantee they check
failed once CATSTACK_HOOK_DISPATCHER (#1122) collapsed an event to a single
_runner/dispatch.py entry: 70 failures and 1 error on #1122's head, all in
these two files.

load_config() in tests/test_install.py now reads an installed config and
expands a collapsed event back into one entry per hook, resolving each hook's
registration the way dispatch.py itself does (dispatch.load_event_hooks: the
cursor registry, or the hook's own manifest for claude and codex). Each
assertion therefore sees the identical shape in both layouts and keeps
checking the same guarantee -- right event, right harness, Stop mirrored to
SubagentStop or opted out, dead entries pruned, non-catstack entries
untouched. test_wrap_installed.py's fixture pins the flag off, since it
asserts the settings bytes install writes rather than a hook's registration.

#1122's own test_default_is_off_and_byte_identical_to_no_flag_at_all now
compares the default install against an install that sets the flag to
whatever flags.py resolves as the default, and clears the key from its own
environment first, so the flag-on run of the full suite cannot leak into the
"default" side of the comparison.

The CATSTACK_HOOK_DISPATCHER default is left off. Flipping it on is gated on
both full-suite runs passing, and the source branch
plan/hook-backlog-1c-install-tests-accept-the-one-entry-per-event-layout-default-on-only-if-both-suites-pass
never changed engine/hooks/_flags/flags.py, so that gate was not met there
and this commit does not claim it.

Cherry-picked from 6330abf on that branch.
The branch's two other content commits (engine/hooks/_runner/doctor.py,
scripts/test/run_skill_scenarios.py) are unrelated to this claim and are
left behind.
…ew claim: tests.test_install and test_wrap_installed accept both install layouts (one entry per hook with CATSTACK_HOOK_DISPATCHER off, one dispatcher entry per event with it on), and the flag defaults to on only if bash scripts/test/run_all_tests.sh passes with the flag on and off.

Review lane: behavior
Safety invariant: If either suite run fails, the default stays off. Per-hook guarantees stay checked in the dispatcher layout.
Files: tests/test_install.py, tests/test_wrap_installed.py
Change types: test
Acceptance criteria: This workflow publishes one pull request for the install-layout claim only.

Exit code: 0
Invoker-Finalize-Id: f459f9c9-a623-4fd7-9708-21cc3ae4cbda
…s/g0.t0.a-a464d403f-4908b6a4 — Review claim: tests.test_install and test_wrap_installed accept both install layouts (one entry per hook with CATSTACK_HOOK_DISPATCHER off, one dispatcher entry per event with it on), and the flag defaults to on only if bash scripts/test/run_all_tests.sh passes with the flag on and off.

Review lane: behavior
Safety invariant: If either suite run fails, the default stays off. Per-hook guarantees stay checked in the dispatcher layout.
Files: tests/test_install.py, tests/test_wrap_installed.py
Change types: test
Acceptance criteria: This workflow publishes one pull request for the install-layout claim only.
Review claim:
- An opt-in payload recorder in the runner plus a replay script can
  feed recorded hook-event payloads through installed hook commands
  and produce a verdict-equivalence report (stdout/context/block/exit)
  per detector.
Review lane: behavior
Safety invariant:
- Recording is off unless CATSTACK_HOOK_PAYLOAD_DIR is set; when on it
  never alters hook stdin/stdout/exit and caps each payload (default
  256KB) and total dir (default 2000 files, oldest evicted).
- Replay runs against a scratch metrics/state dir, never live
  settings or the live runs.jsonl.
Goal:
- Runner: when env var set, append the raw stdin payload to
  $CATSTACK_HOOK_PAYLOAD_DIR/<payload_hash>-<hook>.json before spawning
  the hook child, where <payload_hash> is sha256(stdin)[:12].
- scripts/test/replay_hook_payloads.py: for each recorded payload, run
  the hook command under a scratch env, capture stdout/stderr/exit/
  findings; emit an equivalence report JSON + table comparing two
  command sets (fleet vs dispatcher args taken as parameters).
Motivation:
- The catastrophic regression risk of the dispatcher is a detector
  that silently stops speaking; the only credible gate is
  byte-identical verdicts on real payloads.

Cherry-picked from origin/plan/hook-fleet-dispatcher-measure-the-herd-then-dispatch-it
(e356e8c), scoped to only this claim's files. Dropped this slice's
dependency on the separate metrics-event-uid claim (17ef151, not on
this branch): the payload recorder computes its own local hash instead
of reusing a published `event_uid` metrics-row field, and the README
wording and test imports were adjusted to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… payload recorder in the runner plus a replay script can feed recorded hook-event payloads through installed hook commands and produce a verdict-equivalence report per detector.

Review lane: behavior
Safety invariant: Hook stdout and exit codes stay the same. This slice does not change the other four claims.
Files: engine/hooks/_runner/run.py, scripts/test/replay_hook_payloads.py
Change types: bugfix
Acceptance criteria: The branch contains only this claim, and the review step publishes one pull request.

Exit code: 0
Invoker-Finalize-Id: 61e213a0-a6cd-4950-ba23-0acc17742997
…-1bc38490 — Review claim: An opt-in payload recorder in the runner plus a replay script can feed recorded hook-event payloads through installed hook commands and produce a verdict-equivalence report per detector.

Review lane: behavior
Safety invariant: Hook stdout and exit codes stay the same. This slice does not change the other four claims.
Files: engine/hooks/_runner/run.py, scripts/test/replay_hook_payloads.py
Change types: bugfix
Acceptance criteria: The branch contains only this claim, and the review step publishes one pull request.
The fleet self-saturates: one SubagentStop burst spawned 15-30 processes
that each re-parsed the same transcript, measured at 15.1s p50 wall idle
against 1.55s for a single process, with per-hook durations escalating in
launch order.

dispatch.py now runs opted-in detectors in-process, sequentially, parsing
the event once and passing the same parsed payload to every detector. A
hook opts in with subagent_stop.dispatch in its manifest, naming a
MODULE:FUNCTION entry point (default detect:detect). A detector with no
resolvable entry point still runs as a subprocess and its metrics row is
marked subprocess_fallback. Each detector keeps its own verdict, its own
runs.jsonl row under its own hook name, and its own rule_ids; a detector
that raises, exits, or overruns its 4s soft budget is caught and recorded
without stopping its siblings. The event budget defaults to 9s for
SubagentStop. mirror_stop_hooks_to_subagent_stop.py emits one dispatcher
entry for the opted-in hooks and leaves every other hook's direct entry
alone.

(cherry picked from commit 531f5c8 on
plan/hook-fleet-dispatcher-measure-the-herd-then-dispatch-it)
…op hooks dispatch through one process that parses the event once and shares one transcript parse across all opted-in detectors, emitting the same per-detector metrics rows and verdicts as the subprocess fleet.

Review lane: behavior
Safety invariant: Hook stdout and exit codes stay the same. This slice does not change the other four claims.
Files: engine/hooks/_runner/dispatch.py
Change types: bugfix
Acceptance criteria: The branch contains only this claim, and the review step publishes one pull request.

Exit code: 0
Invoker-Finalize-Id: aaa80940-f2d5-4d79-bb40-79c68fe333ad
…e5bede34 — Review claim: SubagentStop hooks dispatch through one process that parses the event once and shares one transcript parse across all opted-in detectors, emitting the same per-detector metrics rows and verdicts as the subprocess fleet.

Review lane: behavior
Safety invariant: Hook stdout and exit codes stay the same. This slice does not change the other four claims.
Files: engine/hooks/_runner/dispatch.py
Change types: bugfix
Acceptance criteria: The branch contains only this claim, and the review step publishes one pull request.
Subprocess isolation was the hook fleet's free safety property, so the
dispatcher has to prove it reproduced that property rather than assume
it.

_run_sdk_one caught a raising detector but left exit_code at 0, so
outcome.classify saw a zero exit with a catstack-hook-error stderr line
and recorded caught_error instead of crashed; the except branch now sets
exit code 1. Four chaos fixtures under engine/hooks/_runner/tests/chaos
(raise, sleep past the soft budget, exit 3, and a sibling that speaks)
drive a dispatcher test asserting each failure gets its own row with the
right outcome and exit code while both sibling detectors still emit
their verdicts and rows.

The fixtures are test-only: they live under tests/ and are registered in
a scratch manifest, so the mirror script's name allowlist can never
install them into a live settings.json.

(cherry picked from commit b57f27c on
plan/hook-fleet-dispatcher-measure-the-herd-then-dispatch-it)
…tectors that raise, hang past the soft budget, and exit non-zero each produce their own failure row while every sibling detector's verdict and row is still emitted.

Review lane: behavior
Safety invariant: Hook stdout and exit codes stay the same. This slice does not change the other four claims.
Files: engine/hooks/_runner/tests/chaos
Change types: bugfix
Acceptance criteria: The branch contains only this claim, and the review step publishes one pull request.

Exit code: 0
Invoker-Finalize-Id: 7ca2543e-d062-46fa-bbce-58264f6ae48f
…02624463 — Review claim: Fixture detectors that raise, hang past the soft budget, and exit non-zero each produce their own failure row while every sibling detector's verdict and row is still emitted.

Review lane: behavior
Safety invariant: Hook stdout and exit codes stay the same. This slice does not change the other four claims.
Files: engine/hooks/_runner/tests/chaos
Change types: bugfix
Acceptance criteria: The branch contains only this claim, and the review step publishes one pull request.
The SubagentStop dispatcher records an in-process exception as exit 0. This pull request records that same exception as a crashed row, so a sibling can still speak while the failure stays visible.

Co-authored-by: Cursor <cursoragent@cursor.com>
Change-Id: If063e8ba2ce12336b8a515be81a05bb1885d2ba9
@mergify mergify Bot mentioned this pull request Oct 12, 2026
2 tasks done
@mergify mergify Bot closed this Oct 12, 2026
@mergify
mergify Bot deleted the mergify/merge-queue/8ce367170e branch October 12, 2026 16:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant