Skip to content

Windows fixes, agent-friendly MCP replies, simpler README - #9

Merged
IronAdamant merged 11 commits into
mainfrom
claude/windows-verify-readme
Nov 5, 2026
Merged

IronAdamant merged 11 commits into
mainfrom
claude/windows-verify-readme

Conversation

@IronAdamant

Copy link
Copy Markdown
Owner

Verified wikifier 5.0.0 on Windows 11 and made it work better for agents on the first try.

Fixes

  • wikifier.bat now returns the real exit code. It used to exit 0 every time because %ERRORLEVEL% was read inside a parenthesized block. .gitattributes now pins line endings for the launchers.
  • Health hashes read CRLF as LF. On a default Git for Windows checkout, check-changes used to flag 51 untouched files as dirty.
  • src\a.rs and absolute paths now resolve to the same health row as src/a.rs, instead of creating a duplicate row or returning nothing.

Agent improvements

  • A wrong argument name or an unknown file returns an actionable error instead of an empty success.
  • update_maps leaves out the edge list unless you ask for it (277 KB → 0.5 KB). health honours limit/summary (145 KB → 1 KB).
  • init finds source folders in Cargo workspaces and other layouts without src/.

Docs

README shortened from 247 to 173 lines. The Performance and Benchmarks sections are unchanged byte for byte.

Each fix has a test that fails without it. 74 tests pass locally. This PR is the first CI run for the branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CMYkogM3QWVjMLzWKGyjuJ

IronAdamant and others added 11 commits November 5, 2026 15:18
wikifier.bat read %ERRORLEVEL% inside a parenthesized block. cmd expands
it when the block is parsed, before the binary runs, so every failure
exited 0 (e.g. `wikifier.bat no-such-command` printed UnknownCommand and
returned 0). The launcher now picks the binary first and runs it outside
any block.

.gitattributes keeps *.sh LF (bash on WSL/Linux rejects CRLF) and
*.bat/*.ps1 CRLF (cmd misparses labels in LF-only batch files) whatever
core.autocrlf says.

tests/cli_surface.rs runs wikifier.bat on Windows and wikifier.sh
elsewhere against the built binary and checks exit codes 0 and 1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
file_health.json stores a sha256 of each Green file. Git for Windows
checks files out with CRLF (core.autocrlf=true), so on a Windows clone
every baseline hashed from LF elsewhere mismatched: check-changes on this
repo flagged 51 untouched files dirty and rewrote health and pending.

content_sha256_prefixed drops the CR of each CRLF pair before hashing.
LF-only content hashes exactly as before, so existing baselines stay
valid. update-maps uses the same hash for its cache entries. Unit test
in src/sha256.rs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Found by driving `wikifier mcp` the way an agent does, on copies of real
repos (a 17-file crate and a 587-file Cargo workspace):

- prepare_edit / get_dependencies / get_dependents / get_file_wiki with a
  guessed argument name (`file_path`) or an unknown path answered
  success:true with every field empty. MCP now returns InvalidArguments
  naming the missing field, the accepted fields and the received ones;
  the lookups return FileNotFound with a list_paths hint.
- `src\a.rs` and absolute paths (which skills/run.md already promised)
  returned empty lookups, and record-change on `src\a.rs` created a second
  health row. scope::rel_arg turns every file argument into the
  project-relative `/` key.
- MCP update_maps returned the whole edge list (~280 KB on the workspace)
  and health ignored its advertised `limit` (~145 KB). The edge list is
  now opt-in (`edges: true`, count still in edges_persisted); health
  honors `limit` (adds entries_total) and `summary`. The update_maps
  schema now lists full, max_files and edges.
- init always seeded `src/`, so a workspace with crates/ hit ScopeError on
  the first map. It now seeds src/ when present, else the top-level
  directories that hold source.

tests/agent_args.rs covers each case, plus a Green file surviving a CRLF
checkout. skills/run.md and CHANGELOG (Unreleased) describe the changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What it is, install, connecting an agent over MCP (Claude Code command
and .mcp.json), a short quick start of the edit loop, and how it works
(pipeline, artifacts, language table). The Performance and Benchmarks
sections, tables and measurement notes are unchanged byte for byte.
Detail moves to links: skills/run.md, AGENTS.md, CONTRIBUTING.md,
docs/spec.md. README.md.wiki.md describes the new layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
record-change / mark-green for the edited sources, tests and docs;
update-maps refreshed library.md (it listed 25 of the 34 mapped files).
Generated by the wikifier binary, not edited by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured on a 587-file Cargo workspace (Specula) on Windows 11, same
copy before and after. Cache files, library.md, folder cards, health
hashes and the update-maps / cycles / dependencies --full / dependents /
check-changes / session-bootstrap output are byte-identical (timestamps
aside).

Warm MCP calls, median of 5: check_changes 353 -> 53 ms, update_maps
708 -> 50 ms, get_cycles 317 -> 39 ms, session_bootstrap 33 -> 16 ms.
Cold update-maps, interleaved runs: 18.7 s -> 6.4 s.

- Cache commits write files on several threads and flush each
  directory once instead of once per file. Every file is still synced
  and renamed into place; forward files still land before by_dst.
- A full map scans each file once (the second resolution pass reuses
  the scans). Import lines come from one substring search per distinct
  spec, not a per-line loop per import. JS/TS barrel follow-through
  builds its sorted scan table once, not once per imported name.
- cycles and dependencies --full read edges from index.tsv instead of
  one by_src file per mapped file; cycles loads edge flags only for
  files in a cycle. library.md no longer reads the notes files.
- update-maps keeps library.md and the folder cards when the cache
  commit changed nothing.
- check-changes and health seeding use a mapped file's cache hash when
  size and mtime match (the rule update-maps already skips by) and read
  the file otherwise, or when that hash is not the baseline.
- The walk takes file types from the directory entry.
- session-bootstrap --limit caps `files` (files_total gives the count);
  over MCP the default cap is 100 (21.7 KB -> 4.7 KB here).

tests/speed_paths.rs checks each fast path against the slow one; unit
tests cover line_of and the batched writer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYkogM3QWVjMLzWKGyjuJ
…t closes an item.

pending_updates.md kept "(no pending items — run check-changes after
making edits)" above the items once any were added (this repo's own
file showed it). The note now goes when the first item arrives and
comes back when mark-green removes the last one.

A record-change item read `LLM/agent edit — <reason>`, wording carried
over from the Python package. It now reads `<reason> — refresh the
wiki, then mark-green`, the step that clears it.

tests/parity_fixes.rs covers both. CHANGELOG and skills/run.md updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYkogM3QWVjMLzWKGyjuJ
record-change / mark-green for the edited files, then update-maps.
Generated by the wikifier binary, not edited by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYkogM3QWVjMLzWKGyjuJ
The wk_cache files are derived and can be rebuilt from the sources, so
by_src, by_dst, payload, notes and barrel records are now written
through a temp file and a rename (a reader never sees a torn file) but
not synced. To make that safe, every commit records each file's length
in wk_cache/sizes.tsv. Session::open compares those lengths with one
directory listing per kind and reads a file only when no length is
recorded (an older cache, or a lost sizes.tsv). A missing, resized or
malformed file is a miss: update-maps parses that source again, or
rewrites the by_dst record from the index. Lookups that meet a bad
record answer from index.tsv in the meantime.

Health (json and md), the journal and pending_updates.md were plain
overwrites with no sync; they now go through a synced temp file and a
rename (artifacts::write_durable).

Cold update-maps on the same Specula copy, interleaved runs, machine
at ~80% load: median 11.9 s with batched syncs, 12.5 s without. No
measurable change on this Windows box, where creating ~2,000 small
files (antivirus on create) dominates; the sync cost matters more on
Linux and macOS.

tests/speed_paths.rs corrupts and truncates cache records, checks the
lookups still answer, then checks the next update-maps rebuilds every
cache file byte for byte (and catches same-size damage once sizes.tsv
is gone). Another test covers the durable user-state writes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYkogM3QWVjMLzWKGyjuJ
Bump Cargo.toml/Cargo.lock to 5.1.0 and the docs that name the package
version (AGENTS.md, CLAUDE.md, skills/run.md, README install snippet).
The README benchmark section keeps its 5.0.0 measurement note.
CHANGELOG: Unreleased becomes "5.1.0 - 2026-11-05", with a note for MCP
clients that session_bootstrap now caps `files` at 100 unless `limit`
is passed and update_maps leaves out the edge list unless `edges: true`.
README says the same. skills/run.md and CLAUDE.md describe the unsynced
derived cache and the durable user state.

tests/cli_surface.rs checks those docs name CARGO_PKG_VERSION, so the
next bump cannot leave one behind. The binary, tests and release
workflow already read the version from Cargo.toml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYkogM3QWVjMLzWKGyjuJ
Generated by the wikifier binary (record-change, mark-green,
update-maps), not edited by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CMYkogM3QWVjMLzWKGyjuJ
@IronAdamant
IronAdamant merged commit c39f156 into main Nov 5, 2026
3 checks passed
@IronAdamant
IronAdamant deleted the claude/windows-verify-readme branch November 5, 2026 05:39
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.

1 participant