fix(compile): one error assembly, cross-checked against IRIS's own count - #201
Merged
Merged
Conversation
…unt (#199) `iris_doc{mode:put, compile:true}` was the third copy of the compile-console loop and the #80 fix reached only two of them. It matched `ERROR ` (space) while this build prefixes per-method diagnostics with `ERROR:` (colon). Measured live, IRIS 2026.1 (Build 235U), namespace APP, class Zz.MSG.Undercount — three methods, three undefined macros, same class through both tools: iris_compile Detected 13 errors -> 14 entries (13 + the status wrapper) iris_doc put Detected 13 errors -> 1 entry The one entry that survived was `#5123 Unable to find entry point for method 'M1'` — a cascade. ZzUndefined0/1/2, named plainly by IRIS on three console lines, never reached the response, and the standard hint ("fix the first reported error, later ones are cascades of it") pointed at the one line that was definitely not the cause. Two fixes, because the copy and the missing check are separate faults: - `compile_error_list(body, console)` is now the single assembly for the string consumers (`compile_document`, `iris_doc`). A copy cannot fall behind if there is no copy. It also carries the `diag_stands_in_for` rule, so the multi-line status wrapper stops swallowing the first method's own entry. - `detected_error_count(console)` reads IRIS's own `Detected N errors` tally — computed by the compiler, not by our parser — and every compile response compares its list against it. Short lists get `errors_incomplete: true`, `errors_detected_by_iris`, `errors_reported`, and a hint that replaces the cascade advice and names the field holding the rest. The invariant is `reported >= detected`, not equality: the status.errors wrapper is an entry IRIS does not count. Several tallies take the largest, not the sum, so a grand-total line can never manufacture a false undercount. Verified on the wire on this build: the fixed path returns 13 of 13 with no flag; with the parser deliberately reverted to the space-only prefix the same call returns 1 of 13 and the server itself reports errors_incomplete. Refs #80 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GRUAp882PyFWMuQAw1kAzM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
iris_doc{mode:put, compile:true}was the third copy of the compile-console loop, and the #80 fix reached only two of them. Measured live before touching anything — IRIS 2026.1 (Build 235U), namespace APP, MCP 0.18.0 as shipped,Zz.MSG.Undercount(three methods, three undefined macros), the same class through both tools:iris_compile(the path #80 repaired)Detected 13 errorsstatus.errorswrapper)iris_doc{mode:put, compile:true}Detected 13 errorsThe one entry that survived was
#5123 Unable to find entry point for method 'M1'— a cascade.ZzUndefined0/1/2, named plainly by IRIS on three console lines, never reached the response at all, and the response still carried the standard hint "Fix the first reported error and recompile — later errors are often cascades of the first", pointing the caller at the one line that was definitely not the cause.Two faults, two fixes
The copy. Three sites assembled the same list from
status.errors+ console:iris_compile,IrisConnection::compile_document, andiris_doc's inline loop. #80 fixed two. The third could fall behind precisely because it was a copy — so it is no longer a copy.compile_error_list(body, console)is the single assembly for the string consumers, and it carries thediag_stands_in_forrule too, so the multi-line status wrapper stops swallowing the first method's own entry (N broken methods reporting N-1).The missing check. IRIS computes
Detected N errorsitself; the number does not pass through our parser, so it is an independent check available on every compile, and no path used one.detected_error_count(console)reads it and every compile response now compares. When ours is short:errors_incomplete: true,errors_detected_by_iris,errors_reported, and a hint that replaces the cascade advice and names the field holding the rest. Wired at all four assembly sites — bothiris_compilepaths,iris_doc, and the CLI'scompile_result_to_json.The invariant is
reported >= detected, not equality: thestatus.errorswrapper is an entry IRIS does not count (14 against 13 above, and that has to stay silent). Several tallies take the largest, never the sum, so an IRIS that printed per-item lines and a grand total could not manufacture a false undercount.Verification
Wire test on this build, driving the MCP server over stdio, same class both times:
compile_errors= 13, the three macros are the first three entries, noerrors_incomplete— the cross-check stays silent on a complete list.compile_errors= 1, and the server itself returnserrors_incomplete: true,errors_detected_by_iris: 13,errors_reported: 1, hint replaced. The silence above is a measured zero, not an untested path.Three offline mutation controls, each caught: space-only prefix in the shared assembly (2 tests fail),
note_error_undercountnever flagging (2 fail),detected_error_countsumming instead of taking the max (1 fails). The tests call the production assembly, not a copy of the loop, so a regression indoc.rsfails them.Eight new tests, fixtured on the verbatim measured console.
Contract
New response fields on compile failures that undercount, and the
iris_compile/iris_docdescriptions now say whaterrors_incompletemeans — an agent that cannot see the field has no reason to readconsole. No version bump: 0.19.0 is on master and unreleased, so this folds into it.Unrelated, found while running the pre-push gate and filed separately as #200:
mcp_server_startup_latency_under_100msfails about one run in five on an unmodified master.Closes #199