test(svg): pin SVG disambiguation heuristics (fragile area #1) + latent bug - #560
Merged
Conversation
…nt bug Pin the behavior of FallacyMindMapDocumentConfig.CollectPossibleSvgNodes and DisambiguateSvgNodes — CLAUDE.md "Known Fragile Area #1": SVG disambiguation in mind map generation, fragile heuristics dependent on Freeplane's output structure. These private instance methods (bound to TitleFunc/Logger) were audited + rejected for the #204 extraction lane (not cleanly separable). The coordinator dispatched pinning their BEHAVIOR via XElement fixtures instead of extraction, because the silent-wrong-output risk is the #1 documented fragility: a regression in the min-length grouping, the 3-char prefix fallback, or the parent-distance tie-break silently wires each fallacy to the WRONG mind-map node — caught only by visually inspecting every generated SVG. 7 contract tests via reflection against real Fallacy instances (which implement IMindMapItem and expose TextFr, so TitleFunc's {item.TextFr} resolves): - Collect: single exact match returns that node. - Collect: multiple matches with different lengths KEEPS SHORTEST (the title node, not a re-quoting descendant) — the fragile bit. - Collect: no exact match leaves the item ABSENT from the result (silent-drop contract — never a null-value entry). - Collect: substring match across split <text> elements resolves (string.Join). - Collect: title shorter than 3 chars with no match THROWS on the guard-less Substring(0,3) prefix fallback — documents a latent bug. - Disambiguate: single candidate per item = passthrough. - Disambiguate: empty input returns empty, does not throw on Descendants(). Additive only, no production code change. Full suite green (429/0/5, baseline 422 + 7). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
What
Pin the SVG disambiguation heuristics (
FallacyMindMapDocumentConfig.CollectPossibleSvgNodes+DisambiguateSvgNodes) — CLAUDE.md "Known Fragile Area #1" — with 7 contract tests via XElement fixtures. Additive only, no production code change. Full suite 429/0/5.This is the ai-01 PRIMAIRE dispatch (
msg-20260620T094434-yj9f75): "SVG disambiguation contract tests (fragile area #1)... Pin the behavior with XElement fixtures (pas d'extraction prod requise). Je confirme la valeur : risque silencieux #1 documenté."Why
"SVG disambiguation in mind map generation" with "fragile heuristics dependent on Freeplane's output structure" is the #1 documented fragility (CLAUDE.md). A regression in the min-length grouping, the 3-char prefix fallback, or the parent-distance tie-break silently wires each fallacy to the WRONG mind-map node — caught only by visually inspecting every generated SVG.
These methods are PRIVATE instance methods bound to
TitleFunc/Logger— audited and rejected for the #204 extraction lane (delegates + Logger + XElement coupling break the byte-identity-by-inspection bar). The coordinator's call: pin the BEHAVIOR with fixtures (no extraction), because the silent-wrong-output risk justifies the coverage regardless.How — reflection + real Fallacy fixtures
The methods are invoked via reflection against real
Fallacyinstances (which implementIMindMapItemand exposeTextFr, soTitleFunc's{item.TextFr}interpolation resolves cleanly). Minimal<g><text>XElement fixtures exercise each branch.The 7 tests (
SvgDisambiguationContractTests)Collect_SingleExactMatch_ReturnsThatNodeCollect_MultipleMatches_DifferentLengths_KeepsShortestCollect_NoExactMatch_LeavesItemAbsentFromResultCollect_SubstringMatchAcrossTextElements_Resolvesstring.Joinover split<text>children (Freeplane label+detail)Collect_TitleShorterThan3CharsAndNoMatch_ThrowsOnPrefixFallbackSubstring(0,3)on a <3-char title throwsDisambiguate_SingleCandidatePerItem_PassthroughDisambiguate_EmptyInput_ReturnsEmpty_NotThrowsDescendants()A latent bug documented (not fixed — output-neutral)
CollectPossibleSvgNodesline 1304 callstitle.Substring(0, 3)unconditionally in the no-match branch. A title shorter than 3 chars with no exact match throwsArgumentOutOfRangeException. In practice fallacy titles are long enough, but the code has no guard — the test pins the throw so the hazard is documented (a future caller with a short label crashes loud here, not silently misbehaves). Fixing it would be a behavior change → separate PR.Verification
Related
msg-20260620T094434-yj9f75, "couverture tests — SVG disambiguation fragile area Working version of Arguments with sketch #1").🤖 Generated with Claude Code