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:
Jonathan Kirkwood
2026-07-06 14:26:41 -05:00
co-authored by Claude Fable 5
parent b1d7aed9f4
commit 1d1074b625
9 changed files with 54 additions and 15 deletions
+17 -1
View File
@@ -12,7 +12,7 @@ from __future__ import annotations
import os
import re
SUPPORTED_EXTS = {".pdf", ".pptx", ".docx", ".txt", ".md", ".text"}
SUPPORTED_EXTS = {".pdf", ".pptx", ".docx", ".txt", ".md", ".markdown", ".text"}
# Canonical period forms: "2026-Q2", "2026-H1", "2026-05", "FY2026".
_PERIOD_PATTERNS = [
@@ -55,6 +55,22 @@ def parse_period_from_name(filename: str) -> str | None:
return None
def canonicalize_period(text: str | None) -> str | None:
"""Normalize a free-form period string ("2026-q2", "FY 2026", "2026/05")
to the canonical form, or None. Extractor-supplied periods and target
periods must pass through here so ledger lookups match filename periods."""
if not text:
return None
s = str(text).strip().replace("/", "-")
if period_sort_key(s) != _UNKNOWN_KEY:
return s # already canonical
for pat, canon in _PERIOD_PATTERNS:
m = pat.search(s)
if m:
return canon(m)
return None
def period_sort_key(period: str | None) -> tuple:
"""(year, start_month, granularity_rank); unknown/None sorts last."""
if not period: