agent-wiki-cli 0.3.41__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. {agent_wiki_cli-0.3.41/src/agent_wiki_cli.egg-info → agent_wiki_cli-0.5.0}/PKG-INFO +55 -10
  2. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/README.md +54 -9
  3. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/pyproject.toml +1 -1
  4. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0/src/agent_wiki_cli.egg-info}/PKG-INFO +55 -10
  5. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/agent_wiki_cli.egg-info/SOURCES.txt +9 -0
  6. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/cli.py +56 -0
  7. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/bootstrap_cmd.py +38 -10
  8. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/ci_check_cmd.py +20 -11
  9. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/extract_cmd.py +302 -103
  10. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/lint_cmd.py +274 -119
  11. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/migrate_cmd.py +8 -2
  12. agent_wiki_cli-0.5.0/src/llm_wiki_cli/commands/prepare_extractors_cmd.py +66 -0
  13. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/sync_cmd.py +372 -66
  14. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/go_extractor.py +16 -12
  15. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/python_extractor.py +7 -6
  16. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/rust_extractor.py +16 -12
  17. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/ts_extractor.py +13 -60
  18. agent_wiki_cli-0.5.0/src/llm_wiki_cli/services/extractor_helpers.py +431 -0
  19. agent_wiki_cli-0.5.0/src/llm_wiki_cli/services/imports.py +117 -0
  20. agent_wiki_cli-0.5.0/src/llm_wiki_cli/services/inventory_cache.py +357 -0
  21. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/metrics.py +7 -3
  22. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/packages.py +30 -6
  23. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/schema.py +44 -14
  24. agent_wiki_cli-0.5.0/src/llm_wiki_cli/services/source_snapshot.py +248 -0
  25. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/team.py +12 -2
  26. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_bootstrap.py +12 -0
  27. agent_wiki_cli-0.5.0/tests/test_ci_check.py +270 -0
  28. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_docker_extract.py +8 -0
  29. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_extract.py +324 -0
  30. agent_wiki_cli-0.5.0/tests/test_extractor_helpers.py +287 -0
  31. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_go_extract.py +18 -17
  32. agent_wiki_cli-0.5.0/tests/test_imports.py +56 -0
  33. agent_wiki_cli-0.5.0/tests/test_inventory_cache.py +168 -0
  34. agent_wiki_cli-0.5.0/tests/test_lint.py +702 -0
  35. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_multilanguage_wiki.py +30 -0
  36. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_phase4_quality.py +16 -0
  37. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_rust_extract.py +18 -23
  38. agent_wiki_cli-0.5.0/tests/test_schema.py +48 -0
  39. agent_wiki_cli-0.5.0/tests/test_source_snapshot.py +140 -0
  40. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_sync.py +479 -2
  41. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_ts_extract.py +14 -4
  42. agent_wiki_cli-0.3.41/src/llm_wiki_cli/services/imports.py +0 -77
  43. agent_wiki_cli-0.3.41/tests/test_lint.py +0 -221
  44. agent_wiki_cli-0.3.41/tests/test_schema.py +0 -21
  45. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/LICENSE +0 -0
  46. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/setup.cfg +0 -0
  47. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/agent_wiki_cli.egg-info/dependency_links.txt +0 -0
  48. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/agent_wiki_cli.egg-info/entry_points.txt +0 -0
  49. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/agent_wiki_cli.egg-info/requires.txt +0 -0
  50. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/agent_wiki_cli.egg-info/top_level.txt +0 -0
  51. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/__init__.py +0 -0
  52. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/__init__.py +0 -0
  53. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/bump_cmd.py +0 -0
  54. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/context_cmd.py +0 -0
  55. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/generate_prompt_cmd.py +0 -0
  56. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/hook_cmd.py +0 -0
  57. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/init_cmd.py +0 -0
  58. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/install_cmd.py +0 -0
  59. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/mcp_cmd.py +0 -0
  60. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/metrics_cmd.py +0 -0
  61. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/obsidian_cmd.py +0 -0
  62. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/plugins_cmd.py +0 -0
  63. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/release_cmd.py +0 -0
  64. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/review_cmd.py +0 -0
  65. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/status_cmd.py +0 -0
  66. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/team_cmd.py +0 -0
  67. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/trigger_cmd.py +0 -0
  68. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/uninstall_cmd.py +0 -0
  69. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/commands/upgrade_cmd.py +0 -0
  70. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/config.py +0 -0
  71. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/__init__.py +0 -0
  72. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/common.py +0 -0
  73. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/go_scripts/go.mod +0 -0
  74. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/go_scripts/main.go +0 -0
  75. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/rust_scripts/Cargo.lock +0 -0
  76. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/rust_scripts/Cargo.toml +0 -0
  77. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/rust_scripts/src/main.rs +0 -0
  78. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/ts_scripts/extract.js +0 -0
  79. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/extractors/ts_scripts/package.json +0 -0
  80. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/__init__.py +0 -0
  81. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/circuit_breaker.py +0 -0
  82. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/io.py +0 -0
  83. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/lockfile.py +0 -0
  84. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/mcp_server.py +0 -0
  85. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/obsidian.py +0 -0
  86. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/paths.py +0 -0
  87. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/plugins.py +0 -0
  88. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/secure_file.py +0 -0
  89. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/src/llm_wiki_cli/services/versioning.py +0 -0
  90. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_bump.py +0 -0
  91. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_circuit_breaker.py +0 -0
  92. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_config.py +0 -0
  93. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_context.py +0 -0
  94. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_docker_bootstrap.py +0 -0
  95. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_docker_lint.py +0 -0
  96. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_e2e.py +0 -0
  97. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_generate_prompt.py +0 -0
  98. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_hook.py +0 -0
  99. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_init.py +0 -0
  100. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_io.py +0 -0
  101. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_lockfile.py +0 -0
  102. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_mcp.py +0 -0
  103. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_migrate.py +0 -0
  104. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_obsidian.py +0 -0
  105. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_package_metadata.py +0 -0
  106. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_plugins.py +0 -0
  107. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_release.py +0 -0
  108. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_status.py +0 -0
  109. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_team.py +0 -0
  110. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_trigger.py +0 -0
  111. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_uninstall.py +0 -0
  112. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_upgrade.py +0 -0
  113. {agent_wiki_cli-0.3.41 → agent_wiki_cli-0.5.0}/tests/test_versioning.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-wiki-cli
3
- Version: 0.3.41
3
+ Version: 0.5.0
4
4
  Summary: CLI tool to maintain hybrid LLM Wikis for multi-language projects.
5
5
  Author-email: Denis Sivagin <denissvgn@gmail.com>
6
6
  License: MIT
@@ -58,15 +58,16 @@ external tools when they are available on `PATH`.
58
58
  | Area | Implementation | Runtime requirement |
59
59
  |---|---|---|
60
60
  | Python | stdlib `ast` | Python 3.9+ |
61
- | TypeScript / TSX | bundled Node script using `ts-morph` | Node.js and npm |
62
- | Go | bundled Go extractor using `go/ast` | Go toolchain |
63
- | Rust | bundled Rust extractor using `syn` | Cargo / Rust toolchain |
61
+ | TypeScript / TSX | bundled Node script using `ts-morph` | prepared Node.js dependencies |
62
+ | Go | bundled Go extractor using `go/ast` | prepared helper binary |
63
+ | Rust | bundled Rust extractor using `syn` | prepared helper binary |
64
64
  | Docker / Compose | built-in parsers | none |
65
65
  | MCP server | official Python MCP SDK | `agent-wiki-cli[mcp]`, Python 3.10+ |
66
66
 
67
- TypeScript, Go, and Rust extras are metadata-only; the actual toolchains must be
68
- installed separately. The TypeScript extractor runs `npm install` in its bundled
69
- extractor directory on first use if `node_modules` is missing.
67
+ TypeScript, Go, and Rust extras are metadata-only; prepare their helper
68
+ dependencies explicitly with `llm-wiki prepare-extractors`. Lint, CI, and
69
+ extract never run `npm install`, `go build`, `go run`, `cargo build`, or
70
+ `cargo run` automatically.
70
71
 
71
72
  ## Agent Support
72
73
 
@@ -232,16 +233,23 @@ manifest.
232
233
 
233
234
  ```bash
234
235
  llm-wiki sync --src-dir . --wiki-dir docs/llm_wiki
236
+ llm-wiki sync --jobs auto --cache-stats --src-dir . --wiki-dir docs/llm_wiki
235
237
  ```
236
238
 
237
239
  If an older wiki has `index.md` but no manifest, `sync` seeds
238
240
  `.llm-wiki-manifest.json` without modifying pages. If neither a manifest nor an
239
- existing wiki is present, run `bootstrap` first.
241
+ existing wiki is present, run `bootstrap` first. Sync uses the same safe
242
+ persistent inventory cache as lint when a git directory is available. Use
243
+ `--no-cache`, `--rebuild-cache`, `--cache-dir PATH`, and `--cache-stats` to
244
+ control or inspect cache behavior. Use `--jobs N` or `--jobs auto` to opt into
245
+ parallel built-in language extraction. Sync repairs manifests with invalid
246
+ source hashes without touching pages, and stops unusually broad diffs unless
247
+ `--force` is used.
240
248
 
241
249
  ### `extract`
242
250
 
243
251
  Print source inventory as JSON. All registered extractors run; missing optional
244
- toolchains are skipped when there are no matching source files.
252
+ prepared helpers are skipped when there are no matching source files.
245
253
 
246
254
  ```bash
247
255
  llm-wiki extract --src-dir .
@@ -253,6 +261,23 @@ llm-wiki extract --src-dir . --package llm_wiki_cli
253
261
  llm-wiki extract --src-dir . --include-empty
254
262
  ```
255
263
 
264
+ ### `prepare-extractors`
265
+
266
+ Prepare TypeScript dependencies and cached Go/Rust helper binaries outside the
267
+ lint/extract hot path.
268
+
269
+ ```bash
270
+ llm-wiki prepare-extractors --src-dir .
271
+ llm-wiki prepare-extractors --language typescript --language go
272
+ llm-wiki prepare-extractors --cache-dir .cache/llm-wiki
273
+ ```
274
+
275
+ When `--language` is omitted, only helper languages detected in `--src-dir` are
276
+ prepared. Helper cache resolution follows `--cache-dir`, then
277
+ `LLM_WIKI_CACHE_DIR`, then `.git/llm-wiki-extractors/`. If Go is installed in a
278
+ nonstandard location or the `go` on `PATH` cannot run, set
279
+ `LLM_WIKI_GO=/path/to/go` before running `prepare-extractors`.
280
+
256
281
  ### `lint` and `ci-check`
257
282
 
258
283
  Validate wiki links, orphan pages, entities, modules, workflows,
@@ -261,20 +286,40 @@ infrastructure, plugin lint rules, and team policy.
261
286
  ```bash
262
287
  llm-wiki lint --wiki-dir docs/llm_wiki --src-dir .
263
288
  llm-wiki lint --strict --wiki-dir docs/llm_wiki --src-dir .
289
+ llm-wiki lint --profile --wiki-dir docs/llm_wiki --src-dir .
290
+ llm-wiki lint --cache-stats --wiki-dir docs/llm_wiki --src-dir .
291
+ llm-wiki lint --jobs auto --wiki-dir docs/llm_wiki --src-dir .
264
292
  ```
265
293
 
266
294
  Strict mode also requires the core wiki structure and a fresh sync manifest.
295
+ `--profile` suppresses the human-readable lint text and prints one JSON object
296
+ to stdout containing the normal lint report, diagnostics, and phase timings.
297
+ The JSON contract is preserved for extractor failures as well; lint still exits
298
+ nonzero, but stdout remains machine-readable.
299
+ Lint uses a persistent deep-inventory cache by default when a git directory is
300
+ available, storing `.git/llm-wiki-inventory-cache.json`. Override the cache
301
+ directory with `LLM_WIKI_CACHE_DIR` or `--cache-dir PATH`; the CLI flag wins.
302
+ Use `--no-cache` to disable load/save, `--rebuild-cache` to ignore and rewrite
303
+ the cache, and `--cache-stats` to include cache diagnostics. Cache corruption or
304
+ invalid fingerprints fall back to a full extraction without reducing lint
305
+ coverage. With `--profile --cache-stats`, the JSON payload includes a top-level
306
+ `cache` object. Use `--jobs N` or `--jobs auto` to opt into parallel built-in
307
+ language extraction; the default is `--jobs 1`. Plugin extractors remain
308
+ sequential unless future plugin metadata explicitly marks them parallel-safe.
267
309
 
268
310
  For CI:
269
311
 
270
312
  ```bash
271
313
  llm-wiki ci-check --src-dir . --wiki-dir docs/llm_wiki
314
+ llm-wiki ci-check --jobs auto --src-dir . --wiki-dir docs/llm_wiki
272
315
  llm-wiki ci-check --format json --report .git/llm-wiki-ci-report.md
273
316
  llm-wiki ci-check --format markdown
274
317
  ```
275
318
 
276
319
  `ci-check` always runs strict validation, writes a Markdown report, records a
277
- local metrics event, and exits nonzero on validation failure.
320
+ local metrics event, uses the same safe inventory cache when available, and
321
+ exits nonzero on validation failure. `--report` is an output path, so explicit
322
+ absolute paths and relative artifact paths outside the project root are allowed.
278
323
 
279
324
  ### `context`
280
325
 
@@ -28,15 +28,16 @@ external tools when they are available on `PATH`.
28
28
  | Area | Implementation | Runtime requirement |
29
29
  |---|---|---|
30
30
  | Python | stdlib `ast` | Python 3.9+ |
31
- | TypeScript / TSX | bundled Node script using `ts-morph` | Node.js and npm |
32
- | Go | bundled Go extractor using `go/ast` | Go toolchain |
33
- | Rust | bundled Rust extractor using `syn` | Cargo / Rust toolchain |
31
+ | TypeScript / TSX | bundled Node script using `ts-morph` | prepared Node.js dependencies |
32
+ | Go | bundled Go extractor using `go/ast` | prepared helper binary |
33
+ | Rust | bundled Rust extractor using `syn` | prepared helper binary |
34
34
  | Docker / Compose | built-in parsers | none |
35
35
  | MCP server | official Python MCP SDK | `agent-wiki-cli[mcp]`, Python 3.10+ |
36
36
 
37
- TypeScript, Go, and Rust extras are metadata-only; the actual toolchains must be
38
- installed separately. The TypeScript extractor runs `npm install` in its bundled
39
- extractor directory on first use if `node_modules` is missing.
37
+ TypeScript, Go, and Rust extras are metadata-only; prepare their helper
38
+ dependencies explicitly with `llm-wiki prepare-extractors`. Lint, CI, and
39
+ extract never run `npm install`, `go build`, `go run`, `cargo build`, or
40
+ `cargo run` automatically.
40
41
 
41
42
  ## Agent Support
42
43
 
@@ -202,16 +203,23 @@ manifest.
202
203
 
203
204
  ```bash
204
205
  llm-wiki sync --src-dir . --wiki-dir docs/llm_wiki
206
+ llm-wiki sync --jobs auto --cache-stats --src-dir . --wiki-dir docs/llm_wiki
205
207
  ```
206
208
 
207
209
  If an older wiki has `index.md` but no manifest, `sync` seeds
208
210
  `.llm-wiki-manifest.json` without modifying pages. If neither a manifest nor an
209
- existing wiki is present, run `bootstrap` first.
211
+ existing wiki is present, run `bootstrap` first. Sync uses the same safe
212
+ persistent inventory cache as lint when a git directory is available. Use
213
+ `--no-cache`, `--rebuild-cache`, `--cache-dir PATH`, and `--cache-stats` to
214
+ control or inspect cache behavior. Use `--jobs N` or `--jobs auto` to opt into
215
+ parallel built-in language extraction. Sync repairs manifests with invalid
216
+ source hashes without touching pages, and stops unusually broad diffs unless
217
+ `--force` is used.
210
218
 
211
219
  ### `extract`
212
220
 
213
221
  Print source inventory as JSON. All registered extractors run; missing optional
214
- toolchains are skipped when there are no matching source files.
222
+ prepared helpers are skipped when there are no matching source files.
215
223
 
216
224
  ```bash
217
225
  llm-wiki extract --src-dir .
@@ -223,6 +231,23 @@ llm-wiki extract --src-dir . --package llm_wiki_cli
223
231
  llm-wiki extract --src-dir . --include-empty
224
232
  ```
225
233
 
234
+ ### `prepare-extractors`
235
+
236
+ Prepare TypeScript dependencies and cached Go/Rust helper binaries outside the
237
+ lint/extract hot path.
238
+
239
+ ```bash
240
+ llm-wiki prepare-extractors --src-dir .
241
+ llm-wiki prepare-extractors --language typescript --language go
242
+ llm-wiki prepare-extractors --cache-dir .cache/llm-wiki
243
+ ```
244
+
245
+ When `--language` is omitted, only helper languages detected in `--src-dir` are
246
+ prepared. Helper cache resolution follows `--cache-dir`, then
247
+ `LLM_WIKI_CACHE_DIR`, then `.git/llm-wiki-extractors/`. If Go is installed in a
248
+ nonstandard location or the `go` on `PATH` cannot run, set
249
+ `LLM_WIKI_GO=/path/to/go` before running `prepare-extractors`.
250
+
226
251
  ### `lint` and `ci-check`
227
252
 
228
253
  Validate wiki links, orphan pages, entities, modules, workflows,
@@ -231,20 +256,40 @@ infrastructure, plugin lint rules, and team policy.
231
256
  ```bash
232
257
  llm-wiki lint --wiki-dir docs/llm_wiki --src-dir .
233
258
  llm-wiki lint --strict --wiki-dir docs/llm_wiki --src-dir .
259
+ llm-wiki lint --profile --wiki-dir docs/llm_wiki --src-dir .
260
+ llm-wiki lint --cache-stats --wiki-dir docs/llm_wiki --src-dir .
261
+ llm-wiki lint --jobs auto --wiki-dir docs/llm_wiki --src-dir .
234
262
  ```
235
263
 
236
264
  Strict mode also requires the core wiki structure and a fresh sync manifest.
265
+ `--profile` suppresses the human-readable lint text and prints one JSON object
266
+ to stdout containing the normal lint report, diagnostics, and phase timings.
267
+ The JSON contract is preserved for extractor failures as well; lint still exits
268
+ nonzero, but stdout remains machine-readable.
269
+ Lint uses a persistent deep-inventory cache by default when a git directory is
270
+ available, storing `.git/llm-wiki-inventory-cache.json`. Override the cache
271
+ directory with `LLM_WIKI_CACHE_DIR` or `--cache-dir PATH`; the CLI flag wins.
272
+ Use `--no-cache` to disable load/save, `--rebuild-cache` to ignore and rewrite
273
+ the cache, and `--cache-stats` to include cache diagnostics. Cache corruption or
274
+ invalid fingerprints fall back to a full extraction without reducing lint
275
+ coverage. With `--profile --cache-stats`, the JSON payload includes a top-level
276
+ `cache` object. Use `--jobs N` or `--jobs auto` to opt into parallel built-in
277
+ language extraction; the default is `--jobs 1`. Plugin extractors remain
278
+ sequential unless future plugin metadata explicitly marks them parallel-safe.
237
279
 
238
280
  For CI:
239
281
 
240
282
  ```bash
241
283
  llm-wiki ci-check --src-dir . --wiki-dir docs/llm_wiki
284
+ llm-wiki ci-check --jobs auto --src-dir . --wiki-dir docs/llm_wiki
242
285
  llm-wiki ci-check --format json --report .git/llm-wiki-ci-report.md
243
286
  llm-wiki ci-check --format markdown
244
287
  ```
245
288
 
246
289
  `ci-check` always runs strict validation, writes a Markdown report, records a
247
- local metrics event, and exits nonzero on validation failure.
290
+ local metrics event, uses the same safe inventory cache when available, and
291
+ exits nonzero on validation failure. `--report` is an output path, so explicit
292
+ absolute paths and relative artifact paths outside the project root are allowed.
248
293
 
249
294
  ### `context`
250
295
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agent-wiki-cli"
7
- version = "0.3.41"
7
+ version = "0.5.0"
8
8
  description = "CLI tool to maintain hybrid LLM Wikis for multi-language projects."
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-wiki-cli
3
- Version: 0.3.41
3
+ Version: 0.5.0
4
4
  Summary: CLI tool to maintain hybrid LLM Wikis for multi-language projects.
5
5
  Author-email: Denis Sivagin <denissvgn@gmail.com>
6
6
  License: MIT
@@ -58,15 +58,16 @@ external tools when they are available on `PATH`.
58
58
  | Area | Implementation | Runtime requirement |
59
59
  |---|---|---|
60
60
  | Python | stdlib `ast` | Python 3.9+ |
61
- | TypeScript / TSX | bundled Node script using `ts-morph` | Node.js and npm |
62
- | Go | bundled Go extractor using `go/ast` | Go toolchain |
63
- | Rust | bundled Rust extractor using `syn` | Cargo / Rust toolchain |
61
+ | TypeScript / TSX | bundled Node script using `ts-morph` | prepared Node.js dependencies |
62
+ | Go | bundled Go extractor using `go/ast` | prepared helper binary |
63
+ | Rust | bundled Rust extractor using `syn` | prepared helper binary |
64
64
  | Docker / Compose | built-in parsers | none |
65
65
  | MCP server | official Python MCP SDK | `agent-wiki-cli[mcp]`, Python 3.10+ |
66
66
 
67
- TypeScript, Go, and Rust extras are metadata-only; the actual toolchains must be
68
- installed separately. The TypeScript extractor runs `npm install` in its bundled
69
- extractor directory on first use if `node_modules` is missing.
67
+ TypeScript, Go, and Rust extras are metadata-only; prepare their helper
68
+ dependencies explicitly with `llm-wiki prepare-extractors`. Lint, CI, and
69
+ extract never run `npm install`, `go build`, `go run`, `cargo build`, or
70
+ `cargo run` automatically.
70
71
 
71
72
  ## Agent Support
72
73
 
@@ -232,16 +233,23 @@ manifest.
232
233
 
233
234
  ```bash
234
235
  llm-wiki sync --src-dir . --wiki-dir docs/llm_wiki
236
+ llm-wiki sync --jobs auto --cache-stats --src-dir . --wiki-dir docs/llm_wiki
235
237
  ```
236
238
 
237
239
  If an older wiki has `index.md` but no manifest, `sync` seeds
238
240
  `.llm-wiki-manifest.json` without modifying pages. If neither a manifest nor an
239
- existing wiki is present, run `bootstrap` first.
241
+ existing wiki is present, run `bootstrap` first. Sync uses the same safe
242
+ persistent inventory cache as lint when a git directory is available. Use
243
+ `--no-cache`, `--rebuild-cache`, `--cache-dir PATH`, and `--cache-stats` to
244
+ control or inspect cache behavior. Use `--jobs N` or `--jobs auto` to opt into
245
+ parallel built-in language extraction. Sync repairs manifests with invalid
246
+ source hashes without touching pages, and stops unusually broad diffs unless
247
+ `--force` is used.
240
248
 
241
249
  ### `extract`
242
250
 
243
251
  Print source inventory as JSON. All registered extractors run; missing optional
244
- toolchains are skipped when there are no matching source files.
252
+ prepared helpers are skipped when there are no matching source files.
245
253
 
246
254
  ```bash
247
255
  llm-wiki extract --src-dir .
@@ -253,6 +261,23 @@ llm-wiki extract --src-dir . --package llm_wiki_cli
253
261
  llm-wiki extract --src-dir . --include-empty
254
262
  ```
255
263
 
264
+ ### `prepare-extractors`
265
+
266
+ Prepare TypeScript dependencies and cached Go/Rust helper binaries outside the
267
+ lint/extract hot path.
268
+
269
+ ```bash
270
+ llm-wiki prepare-extractors --src-dir .
271
+ llm-wiki prepare-extractors --language typescript --language go
272
+ llm-wiki prepare-extractors --cache-dir .cache/llm-wiki
273
+ ```
274
+
275
+ When `--language` is omitted, only helper languages detected in `--src-dir` are
276
+ prepared. Helper cache resolution follows `--cache-dir`, then
277
+ `LLM_WIKI_CACHE_DIR`, then `.git/llm-wiki-extractors/`. If Go is installed in a
278
+ nonstandard location or the `go` on `PATH` cannot run, set
279
+ `LLM_WIKI_GO=/path/to/go` before running `prepare-extractors`.
280
+
256
281
  ### `lint` and `ci-check`
257
282
 
258
283
  Validate wiki links, orphan pages, entities, modules, workflows,
@@ -261,20 +286,40 @@ infrastructure, plugin lint rules, and team policy.
261
286
  ```bash
262
287
  llm-wiki lint --wiki-dir docs/llm_wiki --src-dir .
263
288
  llm-wiki lint --strict --wiki-dir docs/llm_wiki --src-dir .
289
+ llm-wiki lint --profile --wiki-dir docs/llm_wiki --src-dir .
290
+ llm-wiki lint --cache-stats --wiki-dir docs/llm_wiki --src-dir .
291
+ llm-wiki lint --jobs auto --wiki-dir docs/llm_wiki --src-dir .
264
292
  ```
265
293
 
266
294
  Strict mode also requires the core wiki structure and a fresh sync manifest.
295
+ `--profile` suppresses the human-readable lint text and prints one JSON object
296
+ to stdout containing the normal lint report, diagnostics, and phase timings.
297
+ The JSON contract is preserved for extractor failures as well; lint still exits
298
+ nonzero, but stdout remains machine-readable.
299
+ Lint uses a persistent deep-inventory cache by default when a git directory is
300
+ available, storing `.git/llm-wiki-inventory-cache.json`. Override the cache
301
+ directory with `LLM_WIKI_CACHE_DIR` or `--cache-dir PATH`; the CLI flag wins.
302
+ Use `--no-cache` to disable load/save, `--rebuild-cache` to ignore and rewrite
303
+ the cache, and `--cache-stats` to include cache diagnostics. Cache corruption or
304
+ invalid fingerprints fall back to a full extraction without reducing lint
305
+ coverage. With `--profile --cache-stats`, the JSON payload includes a top-level
306
+ `cache` object. Use `--jobs N` or `--jobs auto` to opt into parallel built-in
307
+ language extraction; the default is `--jobs 1`. Plugin extractors remain
308
+ sequential unless future plugin metadata explicitly marks them parallel-safe.
267
309
 
268
310
  For CI:
269
311
 
270
312
  ```bash
271
313
  llm-wiki ci-check --src-dir . --wiki-dir docs/llm_wiki
314
+ llm-wiki ci-check --jobs auto --src-dir . --wiki-dir docs/llm_wiki
272
315
  llm-wiki ci-check --format json --report .git/llm-wiki-ci-report.md
273
316
  llm-wiki ci-check --format markdown
274
317
  ```
275
318
 
276
319
  `ci-check` always runs strict validation, writes a Markdown report, records a
277
- local metrics event, and exits nonzero on validation failure.
320
+ local metrics event, uses the same safe inventory cache when available, and
321
+ exits nonzero on validation failure. `--report` is an output path, so explicit
322
+ absolute paths and relative artifact paths outside the project root are allowed.
278
323
 
279
324
  ### `context`
280
325
 
@@ -26,6 +26,7 @@ src/llm_wiki_cli/commands/metrics_cmd.py
26
26
  src/llm_wiki_cli/commands/migrate_cmd.py
27
27
  src/llm_wiki_cli/commands/obsidian_cmd.py
28
28
  src/llm_wiki_cli/commands/plugins_cmd.py
29
+ src/llm_wiki_cli/commands/prepare_extractors_cmd.py
29
30
  src/llm_wiki_cli/commands/release_cmd.py
30
31
  src/llm_wiki_cli/commands/review_cmd.py
31
32
  src/llm_wiki_cli/commands/status_cmd.py
@@ -49,7 +50,9 @@ src/llm_wiki_cli/extractors/ts_scripts/extract.js
49
50
  src/llm_wiki_cli/extractors/ts_scripts/package.json
50
51
  src/llm_wiki_cli/services/__init__.py
51
52
  src/llm_wiki_cli/services/circuit_breaker.py
53
+ src/llm_wiki_cli/services/extractor_helpers.py
52
54
  src/llm_wiki_cli/services/imports.py
55
+ src/llm_wiki_cli/services/inventory_cache.py
53
56
  src/llm_wiki_cli/services/io.py
54
57
  src/llm_wiki_cli/services/lockfile.py
55
58
  src/llm_wiki_cli/services/mcp_server.py
@@ -60,10 +63,12 @@ src/llm_wiki_cli/services/paths.py
60
63
  src/llm_wiki_cli/services/plugins.py
61
64
  src/llm_wiki_cli/services/schema.py
62
65
  src/llm_wiki_cli/services/secure_file.py
66
+ src/llm_wiki_cli/services/source_snapshot.py
63
67
  src/llm_wiki_cli/services/team.py
64
68
  src/llm_wiki_cli/services/versioning.py
65
69
  tests/test_bootstrap.py
66
70
  tests/test_bump.py
71
+ tests/test_ci_check.py
67
72
  tests/test_circuit_breaker.py
68
73
  tests/test_config.py
69
74
  tests/test_context.py
@@ -72,10 +77,13 @@ tests/test_docker_extract.py
72
77
  tests/test_docker_lint.py
73
78
  tests/test_e2e.py
74
79
  tests/test_extract.py
80
+ tests/test_extractor_helpers.py
75
81
  tests/test_generate_prompt.py
76
82
  tests/test_go_extract.py
77
83
  tests/test_hook.py
84
+ tests/test_imports.py
78
85
  tests/test_init.py
86
+ tests/test_inventory_cache.py
79
87
  tests/test_io.py
80
88
  tests/test_lint.py
81
89
  tests/test_lockfile.py
@@ -89,6 +97,7 @@ tests/test_plugins.py
89
97
  tests/test_release.py
90
98
  tests/test_rust_extract.py
91
99
  tests/test_schema.py
100
+ tests/test_source_snapshot.py
92
101
  tests/test_status.py
93
102
  tests/test_sync.py
94
103
  tests/test_team.py
@@ -17,6 +17,7 @@ from .commands import (
17
17
  migrate_cmd,
18
18
  obsidian_cmd,
19
19
  plugins_cmd,
20
+ prepare_extractors_cmd,
20
21
  release_cmd,
21
22
  review_cmd,
22
23
  status_cmd,
@@ -37,6 +38,18 @@ def _positive_int(value: str) -> int:
37
38
  return parsed
38
39
 
39
40
 
41
+ def _jobs_value(value: str) -> int:
42
+ if value == "auto":
43
+ return max(1, os.cpu_count() or 1)
44
+ try:
45
+ parsed = int(value)
46
+ except ValueError as exc:
47
+ raise argparse.ArgumentTypeError("must be a positive integer or 'auto'") from exc
48
+ if parsed < 1:
49
+ raise argparse.ArgumentTypeError("must be greater than zero")
50
+ return parsed
51
+
52
+
40
53
  def main():
41
54
  parser = argparse.ArgumentParser(description="LLM Wiki CLI")
42
55
  parser.add_argument("--version", action="version", version=f"llm-wiki {__version__}")
@@ -72,6 +85,33 @@ def main():
72
85
  lint_parser.add_argument("--src-dir", default=".", help="Source directory to cross-reference against")
73
86
  lint_parser.add_argument("--strict", action="store_true",
74
87
  help="Require core wiki structure and a fresh sync manifest")
88
+ lint_parser.add_argument("--profile", action="store_true",
89
+ help="Print combined lint report and phase timings as JSON")
90
+ lint_parser.add_argument("--no-cache", action="store_true",
91
+ help="Disable persistent inventory cache for this run")
92
+ lint_parser.add_argument("--rebuild-cache", action="store_true",
93
+ help="Ignore existing inventory cache and rewrite it after extraction")
94
+ lint_parser.add_argument("--cache-stats", action="store_true",
95
+ help="Include inventory cache diagnostics in lint output")
96
+ lint_parser.add_argument("--cache-dir", default=None, metavar="PATH",
97
+ help="Directory for llm-wiki-inventory-cache.json")
98
+ lint_parser.add_argument("--jobs", type=_jobs_value, default=1, metavar="JOBS",
99
+ help="Parallel built-in extractor jobs: positive integer or 'auto' (default: 1)")
100
+
101
+ # prepare-extractors command
102
+ prepare_parser = subparsers.add_parser(
103
+ "prepare-extractors",
104
+ help="Prepare TypeScript, Go, and Rust extractor helpers",
105
+ )
106
+ prepare_parser.add_argument("--src-dir", default=".", help="Source directory to inspect")
107
+ prepare_parser.add_argument("--cache-dir", default=None, metavar="PATH",
108
+ help="Directory for extractor helper cache")
109
+ prepare_parser.add_argument(
110
+ "--language",
111
+ action="append",
112
+ choices=["typescript", "go", "rust"],
113
+ help="Helper language to prepare; may be repeated",
114
+ )
75
115
 
76
116
  # ci-check command
77
117
  ci_parser = subparsers.add_parser("ci-check", help="Run strict wiki validation and write a CI report")
@@ -82,6 +122,8 @@ def main():
82
122
  help="Console output format (default: text)")
83
123
  ci_parser.add_argument("--report", default=".git/llm-wiki-ci-report.md",
84
124
  help="Markdown report path (default: .git/llm-wiki-ci-report.md)")
125
+ ci_parser.add_argument("--jobs", type=_jobs_value, default=1, metavar="JOBS",
126
+ help="Parallel built-in extractor jobs: positive integer or 'auto' (default: 1)")
85
127
 
86
128
  # hook command
87
129
  hook_parser = subparsers.add_parser("install-hook", help="Install git hooks for wiki sync")
@@ -306,6 +348,18 @@ def main():
306
348
  sync_parser.add_argument("--src-dir", default=".", help="Source directory to scan (default: .)")
307
349
  sync_parser.add_argument("--wiki-dir", default=DEFAULT_WIKI_DIR,
308
350
  help="Wiki directory (default: docs/llm_wiki)")
351
+ sync_parser.add_argument("--no-cache", action="store_true",
352
+ help="Disable persistent inventory cache for this run")
353
+ sync_parser.add_argument("--rebuild-cache", action="store_true",
354
+ help="Ignore existing inventory cache and rewrite it after extraction")
355
+ sync_parser.add_argument("--cache-stats", action="store_true",
356
+ help="Include inventory cache diagnostics in sync output")
357
+ sync_parser.add_argument("--cache-dir", default=None, metavar="PATH",
358
+ help="Directory for llm-wiki-inventory-cache.json")
359
+ sync_parser.add_argument("--jobs", type=_jobs_value, default=1, metavar="JOBS",
360
+ help="Parallel built-in extractor jobs: positive integer or 'auto' (default: 1)")
361
+ sync_parser.add_argument("--force", action="store_true",
362
+ help="Allow sync to apply unusually broad source diffs")
309
363
 
310
364
  # migrate command
311
365
  migrate_parser = subparsers.add_parser(
@@ -349,6 +403,8 @@ def main():
349
403
  extract_cmd.run(args)
350
404
  elif args.command == "lint":
351
405
  lint_cmd.run(args)
406
+ elif args.command == "prepare-extractors":
407
+ prepare_extractors_cmd.run(args)
352
408
  elif args.command == "ci-check":
353
409
  ci_check_cmd.run(args)
354
410
  elif args.command == "install-hook":
@@ -11,9 +11,10 @@ from pathlib import Path
11
11
 
12
12
  from .extract_cmd import get_call_graph, get_docker_inventory, get_inventory_result, print_inventory_failures
13
13
  from ..config import validate_path
14
- from ..services.imports import module_path_candidates
14
+ from ..services.imports import ModulePathResolver, build_module_path_resolver
15
15
  from ..services.io import read_md, write_md
16
16
  from ..services.paths import normalize_source_path
17
+ from ..services.source_snapshot import build_source_snapshot
17
18
 
18
19
 
19
20
  def _module_name_from_path(filepath: str) -> str:
@@ -128,7 +129,13 @@ def build_entity_page_map(inventory: dict) -> dict[tuple[str, str], str]:
128
129
  return page_map
129
130
 
130
131
 
131
- def _build_relationships(inventory: dict, module_page_map: dict[str, str] | None = None) -> dict:
132
+ def _build_relationships(
133
+ inventory: dict,
134
+ module_page_map: dict[str, str] | None = None,
135
+ *,
136
+ target_entities: set[tuple[str, str]] | None = None,
137
+ resolver: ModulePathResolver | None = None,
138
+ ) -> dict:
132
139
  """Cross-reference imports against known entity identities to build a usage graph.
133
140
 
134
141
  Returns a dict mapping ``(entity_name, defining_filepath)`` to a list of
@@ -148,6 +155,7 @@ def _build_relationships(inventory: dict, module_page_map: dict[str, str] | None
148
155
  # relationship map: (entity_name, defining_filepath) -> relationship records
149
156
  relationships = defaultdict(list)
150
157
  _mod_page_map = module_page_map or {}
158
+ module_resolver = resolver or build_module_path_resolver(inventory)
151
159
 
152
160
  for filepath, data in inventory.items():
153
161
  mod_name = _module_name_from_path(filepath)
@@ -158,19 +166,20 @@ def _build_relationships(inventory: dict, module_page_map: dict[str, str] | None
158
166
  if not entity_name or entity_name not in entity_to_files:
159
167
  continue
160
168
  candidates = set(entity_to_files[entity_name])
161
- module_candidates = module_path_candidates(
162
- imp.get("module", ""), filepath, inventory
163
- )
169
+ module_candidates = module_resolver.candidates(imp.get("module", ""), filepath)
164
170
  if module_candidates:
165
171
  candidates &= module_candidates
166
172
  candidates.discard(filepath)
167
173
  if len(candidates) != 1:
168
174
  continue
169
175
  defining_filepath = next(iter(candidates))
176
+ entity_key = (entity_name, defining_filepath)
177
+ if target_entities is not None and entity_key not in target_entities:
178
+ continue
170
179
  visible_names = {entity_name}
171
180
  if imp.get("alias"):
172
181
  visible_names.add(imp["alias"])
173
- imported_entities[(entity_name, defining_filepath)] = visible_names
182
+ imported_entities[entity_key] = visible_names
174
183
 
175
184
  for entity_key, visible_names in imported_entities.items():
176
185
  for fn in data.get("functions", []):
@@ -824,19 +833,26 @@ def run(args):
824
833
  deep = depth == "full"
825
834
  skip_workflows = getattr(args, "skip_workflows", False)
826
835
 
827
- print(f"Bootstrapping wiki from source: {src_dir} (depth={depth})")
828
- print(f"Wiki output directory: {wiki_dir}")
836
+ print(f"Bootstrapping wiki from source: {src_dir} (depth={depth})", flush=True)
837
+ print(f"Wiki output directory: {wiki_dir}", flush=True)
829
838
 
830
839
  # Ensure wiki structure exists
831
840
  for subdir in ["entities", "modules", "workflows", "infrastructure"]:
832
841
  (wiki_dir / subdir).mkdir(parents=True, exist_ok=True)
833
842
 
834
843
  # 1. Extract full AST inventory
835
- inventory_result = get_inventory_result(src_dir, deep=deep)
844
+ print("Extracting source inventory...", flush=True)
845
+ source_snapshot = build_source_snapshot(src_dir)
846
+ inventory_result = get_inventory_result(
847
+ src_dir,
848
+ deep=deep,
849
+ source_snapshot=source_snapshot,
850
+ )
836
851
  if inventory_result.failed:
837
852
  print_inventory_failures(inventory_result)
838
853
  sys.exit(1)
839
854
  inventory = inventory_result.inventory
855
+ print(f"Extracted source inventory: {len(inventory)} file(s).", flush=True)
840
856
 
841
857
  if not inventory:
842
858
  print("No supported source files with classes or functions found. Nothing to bootstrap.")
@@ -855,8 +871,13 @@ def run(args):
855
871
  _entity_page_name_cache: dict = build_entity_page_map(inventory)
856
872
 
857
873
  # 2. Build cross-reference relationships (only meaningful in deep mode)
874
+ if deep:
875
+ print("Building cross-reference relationships...", flush=True)
858
876
  relationships = _build_relationships(inventory, _module_page_map) if deep else {}
877
+ if deep:
878
+ print(f"Built cross-reference relationships: {sum(len(v) for v in relationships.values())}.", flush=True)
859
879
 
880
+ print("Generating entity and module pages...", flush=True)
860
881
  for filepath, file_data in inventory.items():
861
882
  mod_page_name = _module_page_map[filepath]
862
883
  # Map cls_name -> page_stem for classes in this file (used by module page links)
@@ -893,6 +914,10 @@ def run(args):
893
914
  "path": filepath,
894
915
  "docstring": file_data.get("module_docstring", ""),
895
916
  })
917
+ print(
918
+ f"Generated entity/module pages: {entities_created} entities, {modules_created} modules.",
919
+ flush=True,
920
+ )
896
921
 
897
922
  # 3. Generate workflow pages from call graph (deep mode only)
898
923
  workflow_entries = []
@@ -912,7 +937,8 @@ def run(args):
912
937
  # 4. Generate infrastructure pages (Dockerfile, docker-compose, etc.)
913
938
  infra_entries = []
914
939
  infra_created = 0
915
- docker_inventory = get_docker_inventory(src_dir)
940
+ print("Generating infrastructure pages...", flush=True)
941
+ docker_inventory = get_docker_inventory(src_dir, source_snapshot=source_snapshot)
916
942
  for docker_file, docker_info in docker_inventory.items():
917
943
  page_name = docker_file.replace("\\", "/").replace("/", "_").replace(".", "_")
918
944
  infra_path = wiki_dir / "infrastructure" / f"{page_name}.md"
@@ -923,6 +949,7 @@ def run(args):
923
949
  infra_created += 1
924
950
  print(f" CREATE infrastructure: {page_name}")
925
951
  infra_entries.append({"name": page_name, "type": docker_info["type"]})
952
+ print(f"Generated infrastructure pages: {infra_created}.", flush=True)
926
953
 
927
954
  # 5. Rebuild index.md
928
955
  index_path = wiki_dir / "index.md"
@@ -969,6 +996,7 @@ def run(args):
969
996
  manifest = SyncManifest.build_from_inventory(
970
997
  inventory, src_dir, _entity_page_name_cache, _module_page_map,
971
998
  )
999
+ print("Writing sync manifest...", flush=True)
972
1000
  manifest.save(wiki_dir)
973
1001
  print(f" WRITE {wiki_dir / '.llm-wiki-manifest.json'}")
974
1002