Skip to content

exclude .pio/ folder for Platform.io IoT libs#49

Merged
colbymchenry merged 1 commit into
colbymchenry:mainfrom
markhu:main
Mar 19, 2026
Merged

exclude .pio/ folder for Platform.io IoT libs#49
colbymchenry merged 1 commit into
colbymchenry:mainfrom
markhu:main

Conversation

@markhu
Copy link
Copy Markdown
Contributor

@markhu markhu commented Feb 25, 2026

No description provided.

Copy link
Copy Markdown
Owner

@colbymchenry colbymchenry left a comment

Choose a reason for hiding this comment

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

Looks good

@colbymchenry colbymchenry merged commit 3729132 into colbymchenry:main Mar 19, 2026
andreinknv added a commit to andreinknv/codegraph that referenced this pull request May 9, 2026
… intent coverage hint + compare_to_ref skipped/suppress flags

Five friction-tracker items addressed. Three sub-agents in parallel
on disjoint files; reviewer pass with .claude/reviewer-memo.md
prepended caught two real correctness bugs and two info-level items
which are all addressed in this commit.

## colbymchenry#17 — dead_code static excludes test-bed fixtures

src/mcp/tools/dead-code.ts gains an excludeFixtures: boolean arg
(default true). When true, formatStaticDeadCode requests 4× overscan
from findGraphCandidates, runs filterFixtureNodes (regex match
against docs/test-beds/, __tests__/fixtures/, test/fixtures/,
spec/fixtures/), then slices to the user's maxCandidates. New
helper filterFixtureNodes is module-private (no speculative export).

Reviewer-caught correctness gap: the schema described excludeFixtures
as a general filter but llmFindDeadCode in mode='judge' was called
with only { maxCandidates }, so fixture filtering silently no-op'd
in judge mode. Fixed by extending the schema description to caveat
"applies to mode='static' only — judge mode tracked as follow-up";
the wider judge-mode wiring is non-trivial (llmFindDeadCode's args
interface needs extending) and is left as a tracked task.

Reviewer-caught info gap: 4× overscan doesn't suffice when fixture
density exceeds 75% of the candidate set. Now surfaces a warning
when overscan was exhausted AND we still under-filled — the agent
sees "raise maxCandidates if you need more" instead of silently
truncating.

New test file __tests__/mcp-dead-code-fixtures.test.ts (3 cases):
filter on, filter off, spec/fixtures pattern.

## colbymchenry#19 — search mode='intent' attaches coverage hint on 0 hits

src/mcp/tools/_search-intent.ts. When handleSearchIntent returns
empty, computes summary coverage and appends one of two hints:
- coverage < 50%: "intent-search depends on LLM summaries (current
  coverage X%) — run codegraph summarize to expand the corpus, or
  fall back to mode='exact' / codegraph_grep"
- coverage >= 50%: "0 hits at X% coverage — concept may not be
  summarised yet, or may not exist in the codebase. Try
  codegraph_explore"

Non-empty results unchanged. Coverage-stat errors are caught and
logged so they don't fail the search.

Reviewer-caught correctness bug: getSummaryCoverage(cg.queries) was
called WITHOUT a kinds filter; the helper's own JSDoc warns that
"counting parameters/imports/files in the denominator would
understate coverage and confuse the user". Fixed by passing
SUMMARIZABLE_KINDS (already exported from src/llm/summarizer.ts and
used by status.ts the same way). Three OTHER call sites in the
codebase also pass no kinds — filed as colbymchenry#49 follow-up since they're
out of scope for this commit.

New tests added to __tests__/search-intent.test.ts (2 cases:
low-coverage hint, high-coverage hint).

## colbymchenry#23 — compare_to_ref surfaces skipped (non-TS / non-indexed) files

src/compare/index.ts adds filesSkipped: number to CompareResult.
The compare logic counts files git reports as changed but cg can't
structurally diff (non-indexed languages, .md/.json, binary, etc.).
Formatter src/mcp/tools/compare.ts surfaces "> N file(s) skipped
(non-indexed or non-TS)" only when count > 0 (no noise on clean
diffs). Manual eyeball on HEAD~5 confirmed correct count.

## colbymchenry#24 — compare_to_ref suppressLineRangeOnly flag

src/compare/index.ts adds suppressLineRangeOnly: boolean (default
false for backward compat — existing callers asserting on
result.totals.modified would break). Adds lineRangeOnlyCount to
FileDelta. New helpers isPureLineRangeOnly / applyLineRangeOnlySuppression
(module-private). When true, FileDeltas where every modified symbol's
reasons are exactly ['line range changed'] (no signature change, no
modifier flip, no body diff) collapse into a single per-file
roll-up: "src/foo.ts: 14 symbols renumbered (no content change)".
Mixed files (real change + renumber) keep real changes individually
shown. MCP schema in compare.ts exposes the flag.

Manual eyeball on HEAD~5 of this repo: 96/174 modified symbols
(55%) were pure-renumber noise that suppression collapsed cleanly
into 7 roll-up lines.

New tests added to __tests__/compare.test.ts (4 cases): filesSkipped
counts non-TS files, filesSkipped: 0 doesn't add the line, suppress
collapses pure-renumber, mixed files keep real changes individually.

## colbymchenry#34 — at_range rejects paths outside project root

src/mcp/tools/at-range.ts. New validateFileWithinRoot helper:
path.resolve canonicalization on both sides, checks "equals root OR
starts with root + sep". Single-range and bulk-range forms both
validate; bulk form fails the whole call if ANY range is out-of-root
(no silent filtering). Reviewer-caught info: documented symlink
limitation in JSDoc — within-root symlinks pointing OUTSIDE the root
will pass; if untrusted symlinks become an issue, swap to
fs.realpathSync.

New tests added to __tests__/at-range.test.ts (2 cases: traversal
'../../etc/passwd' rejected, bulk form with one out-of-root range
fails the whole call).

## Reviewer-caught items beyond the original 5

- New friction colbymchenry#48 filed: typescript-lsp plugin reverts sub-agent
  Edit calls on first application (not a codegraph defect; harness
  interaction). Sonnet caught it during colbymchenry#23/colbymchenry#24 work and re-applied
  successfully on second pass.
- New friction colbymchenry#49 filed: 3 other getSummaryCoverage call sites in
  status.ts and bin/codegraph.ts have the same denominator-inflation
  bug — out of scope for this commit, tracked separately.

## Verification

- 9 files (8 modified + 1 new test), +398/-13
- npm run typecheck — clean
- 50/50 tests pass in focused slice (compare / at-range /
  mcp-dead-code-fixtures / search-intent)
- New module-private helpers (filterFixtureNodes, isPureLineRangeOnly,
  applyLineRangeOnlySuppression, validateFileWithinRoot) all have
  concrete in-tree callers in the same diff — no speculative
  exports per reviewer-memo item #7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
andreinknv added a commit to andreinknv/codegraph that referenced this pull request May 9, 2026
…polish items

Eight friction-tracker items addressed in parallel by sub-agents (2 Haiku,
1 Sonnet); reviewer caught one real correctness edge case (bucket overlap
on degenerate fresh-index shapes) plus two info items, all addressed in
this commit.

## colbymchenry#21 — at_range cost-benefit JSDoc

Doc-only update to src/mcp/tools/at-range.ts. Tool description and
JSDoc now state "pays off most on dense files (100+ symbols) and
multi-range bulk lookups; for tiny preview fetches on small files,
raw `head -N` is comparable." No code change.

## colbymchenry#25 — blame surfaces rename detection inline

src/git-utils.ts gains a new helper `getFileFollowEarliestTs` that runs
`git log --follow --format=%aI -- <path>` (5 s timeout, ISO timestamp).
src/mcp/tools/blame.ts compares the rename-aware oldest commit against
the line-range-only timeline's oldest. When `--follow` reaches further
back, appends a warning that the timeline truncated at the file's
rename and points at `git log --follow <file>` for the full history.
Edge cases handled: not-a-git-repo, timeout, empty timeline.

Test approach uses `vi.spyOn` to mock pre-rename history because
real fixtures are unreliable: modern git's `git log -L` follows
renames via content-similarity tracking, making a deterministic
black-box rename-fixture impossible.

## colbymchenry#26 — hotspots split into 3 mutually-exclusive categories

src/db/queries-history.ts gains `getCategorizedHotspots` and
src/mcp/tools/hotspots.ts gains a `category: 'risk' | 'maintenance'
| 'brittle' | 'all'` arg (default 'risk' for backward compat).
Thresholds use 75/25 percentile rather than hardcoded magic
numbers — they adapt as the project grows.

Buckets:
- risk        : high centrality AND high churn — where bugs hide
- maintenance : high churn AND not-high centrality — refactor target
- brittle     : high centrality AND not-high churn — stable critical

Reviewer-caught correctness bug: original filters used `<= low` for
the secondary axis, which collapsed buckets when high == low (fresh
index where centrality is uniformly zero, or repos where every file
has identical churn). A file at the threshold could appear in both
risk AND maintenance simultaneously. Fixed by switching maintenance
and brittle to `< highThreshold`, making them strictly disjoint
even on degenerate inputs. Also added a more-hint when any section
hit the per-category cap (the existing `category='risk'` path
already had this; `category='all'` now mirrors).

New `__tests__/hotspots.test.ts` (4 cases) covers all-section
rendering, single-category dispatch, and the backward-compat
default path.

## colbymchenry#27 — search centrality:high differentiates "hook hasn't run"
       vs "no node met the threshold"

src/mcp/tools/search.ts. `probeCentralityFilterCulprit` now runs a
sub-millisecond probe `SELECT 1 FROM nodes WHERE centrality IS NOT
NULL LIMIT 1` (uses the existing `idx_nodes_centrality` index). When
ALL nodes have NULL centrality the agent gets the existing "centrality
hook hasn't run — run codegraph index" hint. When SOME nodes have
centrality but none cleared the filter, a different hint suggests
relaxing the threshold. Two-case hint instead of one.

## colbymchenry#28 — search exact promotes multi-token-query warning to pre-result

src/mcp/tools/search.ts. `buildConceptHintIfNeeded` now returns
`{ preResult, postResult }` instead of a single string. When the
query splits into 2+ space-separated non-qualified tokens (likely
"multiple symbol names"), the agent gets a leading hint to call
search per name OR use codegraph_explore — BEFORE the result list
rather than buried after.

Field-qualified tokens (`kind:function lang:typescript`) and
single-free-token queries are unchanged.

## colbymchenry#33 — callers on "constructor" with no callers explains
       the instantiates-edge model

src/mcp/tools/callers.ts. When the resolved symbol is
`kind=method && name=constructor` AND the callers list is empty,
appends a one-line note: "constructors are invoked via
`new ClassName(...)`, which graph-edges as `instantiates` on the
parent class. To find construction sites, run codegraph_callers on
the enclosing class instead of 'constructor'." Both the multi-match
and single-match paths got the note (guarded by the same
kind+name+empty check). Constructors WITH callers (e.g. via super())
render normally — no false positive.

## colbymchenry#35 — node.symbol tie-break prefers non-fixture, then centrality

src/mcp/tools/symbol-resolver.ts. `pickFromMultipleExactMatches`
now filters out fixture paths first (falls back to all-fixture when
that's all that matches), then sorts by centrality DESC (NULL → 0).
A `helper` symbol that exists in both `src/core.ts` and
`docs/test-beds/fixture.ts` resolves to `src/core.ts` as the displayed
primary. Tier #3 (last_touched_ts) deferred — data not in the
resolver's existing query.

Reviewer-caught DRY issue: the fixture-path regex set was duplicated
between symbol-resolver.ts and dead-code.ts (introduced by parallel
sub-agents on the same brief). Extracted to `isFixturePath` in
src/mcp/tools/shared.ts; both consumers now import the single source.

## colbymchenry#49 — getSummaryCoverage denominator threading (3 call sites)

src/bin/codegraph.ts (lines 348, 1461) + src/mcp/tools/status.ts
(line 440). All three pass `SUMMARIZABLE_KINDS` to getSummaryCoverage
to match the canonical pattern from the previously-fixed
_search-intent.ts:218. Without this, the helper falls back to
COUNT(*) which inflates the denominator with parameters / imports /
file nodes — its own JSDoc explicitly warns against this.

## Test re-additions

Sub-agent #1 deleted its own test files for colbymchenry#33 and colbymchenry#35 (a brief
misread — "DO NOT commit" was interpreted as "DO NOT leave tests in
repo"). Re-added as
`__tests__/mcp-callers-constructor-and-fixture-tiebreak.test.ts`
covering: constructor-with-no-callers note appears,
non-constructor-method note absent, name-collision picks non-fixture
primary.

## Verification

- 15 modified files + 2 new test files, +619/-55
- npm run typecheck — clean
- 74/74 tests pass across 9 LLM/search/hotspots-related test files
- New exports: `isFixturePath` (shared.ts), `getCategorizedHotspots`
  (queries-history.ts), `getFileFollowEarliestTs` (git-utils.ts) —
  all have concrete in-tree callers in the same diff per
  reviewer-memo item #7

Reviewer pass with .claude/reviewer-memo.md prepended caught:
- (request_changes) bucket-exclusivity edge case → fixed
- (info) isFixturePath duplication → deduped
- (info) category='all' missing more-hint → added

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.

2 participants