Summary
cmap route hard fails when .context/generated/stats/route-usage.json exists but contains malformed JSON. This generated stats file should not block routing; route should warn and skip/rebuild the stats file, or recover by starting from empty stats.
Repro
In /Users/gaoyifan/code/lorekit:
cmap version
# 0.2.2
cmap route "docs install skills"
Observed output:
Unexpected non-whitespace character after JSON at position 8182 (line 343 column 1)
The same cmap route "docs install skills" succeeds in /Users/gaoyifan/Desktop/CMAP_coding, so the command itself is installed and runnable.
Evidence
/opt/homebrew/bin/cmap resolves to the local CMAP checkout:
/opt/homebrew/bin/cmap -> ../lib/node_modules/cmap/dist/cli.js
npm ls -g cmap --depth=0 -> cmap@0.2.2 -> /Users/gaoyifan/Desktop/CMAP_coding
The failing generated file in the lorekit repo is:
.context/generated/stats/route-usage.json
JSON validation shows only this generated stats file is invalid; graph JSON files parse correctly:
BAD .context/generated/stats/route-usage.json Unexpected non-whitespace character after JSON at position 8182 (line 343 column 1)
OK .context/graph/edges.json
OK .context/graph/files.json
OK .context/graph/graph.meta.json
OK .context/graph/modules.json
The malformed tail starts at line 343:
342 }
343 intenance",
344 "docs-tests-release"
345 ]
346 }
347 ]
348 }
Expected
Because .context/generated/stats/route-usage.json is generated / auxiliary state, cmap route should still produce the route result. It can:
- warn and skip stats update,
- rewrite stats from an empty default,
- move the malformed stats file aside through a recoverable mechanism,
- or provide a clear repair command.
But it should not prevent route selection from reading .context/MAP.md and .context/modules/*.md.
Suspected code path
runRoute() calls recordRouteUsage() after routeTask() succeeds. recordRouteUsage() reads .context/generated/stats/route-usage.json through readRouteUsageStats(), which currently does a direct JSON.parse(await readFile(...)) without malformed-file recovery.
Relevant source:
src/commands/route.ts
src/core/generated-stats.ts
Impact
This breaks the primary CMAP handoff workflow in repos where route stats become corrupted, even though canonical context files and cmap verify --changed can still be healthy.
Verification context
In /Users/gaoyifan/code/lorekit, these still pass:
cmap verify --changed
cmap obsidian export --check --out _cmap/lorekit
cmap view export --check --ui-lang zh-CN --out _cmap-view
So the issue is not canonical context structure; it is route's dependency on generated stats parseability.
Summary
cmap routehard fails when.context/generated/stats/route-usage.jsonexists but contains malformed JSON. This generated stats file should not block routing; route should warn and skip/rebuild the stats file, or recover by starting from empty stats.Repro
In
/Users/gaoyifan/code/lorekit:Observed output:
The same
cmap route "docs install skills"succeeds in/Users/gaoyifan/Desktop/CMAP_coding, so the command itself is installed and runnable.Evidence
/opt/homebrew/bin/cmapresolves to the local CMAP checkout:The failing generated file in the lorekit repo is:
JSON validation shows only this generated stats file is invalid; graph JSON files parse correctly:
The malformed tail starts at line 343:
Expected
Because
.context/generated/stats/route-usage.jsonis generated / auxiliary state,cmap routeshould still produce the route result. It can:But it should not prevent route selection from reading
.context/MAP.mdand.context/modules/*.md.Suspected code path
runRoute()callsrecordRouteUsage()afterrouteTask()succeeds.recordRouteUsage()reads.context/generated/stats/route-usage.jsonthroughreadRouteUsageStats(), which currently does a directJSON.parse(await readFile(...))without malformed-file recovery.Relevant source:
src/commands/route.tssrc/core/generated-stats.tsImpact
This breaks the primary CMAP handoff workflow in repos where route stats become corrupted, even though canonical context files and
cmap verify --changedcan still be healthy.Verification context
In
/Users/gaoyifan/code/lorekit, these still pass:So the issue is not canonical context structure; it is route's dependency on generated stats parseability.