Skip to content

Releases: gleicon/borescope

v0.4.10 — extractor.rs split (598→366/109/49 LOC)

Choose a tag to compare

@gleicon gleicon released this 31 Aug 12:43

Changes

  • refactor(bs-extract): extractor.rs (598 LOC) split into three focused modules:
    • extractor/mod.rs (366 LOC) — parse_file, extract_repo, extract_file, Raw* structs
    • extractor/write.rs (109 LOC) — all DB write helpers (write_parsed, write_defs, stable_id, etc.)
    • extractor/complexity.rs (49 LOC) — compute_complexity tree walker

Structural integrity status

All source files now under 500 LOC. Five files split across v0.4.6–v0.4.10:

File Before After
store.rs 957 mod.rs 265 + 5 subs
paths.rs 739 mod.rs 145 + bfs 224 + signals 406
smells.rs 668 mod.rs 366 + detectors 224
miner.rs 665 mod.rs 371 + diff 220
extractor.rs 598 mod.rs 366 + write 109 + complexity 49

All 71 tests pass.

v0.4.9 — miner.rs split into mod + diff

Choose a tag to compare

@gleicon gleicon released this 31 Aug 12:33

Refactor: miner.rs → miner/ module directory

669-line miner.rs split into 2 focused modules:

Module Responsibility LOC
miner/mod.rs Miner struct, mine, compute_cochange, list_commits, worklog, git helper, tests 371
miner/diff.rs mine_symbol_spans, diff_line_ranges*, FileDiffRanges, parse_diff_ranges*, parse_hunk_* 220

All diff and hunk-parsing logic grouped with the methods that use them. External API unchanged. 71 tests pass.

v0.4.8 — smells.rs split, detect_semantic simplified

Choose a tag to compare

@gleicon gleicon released this 31 Aug 12:27

Refactor: smells.rs → smells/ module directory

693-line smells.rs split into 2 modules:

Module Responsibility LOC
smells/mod.rs run, args, SmellReport types, format_report, render, tests 366
smells/detectors.rs All detect_* functions, generate_recommendations, percentile 224

detect_semantic simplified: extracted push_semantic helper to eliminate 8× repeated smell construction boilerplate. No logic change.

71 tests pass.

v0.4.7 — paths.rs split, analyze_symbols decomposed

Choose a tag to compare

@gleicon gleicon released this 31 Aug 12:17

Refactor: paths.rs → paths/ module directory

739-line paths.rs split into 3 focused modules:

Module Responsibility LOC
paths/mod.rs CLI entry point: run, PathsArgs, write_html 145
paths/bfs.rs BFS path-finding + tree construction helpers + BFS tests 224
paths/signals.rs Signal, analyze_symbols, render functions + signal tests 406

analyze_symbols (was 150-line function) split into:

  • signals_for_path_shape — path depth + cross-file boundary
  • signals_per_symbol — lock/await, block_on, loop, complexity, hotspot per symbol
  • signals_for_terminal — async handoff + external boundary at path end

No behavior change. 71 tests pass.

v0.4.6 — store.rs split into 6 focused modules

Choose a tag to compare

@gleicon gleicon released this 31 Aug 12:13

Refactor: store.rs → store/ module directory

957-line monolithic split into 6 focused modules, each under 265 lines.

Module Responsibility LOC
store/mod.rs Store struct, open/open_existing, meta ops, OptionalExt, tests 265
store/schema.rs SCHEMA DDL, init_schema, additive migrations 124
store/files.rs File CRUD, purge_deleted_files, cascade delete 119
store/git.rs Git stats + cochange write; hotspot/coupled/age/churn queries 179
store/symbols.rs Symbol CRUD + all symbol queries; row helper functions 190
store/edges.rs Edge CRUD, get_callees/get_callers/get_call_edge_counts 99

No behavior change. 71 tests pass. External API is identical.

v0.4.5 — structural_violation smell, two-tier complexity, structural integrity docs

Choose a tag to compare

@gleicon gleicon released this 31 Aug 02:10

Structural integrity

New: structural_violation smell

borescope smells now reports structural_violation when a function exceeds hard structural limits — regardless of hotspot score or fanin count:

  • complexity > 22 (cyclomatic complexity absolute limit)
  • loc > 200 (per-function LOC absolute limit)

This is distinct from high_complexity_bottleneck which requires complexity + fanin + hotspot to all exceed thresholds simultaneously. A cold function with complexity 32 won't trigger the bottleneck smell but will trigger structural_violation.

Two-tier threshold design

# .borescope/thresholds.toml
[default]
# Hard structural limits — structural_violation fires regardless of hotspot/fanin
complexity_absolute = 22
loc_high            = 200

# Compound bottleneck — needs ALL THREE conditions
complexity_high = 10
fanin_high      = 8
hotspot_medium  = 0.5

Docs: structural integrity section in patterns.md

Every heuristic now has:

  • What it measures (with Wikipedia/research reference)
  • The absolute target value
  • The borescope command that surfaces it
  • Clear separation of what borescope covers vs. external tools (tarpaulin, cargo-mutants)

'Quality heuristics' renamed to 'Structural integrity' throughout — these are objective structural properties, not style preferences.

v0.4.4 — quality heuristics, skill next-steps, complexity fixes

Choose a tag to compare

@gleicon gleicon released this 31 Aug 02:00

Quality heuristics, skill next-steps, complexity fixes

Heuristics exposed for users

docs/patterns.md now maps the full quality heuristic table to borescope commands:

Heuristic Borescope
Cyclomatic complexity < 22 borescope explain <symbol> → complexity field; smells → high_complexity_bottleneck
Dead code smells → unbalanced_fanout (fanout > 8, fanin < 2, churn < 3)
Redundant coupling smells → tangled_pair; coupled <file>
Lock + await smells → lock_across_await; paths --analyze → lock_await signal
Blocking in async smells → sync_in_async

External tools documented for coverage (cargo-tarpaulin), mutants (cargo-mutants), cognitive complexity (rust-code-analysis).

Skill: after-memo decision table

After borescope memo, the skill now tells you exactly what to run next based on what memo showed — danger zones → callers, recent work → explain, first time → memo --update, nothing → hotspots + smells.

Skill: quality check after changes

New section in skill: after every change, verify complexity < 22, loc < 500, 0 new smells before committing.

Complexity fixes shipped in v0.4.3

  • extractor.rs:write_parsed — complexity 32 → ~6 (split into write_defs, write_def_patterns, write_imports, write_calls, write_refs)
  • miner.rs:worklog — complexity 22 → ~10 (extracted parse_commit_line, flush_commit)

v0.4.3 — memo command + doc overhaul

Choose a tag to compare

@gleicon gleicon released this 30 Aug 16:06

What's new

borescope memo — per-project team memory

Two-file design committed to the repo:

  • .borescope/memo.toml — human-curated: project description, entry points, danger zones, architectural decisions, team notes. Commit this.
  • .borescope/worklog.toml — auto-generated from git history: recent commit subjects grouped by files touched. Gitignore this.
borescope memo --update              # generate/refresh from git history
borescope memo                       # show decisions + recent 20 commits
borescope memo --who src/auth        # who worked here recently?
borescope memo --update --days 180   # wider history window

Use it to onboard teammates, avoid duplicate work, and preserve architectural decisions across contributor turnover.

Gitignore pattern

.borescope/*
!.borescope/memo.toml

Documentation overhaul

  • docs/commands.md: memo command documented (format spec, flags, gitignore pattern); global flags updated with mermaid|dot and --no-fence
  • RECIPES.md: three new recipes — team onboarding (#16), worklog refresh (#17), agent cold-start with project context (#18)
  • README.md: memo in the "inherited codebase" scenario; new team-ownership scenario
  • skill/SKILL.md: memo in the agent setup phase and token efficiency notes

Also in v0.4.x (since v0.4.1)

  • EdgeKind::Reference — function values passed as callbacks/HOF args (confidence 0.5)
  • --min-confidence default raised 0.0 to 0.3
  • async_handoff signal on paths --analyze when path terminates at a spawn/channel
  • map --weight fanin — pre-computed fanin weight, normalized against max
  • Linker preserves edge kind through resolution (previously always emitted Calls)

Doc fixes (also in v0.4.3)

  • SPEC.md / docs/SPEC.md: all missing commands documented (explain, explain-pr, skill, memo); mermaid/dot added to output format lists; hotspot formula corrected (churn × recency, not churn × complexity); .borescope/ layout updated with memo/worklog/smells/thresholds files
  • docs/agent-contract.md: version bump; confidence rubric corrected to min(0.3, 1/N) per edge
  • skill/SKILL.md: rewritten scenario-driven (6 task scenarios replace feature catalog); installation section removed from agent context

v0.4.2 — Reference edges, async handoff, fanin map, confidence default

Choose a tag to compare

@gleicon gleicon released this 23 Aug 20:56

What's new

Function-reference edges (EdgeKind::Reference)

Callbacks passed as values to spawn, map, filter, for_each, flat_map, and_then, etc. now emit reference edges (confidence <= 0.5) instead of appearing as dead code. paths, callers, and fanin counts all include reference edges. The linker now preserves edge kind through resolution -- previously everything resolved to calls.

async_handoff signal (paths --analyze)

When a path's terminal symbol performs a task spawn or channel send, --analyze now emits an async_handoff (info) signal naming the mechanism and pointing to where the continuation lives. Backed by a new @pattern.chan capture for send/try_send/blocking_send in rust.scm.

map --weight fanin now works

Was silently returning weight 0 for every symbol because score_symbol returns 0 for Fanin (by design -- callers must pre-compute). The map command never did. Now calls get_call_edge_counts() when --weight fanin and normalises against the graph maximum.

--min-confidence default raised to 0.3

The previous default of 0.0 showed all 191k edges including linker noise. 0.3 is the useful threshold where most name-match resolution lives. External (external:*) edges are unaffected -- they bypass get_callees entirely.

Stats

  • 71 tests, 0 failures
  • 1 new test: reference_edge_preserves_kind_after_resolution

v0.4.1 — hotspot filter correctness + quality pass

Choose a tag to compare

@gleicon gleicon released this 20 Aug 01:43

What's fixed

hotspots --top N now always returns N production files — the previous release used an 8× over-fetch heuristic that silently returned fewer results in test-heavy repos where the top-ranked files were all test files. Now uses LIMIT -1 (SQLite no-limit) with Rust-side filtering, which is always correct.

Internal changes

  • is_test_path moved from store.rs to bs-core::util — now exported from the bs_core public API so downstream crates can use it without importing the persistence layer
  • 8 new tests covering get_hotspots end-to-end filtering, risk::risk_level match arms, and is_high_risk_pr thresholds
  • Stale install path corrected in skill/SKILL.md (flat file → directory form)
  • 3 narrating comments removed