Fix 9 seam-review findings
- Pinned target's profitability flag now overrides the extractor's bucket guess - Extractor/target periods canonicalized so ledger forecast chaining matches - autoRunOnDrop no longer error-loops on ungradeable inbox content; failed batches count as seen - Ship 2 default graders (pipeline requires >=2 valid reports per deck) - UI styles 'failed' deck chips as errors; .markdown discoverable - Unknown adjudicator model disables adjudication loudly instead of silently - Reserved rids extractor/adjudicator; teardown also clears bm-grader-* containers Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
b1d7aed9f4
commit
1d1074b625
+16
-9
@@ -70,11 +70,6 @@ REQUEST_PATH = os.path.join(STATE_DIR, "run_request")
|
||||
TICK_SECONDS = 10
|
||||
RUNNING_PHASES = ("extracting", "grading", "adjudicating", "scoring", "collecting")
|
||||
|
||||
# Canonical-ish reporting periods: 2026-Q2, 2026-H1, FY2026, 2026-05, 2026.
|
||||
_PERIOD_RE = re.compile(
|
||||
r"^(?:FY\s?-?\d{4}|\d{4}(?:[-/ ]?(?:Q[1-4]|H[12]|0[1-9]|1[0-2]))?)$", re.IGNORECASE)
|
||||
|
||||
|
||||
def _inbox_signature() -> tuple[int, str]:
|
||||
"""(count, signature) of supported files anywhere in the inbox tree, for
|
||||
autoRunOnDrop stability checks (decks live in per-company subfolders)."""
|
||||
@@ -229,8 +224,13 @@ class JobRunner:
|
||||
count, sig = _inbox_signature()
|
||||
if count and sig == self._last_sig and sig != self._last_done_sig:
|
||||
# stable across two ticks and not the batch we last processed
|
||||
triggered = True
|
||||
self.log("[runner] inbox stable — auto-running grading")
|
||||
if decks.discover(INBOX).get("units"):
|
||||
triggered = True
|
||||
self.log("[runner] inbox stable — auto-running grading")
|
||||
else:
|
||||
# only ungradeable files (e.g. dropped at the inbox root):
|
||||
# mark the batch seen so we don't retrigger every tick
|
||||
self._last_done_sig = sig
|
||||
self._last_sig = sig
|
||||
|
||||
if not triggered:
|
||||
@@ -288,6 +288,10 @@ class JobRunner:
|
||||
needed = {r["model"] for r in valid} | {extractor_model}
|
||||
adjudicate = bool(cfg.get("adjudicatorEnabled"))
|
||||
adj_model = adj_mod.pick_model(cfg) if adjudicate else ""
|
||||
if adjudicate and adj_model not in catalog:
|
||||
self.log(f"[runner] WARNING: adjudicator model '{adj_model}' is not in the "
|
||||
"model catalog — adjudication disabled for this job")
|
||||
adjudicate, adj_model = False, ""
|
||||
needed_all = needed | ({adj_model} if adjudicate and adj_model else set())
|
||||
|
||||
# Air-gapped mode can't route to second-Spark models (internal net).
|
||||
@@ -364,6 +368,9 @@ class JobRunner:
|
||||
self.message = f"Grading failed: {e}"
|
||||
self.log(f"[runner] JOB FAILED — {e}")
|
||||
self.log(traceback.format_exc().splitlines()[-1])
|
||||
# A failed batch counts as seen — otherwise autoRunOnDrop retries
|
||||
# the same failing inbox every other tick.
|
||||
self._last_done_sig = _inbox_signature()[1]
|
||||
try:
|
||||
serving.tear_down_all(cfg, self.log)
|
||||
except Exception:
|
||||
@@ -545,8 +552,8 @@ class JobRunner:
|
||||
(flagged as period_inferred in the extraction's red-flag candidates)."""
|
||||
if unit.get("period"):
|
||||
return unit["period"], _token(unit["period"])
|
||||
p = ((ext_obj.get("deck") or {}).get("period") or "").strip()
|
||||
if p and _PERIOD_RE.match(p):
|
||||
p = decks.canonicalize_period((ext_obj.get("deck") or {}).get("period"))
|
||||
if p:
|
||||
self.log(f"[runner] period '{p}' taken from the deck text")
|
||||
return p, _token(p)
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user