codingest 0.1.7__tar.gz → 0.2.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 (97) hide show
  1. {codingest-0.1.7 → codingest-0.2.0}/Cargo.lock +44 -38
  2. codingest-0.2.0/Cargo.toml +83 -0
  3. {codingest-0.1.7 → codingest-0.2.0}/PKG-INFO +5 -5
  4. {codingest-0.1.7 → codingest-0.2.0}/README.md +3 -3
  5. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/Cargo.toml +4 -4
  6. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/bin/codingest_bench.rs +161 -29
  7. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/bin/codingest_stats.rs +10 -8
  8. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/call_edges.rs +259 -34
  9. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/js_workspace.rs +1 -6
  10. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/load/edge_frames.rs +26 -10
  11. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/mod.rs +514 -57
  12. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/other_edges.rs +312 -1
  13. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/routes/django.rs +3 -3
  14. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/routes/fastapi.rs +3 -3
  15. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/routes/flask.rs +1 -1
  16. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/routes/mod.rs +152 -11
  17. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/cross_lang.rs +88 -2
  18. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/docs/mod.rs +375 -42
  19. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/lib.rs +12 -0
  20. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/manifest/mod.rs +45 -3
  21. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/models.rs +16 -1
  22. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/agc.rs +14 -11
  23. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/mod.rs +32 -11
  24. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/registry.rs +62 -7
  25. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/typescript.rs +12 -12
  26. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/rev.rs +110 -30
  27. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/tests/goldens/README.md +105 -0
  28. codingest-0.2.0/crates/codingest/tests/goldens/agc_basic.sha256 +1 -0
  29. codingest-0.2.0/crates/codingest/tests/goldens/cross_ts_py.sha256 +1 -0
  30. codingest-0.2.0/crates/codingest/tests/goldens/docs_ext_collide.sha256 +1 -0
  31. codingest-0.2.0/crates/codingest/tests/goldens/docs_mdx.sha256 +1 -0
  32. codingest-0.2.0/crates/codingest/tests/goldens/dup_minified_assets.sha256 +1 -0
  33. codingest-0.2.0/crates/codingest/tests/goldens/html_js_lang_group.sha256 +1 -0
  34. codingest-0.2.0/crates/codingest/tests/goldens/py_basic.sha256 +1 -0
  35. codingest-0.2.0/crates/codingest/tests/goldens/py_inheritance.sha256 +1 -0
  36. codingest-0.2.0/crates/codingest/tests/goldens/py_nested_defs.sha256 +1 -0
  37. codingest-0.2.0/crates/codingest/tests/goldens/py_routes_dup.sha256 +1 -0
  38. codingest-0.2.0/crates/codingest/tests/goldens/ts_callback.sha256 +1 -0
  39. codingest-0.2.0/crates/codingest/tests/goldens/ts_closure_scope.sha256 +1 -0
  40. codingest-0.2.0/crates/codingest/tests/goldens/ts_hof_binding.sha256 +1 -0
  41. codingest-0.2.0/crates/codingest/tests/goldens/ts_monorepo.sha256 +1 -0
  42. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/tests/parity.rs +38 -2
  43. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/Cargo.toml +7 -5
  44. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/skills/codingest-code-review/SKILL.md +29 -0
  45. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/src/code_tree_cli.rs +280 -22
  46. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/tests/exit_codes.rs +155 -0
  47. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-mcp/Cargo.toml +2 -2
  48. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-py/Cargo.toml +4 -4
  49. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-py/src/lib.rs +1 -1
  50. {codingest-0.1.7 → codingest-0.2.0}/pyproject.toml +17 -2
  51. codingest-0.1.7/Cargo.toml +0 -46
  52. codingest-0.1.7/crates/codingest/tests/goldens/agc_basic.sha256 +0 -1
  53. codingest-0.1.7/crates/codingest/tests/goldens/cross_ts_py.sha256 +0 -1
  54. codingest-0.1.7/crates/codingest/tests/goldens/docs_mdx.sha256 +0 -1
  55. codingest-0.1.7/crates/codingest/tests/goldens/dup_minified_assets.sha256 +0 -1
  56. codingest-0.1.7/crates/codingest/tests/goldens/py_basic.sha256 +0 -1
  57. codingest-0.1.7/crates/codingest/tests/goldens/py_inheritance.sha256 +0 -1
  58. codingest-0.1.7/crates/codingest/tests/goldens/py_nested_defs.sha256 +0 -1
  59. codingest-0.1.7/crates/codingest/tests/goldens/ts_callback.sha256 +0 -1
  60. codingest-0.1.7/crates/codingest/tests/goldens/ts_closure_scope.sha256 +0 -1
  61. codingest-0.1.7/crates/codingest/tests/goldens/ts_hof_binding.sha256 +0 -1
  62. codingest-0.1.7/crates/codingest/tests/goldens/ts_monorepo.sha256 +0 -1
  63. {codingest-0.1.7 → codingest-0.2.0}/LICENSE +0 -0
  64. {codingest-0.1.7 → codingest-0.2.0}/codingest/__init__.py +0 -0
  65. {codingest-0.1.7 → codingest-0.2.0}/codingest/__init__.pyi +0 -0
  66. {codingest-0.1.7 → codingest-0.2.0}/codingest/cli.py +0 -0
  67. {codingest-0.1.7 → codingest-0.2.0}/codingest/mcp_server.py +0 -0
  68. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/load/entity_frames.rs +0 -0
  69. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/load.rs +0 -0
  70. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/semantic_edges.rs +0 -0
  71. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/builder/type_edges.rs +0 -0
  72. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/docs/rst.rs +0 -0
  73. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/cpp.rs +0 -0
  74. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/csharp.rs +0 -0
  75. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/css.rs +0 -0
  76. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/dart.rs +0 -0
  77. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/go.rs +0 -0
  78. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/html.rs +0 -0
  79. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/java.rs +0 -0
  80. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/php.rs +0 -0
  81. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/python.rs +0 -0
  82. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/rust_lang.rs +0 -0
  83. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/shared.rs +0 -0
  84. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/parsers/swift.rs +0 -0
  85. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/src/repo.rs +0 -0
  86. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/tests/agc_apollo.rs +0 -0
  87. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest/tests/goldens/rust_xfile.sha256 +0 -0
  88. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/skills/codingest-code-review/references/mcp-upgrade.md +0 -0
  89. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/skills/codingest-code-review/references/public-repositories.md +0 -0
  90. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/skills/codingest-code-review/references/queries.md +0 -0
  91. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/src/lib.rs +0 -0
  92. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/src/main.rs +0 -0
  93. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/src/query.rs +0 -0
  94. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/src/skill.rs +0 -0
  95. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-cli/src/skill_assets.rs +0 -0
  96. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-mcp/src/lib.rs +0 -0
  97. {codingest-0.1.7 → codingest-0.2.0}/crates/codingest-mcp/src/main.rs +0 -0
@@ -124,17 +124,6 @@ dependencies = [
124
124
  "stable_deref_trait",
125
125
  ]
126
126
 
127
- [[package]]
128
- name = "async-trait"
129
- version = "0.1.91"
130
- source = "registry+https://github.com/rust-lang/crates.io-index"
131
- checksum = "ae36dc4177970ef04fde5178d3e2429882def40e57a451f919c098f72baa6cec"
132
- dependencies = [
133
- "proc-macro2",
134
- "quote",
135
- "syn 3.0.3",
136
- ]
137
-
138
127
  [[package]]
139
128
  name = "atomic-polyfill"
140
129
  version = "1.0.3"
@@ -162,6 +151,12 @@ version = "0.22.1"
162
151
  source = "registry+https://github.com/rust-lang/crates.io-index"
163
152
  checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
164
153
 
154
+ [[package]]
155
+ name = "base64"
156
+ version = "0.23.1"
157
+ source = "registry+https://github.com/rust-lang/crates.io-index"
158
+ checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
159
+
165
160
  [[package]]
166
161
  name = "bit-set"
167
162
  version = "0.8.0"
@@ -313,10 +308,10 @@ dependencies = [
313
308
 
314
309
  [[package]]
315
310
  name = "codingest"
316
- version = "0.1.7"
311
+ version = "0.2.0"
317
312
  dependencies = [
318
313
  "aho-corasick",
319
- "base64",
314
+ "base64 0.22.1",
320
315
  "kglite",
321
316
  "rayon",
322
317
  "regex",
@@ -345,7 +340,7 @@ dependencies = [
345
340
 
346
341
  [[package]]
347
342
  name = "codingest-cli"
348
- version = "0.1.7"
343
+ version = "0.2.0"
349
344
  dependencies = [
350
345
  "anyhow",
351
346
  "clap",
@@ -357,7 +352,7 @@ dependencies = [
357
352
 
358
353
  [[package]]
359
354
  name = "codingest-mcp"
360
- version = "0.1.7"
355
+ version = "0.2.0"
361
356
  dependencies = [
362
357
  "anyhow",
363
358
  "codingest",
@@ -366,7 +361,7 @@ dependencies = [
366
361
 
367
362
  [[package]]
368
363
  name = "codingest-py"
369
- version = "0.1.7"
364
+ version = "0.2.0"
370
365
  dependencies = [
371
366
  "codingest",
372
367
  "codingest-cli",
@@ -475,9 +470,9 @@ dependencies = [
475
470
 
476
471
  [[package]]
477
472
  name = "darling"
478
- version = "0.23.0"
473
+ version = "0.24.0"
479
474
  source = "registry+https://github.com/rust-lang/crates.io-index"
480
- checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
475
+ checksum = "88490bf1b990d87eaaa7ac8aa887f629a08e7359765b4911faf63c3763347d23"
481
476
  dependencies = [
482
477
  "darling_core",
483
478
  "darling_macro",
@@ -485,26 +480,26 @@ dependencies = [
485
480
 
486
481
  [[package]]
487
482
  name = "darling_core"
488
- version = "0.23.0"
483
+ version = "0.24.0"
489
484
  source = "registry+https://github.com/rust-lang/crates.io-index"
490
- checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
485
+ checksum = "084e274f91c482280130e1e34e0b8d6e66776a060d7b6de7b84289ca778868c4"
491
486
  dependencies = [
492
487
  "ident_case",
493
488
  "proc-macro2",
494
489
  "quote",
495
490
  "strsim",
496
- "syn 2.0.119",
491
+ "syn 3.0.3",
497
492
  ]
498
493
 
499
494
  [[package]]
500
495
  name = "darling_macro"
501
- version = "0.23.0"
496
+ version = "0.24.0"
502
497
  source = "registry+https://github.com/rust-lang/crates.io-index"
503
- checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
498
+ checksum = "68f5792fa0d41cd2325ce0ffa64f0a340eaebd4971a3a0c5e1ffd2cc488a355e"
504
499
  dependencies = [
505
500
  "darling_core",
506
501
  "quote",
507
- "syn 2.0.119",
502
+ "syn 3.0.3",
508
503
  ]
509
504
 
510
505
  [[package]]
@@ -1393,9 +1388,9 @@ dependencies = [
1393
1388
 
1394
1389
  [[package]]
1395
1390
  name = "kglite"
1396
- version = "0.15.6"
1391
+ version = "0.15.11"
1397
1392
  source = "registry+https://github.com/rust-lang/crates.io-index"
1398
- checksum = "a8cf3016156af6dafbc1041fa443e94002686b6deeee0fea38f9b712c50c96f8"
1393
+ checksum = "ab3210d1c2855536403c7e86725fe673ed4fce3b950bef81832324523b5d0357"
1399
1394
  dependencies = [
1400
1395
  "bzip2",
1401
1396
  "chrono",
@@ -1428,9 +1423,9 @@ dependencies = [
1428
1423
 
1429
1424
  [[package]]
1430
1425
  name = "kglite-mcp-server"
1431
- version = "0.15.6"
1426
+ version = "0.15.11"
1432
1427
  source = "registry+https://github.com/rust-lang/crates.io-index"
1433
- checksum = "afaf8e38626f3991d7d7fca93df9230ec7160af894e855bc5cbe49e6c0342ab3"
1428
+ checksum = "920fed2716305e6be2663153782183c150330b643c06bf349dfaaf764fef54fe"
1434
1429
  dependencies = [
1435
1430
  "anyhow",
1436
1431
  "bytes",
@@ -1532,9 +1527,9 @@ dependencies = [
1532
1527
 
1533
1528
  [[package]]
1534
1529
  name = "mcp-methods"
1535
- version = "0.4.3"
1530
+ version = "0.4.4"
1536
1531
  source = "registry+https://github.com/rust-lang/crates.io-index"
1537
- checksum = "caa2079c12e642cd4b9a20543c85305eb5ffee04b1d565feab47b084db167a99"
1532
+ checksum = "d6d41f37fa137ea40a0cd505729e41ae1156ed119dcf8f240210579889c5ba29"
1538
1533
  dependencies = [
1539
1534
  "anyhow",
1540
1535
  "clap",
@@ -1945,12 +1940,11 @@ dependencies = [
1945
1940
 
1946
1941
  [[package]]
1947
1942
  name = "rmcp"
1948
- version = "2.2.0"
1943
+ version = "3.1.1"
1949
1944
  source = "registry+https://github.com/rust-lang/crates.io-index"
1950
- checksum = "14db48ee17a9ba61810ab1a9c1beb7d06d8136ae39ac25a1137f10d357af01af"
1945
+ checksum = "094c075f6698deef5a657cf4df6b684dff65157d255978b92b552ec22503f17a"
1951
1946
  dependencies = [
1952
- "async-trait",
1953
- "base64",
1947
+ "base64 0.23.1",
1954
1948
  "chrono",
1955
1949
  "futures",
1956
1950
  "pastey",
@@ -1963,19 +1957,20 @@ dependencies = [
1963
1957
  "tokio",
1964
1958
  "tokio-util",
1965
1959
  "tracing",
1960
+ "uuid",
1966
1961
  ]
1967
1962
 
1968
1963
  [[package]]
1969
1964
  name = "rmcp-macros"
1970
- version = "2.2.0"
1965
+ version = "3.1.1"
1971
1966
  source = "registry+https://github.com/rust-lang/crates.io-index"
1972
- checksum = "783d787bf21813b285f13019adc49e11af501c658890c1e519f31f937c68b7e3"
1967
+ checksum = "737d947bcfd946fae6a179a4ef6487be6dcf25c930c2393856b820f1386e52a6"
1973
1968
  dependencies = [
1974
1969
  "darling",
1975
1970
  "proc-macro2",
1976
1971
  "quote",
1977
1972
  "serde_json",
1978
- "syn 2.0.119",
1973
+ "syn 3.0.3",
1979
1974
  ]
1980
1975
 
1981
1976
  [[package]]
@@ -2830,7 +2825,7 @@ version = "2.12.1"
2830
2825
  source = "registry+https://github.com/rust-lang/crates.io-index"
2831
2826
  checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
2832
2827
  dependencies = [
2833
- "base64",
2828
+ "base64 0.22.1",
2834
2829
  "flate2",
2835
2830
  "log",
2836
2831
  "once_cell",
@@ -2866,6 +2861,17 @@ version = "0.2.2"
2866
2861
  source = "registry+https://github.com/rust-lang/crates.io-index"
2867
2862
  checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
2868
2863
 
2864
+ [[package]]
2865
+ name = "uuid"
2866
+ version = "1.24.0"
2867
+ source = "registry+https://github.com/rust-lang/crates.io-index"
2868
+ checksum = "bf3923a6f5c4c6382e0b653c4117f48d631ea17f38ed86e2a828e6f7412f5239"
2869
+ dependencies = [
2870
+ "getrandom 0.4.3",
2871
+ "js-sys",
2872
+ "wasm-bindgen",
2873
+ ]
2874
+
2869
2875
  [[package]]
2870
2876
  name = "valuable"
2871
2877
  version = "0.1.1"
@@ -0,0 +1,83 @@
1
+ [workspace]
2
+ members = ["crates/codingest", "crates/codingest-cli", "crates/codingest-mcp", "crates/codingest-py"]
3
+ resolver = "2"
4
+
5
+ [workspace.package]
6
+ version = "0.2.0"
7
+ edition = "2021"
8
+ rust-version = "1.88"
9
+ license = "MIT"
10
+ repository = "https://github.com/kkollsga/codingest"
11
+
12
+ [workspace.dependencies]
13
+ base64 = "0.22"
14
+ sha2 = "0.11"
15
+ # kglite engine + MCP server — imported as crates.io libraries. The 0.15.11
16
+ # floor brings three things, only one of which changes what we run:
17
+ # * 0.15.10's `add_connections` resolves its edge-property columns once per
18
+ # call instead of once per cell — upstream measured 66.7ms -> 30.4ms
19
+ # (-54%) on 60k edges x 10 property columns. That is exactly the shape of
20
+ # our `control_edges_df` handoff, so it lands on the `calls` stage.
21
+ # * The `NodeData` -> `NodeView` API break from 0.15.9, made migratable in
22
+ # 0.15.11. 0.15.9 deleted `NodeData`'s inherent property accessors and
23
+ # 0.15.11 finally shipped reachable replacements: reads go through
24
+ # `DirGraph::node_view(idx)`, and by-index writes through the inherent
25
+ # `DirGraph::set_node_property(idx, "key", value)`. We migrated 21 read
26
+ # sites and the 2 `revs`/`rev_fp` write sites in `rev.rs` for this floor.
27
+ # It is a compile-time break only — the storage path behind both spellings
28
+ # is the one the removed methods already called, so it is NOT
29
+ # output-affecting.
30
+ # NOTE: do NOT reach the write side via `GraphWrite::set_node_property`
31
+ # with an `InternedKey::from_str` key. That key is never registered: it
32
+ # reads back within the session but breaks property enumeration and is
33
+ # silently dropped by `save_graph`. The inherent string-keyed calls
34
+ # register the name; use them.
35
+ # * 0.15.11's `kglite::api::embeddings` ingest API and `text_score()` query-
36
+ # vector arguments — codingest consumes neither.
37
+ # Per the 0.15.9-0.15.11 changelogs, graph output, property encoding and
38
+ # `.kgl` serialization are unchanged; the frozen parity goldens are what
39
+ # proves it, and they must not move across this bump.
40
+ #
41
+ # Floor history. The 0.15.8
42
+ # floor added recorded storage modes, `--storage` conversion on an existing
43
+ # graph, and boot-validated Cypher recipe catalogs — none of which codingest
44
+ # consumes — plus two changes that do reach us: workspace-graph producers now
45
+ # receive deduplicated changed-path hints alongside full-build requests (our
46
+ # `with_workspace_graph` producer lives in codingest-mcp), and the optimized-
47
+ # plan cache no longer lets a write loop evict other graphs' cached read plans.
48
+ # `OpenGraphResult` gained a `converted_from` field — a documented struct-
49
+ # literal break we are not exposed to, as codingest constructs no
50
+ # `OpenGraphResult`. 0.15.7 aligned the embedded server on mcp-methods 0.4.4
51
+ # and rmcp 3.1.1; dynamic handlers use rmcp's response envelope while
52
+ # preserving their payloads and MCP behavior. The 0.15.6 engine fixes
53
+ # mixed-selection vector dispatch, mixed-metric exact search,
54
+ # community-detection modularity scoring, sampled-centrality validation, and
55
+ # persisted HNSW validation, while adding the bulk node-degree primitive and
56
+ # graph-algorithm/vector-search performance improvements. It builds on the two
57
+ # workspace controls codingest asked upstream for in 0.15.5:
58
+ # `workspace.sandbox_root`, a real containment boundary that confines
59
+ # `set_root_dir` to a subtree instead of trusting the caller's path, and
60
+ # `workspace.adopt_client_roots`. Both land on top of the generic
61
+ # workspace-graph hooks, tri-state `durable` levels, typed
62
+ # constraint/conflict exceptions carrying a stable `.code`, and the
63
+ # deterministic Postcard persistence stack inherited from 0.14.5/0.15.0-0.15.3.
64
+ # 0.15.4 is deliberately skipped: it was WAL/durability and mapped-graph work
65
+ # we consume none of — codingest uses no `durable=` level, no `MappedGraph`,
66
+ # and no disk storage. Neither 0.15.7 nor 0.15.8 changes the `kglite::api` we
67
+ # call, graph output, property encoding, or `.kgl` serialization.
68
+ # Keep both libraries aligned so the graph and server share one engine release.
69
+ kglite = { version = "0.15.11", default-features = false }
70
+ kglite-mcp-server = { version = "0.15.11", default-features = false }
71
+
72
+ # Mirror KGLite's release codegen so the standalone builder has
73
+ # performance parity with the in-tree component (see KGLite
74
+ # workspace Cargo.toml).
75
+ [profile.release]
76
+ lto = "thin"
77
+ codegen-units = 1
78
+ strip = "symbols"
79
+
80
+ [profile.profiling]
81
+ inherits = "release"
82
+ debug = "line-tables-only"
83
+ strip = "none"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codingest
3
- Version: 0.1.7
3
+ Version: 0.2.0
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.15.6,<0.16
15
+ Requires-Dist: kglite>=0.15.11,<0.16
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
@@ -191,7 +191,7 @@ codingest skill install # code-review Agent Skill
191
191
  ```
192
192
 
193
193
  The wheel bundles every grammar plus the `codingest` and `codingest-mcp`
194
- commands. KGLite ≥0.15.6 is installed automatically as the query/storage
194
+ commands. KGLite ≥0.15.11 is installed automatically as the query/storage
195
195
  engine; its MCP server and the transitive `mcp-methods` framework power the
196
196
  builder-aware Codingest server. Nothing else needs to be installed.
197
197
 
@@ -204,7 +204,7 @@ Python prerequisites.
204
204
  ```toml
205
205
  [dependencies]
206
206
  codingest = "0.1"
207
- kglite = "0.15.6"
207
+ kglite = "0.15.11"
208
208
  ```
209
209
 
210
210
  ```rust
@@ -276,7 +276,7 @@ diagnostic.
276
276
  ## Dependency policy
277
277
 
278
278
  `kglite` and `kglite-mcp-server` use matching crates.io requirements with a
279
- 0.15.6 minimum and a shared lockfile. This keeps the builder, persistence
279
+ 0.15.11 minimum and a shared lockfile. This keeps the builder, persistence
280
280
  handoff, and embedded MCP server on one compatible engine patch line.
281
281
 
282
282
  ## Parity with the (now-removed) in-tree component
@@ -164,7 +164,7 @@ codingest skill install # code-review Agent Skill
164
164
  ```
165
165
 
166
166
  The wheel bundles every grammar plus the `codingest` and `codingest-mcp`
167
- commands. KGLite ≥0.15.6 is installed automatically as the query/storage
167
+ commands. KGLite ≥0.15.11 is installed automatically as the query/storage
168
168
  engine; its MCP server and the transitive `mcp-methods` framework power the
169
169
  builder-aware Codingest server. Nothing else needs to be installed.
170
170
 
@@ -177,7 +177,7 @@ Python prerequisites.
177
177
  ```toml
178
178
  [dependencies]
179
179
  codingest = "0.1"
180
- kglite = "0.15.6"
180
+ kglite = "0.15.11"
181
181
  ```
182
182
 
183
183
  ```rust
@@ -249,7 +249,7 @@ diagnostic.
249
249
  ## Dependency policy
250
250
 
251
251
  `kglite` and `kglite-mcp-server` use matching crates.io requirements with a
252
- 0.15.6 minimum and a shared lockfile. This keeps the builder, persistence
252
+ 0.15.11 minimum and a shared lockfile. This keeps the builder, persistence
253
253
  handoff, and embedded MCP server on one compatible engine patch line.
254
254
 
255
255
  ## Parity with the (now-removed) in-tree component
@@ -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 0.15 patch floor (0.15.6).
13
+ # workspace pins the current 0.15 patch floor (0.15.11).
14
14
 
15
15
  [lib]
16
16
  name = "codingest"
@@ -46,7 +46,7 @@ sha2 = { workspace = true }
46
46
 
47
47
  serde = { version = "1.0.229", features = ["derive"] }
48
48
  serde_json = "1.0.151"
49
- regex = "1"
49
+ regex = "1.13.1"
50
50
  rayon = "1.12"
51
51
  tree-sitter = "0.26.11"
52
52
  tree-sitter-python = "0.25.0"
@@ -65,8 +65,8 @@ tree-sitter-css = "0.25.0"
65
65
  tree-sitter-dart = "0.2.0"
66
66
  toml = "1.1.3"
67
67
  walkdir = "2.5.0"
68
- tempfile = "3"
68
+ tempfile = "3.27.0"
69
69
  aho-corasick = "1.1.4"
70
70
 
71
71
  [dev-dependencies]
72
- tempfile = "3"
72
+ tempfile = "3.27.0"
@@ -42,6 +42,7 @@
42
42
  //! cargo run -p codingest --bin codingest_bench --release -- <path>
43
43
  //! cargo run -p codingest --bin codingest_bench --release -- <path> --json
44
44
  //! cargo run -p codingest --bin codingest_bench --release -- <path> --include-untracked
45
+ //! cargo run -p codingest --bin codingest_bench --release -- <path> --no-docs
45
46
 
46
47
  use kglite::api::session::{execute_read, ExecuteOptions, ExecuteOutcome};
47
48
  use kglite::api::{DirGraph, GraphRead, Value};
@@ -264,6 +265,69 @@ fn resolve_corpus(target: &Path, include_untracked: bool) -> Corpus {
264
265
  }
265
266
  }
266
267
 
268
+ // ── command line ─────────────────────────────────────────────────────────
269
+
270
+ const USAGE: &str = "usage: codingest_bench <path> [--json] [--include-untracked] [--no-docs]";
271
+
272
+ /// Everything the command line can say after `<path>`, parsed once so the
273
+ /// configuration a run was taken under is a value that can be echoed and
274
+ /// tested rather than a scatter of `any(|a| a == …)` predicates — the shape
275
+ /// `codingest_stats` already uses.
276
+ #[derive(Debug, PartialEq, Eq)]
277
+ struct Options {
278
+ json: bool,
279
+ include_untracked: bool,
280
+ /// DECISION (2026-08-10): this default points the OPPOSITE way to
281
+ /// `codingest_stats`' `--include-docs`, deliberately.
282
+ ///
283
+ /// Both binaries obey the same rule — a binary's default must reproduce
284
+ /// that binary's own historical rows, or old and new numbers silently stop
285
+ /// being comparable — and they have mirror-image histories. Every
286
+ /// `codingest_stats` row predating its flag was captured docs-OFF, so it
287
+ /// defaults off and opts in. This harness hardcoded docs-ON from the day it
288
+ /// was written, so every bench row ever filed (`BENCHMARKS.md`, the ad-hoc
289
+ /// results log) is a docs-ON measurement: it keeps docs-ON as the default
290
+ /// and gains an explicit `--no-docs` opt-OUT.
291
+ ///
292
+ /// The asymmetry is therefore not an inconsistency to be tidied away; it is
293
+ /// what keeps each binary's own series continuous. Neither default is
294
+ /// self-describing, which is why the effective value is echoed in the JSON
295
+ /// (`include_docs`) and in the human header either way — no row can be
296
+ /// filed without stating the mode it was taken under.
297
+ include_docs: bool,
298
+ }
299
+
300
+ impl Default for Options {
301
+ fn default() -> Self {
302
+ Self {
303
+ json: false,
304
+ include_untracked: false,
305
+ include_docs: true,
306
+ }
307
+ }
308
+ }
309
+
310
+ /// Parse the arguments after `<path>`.
311
+ ///
312
+ /// Rejects anything unrecognised rather than silently ignoring it: a typo'd
313
+ /// `--include-untraked` or `--nodocs` would otherwise change nothing and the
314
+ /// run would be reported as a measurement taken under a mode it never ran in.
315
+ /// That includes `--include-docs`: it is `codingest_stats`' spelling, it is not
316
+ /// this binary's, and accepting it as a no-op would teach the wrong muscle
317
+ /// memory for the one flag whose two binaries disagree.
318
+ fn parse_options(args: &[String]) -> Result<Options, String> {
319
+ let mut out = Options::default();
320
+ for arg in args {
321
+ match arg.as_str() {
322
+ "--json" => out.json = true,
323
+ "--include-untracked" => out.include_untracked = true,
324
+ "--no-docs" => out.include_docs = false,
325
+ other => return Err(format!("unknown argument `{other}`")),
326
+ }
327
+ }
328
+ Ok(out)
329
+ }
330
+
267
331
  struct QueryResult {
268
332
  name: String,
269
333
  rows: usize,
@@ -280,24 +344,20 @@ fn main() {
280
344
  let path = match args.next() {
281
345
  Some(p) => p,
282
346
  None => {
283
- eprintln!("usage: code_tree_bench <path> [--json]");
347
+ eprintln!("{USAGE}");
284
348
  std::process::exit(2);
285
349
  }
286
350
  };
287
351
  let rest: Vec<String> = args.collect();
288
- let json = rest.iter().any(|a| a == "--json");
289
- let include_untracked = rest.iter().any(|a| a == "--include-untracked");
290
- // Reject unknown flags rather than silently ignoring them: a typo'd
291
- // `--include-untraked` would otherwise change nothing and be reported as a
292
- // measurement taken under a mode it never ran in.
293
- if let Some(bad) = rest
294
- .iter()
295
- .find(|a| !matches!(a.as_str(), "--json" | "--include-untracked"))
296
- {
297
- eprintln!("unknown argument `{bad}`");
298
- eprintln!("usage: codingest_bench <path> [--json] [--include-untracked]");
352
+ let Options {
353
+ json,
354
+ include_untracked,
355
+ include_docs,
356
+ } = parse_options(&rest).unwrap_or_else(|e| {
357
+ eprintln!("{e}");
358
+ eprintln!("{USAGE}");
299
359
  std::process::exit(2);
300
- }
360
+ });
301
361
  let target = Path::new(&path);
302
362
 
303
363
  // Resolve the corpus BEFORE any timing: by default this copies the
@@ -306,22 +366,27 @@ fn main() {
306
366
  let corpus = resolve_corpus(target, include_untracked);
307
367
  let build_dir = corpus.build_dir.as_path();
308
368
 
309
- // Two independent codingest builds with identical arguments:
310
- // verbose=false, include_tests=false, save_to=None, max_loc=None, docs=true.
369
+ // Two independent codingest builds with identical arguments: verbose=false,
370
+ // include_tests=false, save_to=None, max_loc=None, docs=`include_docs`
371
+ // (ON unless `--no-docs`). Both sides MUST take the same value — the A/B
372
+ // comparison is a determinism check, so a configuration difference between
373
+ // them would surface as a MISMATCH and be read as a builder regression.
311
374
  let t = Instant::now();
312
- let graph_a = codingest::builder::run_with_options(build_dir, false, false, None, None, true)
313
- .unwrap_or_else(|e| {
314
- eprintln!("build A failed: {e}");
315
- std::process::exit(1);
316
- });
375
+ let graph_a =
376
+ codingest::builder::run_with_options(build_dir, false, false, None, None, include_docs)
377
+ .unwrap_or_else(|e| {
378
+ eprintln!("build A failed: {e}");
379
+ std::process::exit(1);
380
+ });
317
381
  let build_a_secs = t.elapsed().as_secs_f64();
318
382
 
319
383
  let t = Instant::now();
320
- let graph_b = codingest::builder::run_with_options(build_dir, false, false, None, None, true)
321
- .unwrap_or_else(|e| {
322
- eprintln!("build B failed: {e}");
323
- std::process::exit(1);
324
- });
384
+ let graph_b =
385
+ codingest::builder::run_with_options(build_dir, false, false, None, None, include_docs)
386
+ .unwrap_or_else(|e| {
387
+ eprintln!("build B failed: {e}");
388
+ std::process::exit(1);
389
+ });
325
390
  let build_b_secs = t.elapsed().as_secs_f64();
326
391
 
327
392
  let a: &DirGraph = &graph_a;
@@ -486,11 +551,15 @@ fn main() {
486
551
  "corpus_files": corpus.sha256.as_ref().map(|_| corpus.files),
487
552
  "corpus_bytes": corpus.sha256.as_ref().map(|_| corpus.bytes),
488
553
  "corpus_sha256": corpus.sha256,
489
- // Fixed build configuration, echoed so a recorded row states it.
490
- // Unlike codingest_stats, this harness has always built docs-ON,
491
- // so the docs pass IS in its build times and node counts.
554
+ // Build configuration, echoed so a recorded row states it rather
555
+ // than inheriting it from whoever reads the row. `include_docs` is
556
+ // the EFFECTIVE value, not the default: docs are ON unless
557
+ // `--no-docs` was passed, and when they are on the docs pass is in
558
+ // these build times and node counts. Every historical bench row was
559
+ // taken docs-ON — see `Options::include_docs` for why that is this
560
+ // binary's default and the opposite of codingest_stats'.
492
561
  "include_tests": false,
493
- "include_docs": true,
562
+ "include_docs": include_docs,
494
563
  "nodes": nodes,
495
564
  "edges": edges,
496
565
  "build_a_secs": (build_a_secs * 1000.0).round() / 1000.0,
@@ -532,6 +601,9 @@ fn main() {
532
601
  corpus.reason,
533
602
  ),
534
603
  }
604
+ // The effective build configuration, printed for the same reason the JSON
605
+ // echoes it: a pasted bench table must carry the mode it was taken under.
606
+ println!("config : include_tests=false include_docs={include_docs}");
535
607
  println!("graph : {nodes} nodes / {edges} edges (identical across both builds)");
536
608
  println!("build : A {build_a_secs:.3}s | B {build_b_secs:.3}s (one-off, context)");
537
609
  println!("anchor : in-hub = {hot_in}");
@@ -568,3 +640,63 @@ fn main() {
568
640
  mismatches
569
641
  );
570
642
  }
643
+
644
+ #[cfg(test)]
645
+ mod tests {
646
+ use super::*;
647
+
648
+ fn opts(args: &[&str]) -> Result<Options, String> {
649
+ parse_options(&args.iter().map(|a| a.to_string()).collect::<Vec<_>>())
650
+ }
651
+
652
+ #[test]
653
+ fn parse_options_defaults_to_the_historical_docs_on_configuration() {
654
+ // Every bench row ever filed was measured docs-ON, because this harness
655
+ // hardcoded docs-ON before the flag existed. The default must stay that
656
+ // way or old and new rows silently stop being comparable. This is the
657
+ // MIRROR of codingest_stats' equivalent test, which asserts docs-OFF —
658
+ // same rule, opposite history. See `Options::include_docs`.
659
+ let parsed = opts(&[]).expect("empty argv parses");
660
+ assert_eq!(parsed, Options::default());
661
+ assert!(parsed.include_docs, "bench must default to docs-ON");
662
+ assert!(!parsed.json);
663
+ assert!(!parsed.include_untracked);
664
+ }
665
+
666
+ #[test]
667
+ fn parse_options_reads_every_flag() {
668
+ let parsed =
669
+ opts(&["--json", "--include-untracked", "--no-docs"]).expect("all flags parse");
670
+ assert!(parsed.json);
671
+ assert!(parsed.include_untracked);
672
+ assert!(!parsed.include_docs);
673
+ }
674
+
675
+ #[test]
676
+ fn no_docs_turns_docs_off_on_its_own() {
677
+ // The one flag whose absence is not the interesting case: assert it
678
+ // flips the value rather than merely parsing.
679
+ assert!(!opts(&["--no-docs"]).expect("parses").include_docs);
680
+ assert!(opts(&["--json"]).expect("parses").include_docs);
681
+ }
682
+
683
+ #[test]
684
+ fn parse_options_rejects_an_unknown_flag() {
685
+ // A silently-ignored typo would report a measurement taken under a mode
686
+ // the run never used — the reason this parser is strict at all.
687
+ let err = opts(&["--include-untraked"]).expect_err("typo must not parse");
688
+ assert!(err.contains("--include-untraked"), "unhelpful error: {err}");
689
+ assert!(opts(&["--nodocs"]).is_err(), "`--nodocs` must not parse");
690
+ }
691
+
692
+ #[test]
693
+ fn parse_options_rejects_the_stats_spelling_of_the_docs_flag() {
694
+ // `--include-docs` is codingest_stats' flag. Accepting it here as a
695
+ // harmless no-op (docs are already on) would teach that the two
696
+ // binaries share a spelling for the one flag on which they disagree —
697
+ // and would then silently accept `--include-docs` from a user who meant
698
+ // to CHANGE the mode. Rejecting it is what makes the asymmetry visible
699
+ // at the moment it matters.
700
+ assert!(opts(&["--include-docs"]).is_err());
701
+ }
702
+ }