Skip to content

fix(GATE-ISSUE-INDEX-TABLE-SHAPE): record checkers report every failure in one run, not the first - #3347

Closed
phantomic12 wants to merge 1 commit into
mudler:mainfrom
phantomic12:row/GATE-ISSUE-INDEX-TABLE-SHAPE-2
Closed

phantomic12 wants to merge 1 commit into
mudler:mainfrom
phantomic12:row/GATE-ISSUE-INDEX-TABLE-SHAPE-2

Conversation

@phantomic12

@phantomic12 phantomic12 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

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-SHAPE on 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 as row/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.py has one errors list 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.py load_local_files called validate_issue_record bare, so it raised at the first file whose record failed. The first file alphabetically is an _intake record 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.py parse_claim_rows dropped any row whose shape was malformed (cells; header or must have exactly one canonical state → bare continue). 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 the MODEL-DSV41-EXL3 / MODEL-DSV41-GGUF-Q1_0 shape 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_files now reports every invalid file in one run. Parse and validation failures are collected per file and raised as one IssueRecordError naming 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_rows now 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-rows and check-gate-commands collect parse errors and raise before classifying rows, so their censuses only become more complete; 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 (both file paths and both reasons appear in one exception) 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 malformed AND duplicate AND ratchet in one run.

Gates

check-agent-record            rc=0  (ENGINE=179 MODEL=384 QUANT=87 KERNEL=60 BACKEND=90)
test_agent_issue_index.py     13/13
test_audit_live_rows.py       58/58
claim-view --check            rc=0
check-commit-style --range    rc=0
check-commit-trailers --range rc=0

Baseline honesty: test_agent_record.py on a clean checkout of d15b1cc09 fails identically to this branch (26 failures, 32 errors, same case set — the deleted-helper class #3344 repairs), and test_check_gate_commands.py fails 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 --check is rc=2 on a clean checkout of d15b1cc09 — e3539d994 rewrote the ISSUE-GH-1033 record'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]

…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 localai-org-maint-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

mudler-agent added a commit that referenced this pull request Sep 29, 2026
…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]
@mudler-agent

Copy link
Copy Markdown
Collaborator

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants