codingest 0.2.22__tar.gz → 0.2.24__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 (111) hide show
  1. {codingest-0.2.22 → codingest-0.2.24}/Cargo.lock +29 -10
  2. {codingest-0.2.22 → codingest-0.2.24}/Cargo.toml +66 -6
  3. {codingest-0.2.22 → codingest-0.2.24}/PKG-INFO +9 -7
  4. {codingest-0.2.22 → codingest-0.2.24}/README.md +7 -5
  5. {codingest-0.2.22 → codingest-0.2.24}/codingest/__init__.pyi +7 -0
  6. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/Cargo.toml +1 -1
  7. codingest-0.2.24/crates/codingest/assets/code_review/recipes.json +97 -0
  8. codingest-0.2.24/crates/codingest/assets/code_review/skill.md +70 -0
  9. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/docs/mod.rs +13 -4
  10. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/lib.rs +1 -0
  11. codingest-0.2.24/crates/codingest/src/methodology.rs +243 -0
  12. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/Cargo.toml +1 -1
  13. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/skills/codingest-code-review/SKILL.md +1 -1
  14. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/skills/codingest-code-review/references/mcp-upgrade.md +1 -1
  15. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/src/code_tree_cli.rs +23 -0
  16. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/src/query.rs +1 -0
  17. codingest-0.2.24/crates/codingest-cli/tests/embed_skills.rs +127 -0
  18. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/tests/skill_recipes.rs +116 -2
  19. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-mcp/Cargo.toml +1 -1
  20. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-mcp/src/lib.rs +20 -5
  21. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-mcp/tests/response_contract.rs +123 -0
  22. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-py/Cargo.toml +3 -3
  23. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-py/src/lib.rs +19 -4
  24. {codingest-0.2.22 → codingest-0.2.24}/pyproject.toml +2 -2
  25. {codingest-0.2.22 → codingest-0.2.24}/LICENSE +0 -0
  26. {codingest-0.2.22 → codingest-0.2.24}/codingest/__init__.py +0 -0
  27. {codingest-0.2.22 → codingest-0.2.24}/codingest/cli.py +0 -0
  28. {codingest-0.2.22 → codingest-0.2.24}/codingest/mcp_server.py +0 -0
  29. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/bin/codingest_bench.rs +0 -0
  30. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/bin/codingest_stats.rs +0 -0
  31. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/call_edges.rs +0 -0
  32. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/js_workspace.rs +0 -0
  33. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/load/edge_frames.rs +0 -0
  34. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/load/entity_frames.rs +0 -0
  35. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/load.rs +0 -0
  36. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/mod.rs +0 -0
  37. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/other_edges.rs +0 -0
  38. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/routes/django.rs +0 -0
  39. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/routes/fastapi.rs +0 -0
  40. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/routes/flask.rs +0 -0
  41. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/routes/mod.rs +0 -0
  42. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/semantic_edges.rs +0 -0
  43. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/builder/type_edges.rs +0 -0
  44. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/cross_lang.rs +0 -0
  45. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/docs/rst.rs +0 -0
  46. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/manifest/mod.rs +0 -0
  47. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/models.rs +0 -0
  48. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/agc.rs +0 -0
  49. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/cpp.rs +0 -0
  50. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/csharp.rs +0 -0
  51. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/css.rs +0 -0
  52. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/dart.rs +0 -0
  53. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/go.rs +0 -0
  54. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/html.rs +0 -0
  55. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/java.rs +0 -0
  56. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/julia.rs +0 -0
  57. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/mod.rs +0 -0
  58. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/php.rs +0 -0
  59. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/python.rs +0 -0
  60. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/r.rs +0 -0
  61. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/registry.rs +0 -0
  62. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/rust_lang.rs +0 -0
  63. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/shared.rs +0 -0
  64. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/swift.rs +0 -0
  65. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/parsers/typescript.rs +0 -0
  66. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/repo.rs +0 -0
  67. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/src/rev.rs +0 -0
  68. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/agc_apollo.rs +0 -0
  69. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/README.md +0 -0
  70. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/agc_basic.sha256 +0 -0
  71. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/cpp_extern_c.sha256 +0 -0
  72. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/cpp_include.sha256 +0 -0
  73. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/cross_ts_py.sha256 +0 -0
  74. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/csharp_using_alias.sha256 +0 -0
  75. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/dart_import.sha256 +0 -0
  76. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/dart_part_of.sha256 +0 -0
  77. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/docs_ext_collide.sha256 +0 -0
  78. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/docs_mdx.sha256 +0 -0
  79. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/dup_minified_assets.sha256 +0 -0
  80. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/go_interface.sha256 +0 -0
  81. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/html_js_lang_group.sha256 +0 -0
  82. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/java_javadoc.sha256 +0 -0
  83. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/julia_basic.sha256 +0 -0
  84. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/php_group_use.sha256 +0 -0
  85. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/py_basic.sha256 +0 -0
  86. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/py_import.sha256 +0 -0
  87. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/py_inheritance.sha256 +0 -0
  88. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/py_nested_defs.sha256 +0 -0
  89. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/py_routes_dup.sha256 +0 -0
  90. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/py_src_layout.sha256 +0 -0
  91. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/r_basic.sha256 +0 -0
  92. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/rust_import.sha256 +0 -0
  93. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/rust_inline_mod.sha256 +0 -0
  94. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/rust_xfile.sha256 +0 -0
  95. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/swift_basic.sha256 +0 -0
  96. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/ts_callback.sha256 +0 -0
  97. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/ts_closure_scope.sha256 +0 -0
  98. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/ts_hof_binding.sha256 +0 -0
  99. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/ts_monorepo.sha256 +0 -0
  100. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/goldens/web_served_root.sha256 +0 -0
  101. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/grammar_kinds.rs +0 -0
  102. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/parity.rs +0 -0
  103. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest/tests/traversal_semantics.rs +0 -0
  104. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/skills/codingest-code-review/references/public-repositories.md +0 -0
  105. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/skills/codingest-code-review/references/queries.md +0 -0
  106. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/src/lib.rs +0 -0
  107. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/src/main.rs +0 -0
  108. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/src/skill.rs +0 -0
  109. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/src/skill_assets.rs +0 -0
  110. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-cli/tests/exit_codes.rs +0 -0
  111. {codingest-0.2.22 → codingest-0.2.24}/crates/codingest-mcp/src/main.rs +0 -0
@@ -302,7 +302,7 @@ dependencies = [
302
302
 
303
303
  [[package]]
304
304
  name = "codingest"
305
- version = "0.2.22"
305
+ version = "0.2.24"
306
306
  dependencies = [
307
307
  "aho-corasick",
308
308
  "base64 0.22.1",
@@ -338,7 +338,7 @@ dependencies = [
338
338
 
339
339
  [[package]]
340
340
  name = "codingest-cli"
341
- version = "0.2.22"
341
+ version = "0.2.24"
342
342
  dependencies = [
343
343
  "anyhow",
344
344
  "clap",
@@ -350,7 +350,7 @@ dependencies = [
350
350
 
351
351
  [[package]]
352
352
  name = "codingest-mcp"
353
- version = "0.2.22"
353
+ version = "0.2.24"
354
354
  dependencies = [
355
355
  "anyhow",
356
356
  "codingest",
@@ -361,7 +361,7 @@ dependencies = [
361
361
 
362
362
  [[package]]
363
363
  name = "codingest-py"
364
- version = "0.2.22"
364
+ version = "0.2.24"
365
365
  dependencies = [
366
366
  "codingest",
367
367
  "codingest-cli",
@@ -1368,9 +1368,9 @@ dependencies = [
1368
1368
 
1369
1369
  [[package]]
1370
1370
  name = "kglite"
1371
- version = "0.17.6"
1371
+ version = "0.17.9"
1372
1372
  source = "registry+https://github.com/rust-lang/crates.io-index"
1373
- checksum = "6f3f148d8a40ffbfbf0c514a92cadc9382e25443409324628637b30eace18c02"
1373
+ checksum = "84cc52c7ac2e3901aaf1b23311ee329b7509c9dd483cc6e59ed70b079ec9c78e"
1374
1374
  dependencies = [
1375
1375
  "bzip2",
1376
1376
  "chrono",
@@ -1386,6 +1386,7 @@ dependencies = [
1386
1386
  "memmap2",
1387
1387
  "petgraph",
1388
1388
  "postcard",
1389
+ "pulldown-cmark",
1389
1390
  "rayon",
1390
1391
  "regex",
1391
1392
  "rstar 0.13.0",
@@ -1404,11 +1405,12 @@ dependencies = [
1404
1405
 
1405
1406
  [[package]]
1406
1407
  name = "kglite-mcp-server"
1407
- version = "0.17.6"
1408
+ version = "0.17.9"
1408
1409
  source = "registry+https://github.com/rust-lang/crates.io-index"
1409
- checksum = "6f2d4f097da41a62ee5b6ea67fd983ab576ee33dd69656a88de9f97269132f22"
1410
+ checksum = "ffd62a6af8cb4f07b89375612a04c4a71adf525d5054597c466824586a49360a"
1410
1411
  dependencies = [
1411
1412
  "anyhow",
1413
+ "base64 0.22.1",
1412
1414
  "bytes",
1413
1415
  "chrono",
1414
1416
  "clap",
@@ -1510,9 +1512,9 @@ dependencies = [
1510
1512
 
1511
1513
  [[package]]
1512
1514
  name = "mcp-methods"
1513
- version = "0.4.11"
1515
+ version = "0.4.12"
1514
1516
  source = "registry+https://github.com/rust-lang/crates.io-index"
1515
- checksum = "31c5a17334897b67053e843235be8c66610d0c6684c845bea30e70ecff9dd204"
1517
+ checksum = "5bcc5fdac2ffd82893fbc640b569785bdc63ead7f3c6c3d695685b692ddf2d1a"
1516
1518
  dependencies = [
1517
1519
  "anyhow",
1518
1520
  "clap",
@@ -1742,6 +1744,17 @@ dependencies = [
1742
1744
  "cc",
1743
1745
  ]
1744
1746
 
1747
+ [[package]]
1748
+ name = "pulldown-cmark"
1749
+ version = "0.13.4"
1750
+ source = "registry+https://github.com/rust-lang/crates.io-index"
1751
+ checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e"
1752
+ dependencies = [
1753
+ "bitflags",
1754
+ "memchr",
1755
+ "unicase",
1756
+ ]
1757
+
1745
1758
  [[package]]
1746
1759
  name = "pyo3"
1747
1760
  version = "0.29.0"
@@ -2792,6 +2805,12 @@ version = "1.20.1"
2792
2805
  source = "registry+https://github.com/rust-lang/crates.io-index"
2793
2806
  checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
2794
2807
 
2808
+ [[package]]
2809
+ name = "unicase"
2810
+ version = "2.9.0"
2811
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2812
+ checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142"
2813
+
2795
2814
  [[package]]
2796
2815
  name = "unicode-ident"
2797
2816
  version = "1.0.24"
@@ -3,7 +3,7 @@ members = ["crates/codingest", "crates/codingest-cli", "crates/codingest-mcp", "
3
3
  resolver = "2"
4
4
 
5
5
  [workspace.package]
6
- version = "0.2.22"
6
+ version = "0.2.24"
7
7
  edition = "2021"
8
8
  rust-version = "1.88"
9
9
  license = "MIT"
@@ -12,12 +12,72 @@ repository = "https://github.com/kkollsga/codingest"
12
12
  [workspace.dependencies]
13
13
  base64 = "0.22"
14
14
  sha2 = "0.11"
15
- # kglite engine + MCP server — imported as crates.io libraries. The 0.17.6
15
+ # kglite engine + MCP server — imported as crates.io libraries. The 0.17.9
16
+ # floor covers two same-day releases, 0.17.8 (the Obsidian vault format) and
17
+ # 0.17.9 (the vault structure profile). Both land almost entirely on
18
+ # `dialect="obsidian"`, which codingest never selects — but they rebuilt the
19
+ # `kglite::okf` *type* surface underneath our docs pass, so this is the first
20
+ # kglite bump since 0.16.x that needs a source change:
21
+ # * `okf::BuildOptions` gained `profile` (a `Profile` the parser reads for
22
+ # its conventions) and lost `embed` (a field the loader never read — it
23
+ # embedded nothing in any dialect, so removing it changes no behaviour),
24
+ # and `okf::walk::DiscoveredFile` gained `size` / `mtime`. Our docs pass
25
+ # built both as exhaustive struct literals. `BuildOptions` is now
26
+ # constructed through `BuildOptions::for_dialect(Dialect::Okf)` with only
27
+ # the two fields we deliberately differ on overridden — a `Profile` cannot
28
+ # be a struct literal outside kglite any more, and `for_dialect` is the
29
+ # constructor that keeps a future field at its dialect default instead of
30
+ # failing the build a third time. `size`/`mtime` are `0`/`None`: they feed
31
+ # only `okf::fingerprint` and the vault's attachment nodes, and
32
+ # `parse_concepts` — the one entry point we call — reads neither.
33
+ # * The rest of the breaking set does not reach us: `okf::build` now returns
34
+ # `BuildOutput { graph, report }`, `links::extract_links` and
35
+ # `walk::discover` take the options/profile instead of a `Dialect` /
36
+ # `skip_dirs` slice, `Dialect` gained `Obsidian`, `Link` lost
37
+ # `is_wikilink`, and `ExportOptions` / `ExportReport` gained
38
+ # `edge_tables` / `warnings`. codingest calls none of them (grep: zero
39
+ # hits outside `docs/mod.rs`) — we use `okf::parse_concepts` and nothing
40
+ # else, and we read only `concept_id` / `file_path` / `title` / `body` /
41
+ # `props` off each `ConceptDoc`, never its links.
42
+ # * Behaviour under `Dialect::Okf` is the old behaviour by construction:
43
+ # `Profile::default()` is the OKF-bundle profile with every vault feature
44
+ # (wikilinks, embeds, inline tags, frontmatter edges, aliases, folder
45
+ # notes, attachments, `structure:`) off, which is what the parser hardcoded
46
+ # before. The one 0.17.8 parser fix that is dialect-independent and lands
47
+ # on a value we store is the heading rule: a line starting with `#` is a
48
+ # heading only when one to six `#` are followed by a space, a tab, or the
49
+ # line end, so an inline-tag line like `#project see …` is no longer read
50
+ # as an `# H1`. That feeds our `:Doc` title fallback. The 31 frozen
51
+ # goldens are the gate on it, and they are byte-identical across this move.
52
+ # * kglite-mcp-server: `--vault` mode and the vault-authoring skill are new
53
+ # surface we do not register, and the bundled skill set is now gated by
54
+ # graph shape — the four code-graph skills bundle only where the graph
55
+ # carries `Function` / `Class`, which is exactly a codingest graph, so the
56
+ # skills an agent reaches through `codingest-mcp` are unchanged while a
57
+ # document deployment stops paying for ours. Our producer layer
58
+ # (`ServerExtensions::with_skills` / `with_recipes`) is untouched.
59
+ # The preceding 0.17.7
60
+ # floor adds the producer-level methodology hook codingest asked for on
61
+ # 2026-09-16: `ServerExtensions::with_skills` / `with_recipes` let the binary
62
+ # embedding the server register its own skill layer and Cypher recipe
63
+ # catalogue once, applying to every graph it serves in EVERY mode — including
64
+ # codingest-mcp's manifest-less workspace boot, where graph-carried records
65
+ # are never read. Precedence `bundled < producer < graph < operator`; with no
66
+ # manifest, or one that never mentions `skills:`, the server serves the
67
+ # bundled set plus the producer layer, and an explicit `skills: false`
68
+ # silences both. A producer record that fails validation fails the boot
69
+ # naming itself. 0.17.7 also revives the bundled predicate-gated code-graph
70
+ # skills, which were dead in every workspace deployment (no graph at boot,
71
+ # never re-evaluated): they now activate on the first `set_root_dir`.
72
+ # codingest-mcp registers the code-review skill and recipe corpus through
73
+ # these builders (`crates/codingest-mcp/src/lib.rs`).
74
+ # The preceding 0.17.6
16
75
  # floor is the graph-carried skills and recipes release. `kglite::api::skills`
17
- # and `kglite::api::recipes` are new and uncalled here: their `KgliteSkill` /
76
+ # and `kglite::api::recipes` arrived here: their `KgliteSkill` /
18
77
  # `KgliteRecipe` records are system labels, hidden from every type enumeration,
19
78
  # so a codingest graph reports the same `node_types()` / `describe()` as before
20
- # and every golden digest is unchanged. What reaches users is in the embedded
79
+ # and every golden digest is unchanged (codingest writes them only behind the
80
+ # opt-in `codingest build --embed-skills`). What reaches users is in the embedded
21
81
  # `codingest-mcp` server, and only when an operator manifest turns `skills:`
22
82
  # on: methodology skills are now delivered lazily (mcp-methods 0.4.11 — a
23
83
  # skill contributes its when-to-use paragraph to the tools it references and
@@ -530,8 +590,8 @@ sha2 = "0.11"
530
590
  # and no disk storage. Neither 0.15.7 nor 0.15.8 changes the `kglite::api` we
531
591
  # call, graph output, property encoding, or `.kgl` serialization.
532
592
  # Keep both libraries aligned so the graph and server share one engine release.
533
- kglite = { version = "0.17.6", default-features = false }
534
- kglite-mcp-server = { version = "0.17.6", default-features = false }
593
+ kglite = { version = "0.17.9", default-features = false }
594
+ kglite-mcp-server = { version = "0.17.9", default-features = false }
535
595
 
536
596
  # Dependency debuginfo capped at line tables (kglite coordination, 2026-08-31,
537
597
  # after unbounded debug trees filled the build-cache disk to zero): a
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codingest
3
- Version: 0.2.22
3
+ Version: 0.2.24
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: Programming Language :: Python :: 3
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.14
12
12
  Classifier: Programming Language :: Rust
13
13
  Classifier: Topic :: Software Development
14
14
  Classifier: Topic :: Software Development :: Libraries
15
- Requires-Dist: kglite>=0.17.6,<0.18
15
+ Requires-Dist: kglite>=0.17.9,<0.18
16
16
  License-File: LICENSE
17
17
  Summary: Build fast, queryable code graphs for AI agents, MCP code review, and local or GitHub repository analysis.
18
18
  Keywords: ai-agents,mcp,code-review,knowledge-graph,code-analysis,github,tree-sitter,cypher
@@ -59,7 +59,9 @@ a real `kglite.KnowledgeGraph`, ready for Cypher queries.
59
59
  ## Built for agents and code analysis
60
60
 
61
61
  - **Agent-ready MCP:** give an MCP client `graph_overview`, `cypher_query`,
62
- `read_code_source`, repository switching, and automatic graph refresh.
62
+ `read_code_source`, repository switching, automatic graph refresh, and the
63
+ code-review methodology itself — a `code_review` skill and a catalogue of
64
+ parameter-checked review recipes (`run_recipe_query`) served for every graph.
63
65
  [opencode is set up and verified end to end](https://codingest.readthedocs.io/en/latest/mcp.html#using-codingest-mcp-with-opencode)
64
66
  — including a config that needs no absolute paths — and `codingest skill
65
67
  install` packages the review skill for Claude Code and Codex, which opencode
@@ -192,7 +194,7 @@ codingest skill install # code-review Agent Skill
192
194
  ```
193
195
 
194
196
  The wheel bundles every grammar plus the `codingest` and `codingest-mcp`
195
- commands. KGLite ≥0.17.6 is installed automatically as the query/storage
197
+ commands. KGLite ≥0.17.9 is installed automatically as the query/storage
196
198
  engine; its MCP server and the transitive `mcp-methods` framework power the
197
199
  builder-aware Codingest server. Nothing else needs to be installed.
198
200
 
@@ -205,7 +207,7 @@ Python prerequisites.
205
207
  ```toml
206
208
  [dependencies]
207
209
  codingest = "0.2"
208
- kglite = "0.17.6"
210
+ kglite = "0.17.9"
209
211
  ```
210
212
 
211
213
  ```rust
@@ -237,7 +239,7 @@ Documentation: **[codingest.readthedocs.io](https://codingest.readthedocs.io)**
237
239
  |---|---|
238
240
  | `crates/codingest` | The component library (`codingest`): builder, parsers, manifest reader, docs pass, multi-rev merge, cross-language edges. Extracted from the former `KGLite/crates/kglite/src/code_tree/` (removed upstream 2026-07-16) and re-targeted at the public `kglite::api` facade. Ships the `codingest_stats` + `codingest_bench` binaries. |
239
241
  | `crates/codingest-cli` | `codingest` binary — `build` a checkout or git revision(s) into a `.kgl` graph, `status` to check staleness, and `skill` to install Codingest's code-review Agent Skill. |
240
- | `crates/codingest-mcp` | `codingest-mcp` binary — the full MCP tool surface imported from the `kglite-mcp-server` library, with the codingest builder injected. |
242
+ | `crates/codingest-mcp` | `codingest-mcp` binary — the full MCP tool surface imported from the `kglite-mcp-server` library, with the codingest builder injected and codingest's `code_review` skill + recipe catalogue registered as the producer's methodology. |
241
243
  | `crates/codingest-py` | PyO3 wrapper built by maturin into the `codingest` wheel (`pip install codingest`). Python package source is `codingest/`; `pyproject.toml` drives the maturin build. Not published to crates.io (`publish = false`). |
242
244
 
243
245
  ## CI-equivalent local gate
@@ -277,7 +279,7 @@ diagnostic.
277
279
  ## Dependency policy
278
280
 
279
281
  `kglite` and `kglite-mcp-server` use matching crates.io requirements with a
280
- 0.17.6 minimum and a shared lockfile. This keeps the builder, persistence
282
+ 0.17.9 minimum and a shared lockfile. This keeps the builder, persistence
281
283
  handoff, and embedded MCP server on one compatible engine patch line.
282
284
 
283
285
  ## Parity with the (now-removed) in-tree component
@@ -32,7 +32,9 @@ a real `kglite.KnowledgeGraph`, ready for Cypher queries.
32
32
  ## Built for agents and code analysis
33
33
 
34
34
  - **Agent-ready MCP:** give an MCP client `graph_overview`, `cypher_query`,
35
- `read_code_source`, repository switching, and automatic graph refresh.
35
+ `read_code_source`, repository switching, automatic graph refresh, and the
36
+ code-review methodology itself — a `code_review` skill and a catalogue of
37
+ parameter-checked review recipes (`run_recipe_query`) served for every graph.
36
38
  [opencode is set up and verified end to end](https://codingest.readthedocs.io/en/latest/mcp.html#using-codingest-mcp-with-opencode)
37
39
  — including a config that needs no absolute paths — and `codingest skill
38
40
  install` packages the review skill for Claude Code and Codex, which opencode
@@ -165,7 +167,7 @@ codingest skill install # code-review Agent Skill
165
167
  ```
166
168
 
167
169
  The wheel bundles every grammar plus the `codingest` and `codingest-mcp`
168
- commands. KGLite ≥0.17.6 is installed automatically as the query/storage
170
+ commands. KGLite ≥0.17.9 is installed automatically as the query/storage
169
171
  engine; its MCP server and the transitive `mcp-methods` framework power the
170
172
  builder-aware Codingest server. Nothing else needs to be installed.
171
173
 
@@ -178,7 +180,7 @@ Python prerequisites.
178
180
  ```toml
179
181
  [dependencies]
180
182
  codingest = "0.2"
181
- kglite = "0.17.6"
183
+ kglite = "0.17.9"
182
184
  ```
183
185
 
184
186
  ```rust
@@ -210,7 +212,7 @@ Documentation: **[codingest.readthedocs.io](https://codingest.readthedocs.io)**
210
212
  |---|---|
211
213
  | `crates/codingest` | The component library (`codingest`): builder, parsers, manifest reader, docs pass, multi-rev merge, cross-language edges. Extracted from the former `KGLite/crates/kglite/src/code_tree/` (removed upstream 2026-07-16) and re-targeted at the public `kglite::api` facade. Ships the `codingest_stats` + `codingest_bench` binaries. |
212
214
  | `crates/codingest-cli` | `codingest` binary — `build` a checkout or git revision(s) into a `.kgl` graph, `status` to check staleness, and `skill` to install Codingest's code-review Agent Skill. |
213
- | `crates/codingest-mcp` | `codingest-mcp` binary — the full MCP tool surface imported from the `kglite-mcp-server` library, with the codingest builder injected. |
215
+ | `crates/codingest-mcp` | `codingest-mcp` binary — the full MCP tool surface imported from the `kglite-mcp-server` library, with the codingest builder injected and codingest's `code_review` skill + recipe catalogue registered as the producer's methodology. |
214
216
  | `crates/codingest-py` | PyO3 wrapper built by maturin into the `codingest` wheel (`pip install codingest`). Python package source is `codingest/`; `pyproject.toml` drives the maturin build. Not published to crates.io (`publish = false`). |
215
217
 
216
218
  ## CI-equivalent local gate
@@ -250,7 +252,7 @@ diagnostic.
250
252
  ## Dependency policy
251
253
 
252
254
  `kglite` and `kglite-mcp-server` use matching crates.io requirements with a
253
- 0.17.6 minimum and a shared lockfile. This keeps the builder, persistence
255
+ 0.17.9 minimum and a shared lockfile. This keeps the builder, persistence
254
256
  handoff, and embedded MCP server on one compatible engine patch line.
255
257
 
256
258
  ## Parity with the (now-removed) in-tree component
@@ -23,6 +23,7 @@ def build(
23
23
  rev: Optional[str] = None,
24
24
  revs: Optional[list[str]] = None,
25
25
  repo_root: Optional[str] = None,
26
+ embed_skills: bool = False,
26
27
  ) -> KnowledgeGraph:
27
28
  """Parse a codebase at ``src_dir`` into a :class:`kglite.KnowledgeGraph`.
28
29
 
@@ -70,6 +71,12 @@ def build(
70
71
  include_tests: Include test files/dirs in the graph (default True).
71
72
  max_loc_per_file: Skip files longer than this many lines (None = no cap).
72
73
  include_docs: Ingest markdown as ``:Doc`` nodes (see above).
74
+ embed_skills: Also write codingest's ``code_review`` skill and its
75
+ recipe catalogue into the graph as graph-carried records
76
+ (``KgliteSkill`` / ``KgliteRecipe``), for a ``.kgl`` served by a
77
+ plain ``kglite-mcp-server --graph``. Off by default: the default
78
+ graph is byte-identical to earlier releases, and ``codingest-mcp``
79
+ serves the methodology by itself. ``repo_tree`` never embeds.
73
80
  rev: A single git revspec to build (mutually exclusive with ``revs``).
74
81
  revs: A list of git revspecs to merge into a multi-rev graph.
75
82
  repo_root: Override the auto-resolved git root for ``rev``/``revs``.
@@ -10,7 +10,7 @@ keywords = ["knowledge-graph", "code-analysis", "tree-sitter", "cypher", "kglite
10
10
  categories = ["development-tools", "parser-implementations"]
11
11
 
12
12
  # Requires the kglite 0.15 engine API (`kglite::api::code_entities`); the
13
- # workspace pins the current engine floor (0.17.6).
13
+ # workspace pins the current engine floor (0.17.9).
14
14
 
15
15
  [lib]
16
16
  name = "codingest"
@@ -0,0 +1,97 @@
1
+ {
2
+ "code_review": {
3
+ "description": "Exact, parameter-checked operations for reviewing a change to a codingest code graph: resolve targets, count and page callers, walk callees, witness bounded call paths, and find type consumers and trait implementors.",
4
+ "queries": {
5
+ "target_coverage": {
6
+ "description": "For each requested qualified name: whether the Function exists (target is null when missing) and how many Functions call it (callers is zero for an existing target with no callers). Run this before reading any empty result as an absence.",
7
+ "parameters": {
8
+ "type": "object",
9
+ "properties": {
10
+ "requested": {
11
+ "type": "array",
12
+ "items": { "type": "string" },
13
+ "description": "Exact Function qualified names to resolve."
14
+ }
15
+ },
16
+ "required": ["requested"],
17
+ "additionalProperties": false
18
+ },
19
+ "cypher": "UNWIND $requested AS requested OPTIONAL MATCH (target:Function {qualified_name: requested}) OPTIONAL MATCH (caller:Function)-[:CALLS]->(target) RETURN requested, target.qualified_name AS target, count(caller) AS callers ORDER BY requested"
20
+ },
21
+ "caller_coverage": {
22
+ "description": "Caller counts of one Function split by whether the caller is a test (is_test), so production and test pages can be requested separately with callers_page.",
23
+ "parameters": {
24
+ "type": "object",
25
+ "properties": {
26
+ "qualified_name": { "type": "string", "description": "Exact Function qualified name." }
27
+ },
28
+ "required": ["qualified_name"],
29
+ "additionalProperties": false
30
+ },
31
+ "cypher": "MATCH (caller:Function)-[:CALLS]->(target:Function) WHERE target.qualified_name = $qualified_name RETURN target.qualified_name AS target, caller.is_test AS is_test, count(caller) AS callers ORDER BY is_test"
32
+ },
33
+ "callers_page": {
34
+ "description": "One page (25 rows) of direct callers of a Function, production (is_test false) or test (is_test true), with each caller's location and the evidence behind the CALLS edge: resolution, candidates (>1 means the call site fanned out), import_backed (false is unconfirmed, not refuted) and call_lines.",
35
+ "parameters": {
36
+ "type": "object",
37
+ "properties": {
38
+ "qualified_name": { "type": "string", "description": "Exact Function qualified name of the callee." },
39
+ "is_test": { "type": "boolean", "description": "true for test callers, false for production callers." }
40
+ },
41
+ "required": ["is_test", "qualified_name"],
42
+ "additionalProperties": false
43
+ },
44
+ "cypher": "MATCH (caller:Function)-[rel:CALLS]->(target:Function) WHERE target.qualified_name = $qualified_name AND caller.is_test = $is_test RETURN target.qualified_name AS target, caller.qualified_name AS caller, caller.file_path AS file, caller.line_number AS line, rel.resolution AS resolution, rel.candidates AS candidates, rel.import_backed AS import_backed, rel.call_lines AS call_lines ORDER BY caller, file, line LIMIT 25"
45
+ },
46
+ "direct_callees": {
47
+ "description": "Up to 25 Functions a Function calls directly, with both locations and the CALLS edge evidence (resolution, candidates, import_backed, call_lines). An unresolved source call has no CALLS edge; inspect the source before concluding a call is absent.",
48
+ "parameters": {
49
+ "type": "object",
50
+ "properties": {
51
+ "qualified_name": { "type": "string", "description": "Exact Function qualified name of the caller." }
52
+ },
53
+ "required": ["qualified_name"],
54
+ "additionalProperties": false
55
+ },
56
+ "cypher": "MATCH (caller:Function)-[rel:CALLS]->(callee:Function) WHERE caller.qualified_name = $qualified_name RETURN caller.qualified_name AS caller, callee.qualified_name AS callee, caller.file_path AS caller_file, caller.line_number AS caller_line, callee.file_path AS callee_file, callee.line_number AS callee_line, rel.resolution AS resolution, rel.candidates AS candidates, rel.import_backed AS import_backed, rel.call_lines AS call_lines ORDER BY callee, callee_file, callee_line LIMIT 25"
57
+ },
58
+ "bounded_call_path": {
59
+ "description": "Up to ten CALLS paths of one to four hops from one Function to another, shortest first: bounded path witnesses instead of an unbounded neighbourhood.",
60
+ "parameters": {
61
+ "type": "object",
62
+ "properties": {
63
+ "start": { "type": "string", "description": "Exact qualified name of the starting Function." },
64
+ "finish": { "type": "string", "description": "Exact qualified name of the Function to reach." }
65
+ },
66
+ "required": ["finish", "start"],
67
+ "additionalProperties": false
68
+ },
69
+ "cypher": "MATCH path = (start:Function)-[:CALLS*1..4]->(finish:Function) WHERE start.qualified_name = $start AND finish.qualified_name = $finish RETURN [step IN nodes(path) | step.qualified_name] AS functions, length(path) AS hops ORDER BY hops, functions LIMIT 10"
70
+ },
71
+ "type_consumers": {
72
+ "description": "Up to 25 Functions that take a Struct as an explicit parameter (position parameter or both, since one USES_TYPE edge aggregates a type used as both parameter and return value), with each consumer's location.",
73
+ "parameters": {
74
+ "type": "object",
75
+ "properties": {
76
+ "qualified_name": { "type": "string", "description": "Exact Struct qualified name." }
77
+ },
78
+ "required": ["qualified_name"],
79
+ "additionalProperties": false
80
+ },
81
+ "cypher": "MATCH (consumer:Function)-[use:USES_TYPE]->(used:Struct) WHERE used.qualified_name = $qualified_name AND use.position IN ['parameter', 'both'] RETURN used.qualified_name AS used_type, consumer.qualified_name AS consumer, consumer.file_path AS file, consumer.line_number AS line, use.position AS position ORDER BY consumer, file, line LIMIT 25"
82
+ },
83
+ "trait_implementations": {
84
+ "description": "Up to 25 Structs with an IMPLEMENTS edge to a Trait, with each implementor's location. Macro-generated or heuristic structure may be absent from the graph: a missing edge is a reason to inspect source, not proof of no implementation.",
85
+ "parameters": {
86
+ "type": "object",
87
+ "properties": {
88
+ "qualified_name": { "type": "string", "description": "Exact Trait qualified name." }
89
+ },
90
+ "required": ["qualified_name"],
91
+ "additionalProperties": false
92
+ },
93
+ "cypher": "MATCH (implementor:Struct)-[:IMPLEMENTS]->(implemented:Trait) WHERE implemented.qualified_name = $qualified_name RETURN implemented.qualified_name AS trait, implementor.qualified_name AS implementor, implementor.file_path AS file, implementor.line_number AS line ORDER BY implementor, file, line LIMIT 25"
94
+ }
95
+ }
96
+ }
97
+ }
@@ -0,0 +1,70 @@
1
+ # Reviewing a codingest code graph
2
+
3
+ codingest built every graph this server serves, so the shapes are fixed:
4
+ `Function`, `Struct`, `Class`, `Trait`, `Interface`, `Protocol`, `Enum`,
5
+ `Module`, `File`, `Doc` nodes keyed by `qualified_name`; `CALLS`,
6
+ `USES_TYPE`, `IMPLEMENTS`, `EXTENDS`, `HAS_METHOD`, `IMPORTS`, `DEFINES`,
7
+ `HAS_FILE` edges. Functions carry `file_path`, `line_number`, `is_test`.
8
+ The graph is structural evidence beside the diff and the source; use it
9
+ only as far as the question requires.
10
+
11
+ ## Sequence
12
+
13
+ 1. **Resolve targets first** with `run_recipe_query("code_review",
14
+ "target_coverage", {"requested": [...]})`. A null `target` means the name is
15
+ not in this graph (typo, macro-generated, other revision); `callers` of zero
16
+ for an existing target is a real absence. Never read an empty result as an
17
+ absence until the target has resolved.
18
+ 2. **Count before paging.** `caller_coverage` splits one target's callers into
19
+ production and test counts. One target per call: a shared page can fill
20
+ with one target and hide another.
21
+ 3. **Page callers by kind.** `callers_page` with `is_test: false` gives the
22
+ production callers, `is_test: true` the tests that would notice, 25 at a
23
+ time with file and line. Each row carries the `CALLS` edge's evidence:
24
+ `resolution`, `candidates` (>1 = the call site fanned out), `import_backed`
25
+ (false is unconfirmed, not refuted) and `call_lines`.
26
+ 4. **Walk the other way** with `direct_callees`, same evidence columns. An
27
+ unresolved source call has no `CALLS` edge at all, so read the source before
28
+ concluding a call is absent.
29
+ 5. **Witness reachability, do not explore it.** `bounded_call_path` returns up
30
+ to ten paths of at most four hops between two resolved functions.
31
+ 6. **Type and trait impact.** `type_consumers` lists functions taking a struct
32
+ as an explicit parameter; `trait_implementations` lists structs with an
33
+ `IMPLEMENTS` edge to a trait. Macro-generated or heuristic structure may be
34
+ missing, so a missing edge is a reason to read source.
35
+ 7. **Read the selected source** with `read_code_source` (qualified name) or
36
+ `read_source` (path), bounded by `start_line` / `end_line`.
37
+ 8. **Use `cypher_query` only for a question no recipe shapes** — imports,
38
+ module structure, docs links, `CALL rev_diff({from, to})` on a multi-rev
39
+ graph — and check the shape with `graph_overview` first.
40
+
41
+ ## Recipes served for this graph
42
+
43
+ - `code_review/target_coverage` — existence plus caller count, for a list of names.
44
+ - `code_review/caller_coverage` — production versus test caller counts for one target.
45
+ - `code_review/callers_page` — direct callers of one kind, 25 at a time, with edge evidence.
46
+ - `code_review/direct_callees` — what one function calls, 25 at a time, with edge evidence.
47
+ - `code_review/bounded_call_path` — up to ten paths of at most four hops between two functions.
48
+ - `code_review/type_consumers` — functions taking a struct as an explicit parameter.
49
+ - `code_review/trait_implementations` — structs implementing a trait.
50
+
51
+ For a diff-scoped review, start from the functions whose `file_path` the
52
+ diff touched, resolve them, then run steps 2 to 4 on each.
53
+
54
+ ## Reading results
55
+
56
+ A page is complete only up to its literal size (25 rows, 10 paths); a full
57
+ page proves nothing about other targets or edges the builder never emitted.
58
+ Follow a retained result's advertised expansion; expansion cannot recover
59
+ rows a `LIMIT` excluded — narrow the target instead. A warning about an
60
+ unknown property or reversed relationship means the query shape is wrong, not
61
+ that the result is empty.
62
+
63
+ ## Findings and honesty
64
+
65
+ A finding names a concrete failure — the input or state and the wrong outcome
66
+ — verified against exact source lines at the reviewed revision. "No findings"
67
+ is a valid review; design preferences are not findings, and an edge showing
68
+ coupling is a fact, not a defect. Never invent labels, properties, edge types
69
+ or recipe names; a missing edge is absence of evidence, not proof of absence;
70
+ never build or execute a repository's code merely to review it.
@@ -249,20 +249,29 @@ fn discover_and_parse(root: &Path) -> Result<Vec<DocEntry>, String> {
249
249
  // computes titles from frontmatter / first heading, honors `kg_skip`,
250
250
  // flattens frontmatter). We bypass `okf::walk` so `.rst` shares one traversal and so
251
251
  // `index.md` is kept (the docs pass builds no Folder hierarchy).
252
+ // `for_dialect` rather than a struct literal: it carries the dialect's
253
+ // `Profile` (the conventions the parser reads — id scheme, reserved keys,
254
+ // wikilinks, collection encoding), which a literal cannot construct from
255
+ // outside kglite and which a bare `dialect:` assignment would leave at the
256
+ // wrong dialect's defaults. Only the two fields the docs pass deliberately
257
+ // differs on are overridden: every `.md` is admitted (a repo's docs carry
258
+ // no frontmatter) and the body is stored (the `:Doc` node's prose).
252
259
  let md_opts = okf::BuildOptions {
253
- dialect: okf::Dialect::Okf,
254
260
  require_frontmatter: false,
255
- respect_skip: true,
256
- skip_dirs: Vec::new(),
257
261
  with_body: true,
258
- embed: false,
262
+ ..okf::BuildOptions::for_dialect(okf::Dialect::Okf)
259
263
  };
264
+ // `size` / `mtime` feed only `okf::fingerprint` and the attachment nodes,
265
+ // neither of which the docs pass reaches — `parse_concepts` reads nothing
266
+ // but the two paths — so the walk does not stat a second time to fill them.
260
267
  let md_files: Vec<okf::walk::DiscoveredFile> = found
261
268
  .iter()
262
269
  .filter(|d| d.format == DocFormat::Markdown)
263
270
  .map(|d| okf::walk::DiscoveredFile {
264
271
  rel_path: d.rel_path.clone(),
265
272
  abs_path: d.abs_path.clone(),
273
+ size: 0,
274
+ mtime: None,
266
275
  })
267
276
  .collect();
268
277
  let mut docs: Vec<DocEntry> = okf::parse_concepts(&md_files, &md_opts)
@@ -23,6 +23,7 @@ pub mod cross_lang;
23
23
  #[cfg(feature = "docs")]
24
24
  pub mod docs;
25
25
  pub mod manifest;
26
+ pub mod methodology;
26
27
  pub mod models;
27
28
  pub mod parsers;
28
29
  pub mod repo;