Skip to content

Commit 3f2c69e

Browse files
Repair parity registry review findings
1 parent 037a696 commit 3f2c69e

6 files changed

Lines changed: 2202 additions & 1147 deletions

File tree

compat-test/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ python compat_test.py --rounds 5 # override the official round cou
7979
python compat_test.py --retry-failed # re-run only FAIL/ERROR robots
8080
python compat_test.py --retry-unresolved # re-run every unresolved parity case
8181
python compat_test.py --retest-cause lifecycle # re-run unresolved cases tagged to one cause
82+
python compat_test.py --retest-cause lifecycle --repair 249cdaf # link retest to its repair
8283
python compat_test.py --sync-registry --registry-manifest C:\path\to\run-manifest.json
8384
python compat_test.py --force # re-run everything
8485
python compat_test.py --report-only # just regenerate the report
@@ -198,7 +199,7 @@ untested robot. Completed robots are never re-run unless `--force` (everything)
198199
Full error details land in `errors/robocode/<robot>.log` and
199200
`errors/tank-royale/<robot>.log`; the master table is `compatibility_report.md`.
200201

201-
`parity-registry.json` is the tracked evidence carrier. It appends each subject observation with its jar identity, setup, engine artifacts, normalized errors, and current diagnosis. `parity-registry.md` renders the current status of every subject for review. Import an existing checkpoint with `--sync-registry`; after a diagnosis, tag a case with `--set-cause <subject> <cause> <owner>` and rerun that cause with `--retest-cause <cause>`.
202+
`parity-registry.json` is the tracked evidence carrier. It appends each subject observation with the exact jar identity, setup, engine artifacts, normalized errors, and focused retest link. It also retains an append-only diagnosis history, so a later triage decision cannot rewrite an earlier one. `parity-registry.md` renders the current status of every subject for review. Import an existing checkpoint with `--sync-registry`; after a diagnosis, tag a case with `--set-cause <subject> <cause> <owner>` and rerun that cause with `--retest-cause <cause> --repair <commit-or-PR>`.
202203

203204
**Every row states the setup it was measured at.** The report is regenerated from the state
204205
file long after the battles ran, so a single header describing the current configuration

compat-test/compat_test.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@
3939
from pathlib import Path
4040

4141
from parity_registry import (
42+
add_diagnosis,
4243
compare_errors,
44+
diagnosis_for_cause,
4345
error_signatures,
4446
is_unresolved,
4547
load_registry,
@@ -302,7 +304,7 @@ def collected():
302304
if time.time() > deadline:
303305
kill_process_tree(proc)
304306
return -1, collected() + "\n<killed: orchestrator timeout>", True
305-
if abort_when():
307+
if abort_when("".join(chunks)):
306308
kill_process_tree(proc)
307309
return -1, collected() + "\n<stopped: exception with no classic counterpart>", False
308310
time.sleep(poll_seconds)
@@ -338,13 +340,23 @@ def __init__(self, bot_dirs, rc_signatures):
338340
self.found = set()
339341
self.triggered = False
340342

341-
def __call__(self):
343+
def __call__(self, worker_output=""):
344+
"""Check both bot logs and runner/worker output received so far.
345+
346+
Runner output arrives through ``run_java`` while the process is live. Looking at
347+
it here gives C-004 the same fail-fast behavior for exceptions reported by the
348+
runner or worker as for exceptions written by a staged bot.
349+
"""
342350
for d in self.bot_dirs:
343351
for log_name in ("stderr.log", "stdout.log"):
344352
for signature in error_signatures([], read_capped(d / log_name)):
345353
key = (signature["exception"], signature["origin"])
346354
if key not in self.rc_signatures:
347355
self.found.add(key)
356+
for signature in error_signatures([], worker_output):
357+
key = (signature["exception"], signature["origin"])
358+
if key not in self.rc_signatures:
359+
self.found.add(key)
348360
self.triggered = bool(self.found)
349361
return self.triggered
350362

@@ -970,9 +982,10 @@ def should_run(entry, opts, registry=None, key=None):
970982
if opts.confirm_score and entry.get("status") == "DISCREPANCY (score)":
971983
return True
972984
if opts.retest_cause and registry is not None and key:
973-
diagnosis = registry.get("subjects", {}).get(key, {}).get("diagnosis", {})
985+
diagnosis = diagnosis_for_cause(registry.get("subjects", {}).get(key, {}),
986+
opts.retest_cause)
974987
return (is_unresolved(entry.get("status", ""))
975-
and diagnosis.get("cause") == opts.retest_cause)
988+
and diagnosis is not None)
976989
if opts.retry_failed:
977990
return entry.get("status", "").startswith(("FAIL", "ERROR", "HARNESS", "DISCREPANCY"))
978991
return False
@@ -1036,6 +1049,8 @@ def parse_args():
10361049
help="run five official repeats for score-review cases")
10371050
p.add_argument("--retest-cause",
10381051
help="re-run unresolved registry cases tagged with this diagnosis cause")
1052+
p.add_argument("--repair",
1053+
help="repair reference recorded on observations made by --retest-cause")
10391054
p.add_argument("--set-cause", nargs=3, metavar=("SUBJECT", "CAUSE", "OWNER"),
10401055
help="tag a registry subject with its diagnosed cause and owner")
10411056
p.add_argument("--sync-registry", action="store_true",
@@ -1618,6 +1633,10 @@ def division_setup(collection, opts):
16181633
def main():
16191634
opts = parse_args()
16201635

1636+
if opts.repair and not opts.retest_cause:
1637+
print("--repair requires --retest-cause so it can be linked to a diagnosis.", file=sys.stderr)
1638+
return 2
1639+
16211640
if opts.conformance:
16221641
return run_conformance(opts)
16231642
if opts.regression:
@@ -1646,7 +1665,7 @@ def main():
16461665
if subject is None:
16471666
print(f"Registry subject not found: {subject_key}", file=sys.stderr)
16481667
return 2
1649-
subject["diagnosis"] = {"state": "diagnosed", "cause": cause, "owner": owner}
1668+
add_diagnosis(subject, cause, owner, now_iso())
16501669
save_registry(registry, PARITY_REGISTRY_FILE, PARITY_REGISTRY_REPORT)
16511670
print(f"Tagged {subject_key} with cause {cause} ({owner}).")
16521671
return 0
@@ -1674,6 +1693,12 @@ def main():
16741693
print(f"{index} {key} ...", flush=True)
16751694

16761695
setup = division_setup(collection, opts)
1696+
diagnosis = diagnosis_for_cause(
1697+
registry.get("subjects", {}).get(key, {}), opts.retest_cause) \
1698+
if opts.retest_cause else None
1699+
retest = ({"cause": diagnosis["cause"], "owner": diagnosis.get("owner"),
1700+
"diagnosis_id": diagnosis["id"], "repair": opts.repair}
1701+
if diagnosis else None)
16771702
if opts.confirm_score:
16781703
measured = measure_repeatedly(jar, classname, version, opts, setup, REGRESSION_REPEATS)
16791704
if measured["bridge_only_signatures"]:
@@ -1694,6 +1719,8 @@ def main():
16941719
"confirmation": measured,
16951720
"completed_at": now_iso(),
16961721
}
1722+
if retest:
1723+
state["robots"][key]["retest"] = retest
16971724
save_state(state)
16981725
regenerate_report(state)
16991726
tested += 1
@@ -1725,6 +1752,8 @@ def main():
17251752
"errors", "error_signatures", "bridge_only_signatures", "has_log", "skipped")},
17261753
"completed_at": now_iso(),
17271754
}
1755+
if retest:
1756+
state["robots"][key]["retest"] = retest
17281757
save_state(state)
17291758
regenerate_report(state)
17301759
tested += 1

0 commit comments

Comments
 (0)