Releases: gleicon/borescope
Release list
v0.4.10 — extractor.rs split (598→366/109/49 LOC)
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* structsextractor/write.rs(109 LOC) — all DB write helpers (write_parsed,write_defs,stable_id, etc.)extractor/complexity.rs(49 LOC) —compute_complexitytree 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
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
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
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 boundarysignals_per_symbol— lock/await, block_on, loop, complexity, hotspot per symbolsignals_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
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
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.5Docs: 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
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
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 windowUse 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 withmermaid|dotand--no-fenceRECIPES.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 scenarioskill/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-confidencedefault raised 0.0 to 0.3async_handoffsignal onpaths --analyzewhen path terminates at a spawn/channelmap --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
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
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_pathmoved fromstore.rstobs-core::util— now exported from thebs_corepublic API so downstream crates can use it without importing the persistence layer- 8 new tests covering
get_hotspotsend-to-end filtering,risk::risk_levelmatch arms, andis_high_risk_prthresholds - Stale install path corrected in
skill/SKILL.md(flat file → directory form) - 3 narrating comments removed