Repository navigation
fix: show REPEAT_ERROR in replay verdicts #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -109,6 +109,10 @@ def build_parser() -> argparse.ArgumentParser: | |
|
|
||
| replay = sub.add_parser("replay", help="Print an annotated event-by-event replay with detector verdicts.") | ||
| replay.add_argument("path", help="Path to a .jsonl file or directory.") | ||
| replay.add_argument( | ||
| "--repeat-n", type=int, default=REPEAT_N, metavar="N", | ||
| help=f"Consecutive failed bash threshold for REPEAT_ERROR (default: {REPEAT_N}).", | ||
| ) | ||
| return p | ||
|
|
||
|
|
||
|
|
@@ -501,12 +505,13 @@ def _process_new_lines(file_handle) -> int: | |
|
|
||
| # ── Replay ───────────────────────────────────────────────────────────────────── | ||
|
|
||
| def replay_file(filepath: str, *, loop_n: int = LOOP_N, loop_m: int = LOOP_M, osc_n: int = 4) -> int: | ||
| def replay_file(filepath: str, *, loop_n: int = LOOP_N, loop_m: int = LOOP_M, osc_n: int = 4, repeat_n: int = REPEAT_N) -> int: | ||
| """ | ||
| Print one annotated line per tool event with the detector verdict at that | ||
| point. Doubles as a debug surface and an honest terminal demo. | ||
| """ | ||
| window: deque = deque(maxlen=loop_m) | ||
| streak = 0 | ||
| exit_code = 0 | ||
| try: | ||
| fh = open(filepath, "r", encoding="utf-8", errors="replace") | ||
|
|
@@ -526,8 +531,11 @@ def replay_file(filepath: str, *, loop_n: int = LOOP_N, loop_m: int = LOOP_M, os | |
| window.append(fp) | ||
| osc, _ = detect_oscillation(window, osc_n) | ||
| loop_hit, _ = detect_loop(window, loop_n) | ||
| verdict = "⚠ OSCILLATION" if osc else ("⚠ LOOP" if loop_hit else "ok") | ||
| if osc or loop_hit: | ||
| streak = update_repeat_streak(streak, ev) | ||
| repeat_hit = streak >= repeat_n | ||
| verdict = ("⚠ OSCILLATION" if osc else ("⚠ LOOP" if loop_hit | ||
| else ("⚠ REPEAT_ERROR" if repeat_hit else "ok"))) | ||
| if osc or loop_hit or repeat_hit: | ||
| exit_code = 1 | ||
| print(f"{i:>4} {ev['tool']:<24} {verdict}", flush=True) | ||
| return exit_code | ||
|
|
@@ -567,7 +575,7 @@ def main(argv: list[str] | None = None) -> int: | |
| return 2 | ||
|
|
||
| if args.command == "replay": | ||
| return replay_file(target) | ||
| return replay_file(target, repeat_n=args.repeat_n) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Every Useful? React with 👍 / 👎.
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Already fixed — this finding is against a stale intermediate push. The PR branch was force-updated from |
||
|
|
||
| return watch_file( | ||
| target, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 Replay command crashes on every transcript
For any existing transcript,
mainreadsargs.repeat_n, but the replay parser never defines it. Replay exits withAttributeErrorbefore printing verdicts.Learn more
The replay subparser only registers
pathin build_parser. Argparse therefore creates norepeat_nattribute for replay. Reading it before invokingreplay_fileraisesAttributeError, so even ordinary replay commands fail. The new test checks return code 1, which is also the exit code from this unhandled exception.Example:
loopguard replay fixtures/repeat_error.jsonlprints a traceback and exits 1 instead of printing three annotated events.loopguard replay fixtures/repeat_error.jsonl --repeat-n 5rejects the option and exits 2.Recommended fix: Register
--repeat-nwith the replay subparser inbuild_parser, using the same default and integer type as watch. Extend the CLI test to assert the expected verdict, successful quiet replay with a higher threshold, and no traceback.Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already fixed — this finding is against a stale intermediate push. The PR branch was force-updated from
bd65b86(which had theAttributeErrorbug) to287cba9before merge;287cba9already registers--repeat-non the replay parser (build_parser, replay subparser) and passesrepeat_n=args.repeat_ntoreplay_file. Verified on currentmain(4a1a3ae):loopguard.py replay fixtures/repeat_error.jsonl→ prints verdicts, noAttributeError;replay --repeat-n 5→ quiet, exit 0. Also notetest_replay_detects_repeat_errorasserts on stdout content (REPEAT_ERRORverdict), not just the exit code, so it can't pass via a crash.