Skip to content

fix: K5/K6 walk every column, count K6 once per row, and get a real test - #101

Merged
svedbg merged 1 commit into
mainfrom
fix/k-checker-real-columns
Sep 6, 2026
Merged

fix: K5/K6 walk every column, count K6 once per row, and get a real test#101
svedbg merged 1 commit into
mainfrom
fix/k-checker-real-columns

Conversation

@svedbg

@svedbg svedbg commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

A same-day external review of 2.14.0 found three real defects in tools/k_checker.py before anyone relied on it in production:

  1. K5 missed every defect outside preflight.py's known-concept columns — 0 of 28 found against test/generate_wide.py's own fixtures. The check only walked analyse()'s known-concept dict; a real benefit/deduction column (e.g. "Карта (за сметка на работодателя)") isn't in that closed vocabulary. Fixed by reading every header on the sheet directly — matches the docstring's own argument that K5/K6 need no column-meaning knowledge.
  2. K6 double-counted a cause and its consequence — an unrounded class supplement flowing into gross surfaced as two findings (20 injected rows → 40 findings). Now caps at one K6 finding per row, in header order, excluding day/percent/hour columns — matching structural_test.py's existing "one per row" convention and otchet.md's ban on counting a chain twice.
  3. The test couldn't have caught either bug — its hand-built fixture put every defect in a known-concept column. Now also runs against test/generate_wide.py across seeds and compares counts to the manifest exactly, wired into the pre-commit hook (which now also fires on tools/ changes, not just test/) and both CI jobs (--seeds 300 in validate, --seeds 3000 in deep-suites).

Test plan

  • python test/k_checker_test.py --seeds 300 — K5 129/129, K6 130/130, zero false positives
  • Proved the new test has teeth: reverted to the pre-fix check(), watched 23 seeds go red, restored it
  • python test/run_tests.py, python test/skill_test.py — unaffected, still green
  • pre-commit hook fires correctly on this PR's tools/ change and passes

🤖 Generated with Claude Code

https://claude.ai/code/session_01XvbzEbQwxwxxHAtXfPMrno

A same-day external review of 2.14.0 found three defects in tools/k_checker.py
before anyone relied on it:

1. check() only walked analyse()'s known-concept columns. Against
   test/generate_wide.py's own injected fixtures that found 0 of 28 K5 defects,
   because a real file's benefit and deduction columns (a card allowance, a
   voluntary-insurance premium) are not all in preflight.py's closed CONCEPTS
   vocabulary - and the docstring's own argument for why K5/K6 are safe to
   automate ("ask nothing about any other column") gave no reason to limit the
   walk to known ones. Fixed by reading every header on the sheet directly.

2. K6 counted a cause and its consequence as two findings: an unrounded class
   supplement flows into gross by construction, so the same defect surfaced once
   in its own column and once in БРУТО (20 injected rows produced 40 findings).
   otchet.md forbids counting a chain twice and test/structural_test.py already
   enforces one K6 finding per row for the model's own checks; this tool now
   does the same, in header order, stopping at the first money-like column.
   Money-like excludes day counts, percentages and hours by concept or by the
   same words a real layout uses for them (a generic exclusion needed once K5's
   fix made every header, not only known ones, eligible for K6 too).

3. test/k_checker_test.py tested a hand-built fixture with every defect landing
   in a known-concept column, so it could not have caught either bug. It now
   also runs against test/generate_wide.py across seeds and compares counts to
   the manifest exactly - no less, no more, the way structural_test.py already
   does for the model's checks - and is wired into the pre-commit hook and both
   CI jobs so a future regression here is caught the same way. Two new
   hand-built shapes pin the exact regressions: K5 in an unrecognised column,
   K6 chained into a second column for the same row.

Verified against test/generate_wide.py at 300 seeds: K5 129/129, K6 130/130,
zero false positives. Confirmed the new test has teeth by reverting to the
pre-fix check() and watching 23 seeds go red before restoring it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XvbzEbQwxwxxHAtXfPMrno
@svedbg
svedbg merged commit be74c32 into main Sep 6, 2026
12 checks passed
@svedbg
svedbg deleted the fix/k-checker-real-columns branch September 6, 2026 07:06
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.

1 participant