Skip to content

Hook fleet (1) event uid - #1331

Merged
mergify[bot] merged 3 commits into
mainfrom
plan/hook-fleet-1-event-uid
Oct 11, 2026
Merged

mergify[bot] merged 3 commits into
mainfrom
plan/hook-fleet-1-event-uid

Conversation

@EdbertChan

@EdbertChan EdbertChan commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

Summary

Small checker scripts fire each time the coding assistant does something, like sending a reply. Each one writes a line to a log saying how it went.

One action can fire many checkers. The log lines had nothing tying them back to the same action, so nobody could tell which lines belonged together.

Each log line now carries a short tag made from the message the assistant sent. Checkers fired by the same message get the same tag.

What the checkers print, and whether they pass or block, stays the same.

Review Claim

Every log line a checker writes gains a short tag that is the same for all checkers fired by one message, and nothing the checkers print or return changes.

Review Lane

behavior

Review Unit

engine-runtime

Safety Invariant

Hook stdout, stderr, and exit codes stay the same. The only change is one extra key, event_uid, on each row written to runs.jsonl.

The key is computed inside _row (engine/hooks/_runner/run.py:238 @ HEAD). The call to _row sits inside a try whose except Exception only sets a stderr line (engine/hooks/_runner/run.py:310-317 @ HEAD); the hook's own stdout and exit code are set before that block.

Assumptions: this body was drafted in a headless run, so this invariant is taken from the workflow's task description and is not confirmed by a person.

Slice Rationale

This is one claim split out of the larger hook fleet dispatcher work. It only adds the field. Anything that reads the field ships in its own later slice, producer first.

Non-goals

  • No reader of event_uid is added. report.py, dispatch.py, and doctor.py are untouched.
  • No change to hook stdout, stderr, exit codes, timeouts, or log rotation.
  • No test is added in this slice; test_run.py does not assert the new key. The proof is the base and head output under Measured.
  • The tag is the first 12 hex characters of a SHA-256 of the payload bytes. It is not a unique event id: two events with byte-identical payloads share a tag, and so do notify-mode runs with the same type and thread, because notify mode hashes only those two fields.

Measured

Command: bash /tmp/event_uid_repro.sh <ref> — copies run.py and outcome.py from the ref into a temp hooks folder, runs hook a.py and hook b.py on one payload, then a.py on a second payload, and prints each hook's exit, stdout, stderr, and the event_uid of each row in runs.jsonl.

  • base: origin/main at 0adc86f7
hook=a.py exit=0 stdout=hi stderr=
hook=b.py exit=2 stdout= stderr=blocked
hook=a.py exit=0 stdout=hi stderr=
row script=a.py event_uid=<missing>
row script=b.py event_uid=<missing>
row script=a.py event_uid=<missing>
repro exit=0
  • head: 40720858
hook=a.py exit=0 stdout=hi stderr=
hook=b.py exit=2 stdout= stderr=blocked
hook=a.py exit=0 stdout=hi stderr=
row script=a.py event_uid=5c6eb2624c27
row script=b.py event_uid=5c6eb2624c27
row script=a.py event_uid=e0b8cbc67860
repro exit=0

On head, rows one and two were fed the same payload and show the same tag; row three was fed a different payload and shows a different tag. The three hook= lines are identical in the base and head blocks above.

Test Plan

Test Plan
  • python3 engine/skills/make-pr/scripts/preflight.py --base origin/main --commit-only --dry-run
unit    engine-runtime: 1 file(s)
declare Review Unit: engine-runtime
gate    python3 scripts/ci/check_hook_test_coverage.py engine/hooks/_runner
gate    ruff check --select E9,F engine/hooks/_runner/run.py
ok      preflight passed
preflight exit=0
  • python3 -m unittest discover -s engine/hooks/_runner/tests -p "test_run.py" (Python 3.9.6)
Ran 20 tests in 3.921s

OK
  • python3 scripts/ci/check_hook_test_coverage.py engine/hooks/_runner
check_hook_test_coverage: OK (1 hook(s) checked)
exit=0
  • ruff check --select E9,F engine/hooks/_runner/run.py
All checks passed!
exit=0
  • python3.12 -m unittest discover -s engine/hooks/_runner/tests (every runner test file) — one test fails, the same one on base and head
FAIL: test_drained_verdict_leaves_a_metrics_row (test_outcome_gaps.JudgeVerdictsReachMetrics.test_drained_verdict_leaves_a_metrics_row)
AssertionError: 1 != 0 : []
Ran 113 tests in 19.775s

FAILED (failures=1)

The same command in a worktree at origin/main printed the same single FAIL: line and FAILED (failures=1). That test file is not in this diff.

Revert Plan

Revert Plan
  • Safe to revert? Yes
  • Revert command: git revert 083c513b
  • Post-revert steps: None. Rows written while this was live keep the extra key; nothing reads it.
  • Data migration? No

🤖 Generated with Claude Code


Note

Low Risk
Additive field on metrics logging only; no consumers or hook execution path changes.

Overview
Hook run metrics written to runs.jsonl now include event_uid, a 12-character hex prefix of SHA-256 over the stdin bytes passed into _row (full hook payload, or notify-mode meta). Checkers triggered by the same input share the same tag so log lines from one assistant action can be grouped.

Hook stdout, stderr, and exit codes are unchanged; only the JSONL row shape gains one key.

Reviewed by Cursor Bugbot for commit 4072085. Bugbot is set up for automated code reviews on this repo. Configure here.

EdbertChan and others added 3 commits October 11, 2026 14:22
Hook runs belonging to the same harness event had no shared key, so
grouping them for herd/wall-clock metrics relied on fragile 2s-window
inference. Add event_uid = sha256(stdin)[:12] to _row() so every
runner that receives the same stdin self-groups with zero coordination.
…runner metrics row gains an event_uid field that groups all hook runs belonging to one harness event, with no change to hook stdout, stderr, or exit codes.

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
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: 5330cf4f-7efd-43e4-9fc5-fbc19b9c9a89
…770-8d121c9e — Review claim: Every runner metrics row gains an event_uid field that groups all hook runs belonging to one harness event, with no change to hook stdout, stderr, or exit codes.

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
Change types: bugfix
Acceptance criteria: The branch contains only this claim, and the review step publishes one pull request.
@cursor

cursor Bot commented Oct 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: ac774614-69e2-4d91-a7eb-ecfdf3ac7a34)

@mergify

mergify Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Queued — the merge queue status continues in this comment ↓.

@EdbertChan

Copy link
Copy Markdown
Owner Author

@Mergifyio queue

@mergify

mergify Bot commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Merge Queue Status

This pull request spent 1 hour 59 seconds in the queue, including 59 minutes 58 seconds running CI.

Required conditions to merge
  • check-success = lint
  • check-success = test
  • check-success = validate

@mergify mergify Bot added the queued label Oct 11, 2026
@mergify
mergify Bot merged commit 24add65 into main Oct 11, 2026
7 checks passed
@mergify mergify Bot removed the queued label Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant