to_wiki() writes a fresh set of community + god-node articles each call but
never deletes old files from previous runs. Since community labels are
LLM-generated and non-deterministic across rebuilds (per skill.md Step 5),
the same conceptual community is often named differently each time, leaving
its previous file as an orphan. After N rebuilds, wiki/ contains roughly N
times the active article count, with index.md only referencing the most
recent run's labels.
Real-world: a knowledge corpus accumulated 822 wiki .md files over 5
rebuilds, of which only 111 were referenced by index.md (710 orphans).
Fix: clear *.md files in the output directory at the start of to_wiki().
This is consistent with its existing fully-regenerative behavior — it
always writes the full set of articles + index, never partial updates.
Subdirectories and non-.md files are preserved (only top-level .md is
touched), so any user-placed auxiliary assets survive.
Tests: two new regression tests cover (1) stale article cleanup across
runs with different labels, and (2) preservation of non-.md user files
and nested subdirectories.
Closes#540.
Production audit on a 10,129-edge graph showed the INFERRED
confidence_score distribution is bimodal, not graded:
| Score bucket | Count | % of INFERRED |
|--------------|-------|---------------|
| <0.4 | 0 | 0% |
| 0.4-0.6 | 5,807 | 57% |
| 0.6-0.8 | 14 | 0.1% |
| 0.8+ | 4,308 | 42% |
Subagents collapse the continuous "0.4-0.9" guidance to a binary:
0.5 for "uncertain", 0.85+ for "confident", almost nothing in between.
Downstream filtering by confidence is therefore an on/off switch, not
the gradient the prompt promises.
Replace continuous ranges with a forced-rank discrete set:
0.95 direct structural evidence
0.85 strong inference
0.75 reasonable inference
0.65 weak inference
0.55 speculative but plausible
Models follow discrete rubrics far better than continuous ranges
(documented in calibration literature; same reason MCQ rubrics
outperform 0-100 scales). The set is anchored at non-round midpoints
to discourage 0.5 as a default.
Applied uniformly across all 10 skill-*.md files:
- 7 long-form (skill.md, skill-codex.md, skill-copilot.md,
skill-droid.md, skill-opencode.md, skill-windows.md, skill-trae.md):
full forced-rank table.
- 3 short-form (skill-claw.md, skill-aider.md, skill-kiro.md):
inline set notation INFERRED ∈ {0.55, 0.65, 0.75, 0.85, 0.95}.
Pure prompt edit — no code changes, no test impact. Effect is
observable only via re-extraction and inspection of the new
confidence_score distribution.
Closes#538.
The full-pipeline path's Step 9 already calls save_manifest, so the
NEXT --update can diff against the full-rebuild's baseline.
But the --update flow itself does NOT save the manifest after merging
the incremental result. Consequence: a file deleted between
--update #1 and --update #2 keeps reappearing in #2's deleted_files
list (since the manifest still records its old mtime), generating a
spurious ghost-node prune attempt every run.
Add save_manifest(incremental['files']) at the end of the --update
merge step in both skill.md and skill-copilot.md (the only two skill
files carrying the merge step verbatim). The 'incremental' dict is
already in scope from the prune block above; its 'files' key is the
full current file list, which is exactly what save_manifest needs.
Pure prompt edit — no code changes, no test impact.
Closes#539.
The current prune message in the --update flow is ambiguous:
Pruned 0 ghost nodes from 13 deleted file(s)
A reader can't tell whether (a) 13 files deleted, 0 of them had nodes
worth pruning (benign — graph already clean), or (b) 13 ghost nodes
still exist and only 0 got pruned (bug). The denominator is opaque.
Split into two messages so the semantics are explicit:
- Drift case: "Pruned N ghost node(s) from M deleted file(s) — drift
detected and corrected."
- No-drift case: "M file(s) deleted since last run, but no ghost
nodes were present in the graph — no drift."
Applied to both skill.md and skill-copilot.md (the only two skill
files carrying the --update merge step verbatim).
When a user configures core.hooksPath = ~/gitconfig/hooks in .gitconfig,
_hooks_dir() was constructing Path("~/gitconfig/hooks") without calling
expanduser(), so hooks were installed into <repo>/~/gitconfig/hooks instead
of the intended absolute path.
Add Path.expanduser() call immediately after reading the raw string from
git config, before the is_absolute() / root-relative fallback logic.
Fixes#547
AST and semantic entries now write to cache/ast/ and cache/semantic/
respectively. Previously both used the flat cache/ dir causing semantic
results to overwrite AST entries for code files on mixed corpora, making
the shrink guard fire on every subsequent update run.
Migration: load_cached falls back to legacy flat cache/ for AST reads
so existing cache entries are not lost on upgrade.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Grep and Glob tools removed in CC v2.1.117; searches now go through Bash.
Hook now reads stdin tool_input and pattern-matches on search commands.
Uninstall/reinstall handles both old and new matcher for clean upgrades.
Closes#578
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- #550: _file_stem() includes parent dir to prevent node ID collisions for same-named files
- #555: extract() relativizes source_file paths before returning for cross-machine portability
- #562: to_json() returns bool; _rebuild_code() writes report/html only if json succeeded
- #563: skill prompts store rationale as node attribute, not separate node; enforce calls direction
- #566: Show All / Hide All buttons added to HTML community panel
- #575: _import_js() resolves tsconfig.json compilerOptions.paths aliases before external fallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- analyze.py: add seed=42 to betweenness_centrality() — eliminates non-deterministic GRAPH_REPORT.md diffs on graphs >1000 nodes (#499)
- extract.py: fix common-root inference to stop at first diverging segment not sum of all matches (#502)
- extract.py: resolve root to absolute path; post-process file node IDs to project-relative after extraction so graph.json edge endpoints are stable across machines (#502)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>