fix(GATE-ISSUE-INDEX-TABLE-SHAPE): record checkers report every failure in one run, not the first - #3347
fix(GATE-ISSUE-INDEX-TABLE-SHAPE): record checkers report every failure in one run, not the first#3347phantomic12 wants to merge 1 commit into
Conversation
…re in one run, not the first Both record validators stopped at the first invalid input, so one run revealed one defect and each fix exposed the next only after another run. The ORPHAN-MODEL-ROWS repair met exactly this: three separate defects (two one-cell-short rows and an ownerless SPIKE row) hid behind one another, and the tool output never named more than the first. The loader's first file alphabetically is an _intake record nobody is editing, which made the pattern worse: the error a maintainer saw rarely belonged to the row they touched. Two changes, one per validator. scripts/agent-issue-index.py load_local_files now collects every record that fails parse or validation and raises one IssueRecordError naming every file with its reason, instead of raising at the first. A file that fails to read joins the same list. The record collection is only returned when every file is valid, so callers guarded by the exception see no new empty-collection state. check-agent-record.py parse_claim_rows now REPORTS a malformed row and still parses it, instead of dropping it: the ratchet counts what is on disk, duplicate detection sees the duplicate, and the per-row contract checks can add their own findings to the same run. A malformed row parses with an empty state so no state-conditional contract fires on it; the reported defects stay the shape ones. Both consumers of parse_claim_rows stay correct: audit-live-rows and check-gate-commands collect parse errors and raise before classifying rows, so their censuses only become more complete, and claim-view already rejects on any collected error. Tests: LoadLocalFilesReportsEveryInvalidFile in tests/scripts/test_agent_issue_index.py holds the two-files-one-run contract and the clean-load path. Two cases in tests/scripts/test_agent_record.py hold that a malformed row no longer corrupts the ratchet count and that a malformed duplicate is reported as both malformed AND duplicate in one run. MEASURED on this tree: check-agent-record rc=0 (ENGINE=179 MODEL=384 QUANT=87 KERNEL=60 BACKEND=90); test_agent_issue_index 13/13; test_audit_live_rows 58/58; claim-view --check rc=0. On a clean checkout of d15b1cc the test_agent_record suite fails identically (26 failures, 32 errors, same case set), so this change introduces no regression there; those are the deleted-helper class the RECORD-ANCHOR-UNWIRED branch repairs. ISSUE-LOCAL-01M3NC14GE995V9E6F7GTYSQJ3 FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:codebuff/buffy [freebuff]
localai-org-maint-bot
left a comment
There was a problem hiding this comment.
The new recovery path can crash on the malformed input it is intended to diagnose. In scripts/check-agent-record.py:604-605, a short row now continues after the column-count error and reads cells[state_index] without checking that the cell exists. For example, under a header containing ID and State, a row containing only | MODEL-EXAMPLE | reaches that access with one cell and a state index greater than zero. Previously the shape-error branch continued to the next line; now it raises IndexError and stops the entire gate. ClaimRow.field already uses the bounds check needed here.
Please guard the state-cell access and add a regression with a row truncated before the State column, followed by another invalid row. Both diagnostics should be returned without an exception. The added tests remove only the last column and therefore do not exercise this case.
This is source review at 8a1c212, not an executed Python test. Python is absent in this environment, and downloading a standalone interpreter was denied by the release-asset host, so I cannot validate a repair here.
…re in one run, not the first (rebased onto the frozen-evidence stack) (#3353) fix(GATE-ISSUE-INDEX-TABLE-SHAPE): record checkers report every failure in one run, not the first Both record validators stopped at the first invalid input, so one run revealed one defect and each fix exposed the next only after another run. The ORPHAN-MODEL-ROWS repair met exactly this: three separate defects (two one-cell-short rows and an ownerless SPIKE row) hid behind one another, and the tool output never named more than the first. The loader's first file alphabetically is an _intake record nobody is editing, which made the pattern worse: the error a maintainer saw rarely belonged to the row they touched. Two changes, one per validator. scripts/agent-issue-index.py load_local_files now collects every record that fails parse or validation and raises one IssueRecordError naming every file with its reason, instead of raising at the first. A file that fails to read joins the same list. The record collection is only returned when every file is valid, so callers guarded by the exception see no new empty-collection state. check-agent-record.py parse_claim_rows now REPORTS a malformed row and still parses it, instead of dropping it: the ratchet counts what is on disk, duplicate detection sees the duplicate, and the per-row contract checks can add their own findings to the same run. A malformed row parses with an empty state so no state-conditional contract fires on it; the reported defects stay the shape ones. Both consumers of parse_claim_rows stay correct: audit-live-rows and check-gate-commands collect parse errors and raise before classifying rows, so their censuses only become more complete, and claim-view already rejects on any collected error. Tests: LoadLocalFilesReportsEveryInvalidFile in tests/scripts/test_agent_issue_index.py holds the two-files-one-run contract and the clean-load path. Two cases in tests/scripts/test_agent_record.py hold that a malformed row no longer corrupts the ratchet count and that a malformed duplicate is reported as both malformed AND duplicate in one run. MEASURED on THIS tree (the stack below plus this commit): check-agent-record rc=0 (ENGINE=179 MODEL=384 QUANT=87 KERNEL=60 BACKEND=90); test_issue_records 123 passed; test_agent_issue_index 11 passed, 3 subtests passed; test_audit_live_rows 58/58; claim-view --check rc=0; commit-style and commit-trailers rc=0 over the range. agent-issue-index --check now reports ALL FOUR pre-existing invalid records in one run (three non-canonical-row records and one State: PARTIAL), where every prior tree stopped at the first. test_agent_record is 74 failed / 82 passed here against 73 / 82 at pristine d15b1cc (pytest 9.1.1; the original session's unittest runner counted the same case set as 26 failures + 32 errors). The one-case delta is SUBFAILED(.agents/completed/issue-index.md start=1973): the restored archive row for #2317 cites check-agent-record.py:1973, a citation ALREADY dangling at pristine -- the tracked record ISSUE-GH-2317 cites the same moved line and fails the same test at d15b1cc -- so the restore surfaces a second copy of an existing dangling citation rather than breaking a live one; INDEX_PREAMBLE no longer exists in the checker. Editing that citation means editing a frozen archive row and its quoting record in lockstep, which is a records fix for the ENG-RECORD-CONFLICT-SURFACES owner, not a checker change; deliberately out of scope here. #3347's own checker edits add ZERO new failures: enforce-tree vs rebase-tree fail sets are identical, and the suite's citation-floor test confirms the parse_claim_rows padding kept every tracked anchor stable. THIS PR IS A STACK OF FOUR COMMITS, squashed by the merge. The landed message below describes the report-all commit; the stack carries the frozen-evidence work with it, in order: the 27 dropped archive rows restored (#3351, 617730b), the relative-link rebase comparison (#3350, 957be3a), the enforcement of the frozen-evidence contract outside _intake (#3352's tip, 9e17af3), and this report-all change (41519cc). If #3352 merges first, this branch reduces to the single report-all commit and rebases clean; the tree here already contains the whole stack, and the four PRs are mutually consistent. ISSUE-LOCAL-01M3NC14GE995V9E6F7GTYSQJ3 FOLLOWING_AGENTS_PROTOCOL Following-Agents-Protocol: true AI-Assisted: true Assisted-by: AGENT:codebuff/buffy [freebuff]
|
Closing as superseded by #3353. The tip commit merged there has the same stable patch ID as this PR and includes the required frozen-evidence dependency stack. |
Closes the local record added in this branch,
.agents/issues/GATE-ISSUE-INDEX-TABLE-SHAPE/ISSUE-LOCAL-01M3NC14GE995V9E6F7GTYSQJ3.md.Branch name note: the canonical branch
row/GATE-ISSUE-INDEX-TABLE-SHAPEon this fork is the maintainer's own long-open work on this row (42cf62bba, "a sixth grep-alternation row, from a sixth author", open since the #995 era). This PR therefore pushes asrow/GATE-ISSUE-INDEX-TABLE-SHAPE-2, touches none of that branch's files, and should merge independently of it.The masking pattern, measured
The record suite aggregates (
check-agent-record.pyhas oneerrorslist and reports every finding in one run — the premise this row's frozen archive already recorded), but the two layers below and beside that aggregation each re-introduce first-failure-only semantics, and that is where #3342's three defects hid:scripts/agent-issue-index.pyload_local_filescalledvalidate_issue_recordbare, so it raised at the first file whose record failed. The first file alphabetically is an_intakerecord nobody is editing, so the error a maintainer saw rarely belonged to the row they touched — the exact reason the orphan-row finding needed a full enumeration of every record to see past the first_intake.scripts/check-agent-record.pyparse_claim_rowsdropped any row whose shape was malformed (cells; headerormust have exactly one canonical state→ barecontinue). The dropped row then (a) silently moved the matrix ratchet counts and (b) never reached the downstream contract checks, so a one-cell-short row reported its pipe count and nothing else. This is precisely theMODEL-DSV41-EXL3/MODEL-DSV41-GGUF-Q1_0shape from fix(GATE-ISSUE-INDEX-TABLE-SHAPE): declare the three rows their own specs name, so the issue index can validate a record again #3342: "The checker reports one failure at a time, so this was masking the next two."The two fixes
load_local_filesnow reports every invalid file in one run. Parse and validation failures are collected per file and raised as oneIssueRecordErrornaming every path with its reason; unreadable files join the same list. The record collection is returned only when every file is valid, so callers guarded by the exception see no new empty-collection state.parse_claim_rowsnow reports a malformed row and still parses it. The ratchet counts what is on disk, duplicate detection sees the duplicate, and the per-row contract checks add their own findings to the same run. A malformed row parses with an empty state so no state-conditional contract fires on it — the reported defects stay the shape ones.Consumers audited:
audit-live-rowsandcheck-gate-commandscollect parse errors and raise before classifying rows, so their censuses only become more complete;claim-viewalready rejects on any collected error.Tests
LoadLocalFilesReportsEveryInvalidFileintests/scripts/test_agent_issue_index.pyholds the two-files-one-run contract (both file paths and both reasons appear in one exception) and the clean-load path. Two cases intests/scripts/test_agent_record.pyhold that a malformed row no longer corrupts the ratchet count, and that a malformed duplicate is reported as malformed AND duplicate AND ratchet in one run.Gates
Baseline honesty:
test_agent_record.pyon a clean checkout ofd15b1cc09fails identically to this branch (26 failures, 32 errors, same case set — the deleted-helper class #3344 repairs), andtest_check_gate_commands.pyfails identically (13 cases). This change introduces no regression there.The known defect this does not fix, found while probing the base tree:
agent-issue-index.py --checkis rc=2 on a clean checkout ofd15b1cc09—e3539d994rewrote theISSUE-GH-1033record's frozen-evidence quote (../specs/→../../specs/) so it no longer byte-matches.agents/completed/issue-index.md:350. That is a separate one-line repair with a real question behind it (the quote cannot both byte-match the archive and link-resolve from the record's own directory) and will get its own row and PR.FOLLOWING_AGENTS_PROTOCOL
Following-Agents-Protocol: true
AI-Assisted: true
Assisted-by: AGENT:codebuff/buffy [freebuff]