codingest 0.2.19__tar.gz → 0.2.20__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.
- {codingest-0.2.19 → codingest-0.2.20}/Cargo.lock +12 -10
- {codingest-0.2.19 → codingest-0.2.20}/Cargo.toml +12 -4
- {codingest-0.2.19 → codingest-0.2.20}/PKG-INFO +5 -5
- {codingest-0.2.19 → codingest-0.2.20}/README.md +3 -3
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/Cargo.toml +1 -1
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/other_edges.rs +7 -5
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/rev.rs +132 -18
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/Cargo.toml +1 -1
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/skills/codingest-code-review/SKILL.md +74 -21
- codingest-0.2.20/crates/codingest-cli/skills/codingest-code-review/references/mcp-upgrade.md +88 -0
- codingest-0.2.20/crates/codingest-cli/skills/codingest-code-review/references/queries.md +186 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/src/query.rs +62 -6
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/src/skill.rs +57 -33
- codingest-0.2.20/crates/codingest-cli/tests/skill_recipes.rs +754 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-mcp/Cargo.toml +5 -1
- codingest-0.2.20/crates/codingest-mcp/tests/response_contract.rs +800 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-py/Cargo.toml +3 -3
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-py/src/lib.rs +1 -1
- {codingest-0.2.19 → codingest-0.2.20}/pyproject.toml +2 -2
- codingest-0.2.19/crates/codingest-cli/skills/codingest-code-review/references/mcp-upgrade.md +0 -18
- codingest-0.2.19/crates/codingest-cli/skills/codingest-code-review/references/queries.md +0 -87
- {codingest-0.2.19 → codingest-0.2.20}/LICENSE +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/codingest/__init__.py +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/codingest/__init__.pyi +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/codingest/cli.py +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/codingest/mcp_server.py +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/bin/codingest_bench.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/bin/codingest_stats.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/call_edges.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/js_workspace.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/load/edge_frames.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/load/entity_frames.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/load.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/mod.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/routes/django.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/routes/fastapi.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/routes/flask.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/routes/mod.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/semantic_edges.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/builder/type_edges.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/cross_lang.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/docs/mod.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/docs/rst.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/lib.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/manifest/mod.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/models.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/agc.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/cpp.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/csharp.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/css.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/dart.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/go.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/html.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/java.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/julia.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/mod.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/php.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/python.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/r.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/registry.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/rust_lang.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/shared.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/swift.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/parsers/typescript.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/src/repo.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/agc_apollo.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/README.md +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/agc_basic.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/cpp_extern_c.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/cpp_include.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/cross_ts_py.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/csharp_using_alias.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/dart_import.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/dart_part_of.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/docs_ext_collide.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/docs_mdx.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/dup_minified_assets.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/go_interface.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/html_js_lang_group.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/java_javadoc.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/julia_basic.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/php_group_use.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/py_basic.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/py_import.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/py_inheritance.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/py_nested_defs.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/py_routes_dup.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/py_src_layout.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/r_basic.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/rust_import.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/rust_inline_mod.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/rust_xfile.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/swift_basic.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/ts_callback.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/ts_closure_scope.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/ts_hof_binding.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/ts_monorepo.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/goldens/web_served_root.sha256 +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/grammar_kinds.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/parity.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest/tests/traversal_semantics.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/skills/codingest-code-review/references/public-repositories.md +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/src/code_tree_cli.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/src/lib.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/src/main.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/src/skill_assets.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/tests/exit_codes.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/crates/codingest-mcp/src/lib.rs +0 -0
- {codingest-0.2.19 → codingest-0.2.20}/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.
|
|
305
|
+
version = "0.2.20"
|
|
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.
|
|
341
|
+
version = "0.2.20"
|
|
342
342
|
dependencies = [
|
|
343
343
|
"anyhow",
|
|
344
344
|
"clap",
|
|
@@ -350,16 +350,18 @@ dependencies = [
|
|
|
350
350
|
|
|
351
351
|
[[package]]
|
|
352
352
|
name = "codingest-mcp"
|
|
353
|
-
version = "0.2.
|
|
353
|
+
version = "0.2.20"
|
|
354
354
|
dependencies = [
|
|
355
355
|
"anyhow",
|
|
356
356
|
"codingest",
|
|
357
357
|
"kglite-mcp-server",
|
|
358
|
+
"serde_json",
|
|
359
|
+
"tempfile",
|
|
358
360
|
]
|
|
359
361
|
|
|
360
362
|
[[package]]
|
|
361
363
|
name = "codingest-py"
|
|
362
|
-
version = "0.2.
|
|
364
|
+
version = "0.2.20"
|
|
363
365
|
dependencies = [
|
|
364
366
|
"codingest",
|
|
365
367
|
"codingest-cli",
|
|
@@ -1366,9 +1368,9 @@ dependencies = [
|
|
|
1366
1368
|
|
|
1367
1369
|
[[package]]
|
|
1368
1370
|
name = "kglite"
|
|
1369
|
-
version = "0.17.
|
|
1371
|
+
version = "0.17.4"
|
|
1370
1372
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1371
|
-
checksum = "
|
|
1373
|
+
checksum = "ffc03d38445c638a848109cb8f9b22fca8a5e7fdbe571b686b9ae11c671fb3b7"
|
|
1372
1374
|
dependencies = [
|
|
1373
1375
|
"bzip2",
|
|
1374
1376
|
"chrono",
|
|
@@ -1402,9 +1404,9 @@ dependencies = [
|
|
|
1402
1404
|
|
|
1403
1405
|
[[package]]
|
|
1404
1406
|
name = "kglite-mcp-server"
|
|
1405
|
-
version = "0.17.
|
|
1407
|
+
version = "0.17.4"
|
|
1406
1408
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1407
|
-
checksum = "
|
|
1409
|
+
checksum = "6bce52afae0ad63db082643cf33ca89476eb70c02f6c84dc8f5e360f8b4b6bac"
|
|
1408
1410
|
dependencies = [
|
|
1409
1411
|
"anyhow",
|
|
1410
1412
|
"bytes",
|
|
@@ -1508,9 +1510,9 @@ dependencies = [
|
|
|
1508
1510
|
|
|
1509
1511
|
[[package]]
|
|
1510
1512
|
name = "mcp-methods"
|
|
1511
|
-
version = "0.4.
|
|
1513
|
+
version = "0.4.9"
|
|
1512
1514
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1513
|
-
checksum = "
|
|
1515
|
+
checksum = "140792f5b2f41ef005ea26c180869d05afda7174a22d0aedec22708fadfa879f"
|
|
1514
1516
|
dependencies = [
|
|
1515
1517
|
"anyhow",
|
|
1516
1518
|
"clap",
|
|
@@ -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.
|
|
6
|
+
version = "0.2.20"
|
|
7
7
|
edition = "2021"
|
|
8
8
|
rust-version = "1.88"
|
|
9
9
|
license = "MIT"
|
|
@@ -12,7 +12,15 @@ 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.
|
|
15
|
+
# kglite engine + MCP server — imported as crates.io libraries. The 0.17.4
|
|
16
|
+
# floor rejects every unbound Cypher parameter before candidate selection, so
|
|
17
|
+
# an empty label scan, inline map, WHERE or subquery cannot hide a missing
|
|
18
|
+
# binding behind zero rows. Installing or clearing a declared schema now
|
|
19
|
+
# invalidates cached diagnostics, including on the Python graph returned by
|
|
20
|
+
# `codingest.build()`. The embedded MCP server gains bounded, navigable query
|
|
21
|
+
# responses backed by retained complete results; the standalone codingest CLI
|
|
22
|
+
# keeps complete JSON and CSV output.
|
|
23
|
+
# The preceding 0.17.3
|
|
16
24
|
# floor spans the 0.17.2 and 0.17.3 query releases. Nothing in codingest's
|
|
17
25
|
# builder source moved for either release; the changes reach users through
|
|
18
26
|
# `codingest query` and the embedded `codingest-mcp` server:
|
|
@@ -499,8 +507,8 @@ sha2 = "0.11"
|
|
|
499
507
|
# and no disk storage. Neither 0.15.7 nor 0.15.8 changes the `kglite::api` we
|
|
500
508
|
# call, graph output, property encoding, or `.kgl` serialization.
|
|
501
509
|
# Keep both libraries aligned so the graph and server share one engine release.
|
|
502
|
-
kglite = { version = "0.17.
|
|
503
|
-
kglite-mcp-server = { version = "0.17.
|
|
510
|
+
kglite = { version = "0.17.4", default-features = false }
|
|
511
|
+
kglite-mcp-server = { version = "0.17.4", default-features = false }
|
|
504
512
|
|
|
505
513
|
# Dependency debuginfo capped at line tables (kglite coordination, 2026-08-31,
|
|
506
514
|
# 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.
|
|
3
|
+
Version: 0.2.20
|
|
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.
|
|
15
|
+
Requires-Dist: kglite>=0.17.4,<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
|
|
@@ -192,7 +192,7 @@ codingest skill install # code-review Agent Skill
|
|
|
192
192
|
```
|
|
193
193
|
|
|
194
194
|
The wheel bundles every grammar plus the `codingest` and `codingest-mcp`
|
|
195
|
-
commands. KGLite ≥0.17.
|
|
195
|
+
commands. KGLite ≥0.17.4 is installed automatically as the query/storage
|
|
196
196
|
engine; its MCP server and the transitive `mcp-methods` framework power the
|
|
197
197
|
builder-aware Codingest server. Nothing else needs to be installed.
|
|
198
198
|
|
|
@@ -205,7 +205,7 @@ Python prerequisites.
|
|
|
205
205
|
```toml
|
|
206
206
|
[dependencies]
|
|
207
207
|
codingest = "0.2"
|
|
208
|
-
kglite = "0.17.
|
|
208
|
+
kglite = "0.17.4"
|
|
209
209
|
```
|
|
210
210
|
|
|
211
211
|
```rust
|
|
@@ -277,7 +277,7 @@ diagnostic.
|
|
|
277
277
|
## Dependency policy
|
|
278
278
|
|
|
279
279
|
`kglite` and `kglite-mcp-server` use matching crates.io requirements with a
|
|
280
|
-
0.17.
|
|
280
|
+
0.17.4 minimum and a shared lockfile. This keeps the builder, persistence
|
|
281
281
|
handoff, and embedded MCP server on one compatible engine patch line.
|
|
282
282
|
|
|
283
283
|
## Parity with the (now-removed) in-tree component
|
|
@@ -165,7 +165,7 @@ codingest skill install # code-review Agent Skill
|
|
|
165
165
|
```
|
|
166
166
|
|
|
167
167
|
The wheel bundles every grammar plus the `codingest` and `codingest-mcp`
|
|
168
|
-
commands. KGLite ≥0.17.
|
|
168
|
+
commands. KGLite ≥0.17.4 is installed automatically as the query/storage
|
|
169
169
|
engine; its MCP server and the transitive `mcp-methods` framework power the
|
|
170
170
|
builder-aware Codingest server. Nothing else needs to be installed.
|
|
171
171
|
|
|
@@ -178,7 +178,7 @@ Python prerequisites.
|
|
|
178
178
|
```toml
|
|
179
179
|
[dependencies]
|
|
180
180
|
codingest = "0.2"
|
|
181
|
-
kglite = "0.17.
|
|
181
|
+
kglite = "0.17.4"
|
|
182
182
|
```
|
|
183
183
|
|
|
184
184
|
```rust
|
|
@@ -250,7 +250,7 @@ diagnostic.
|
|
|
250
250
|
## Dependency policy
|
|
251
251
|
|
|
252
252
|
`kglite` and `kglite-mcp-server` use matching crates.io requirements with a
|
|
253
|
-
0.17.
|
|
253
|
+
0.17.4 minimum and a shared lockfile. This keeps the builder, persistence
|
|
254
254
|
handoff, and embedded MCP server on one compatible engine patch line.
|
|
255
255
|
|
|
256
256
|
## 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 engine floor (0.17.
|
|
13
|
+
# workspace pins the current engine floor (0.17.4).
|
|
14
14
|
|
|
15
15
|
[lib]
|
|
16
16
|
name = "codingest"
|
|
@@ -45,12 +45,14 @@ pub struct UsesTypeEdge {
|
|
|
45
45
|
pub target_node_type: &'static str,
|
|
46
46
|
/// Where in the function signature this type appears. Aggregates across
|
|
47
47
|
/// all sites in the same function — a type used as both a parameter and
|
|
48
|
-
/// a return value yields `"both"`. Values: `"parameter"` | `"
|
|
49
|
-
/// `"both"` | `"signature"`. `"
|
|
50
|
-
///
|
|
51
|
-
///
|
|
48
|
+
/// a return value yields `"both"`. Values: `"parameter"` | `"receiver"` |
|
|
49
|
+
/// `"return"` | `"both"` | `"signature"`. `"receiver"` is the implicit
|
|
50
|
+
/// input of a method, kept distinct from an explicit parameter;
|
|
51
|
+
/// `"signature"` is the fallback when the parser couldn't extract
|
|
52
|
+
/// structured parameters (typically the AC scanner found the type embedded
|
|
53
|
+
/// in the signature string).
|
|
52
54
|
///
|
|
53
|
-
/// Cypher: `WHERE r.position IN ['parameter','both']` for "consumes T",
|
|
55
|
+
/// Cypher: `WHERE r.position IN ['parameter','receiver','both']` for "consumes T",
|
|
54
56
|
/// `WHERE r.position IN ['return','both']` for "produces T".
|
|
55
57
|
pub position: &'static str,
|
|
56
58
|
}
|
|
@@ -221,9 +221,28 @@ fn verify_rev(repo_root: &Path, rev: &str) -> Result<String, String> {
|
|
|
221
221
|
Ok(String::from_utf8_lossy(&out.stdout).trim().to_string())
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
+
fn spawn_archive_extractor(
|
|
225
|
+
archive_stdout: impl Into<Stdio>,
|
|
226
|
+
dest: &Path,
|
|
227
|
+
) -> Result<std::process::Child, String> {
|
|
228
|
+
Command::new("tar")
|
|
229
|
+
// Both bsdtar and GNU tar otherwise stop at the first end-of-archive
|
|
230
|
+
// blocks. Git can still be writing record padding at that point and
|
|
231
|
+
// receive SIGPIPE even though extraction completed successfully.
|
|
232
|
+
.arg("--ignore-zeros")
|
|
233
|
+
.arg("-x")
|
|
234
|
+
.arg("-C")
|
|
235
|
+
.arg(dest)
|
|
236
|
+
.stdin(archive_stdout)
|
|
237
|
+
.stderr(Stdio::piped())
|
|
238
|
+
.spawn()
|
|
239
|
+
.map_err(|e| format!("tar failed to start: {}", e))
|
|
240
|
+
}
|
|
241
|
+
|
|
224
242
|
/// Stream `git archive --format=tar <rev>` into `tar -x -C <dest>`. Both run
|
|
225
243
|
/// concurrently over a pipe (bounded memory — the tar is never buffered
|
|
226
|
-
/// whole); list args, no shell.
|
|
244
|
+
/// whole); list args, no shell. The extractor reads through tar end markers to
|
|
245
|
+
/// EOF so Git can finish writing record padding without receiving SIGPIPE.
|
|
227
246
|
fn archive_into(repo_root: &Path, rev: &str, dest: &Path) -> Result<(), String> {
|
|
228
247
|
let mut archive = Command::new("git")
|
|
229
248
|
.arg("-C")
|
|
@@ -240,14 +259,7 @@ fn archive_into(repo_root: &Path, rev: &str, dest: &Path) -> Result<(), String>
|
|
|
240
259
|
.take()
|
|
241
260
|
.ok_or_else(|| "git archive produced no stdout".to_string())?;
|
|
242
261
|
|
|
243
|
-
let tar =
|
|
244
|
-
.arg("-x")
|
|
245
|
-
.arg("-C")
|
|
246
|
-
.arg(dest)
|
|
247
|
-
.stdin(Stdio::from(archive_stdout))
|
|
248
|
-
.stderr(Stdio::piped())
|
|
249
|
-
.spawn()
|
|
250
|
-
.map_err(|e| format!("tar failed to start: {}", e))?;
|
|
262
|
+
let tar = spawn_archive_extractor(Stdio::from(archive_stdout), dest)?;
|
|
251
263
|
|
|
252
264
|
// tar reads the pipe as git writes; wait for the reader first, then the
|
|
253
265
|
// writer, so neither blocks on a full pipe.
|
|
@@ -258,16 +270,14 @@ fn archive_into(repo_root: &Path, rev: &str, dest: &Path) -> Result<(), String>
|
|
|
258
270
|
.wait_with_output()
|
|
259
271
|
.map_err(|e| format!("git archive wait failed: {}", e))?;
|
|
260
272
|
|
|
261
|
-
if !archive_out.status.success() {
|
|
273
|
+
if !archive_out.status.success() || !tar_out.status.success() {
|
|
262
274
|
return Err(format!(
|
|
263
|
-
"
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
"tar extract failed: {}",
|
|
270
|
-
String::from_utf8_lossy(&tar_out.stderr).trim()
|
|
275
|
+
"archive pipeline failed: git archive status {}; stderr {:?}; \
|
|
276
|
+
tar extract status {}; stderr {:?}",
|
|
277
|
+
archive_out.status,
|
|
278
|
+
String::from_utf8_lossy(&archive_out.stderr).trim(),
|
|
279
|
+
tar_out.status,
|
|
280
|
+
String::from_utf8_lossy(&tar_out.stderr).trim(),
|
|
271
281
|
));
|
|
272
282
|
}
|
|
273
283
|
Ok(())
|
|
@@ -867,6 +877,110 @@ mod tests {
|
|
|
867
877
|
assert!(error.contains("outside repository root"), "{error}");
|
|
868
878
|
}
|
|
869
879
|
|
|
880
|
+
#[test]
|
|
881
|
+
fn archive_pipeline_reports_both_children_for_invalid_revision() {
|
|
882
|
+
let (repo, _) = commit_files(&[("app.py", "def compute():\n return 1\n")]);
|
|
883
|
+
let destination = tempfile::tempdir().unwrap();
|
|
884
|
+
let error = archive_into(
|
|
885
|
+
repo.path(),
|
|
886
|
+
"revision-that-does-not-exist",
|
|
887
|
+
destination.path(),
|
|
888
|
+
)
|
|
889
|
+
.expect_err("invalid revision must fail");
|
|
890
|
+
|
|
891
|
+
assert!(error.contains("git archive status"), "{error}");
|
|
892
|
+
assert!(error.contains("tar extract status"), "{error}");
|
|
893
|
+
assert_eq!(error.matches("stderr").count(), 2, "{error}");
|
|
894
|
+
assert!(error.contains("revision-that-does-not-exist"), "{error}");
|
|
895
|
+
assert!(
|
|
896
|
+
!error.contains("git archive status exit status: 0"),
|
|
897
|
+
"{error}"
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
#[test]
|
|
902
|
+
fn archive_pipeline_reports_both_children_after_early_consumer_exit() {
|
|
903
|
+
let body = "x".repeat(4 * 1024 * 1024);
|
|
904
|
+
let (repo, revision) = commit_files(&[("large.bin", &body)]);
|
|
905
|
+
let missing_destination = repo.path().join("missing").join("destination");
|
|
906
|
+
let error = archive_into(repo.path(), &revision, &missing_destination)
|
|
907
|
+
.expect_err("missing extraction destination must fail");
|
|
908
|
+
|
|
909
|
+
assert!(error.contains("git archive status"), "{error}");
|
|
910
|
+
assert!(error.contains("tar extract status"), "{error}");
|
|
911
|
+
assert_eq!(error.matches("stderr").count(), 2, "{error}");
|
|
912
|
+
assert!(
|
|
913
|
+
error.contains(&missing_destination.to_string_lossy().to_string()),
|
|
914
|
+
"{error}"
|
|
915
|
+
);
|
|
916
|
+
assert!(
|
|
917
|
+
!error.contains("git archive status exit status: 0"),
|
|
918
|
+
"{error}"
|
|
919
|
+
);
|
|
920
|
+
assert!(
|
|
921
|
+
!error.contains("tar extract status exit status: 0"),
|
|
922
|
+
"{error}"
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
#[cfg(unix)]
|
|
927
|
+
#[test]
|
|
928
|
+
fn archive_extractor_drains_padding_after_end_marker() {
|
|
929
|
+
let expected = "def compute():\n return 1\n";
|
|
930
|
+
let (repo, revision) = commit_files(&[("app.py", expected)]);
|
|
931
|
+
let archive_path = repo.path().join("fixture.tar");
|
|
932
|
+
let archive_file = std::fs::File::create(&archive_path).unwrap();
|
|
933
|
+
let archived = Command::new("git")
|
|
934
|
+
.arg("-C")
|
|
935
|
+
.arg(repo.path())
|
|
936
|
+
.args(["archive", "--format=tar"])
|
|
937
|
+
.arg(&revision)
|
|
938
|
+
.stdout(archive_file)
|
|
939
|
+
.stderr(Stdio::piped())
|
|
940
|
+
.output()
|
|
941
|
+
.unwrap();
|
|
942
|
+
assert!(
|
|
943
|
+
archived.status.success(),
|
|
944
|
+
"git archive fixture failed: {}",
|
|
945
|
+
String::from_utf8_lossy(&archived.stderr)
|
|
946
|
+
);
|
|
947
|
+
|
|
948
|
+
let destination = tempfile::tempdir().unwrap();
|
|
949
|
+
let mut producer = Command::new("sh")
|
|
950
|
+
.args([
|
|
951
|
+
"-c",
|
|
952
|
+
"cat \"$1\"; sleep 0.25; dd if=/dev/zero bs=1048576 count=4 2>/dev/null",
|
|
953
|
+
"padding-producer",
|
|
954
|
+
])
|
|
955
|
+
.arg(&archive_path)
|
|
956
|
+
.stdout(Stdio::piped())
|
|
957
|
+
.stderr(Stdio::piped())
|
|
958
|
+
.spawn()
|
|
959
|
+
.unwrap();
|
|
960
|
+
let producer_stdout = producer.stdout.take().unwrap();
|
|
961
|
+
let extractor = spawn_archive_extractor(Stdio::from(producer_stdout), destination.path())
|
|
962
|
+
.expect("spawn archive extractor");
|
|
963
|
+
let extracted = extractor.wait_with_output().unwrap();
|
|
964
|
+
let produced = producer.wait_with_output().unwrap();
|
|
965
|
+
|
|
966
|
+
assert!(
|
|
967
|
+
extracted.status.success(),
|
|
968
|
+
"tar status {}; stderr {:?}",
|
|
969
|
+
extracted.status,
|
|
970
|
+
String::from_utf8_lossy(&extracted.stderr).trim()
|
|
971
|
+
);
|
|
972
|
+
assert!(
|
|
973
|
+
produced.status.success(),
|
|
974
|
+
"producer status {}; stderr {:?}",
|
|
975
|
+
produced.status,
|
|
976
|
+
String::from_utf8_lossy(&produced.stderr).trim()
|
|
977
|
+
);
|
|
978
|
+
assert_eq!(
|
|
979
|
+
std::fs::read_to_string(destination.path().join("app.py")).unwrap(),
|
|
980
|
+
expected
|
|
981
|
+
);
|
|
982
|
+
}
|
|
983
|
+
|
|
870
984
|
fn build(dir: &Path, revs: &[String]) -> Arc<DirGraph> {
|
|
871
985
|
build_code_tree_revs(dir, revs, Some(dir), false, false, None, None, false)
|
|
872
986
|
.expect("build_code_tree_revs")
|
|
@@ -14,7 +14,7 @@ name = "codingest"
|
|
|
14
14
|
path = "src/main.rs"
|
|
15
15
|
|
|
16
16
|
[dependencies]
|
|
17
|
-
codingest = { version = "0.2.
|
|
17
|
+
codingest = { version = "0.2.20", path = "../codingest" }
|
|
18
18
|
kglite = { workspace = true }
|
|
19
19
|
anyhow = "1.0.104"
|
|
20
20
|
clap = { version = "4.6.4", features = ["derive"] }
|
{codingest-0.2.19 → codingest-0.2.20}/crates/codingest-cli/skills/codingest-code-review/SKILL.md
RENAMED
|
@@ -10,9 +10,12 @@ git diff, source reading, and literal-text search; it does not replace them.
|
|
|
10
10
|
|
|
11
11
|
## Review workflow
|
|
12
12
|
|
|
13
|
-
> **Prerequisites:** the `codingest`
|
|
14
|
-
> `
|
|
15
|
-
>
|
|
13
|
+
> **Prerequisites:** the `codingest` CLI must be on PATH. `pip install
|
|
14
|
+
> codingest` also provides the builder-aware `codingest-mcp` server and a
|
|
15
|
+
> compatible graph engine. Rust-only environments can alternatively use Cargo.
|
|
16
|
+
> Examples that invoke the external `kglite` CLI require a compatible
|
|
17
|
+
> `kglite>=0.17.4,<0.18`; verify `kglite --version` before using its
|
|
18
|
+
> agent-response features.
|
|
16
19
|
|
|
17
20
|
Inspect the diff and repository guidance first. Identify changed symbols and
|
|
18
21
|
the base/head revisions, then build or refresh the graph without executing
|
|
@@ -35,21 +38,43 @@ Before reusing an artifact, check freshness:
|
|
|
35
38
|
codingest status --output .kglite/code-review.kgl --format json
|
|
36
39
|
```
|
|
37
40
|
|
|
38
|
-
##
|
|
41
|
+
## Work from the question
|
|
42
|
+
|
|
43
|
+
Use this loop only as far as the question requires. It has no required map set
|
|
44
|
+
or fixed query count.
|
|
45
|
+
|
|
46
|
+
1. **Establish target and coverage.** Record the exact repository, revision,
|
|
47
|
+
symbol, path, or subsystem in scope. For a completeness or absence claim,
|
|
48
|
+
identify the relevant groups before retrieving their rows and record every
|
|
49
|
+
query, executor, or presentation boundary.
|
|
50
|
+
2. **Retrieve a relevant relation.** Ask the smallest structural question that
|
|
51
|
+
can change the answer: callers, callees, implementers, imports, dependencies,
|
|
52
|
+
routes, tests, or revision identity.
|
|
53
|
+
3. **Inspect selected source.** Open the implicated definitions and call sites
|
|
54
|
+
at exact lines. Graph edges identify candidates; source and executed tests
|
|
55
|
+
establish behavior.
|
|
56
|
+
4. **Retain an evidence map.** Keep each working claim with its graph revision,
|
|
57
|
+
exact query or reference, concrete example or input state, what an assertion
|
|
58
|
+
actually guarantees, and any unresolved question. These fields can be a
|
|
59
|
+
compact note rather than separate documents.
|
|
60
|
+
5. **Resolve consequential uncertainty.** Expand only when a contradiction,
|
|
61
|
+
missing precondition, or correctness risk could change the answer. Stop when
|
|
62
|
+
the requested conclusions have direct support.
|
|
39
63
|
|
|
40
64
|
Choose the narrowest route for the uncertainty in front of you; these are
|
|
41
65
|
alternatives, not a compulsory sequence. Reuse tool signatures already known
|
|
42
|
-
in the current session
|
|
66
|
+
in the current session. If a needed tool is not visible, discover that tool
|
|
43
67
|
rather than loading a broad catalog.
|
|
44
68
|
|
|
45
69
|
- **Known symbol or location:** read it directly. With MCP, use
|
|
46
70
|
`read_code_source` for a qualified name or `read_source` for a path, applying
|
|
47
71
|
`start_line`, `end_line`, and `max_chars` when a full body or file is not
|
|
48
72
|
needed.
|
|
49
|
-
- **Exact structural question:** use `cypher_query`, or `kglite query`
|
|
50
|
-
CLI. Reuse a schema already observed for
|
|
51
|
-
inspect only the needed node or
|
|
52
|
-
`kglite describe`; do not retrieve
|
|
73
|
+
- **Exact structural question:** use `cypher_query`, or `kglite query` when the
|
|
74
|
+
compatible external CLI is installed. Reuse a schema already observed for
|
|
75
|
+
the same unchanged graph. Otherwise inspect only the needed node or
|
|
76
|
+
connection shape with `graph_overview` or `kglite describe`; do not retrieve
|
|
77
|
+
the whole schema by habit.
|
|
53
78
|
- **Broad explanation or unfamiliar subsystem:** use bounded `explore`, starting
|
|
54
79
|
with a short topic, a few `max_entities`, shallow `max_depth`, and
|
|
55
80
|
`include_source: false` unless bodies are needed. Narrow to selected symbols
|
|
@@ -60,14 +85,41 @@ rather than loading a broad catalog.
|
|
|
60
85
|
Every additional read should resolve a concrete uncertainty needed for the
|
|
61
86
|
answer. Project only useful Cypher properties, return a few relevant candidates,
|
|
62
87
|
and exclude unrelated fixtures, generated code, vendors, or examples when the
|
|
63
|
-
question does not cover them.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
88
|
+
question does not cover them. Reuse evidence already seen unless its source or
|
|
89
|
+
active graph changed.
|
|
90
|
+
|
|
91
|
+
Treat response presentation separately from query coverage. When an MCP
|
|
92
|
+
response says the completed result was retained, follow its advertised action
|
|
93
|
+
to expand the needed value or page within the authorized read-only
|
|
94
|
+
investigation; this does not require separate human approval. Expansion cannot
|
|
95
|
+
recover rows excluded by a Cypher `LIMIT`, an executor row limit, or tool-level
|
|
96
|
+
omission. Broaden or regroup the query when those boundaries matter. Narrow a
|
|
97
|
+
source range when only a source read was clipped. See
|
|
98
|
+
[mcp-upgrade.md](references/mcp-upgrade.md) for the expansion procedure.
|
|
99
|
+
|
|
100
|
+
Macro-generated structure may not exist as source-level graph nodes, and
|
|
101
|
+
heuristic relationships are candidates rather than runtime proof. Inspect the
|
|
102
|
+
source or an executed test before turning either limitation into a behavioral
|
|
103
|
+
claim.
|
|
104
|
+
|
|
105
|
+
## Verify the answer
|
|
106
|
+
|
|
107
|
+
Before reporting a finding or a consequential conclusion, use focused reads to
|
|
108
|
+
check:
|
|
109
|
+
|
|
110
|
+
- each required precondition holds at the reviewed revision;
|
|
111
|
+
- the stated input, state, or sequence reaches the claimed behavior;
|
|
112
|
+
- a returned value or error observed below the claimed API boundary is traced
|
|
113
|
+
through catches, fallbacks, retries, and active options to that boundary;
|
|
114
|
+
- one observed path is used as evidence for that case, not as a universal
|
|
115
|
+
outcome;
|
|
116
|
+
- each cited assertion runs on that input and guarantees what the answer says;
|
|
117
|
+
- every file and line reference still points to the supporting code; and
|
|
118
|
+
- completeness, absence, ownership, and reachability claims are limited to the
|
|
119
|
+
coverage actually established.
|
|
120
|
+
|
|
121
|
+
Label source-composed examples that were not executed. Leave unresolved
|
|
122
|
+
questions explicit rather than converting them into findings.
|
|
71
123
|
|
|
72
124
|
See [queries.md](references/queries.md) for query patterns,
|
|
73
125
|
[public-repositories.md](references/public-repositories.md) for safe public-repo
|
|
@@ -77,7 +129,7 @@ workflow.
|
|
|
77
129
|
## What counts as a finding
|
|
78
130
|
|
|
79
131
|
The workflow above verifies a finding against exact source lines. This is the
|
|
80
|
-
prior question
|
|
132
|
+
prior question: what is eligible to be a finding at all.
|
|
81
133
|
|
|
82
134
|
- **A finding names a concrete failure**: the input, state, or sequence, and the
|
|
83
135
|
wrong outcome it produces. A wrong result, a crash, data loss or corruption, a
|
|
@@ -86,7 +138,7 @@ prior question — what is eligible to be a finding at all.
|
|
|
86
138
|
code contradicts. **"No findings" is a valid review**, and a good one.
|
|
87
139
|
- **Design, structure, naming, "consider using X", and "this won't scale" are
|
|
88
140
|
not findings** — they are mis-staged. Their venue is planning, where "I would
|
|
89
|
-
have designed this differently" is invited and settled before
|
|
141
|
+
have designed this differently" is invited and settled before code exists.
|
|
90
142
|
After a plan is approved, review measures the implementation against that plan
|
|
91
143
|
and against correctness, never against a design the reviewer would have
|
|
92
144
|
preferred. A design opinion formed while reading a diff is input to the *next*
|
|
@@ -105,8 +157,9 @@ prior question — what is eligible to be a finding at all.
|
|
|
105
157
|
|
|
106
158
|
## Honesty rules
|
|
107
159
|
|
|
108
|
-
- Never invent labels, properties,
|
|
109
|
-
|
|
160
|
+
- Never invent labels, properties, connection types, response-control fields,
|
|
161
|
+
expansion-tool names, or retained-result IDs. Discover unfamiliar shapes and
|
|
162
|
+
controls; reuse them only while the graph and session remain unchanged.
|
|
110
163
|
- Treat unresolved or missing graph edges as absence of evidence, not proof.
|
|
111
164
|
- Quote paths and revisions passed through the shell.
|
|
112
165
|
- Never build, import, or execute code from a repository merely to review it.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# When to use the MCP server
|
|
2
|
+
|
|
3
|
+
The CLI skill is the low-friction path: no agent configuration, one process per
|
|
4
|
+
command, and a review artifact that can be rebuilt explicitly.
|
|
5
|
+
|
|
6
|
+
Upgrade to `codingest-mcp` when the work benefits from:
|
|
7
|
+
|
|
8
|
+
- a graph kept warm across many queries;
|
|
9
|
+
- watch mode and automatic refresh after file changes;
|
|
10
|
+
- typed tool input/output schemas rather than shell quoting;
|
|
11
|
+
- switching among several repository roots;
|
|
12
|
+
- cached public-repository lifecycle and GitHub/source tools; or
|
|
13
|
+
- long collaborative sessions where process startup becomes noticeable.
|
|
14
|
+
|
|
15
|
+
The local-code-review MCP workspace covers a changing checkout. The
|
|
16
|
+
open-source workspace covers cached public repositories and adds constrained
|
|
17
|
+
source and GitHub tooling. Codingest builds the code graph; both workflows use
|
|
18
|
+
KGLite's graph engine, query language, and read-tool surface.
|
|
19
|
+
|
|
20
|
+
## Expand retained MCP evidence
|
|
21
|
+
|
|
22
|
+
A bounded presentation is a view of a completed retained result. It does not
|
|
23
|
+
change query semantics and expansion does not rerun the original tool. A
|
|
24
|
+
Cypher `LIMIT`, an executor row limit, or a tool-level omission is different:
|
|
25
|
+
excluded rows require another reviewed query.
|
|
26
|
+
|
|
27
|
+
Use the response itself as the protocol contract:
|
|
28
|
+
|
|
29
|
+
1. Discover the query tool's response-control property and the expansion tool
|
|
30
|
+
through the current session's tool listing. Names may be changed to avoid a
|
|
31
|
+
collision, so do not assume `_response` or `expand_response`.
|
|
32
|
+
2. When the result is bounded, copy its complete advertised
|
|
33
|
+
`next.selected_value` action. Keep the action's `name` and
|
|
34
|
+
`arguments.result_id` unchanged.
|
|
35
|
+
3. Choose a target actually advertised by the response. Apply its patch by
|
|
36
|
+
copying `json_pointer`, `offset`, and `response` to the action arguments
|
|
37
|
+
named `path`, `offset`, and `response`. Do not infer paths or semantic groups
|
|
38
|
+
that are absent from the returned navigation data.
|
|
39
|
+
4. Dispatch the patched action and use the returned value as evidence from the
|
|
40
|
+
original completed result. Follow an advertised page action when more of the
|
|
41
|
+
same selected value is required.
|
|
42
|
+
|
|
43
|
+
Within an already authorized read-only investigation, selecting an advertised
|
|
44
|
+
page, requesting a larger per-call budget, or requesting an advertised full
|
|
45
|
+
response needs no additional human approval. Copy the discovered control field
|
|
46
|
+
and supported shape into that individual call. Do not turn expansion into a
|
|
47
|
+
replay of the original query, especially when that tool may mutate state.
|
|
48
|
+
|
|
49
|
+
Retained MCP results are short-lived, held in memory, and scoped to the current
|
|
50
|
+
MCP session. Honor the retention and eviction facts in the response. If a
|
|
51
|
+
handle is unavailable, rerun only a read that remains authorized and whose
|
|
52
|
+
preconditions are still current.
|
|
53
|
+
|
|
54
|
+
## External CLI agent output is optional
|
|
55
|
+
|
|
56
|
+
The examples below require an external `kglite` CLI satisfying
|
|
57
|
+
`>=0.17.4,<0.18`:
|
|
58
|
+
|
|
59
|
+
```console
|
|
60
|
+
kglite --version
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The following source-composed example is exercised against a generated graph by
|
|
64
|
+
the packaged-consumer test:
|
|
65
|
+
|
|
66
|
+
<!-- example: kglite-agent-query -->
|
|
67
|
+
```console
|
|
68
|
+
kglite query <graph> "RETURN 'agent-evidence' AS evidence" --format agent
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Agent output advertises executable expansion commands. Copy the returned
|
|
72
|
+
command and its result ID; do not construct either. KGLite's CLI retention uses
|
|
73
|
+
a private disk cache, so expansion can run in a later process. This lifecycle
|
|
74
|
+
is separate from the MCP server's in-memory, session-scoped retention.
|
|
75
|
+
|
|
76
|
+
If the compatible external CLI is unavailable, report the agent example as
|
|
77
|
+
untested. Codingest's own query command remains the portable complete-output
|
|
78
|
+
path and does not require response retention:
|
|
79
|
+
|
|
80
|
+
```console
|
|
81
|
+
codingest query "MATCH (n:Evidence) RETURN n.id ORDER BY n.id" \
|
|
82
|
+
--graph app.kgl --format json
|
|
83
|
+
codingest query "MATCH (n:Evidence) RETURN n.id ORDER BY n.id" \
|
|
84
|
+
--graph app.kgl --format csv
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Codingest JSON and CSV contain every row produced by the query and executor.
|
|
88
|
+
They do not make a literal `LIMIT` or another execution boundary broader.
|