Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e024cd3
llm-judge: a shared background model judge for hooks
edbert-bot Sep 11, 2026
5efb763
invoker: wf-1789117938963-6/implement-llm-judge-library — Add engine/…
edbert-bot Sep 11, 2026
7be661c
invoker: wf-1789117938963-6/verify-llm-judge-library — Run the judge …
edbert-bot Sep 11, 2026
0e6fb2c
invoker: wf-1789117938963-6/scrub-handoff-artifacts — Terminal read-o…
edbert-bot Sep 11, 2026
d90b880
Merge experiment/wf-1789117938963-6/scrub-handoff-artifacts/g0.t0.a-a…
edbert-bot Sep 11, 2026
99852d1
llm-judge: deliver finished verdicts on the agent's next turn
edbert-bot Sep 11, 2026
e322f6e
invoker: wf-1789118621517-7/implement-llm-judge-inbox — Add the llm-j…
edbert-bot Sep 11, 2026
ece2f67
invoker: wf-1789118621517-7/verify-llm-judge-inbox — Run the inbox te…
edbert-bot Sep 11, 2026
84a9065
invoker: wf-1789118621517-7/scrub-handoff-artifacts — Terminal read-o…
edbert-bot Sep 11, 2026
81f2b22
Merge experiment/wf-1789118621517-7/scrub-handoff-artifacts/g0.t0.a-a…
edbert-bot Sep 11, 2026
fdc3f18
invoker: wf-1789119854592-8/implement-wrong-check-judge — wrong-check…
edbert-bot Sep 11, 2026
71ab0d8
invoker: wf-1789119854592-8/verify-wrong-check-judge — Run wrong-chec…
edbert-bot Sep 11, 2026
a200478
invoker: wf-1789119854592-8/scrub-handoff-artifacts — Terminal read-o…
edbert-bot Sep 11, 2026
78dc644
Merge experiment/wf-1789119854592-8/scrub-handoff-artifacts/g0.t0.a-a…
edbert-bot Sep 11, 2026
05eb32a
wrong-check-reflect: drop 7 comment lines the no-comments gate bans
EdbertChan Sep 11, 2026
2e0bb00
Add llm judge phrase loader
Sep 11, 2026
05bc597
invoker: wf-1789159008754-1/add-phrase-loader — Review claim: A check…
Sep 11, 2026
a3013d7
docs: add phrase judge skill
Sep 11, 2026
081809e
invoker: wf-1789159008754-1/document-phrase-judge-skill — Review clai…
Sep 11, 2026
cbf3b6b
invoker: wf-1789159008754-1/verify-phrase-loader-tests — Review claim…
Sep 11, 2026
b53b5d3
invoker: wf-1789159008754-1/verify-phrase-module-dormant — Review cla…
Sep 11, 2026
00bc2c1
invoker: wf-1789159008754-1/verify-phrase-skill-checks — Review claim…
Sep 11, 2026
4e78d32
Invoker: merge experiment/wf-1789159008754-1/verify-phrase-skill-chec…
Sep 11, 2026
2dbd843
Invoker: merge experiment/wf-1789159008754-1/verify-phrase-module-dor…
Sep 11, 2026
2a072f8
invoker: wf-1789159008754-1/scrub-handoff-artifacts — Review claim: N…
Sep 11, 2026
37bb35c
Merge experiment/wf-1789159008754-1/scrub-handoff-artifacts/g0.t0.a-a…
EdbertChan Sep 11, 2026
3008239
llm-judge phrases: ask the judge to match meaning in any wording
EdbertChan Sep 11, 2026
4274083
test_install: expect phrase-judge in the engine-only skill set
EdbertChan Sep 11, 2026
9f63b22
Merge origin/main into phrase judge (1) after #425's squash merge
EdbertChan Sep 11, 2026
6ad6afd
llm-judge: add after-tool delivery scripts
EdbertChan Sep 12, 2026
e9f096b
invoker: wf-1789160500325-2/add-after-tool-delivery-scripts — Review …
Sep 12, 2026
895ef75
invoker: wf-1789160500325-2/verify-after-tool-scripts-not-installed —…
EdbertChan Sep 12, 2026
6fd77d8
invoker: wf-1789160500325-2/verify-after-tool-delivery-tests — Review…
EdbertChan Sep 12, 2026
94d1a62
invoker: wf-1789160500325-2/verify-after-tool-scripts-not-installed —…
EdbertChan Sep 12, 2026
d654dce
invoker: wf-1789160500325-2/verify-after-tool-scripts-not-installed —…
EdbertChan Sep 12, 2026
2fba057
invoker: wf-1789160500325-2/verify-after-tool-scripts-not-installed —…
EdbertChan Sep 12, 2026
afb5f6a
Invoker: merge experiment/wf-1789160500325-2/verify-after-tool-script…
Sep 12, 2026
220b253
invoker: wf-1789160500325-2/scrub-handoff-artifacts — Review claim: N…
Sep 12, 2026
79e3e90
Merge main: adopt landed llm-judge PostToolUse tests (#444), keep the…
EdbertChan Sep 12, 2026
b2f5c95
Merge main: adopt landed llm-judge PostToolUse tests (#444), keep the…
EdbertChan Sep 12, 2026
55184b7
Merge main: adopt landed llm-judge PostToolUse tests (#444), keep the…
EdbertChan Sep 12, 2026
779eb78
Merge main: adopt landed llm-judge PostToolUse tests (#444), keep the…
EdbertChan Sep 12, 2026
ef8aa81
Merge experiment/wf-1789160500325-2/add-after-tool-delivery-scripts/g…
EdbertChan Sep 12, 2026
959e376
Merge experiment/wf-1789160500325-2/verify-after-tool-delivery-tests/…
EdbertChan Sep 12, 2026
7e78683
Merge experiment/wf-1789160500325-2/verify-after-tool-scripts-not-ins…
EdbertChan Sep 12, 2026
fbdc0ce
Merge experiment/wf-1789160500325-2/scrub-handoff-artifacts/g1.t6.a-a…
EdbertChan Sep 12, 2026
4ccb37d
Merge main
EdbertChan Sep 12, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion engine/hooks/bug-complaint-leak/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ like "add a comment to Foo.ts".
- `state.py` — session cache for empty/repeat Grep
- `claude_prompt_submit.py` — Claude `UserPromptSubmit` inject
- `claude_pretooluse_grep.py` / `claude_posttooluse.py` — Grep leak gate
- `cursor_before_submit.py` / `cursor_post_tool_use.py` — Cursor parity
- `cursor_before_submit.py` / `cursor_posttooluse.py` — Cursor parity
(`beforeSubmitPrompt` cannot inject context; checklist arrives on first
`postToolUse` via `additional_context`)
- `install_claude_hook.py` / `install_cursor_hook.py` — merge, do not overwrite
Expand Down
2 changes: 1 addition & 1 deletion engine/hooks/bug-complaint-leak/cursor_before_submit.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""Cursor beforeSubmitPrompt: remember bug-complaint checklist for later inject.

Cursor's beforeSubmitPrompt schema is continue/user_message only; injection
happens on the next postToolUse via cursor_post_tool_use.py. Fail-open.
happens on the next postToolUse via cursor_posttooluse.py. Fail-open.
"""
from __future__ import annotations

Expand Down
14 changes: 7 additions & 7 deletions engine/hooks/bug-complaint-leak/install_cursor_hook.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

If hooks.json is currently a symlink into diu-stop (legacy install.sh layout),
replace it with a real file so merges never rewrite the diu-stop fragment.

Our own entries are recognised by hook directory (MARKER), not by script
filename, so a reinstall replaces an entry written under an earlier script name
instead of leaving it behind pointing at a path that no longer exists.
"""
from __future__ import annotations

Expand All @@ -27,17 +31,13 @@
],
"postToolUse": [
{
"command": "python3 $HOME/.cursor/hooks/bug-complaint-leak/cursor_post_tool_use.py",
"command": "python3 $HOME/.cursor/hooks/bug-complaint-leak/cursor_posttooluse.py",
"timeout": 5,
}
],
}

MARKERS = {
"beforeSubmitPrompt": "bug-complaint-leak/cursor_before_submit.py",
"preToolUse": "bug-complaint-leak/claude_pretooluse_grep.py",
"postToolUse": "bug-complaint-leak/cursor_post_tool_use.py",
}
MARKER = "bug-complaint-leak/"

DIU_STOP = {
"type": "prompt",
Expand Down Expand Up @@ -99,7 +99,7 @@ def main() -> None:
changed = False
for key, incoming in FRAGMENT.items():
before = json.dumps(hooks.get(key, []), sort_keys=True)
hooks[key] = merge_list(list(hooks.get(key, [])), incoming, MARKERS[key])
hooks[key] = merge_list(list(hooks.get(key, [])), incoming, MARKER)
after = json.dumps(hooks[key], sort_keys=True)
if before != after:
changed = True
Expand Down
3 changes: 3 additions & 0 deletions engine/hooks/llm-judge/tests/test_post_tool_use.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ def test_hit_is_delivered_as_additional_context_once(self):
again = self.run_script(self.script, self.payload())
self.assert_empty_success(again)
self.assertEqual(again.stderr, "")
self.assertEqual(json.dumps(data).count(ON_HIT) + again.stdout.count(ON_HIT), 1)

def test_no_verdict_prints_nothing(self):
result = self.run_script(self.script, self.payload())
Expand All @@ -111,6 +112,7 @@ def test_hit_is_delivered_as_additional_context_once(self):
again = self.run_script(self.script, self.payload())
self.assert_empty_success(again)
self.assertEqual(again.stderr, "")
self.assertEqual(json.dumps(data).count(ON_HIT) + again.stdout.count(ON_HIT), 1)

def test_no_verdict_prints_nothing(self):
result = self.run_script(self.script, self.payload())
Expand All @@ -135,6 +137,7 @@ def test_hit_is_delivered_as_additional_context_once(self):
again = self.run_script(self.script, self.payload())
self.assert_empty_success(again)
self.assertEqual(again.stderr, "")
self.assertEqual(json.dumps(data).count(ON_HIT) + again.stdout.count(ON_HIT), 1)

def test_no_verdict_prints_nothing(self):
result = self.run_script(self.script, self.payload())
Expand Down
14 changes: 9 additions & 5 deletions engine/hooks/repeat-error-stop/install_cursor_hook.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
#!/usr/bin/env python3
"""Idempotently merge repeat-error-stop into Cursor hooks.json."""
"""Idempotently merge repeat-error-stop into Cursor hooks.json.

Our own entries are recognised by hook directory (MARKER), not by script
filename, so a reinstall replaces an entry written under an earlier script name
instead of leaving it behind pointing at a path that no longer exists.
"""
from __future__ import annotations

import copy
Expand All @@ -19,20 +24,19 @@
}],
"postToolUse": [{
"matcher": "*",
"command": "python3 $HOME/.cursor/hooks/repeat-error-stop/cursor_post_tool_use.py",
"command": "python3 $HOME/.cursor/hooks/repeat-error-stop/cursor_posttooluse.py",
"timeout": 5,
}],
}
MARKERS = {key: entries[0]["command"].split("$HOME/.cursor/hooks/")[1] for key, entries in FRAGMENT.items()}
MARKER = "repeat-error-stop/"


def merge_hooks(data: dict) -> dict:
result = copy.deepcopy(data)
result.setdefault("version", 1)
hooks = result.setdefault("hooks", {})
for hook_type, incoming in FRAGMENT.items():
marker = MARKERS[hook_type]
kept = [entry for entry in hooks.get(hook_type, []) if marker not in str(entry.get("command", ""))]
kept = [entry for entry in hooks.get(hook_type, []) if MARKER not in str(entry.get("command", ""))]
hooks[hook_type] = kept + copy.deepcopy(incoming)
return result

Expand Down
Loading