Repository navigation
fix: tool output quality — query_context cap, list_concerns noise, deliver-phase detection, resolve_concern nudge - #5
Merged
Conversation
Bundled regression-recovery round fixing 4 defects found via live dogfooding of the already-shipped lore-mcp tools: query_context has no size cap (97,705-char bug), list_concerns is noisy with generic headers, list_features can't detect a completed DELIVER wave, and resolve_concern's error doesn't chain to list_concerns. DISCUSS, DESIGN (ADR-007), and DISTILL waves completed and peer-reviewed (approved). Acceptance tests confirmed RED (not BROKEN) against current production code -- 7 of 8 assertions genuinely RED, 4 of 8 scenarios pass trivially as expected regression-safety behavior.
Layers two truncation mechanisms, discovered through live dogfooding to both be necessary: 1. Per-file cap (8000 chars, reusing the existing capSnippetAtHeadingBoundary from resolve_concern) -- query_context previously had ZERO per-file cap, so a single file like brief.md (49,501 chars) or a large ADR was returned whole on every query. 2. Total-response cap (60000 chars) with feature-specific-content priority over repo-wide ADR/CLAUDE.md content -- query_context includes ALL ADRs + the full architecture brief on every per-feature query by design, so as those grow, pure oldest-first truncation was dropping a feature's OWN foundational decisions before dropping unrelated repo-wide content. Both findings surfaced via dogfooding against this repo's own deepest feature (ab-mcp, 15 results / 135,434 uncapped chars) -- see docs/feature/tool-output-quality/distill/upstream-issues.md for the full root-cause analysis and how the DESIGN-wave assumptions were corrected mid-implementation. Step-ID: 01-01
…rd list_concerns Step-ID: 01-04
… reads query_context now spuriously warned "deliver/wave-decisions.md could not be read (file may have been removed)" for every feature, once list_features started correctly detecting the deliver phase (tool-output- quality step 01-03). DELIVER produces execution-log.json, never wave-decisions.md, so this was a guaranteed TOCTOU "failure" on every query, not an actual file-removal signal. Found via live dogfooding during this round's post-merge integration gate.
Document the intentional duplication of SNIPPET_MAX_CHARS (format-response.ts vs concern-matcher.ts) and the "deliver" phase literal (classify-structure.ts vs server.ts's DELIVER_PHASE_NAME), consistent with the project's existing core/shell duplication-with-comment convention. No behavior change. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…her.ts to >=80% concern-matcher.ts was at 75.21% file-level mutation score, below the project's per-feature 80% gate. Added targeted unit tests pinning the GENERIC_HEADING_STOPLIST entries, isStructuralAncestor/excludeStructuralAncestors boundary conditions, findSectionEnd/findFirstChildHeadingLineIndex edge cases, splitIntoParagraphs filter precision, and ADR regex anchoring/exactness. Also added a format-response.ts test exercising the per-file-truncation warning branch (perFileTruncations > 0) that previously had no test forcing a truncated individual snippet through formatQueryContextResponse. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…admap + execution log
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.
Summary
Bundled regression-recovery round fixing 4 independent defects in the already-shipped lore-mcp MCP tools, all found via live dogfooding immediately after
list-concernsshipped:query_contexthad no size cap at all — a single feature's response could balloon past 97,000 characters with no truncation, no warning.list_concernswas noisy — generic nWave section headers ("Decisions", "Summary", "Mode") cluttered the candidate list with zero topic signal.list_featurescouldn't tell if DELIVER actually happened — it reported phases based on directory existence, not whether any work was committed.resolve_concern'sCONCERN_NOT_FOUNDdidn't chain tolist_concerns— despite the two tools being designed to work together.What changed
query_contextnow applies a per-file cap (8000 chars, reusing the existingcapSnippetAtHeadingBoundaryfromresolve_concern) and a total-response cap (60000 chars) that prioritizes a feature's own content over repo-wide ADR/brief.mdcontent when truncating.list_concernsfilters a stoplist of generic, convention-driven section headers from heading-text candidates only — never from feature directory names or ADR titles.list_featuresnow requiresdeliver/execution-log.jsonto contain at least oneCOMMIT-phase entry before reporting thedeliverphase, not mere directory existence.resolve_concern'sCONCERN_NOT_FOUNDmessage now mentionslist_concerns()as the next step.query_contextno longer emits a spurious "file could not be read" warning for every feature'sdeliverphase (DELIVER producesexecution-log.json, neverwave-decisions.md).What a reviewer should know
query_contexthad no per-file cap at all.brief.mdalone (49,501 chars) was returned whole on every query. No total-response number alone could have fixed the original bug. The fix grew into two layered mechanisms, both verified against this repo's ownab-mcpfeature (97,705 chars → 55,708 chars) before being called done.concern-matcher.tsto 75.21% (below the 80% per-file gate) due to this round's newGENERIC_HEADING_STOPLISTcode — closed to 86.04% with added tests, no production changes.docs/feature/tool-output-quality/. Root-cause writeup for the mid-implementation finding:docs/feature/tool-output-quality/distill/upstream-issues.md. Evolution summary:docs/evolution/tool-output-quality-evolution.md.Test plan
npm test)npm run build(tsc strict) cleannpm run check:arch(dependency-cruiser core/shell boundary) cleanconcern-matcher.ts86.04%,format-response.ts87.65%, project-wide 87.92% (threshold 80%)list-concernsfeature'squery_contextresponse: 97,705 → 55,708 charslist_concerns()candidates: 96 → 78, generic headers gonedeliverphase correctly shown for all 4 features with committed DELIVER wavesresolve_concern's nudge text confirmed present