cc-transcript 14.33.1__tar.gz → 14.35.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.
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/Cargo.lock +1 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/PKG-INFO +1 -1
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/snapshot_schema/config.schema.json +35 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/pyproject.toml +1 -1
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/grep.rs +154 -82
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/Cargo.toml +1 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/lib.rs +4 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/render.rs +1 -1
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/scan.rs +120 -45
- cc_transcript-14.35.0/rust/crates/core/src/scan_checkpoint.rs +606 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/scan_grep.rs +269 -108
- cc_transcript-14.35.0/rust/crates/core/src/scan_grep_stream.rs +1144 -0
- cc_transcript-14.35.0/rust/crates/core/src/scan_grep_stream_tests.rs +3145 -0
- cc_transcript-14.35.0/rust/crates/core/src/scan_index.rs +937 -0
- cc_transcript-14.35.0/rust/crates/core/src/scan_projection.rs +223 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/scan_regressions.rs +49 -0
- cc_transcript-14.35.0/rust/crates/core/src/scan_stream.rs +272 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot.rs +25 -6
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/Cargo.toml +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/LICENSE +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/README.md +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/__init__.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/__init__.pyi +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/_native.pyi +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/activity.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/activity_probe.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/builders.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/codex.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/command.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/context.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/corrections.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/cost.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/decision_store.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/decisions.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/discovery.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/disktruth.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/evidence.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/extract/__init__.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/extract/correct.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/facts.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/filterspec.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/heartbeats.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/ids.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/judge/__init__.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/judge/llm.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/judge/similar.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/judge/verdicts.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/ledger.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/literals.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/__init__.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/candidates.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/confidence.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/engine.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/formats.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/sampling.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/signals.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/sourcekind.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/spec.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/mining/store.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/models.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/nlp.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/notifications.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/parser.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/py.typed +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/query.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/render.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/sentiment/__init__.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/sentiment/buckets.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/sentiment/data/afinn-en-165.tsv +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/sentiment/data/domain_overrides.tsv +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/sentiment/data/en-ewt.udpipe +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/sentiment/engine.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/sentiment/lexicon.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/sentiment/scorespec.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/snapshot_schema/context.schema.json +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/snapshot_schema/request.schema.json +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/snapshot_schema/response.schema.json +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/snapshot_schema/tool_registry.schema.json +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/snapshots.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/synthetic.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/tools.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/watch.py +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/Cargo.toml +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/blame.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/corpus.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/corrections.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/digest.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/facts.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/list.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/mod.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/scratchpad.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/show.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/slice.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/stats.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/commands/watch.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/lib.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/main.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/output.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/target.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/cli/src/timearg.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/benches/parse.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/benches/render.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/benches/toolcall.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/activity.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/actor.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/blame.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/buckets.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/codex/discovery.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/codex/lower.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/codex/mod.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/codex/parse.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/codex/probe.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/codex/protocol.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/codex/types.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/command.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/context.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/corrections.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/cost.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/discovery.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/facts.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/feedback.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/filter.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/gateway.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/ids.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/judge.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/literals/command.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/literals/corrections.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/literals/feedback.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/literals/mining.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/literals/mod.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/literals/protocol.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/notifications.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/parse.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/protocol.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/pystr.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/query.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/rng.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/schema.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_activity.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_codec.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_codex_append.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_labels.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_memory.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_owned.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_prepared.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_prepared_disk.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_prepared_service.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_projection.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_regressions.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_root_warm.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/snapshot_text.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/sqlite.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/toolcall.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/types.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/value.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/core/src/watch.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/Cargo.toml +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/build.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/data/command_prefix_pins.tsv +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/actor_bridge.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/bin/stub_gen.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/codex.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/command.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/context.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/corrections.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/discovery.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/feedback.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/judge.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/lexicon.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/lib.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/mining.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/nlp.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/python.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/render.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/score.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/snapshot_decode.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/snapshots.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/sqlite.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/toolcall.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/attachment.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/blocks.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/command.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/convert.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/dunder.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/events.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/meta.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/mod.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/print.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/store.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/system.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/toolcall.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/toolresult.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/views/transcript.rs +0 -0
- {cc_transcript-14.33.1 → cc_transcript-14.35.0}/rust/crates/py/src/watch.rs +0 -0
{cc_transcript-14.33.1 → cc_transcript-14.35.0}/cc_transcript/snapshot_schema/config.schema.json
RENAMED
|
@@ -86,6 +86,41 @@
|
|
|
86
86
|
"title": "Max Retained Bytes",
|
|
87
87
|
"type": "integer"
|
|
88
88
|
},
|
|
89
|
+
"max_scan_discovery_entries": {
|
|
90
|
+
"default": 4096,
|
|
91
|
+
"exclusiveMinimum": 0,
|
|
92
|
+
"maximum": 9007199254740991,
|
|
93
|
+
"title": "Max Scan Discovery Entries",
|
|
94
|
+
"type": "integer"
|
|
95
|
+
},
|
|
96
|
+
"max_scan_events": {
|
|
97
|
+
"default": 4096,
|
|
98
|
+
"exclusiveMinimum": 0,
|
|
99
|
+
"maximum": 9007199254740991,
|
|
100
|
+
"title": "Max Scan Events",
|
|
101
|
+
"type": "integer"
|
|
102
|
+
},
|
|
103
|
+
"max_scan_read_bytes": {
|
|
104
|
+
"default": 8388608,
|
|
105
|
+
"exclusiveMinimum": 0,
|
|
106
|
+
"maximum": 9007199254740991,
|
|
107
|
+
"title": "Max Scan Read Bytes",
|
|
108
|
+
"type": "integer"
|
|
109
|
+
},
|
|
110
|
+
"max_scan_sources": {
|
|
111
|
+
"default": 256,
|
|
112
|
+
"exclusiveMinimum": 0,
|
|
113
|
+
"maximum": 9007199254740991,
|
|
114
|
+
"title": "Max Scan Sources",
|
|
115
|
+
"type": "integer"
|
|
116
|
+
},
|
|
117
|
+
"max_scan_validate_bytes": {
|
|
118
|
+
"default": 1073741824,
|
|
119
|
+
"exclusiveMinimum": 0,
|
|
120
|
+
"maximum": 9007199254740991,
|
|
121
|
+
"title": "Max Scan Validate Bytes",
|
|
122
|
+
"type": "integer"
|
|
123
|
+
},
|
|
89
124
|
"max_source_bytes": {
|
|
90
125
|
"default": 536870912,
|
|
91
126
|
"exclusiveMinimum": 0,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cc-transcript"
|
|
3
|
-
version = "14.
|
|
3
|
+
version = "14.35.0" # informational — releases stamp the version from the git tag
|
|
4
4
|
description = "Grep every Claude Code session you've ever run."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = "PolyForm-Noncommercial-1.0.0"
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
use std::collections::HashMap;
|
|
2
|
+
use std::os::unix::fs::MetadataExt;
|
|
1
3
|
use std::path::{Path, PathBuf};
|
|
2
4
|
|
|
3
5
|
use cc_transcript_core::render::{compact_line, display_path, event_json, transcript_header, Json};
|
|
4
6
|
use cc_transcript_core::scan::{
|
|
5
7
|
scan_corpus, ScanBudget, ScanControl, ScanOutcome, ScanPlan, ScanSession,
|
|
6
8
|
};
|
|
7
|
-
use cc_transcript_core::
|
|
9
|
+
use cc_transcript_core::scan_checkpoint::GrepCheckpoints;
|
|
10
|
+
use cc_transcript_core::scan_grep::{
|
|
11
|
+
GrepEvent, GrepOptions, GrepPatternSpec, GrepReducer, GrepResultMetadata,
|
|
12
|
+
};
|
|
8
13
|
use cc_transcript_core::snapshot::{Cancellation, NativeStore, SnapshotError, Status, WorkLimits};
|
|
9
14
|
use cc_transcript_core::types::{ContentBlock, Entry};
|
|
10
15
|
use regex::{Regex, RegexBuilder};
|
|
@@ -212,8 +217,11 @@ impl Emitter {
|
|
|
212
217
|
}
|
|
213
218
|
self.out.finish()?;
|
|
214
219
|
if let Some(reason) = &outcome.reason {
|
|
215
|
-
if
|
|
220
|
+
if let Some(scope) = reason.strip_prefix("result_limit") {
|
|
216
221
|
eline(&format!("warning: stopped at --max-matches {}; more matches may exist — raise it, or pass --max-matches 0 for no cap",counts.first().copied().unwrap_or(0)));
|
|
222
|
+
if let Some(scope) = scope.strip_prefix("; ") {
|
|
223
|
+
eline(&format!("warning: partial view: {scope}"));
|
|
224
|
+
}
|
|
217
225
|
} else {
|
|
218
226
|
eline(&format!("warning: scan incomplete: {reason}"));
|
|
219
227
|
return Err(CliExit(3));
|
|
@@ -226,7 +234,10 @@ impl Emitter {
|
|
|
226
234
|
}
|
|
227
235
|
}
|
|
228
236
|
|
|
229
|
-
fn result_fields(
|
|
237
|
+
fn result_fields(
|
|
238
|
+
event: &Entry,
|
|
239
|
+
results: &HashMap<&str, GrepResultMetadata<'_>>,
|
|
240
|
+
) -> Vec<(String, Json)> {
|
|
230
241
|
if !matches!(event, Entry::Assistant(_)) {
|
|
231
242
|
return Vec::new();
|
|
232
243
|
}
|
|
@@ -237,7 +248,7 @@ fn result_fields(event: &Entry, result: &GrepSourceResult<'_, '_>) -> Vec<(Strin
|
|
|
237
248
|
let ContentBlock::ToolUse(tool) = block else {
|
|
238
249
|
return None;
|
|
239
250
|
};
|
|
240
|
-
let value =
|
|
251
|
+
let value = results.get(tool.id.as_str())?;
|
|
241
252
|
Some((
|
|
242
253
|
tool.id.clone(),
|
|
243
254
|
Json::Obj(vec![
|
|
@@ -253,7 +264,7 @@ fn result_fields(event: &Entry, result: &GrepSourceResult<'_, '_>) -> Vec<(Strin
|
|
|
253
264
|
.collect()
|
|
254
265
|
}
|
|
255
266
|
|
|
256
|
-
fn result_suffix(event: &Entry,
|
|
267
|
+
fn result_suffix(event: &Entry, results: &HashMap<&str, GrepResultMetadata<'_>>) -> String {
|
|
257
268
|
if !matches!(event, Entry::Assistant(_)) {
|
|
258
269
|
return String::new();
|
|
259
270
|
}
|
|
@@ -264,7 +275,7 @@ fn result_suffix(event: &Entry, result: &GrepSourceResult<'_, '_>) -> String {
|
|
|
264
275
|
let ContentBlock::ToolUse(tool) = block else {
|
|
265
276
|
return None;
|
|
266
277
|
};
|
|
267
|
-
let value =
|
|
278
|
+
let value = results.get(tool.id.as_str())?;
|
|
268
279
|
let status = if value.denied {
|
|
269
280
|
"[denied]"
|
|
270
281
|
} else if value.is_error {
|
|
@@ -329,84 +340,39 @@ pub fn run(args: GrepArgs) -> Result<(), CliExit> {
|
|
|
329
340
|
contains: args.discovery.contains.clone(),
|
|
330
341
|
source_limit: args.discovery.effective_limit(),
|
|
331
342
|
};
|
|
332
|
-
let
|
|
333
|
-
let
|
|
334
|
-
let mut
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
343
|
+
let structured = args.json || args.scan_json;
|
|
344
|
+
let checkpoints = checkpoints();
|
|
345
|
+
let mut render = Render {
|
|
346
|
+
args: &args,
|
|
347
|
+
emitter: Emitter::new(args.scan_json, &mut session.budget, &cancel)?,
|
|
348
|
+
files: 0,
|
|
349
|
+
};
|
|
350
|
+
let mut outcome = session.each_source(&plan, |session, path| {
|
|
351
|
+
if reducer.streams() {
|
|
352
|
+
if let Some(control) = reducer.scan_stream(
|
|
353
|
+
path,
|
|
354
|
+
!structured,
|
|
355
|
+
Some(&checkpoints),
|
|
356
|
+
&mut session.budget,
|
|
357
|
+
&cancel,
|
|
358
|
+
|event, budget, cancel| render.event(path, event, budget, cancel),
|
|
359
|
+
)? {
|
|
360
|
+
return Ok(control);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
session.visit_snapshot(path, &mut |path, snapshot, budget, cancel| {
|
|
364
|
+
let result = reducer.scan_source(snapshot, budget, cancel)?;
|
|
365
|
+
result.emit(snapshot, budget, cancel, |event, budget, cancel| {
|
|
366
|
+
render.event(path, event, budget, cancel)
|
|
367
|
+
})?;
|
|
368
|
+
Ok(if result.quota_reached {
|
|
338
369
|
ScanControl::Stop {
|
|
339
370
|
source_complete: result.source_complete,
|
|
371
|
+
names_through: None,
|
|
340
372
|
}
|
|
341
373
|
} else {
|
|
342
374
|
ScanControl::Continue
|
|
343
|
-
})
|
|
344
|
-
}
|
|
345
|
-
files += 1;
|
|
346
|
-
if !args.json && !args.scan_json {
|
|
347
|
-
emitter.emit(transcript_header(&path.to_string_lossy()), budget, cancel)?;
|
|
348
|
-
}
|
|
349
|
-
for (window_index, window) in result.windows.iter().enumerate() {
|
|
350
|
-
if !args.json && !args.scan_json && args.context > 0 && window_index > 0 {
|
|
351
|
-
emitter.emit("--".to_owned(), budget, cancel)?;
|
|
352
|
-
}
|
|
353
|
-
for index in window.clone() {
|
|
354
|
-
let _render_staging = result.preflight_render(snapshot, index, budget, cancel)?;
|
|
355
|
-
let event = snapshot.entry(index);
|
|
356
|
-
let hit = result.hits.iter().find(|hit| hit.event_index == index);
|
|
357
|
-
let line = if args.json || args.scan_json {
|
|
358
|
-
let Json::Obj(mut fields) = event_json(index, event) else {
|
|
359
|
-
unreachable!("event_json object")
|
|
360
|
-
};
|
|
361
|
-
fields.insert(
|
|
362
|
-
0,
|
|
363
|
-
(
|
|
364
|
-
"path".into(),
|
|
365
|
-
Json::Str(path.to_string_lossy().into_owned()),
|
|
366
|
-
),
|
|
367
|
-
);
|
|
368
|
-
if hit.is_none() {
|
|
369
|
-
fields.push(("context".into(), Json::Bool(true)));
|
|
370
|
-
}
|
|
371
|
-
if args.with_result {
|
|
372
|
-
let results = result_fields(event, &result);
|
|
373
|
-
if !results.is_empty() {
|
|
374
|
-
fields.push(("results".into(), Json::Obj(results)));
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
if args.scan_json {
|
|
378
|
-
fields.push(("generation".into(), Json::Str(snapshot.id.clone())));
|
|
379
|
-
fields.push((
|
|
380
|
-
"pattern_ids".into(),
|
|
381
|
-
Json::Arr(
|
|
382
|
-
hit.map(|hit| {
|
|
383
|
-
hit.pattern_ids
|
|
384
|
-
.iter()
|
|
385
|
-
.map(|id| Json::Int(*id as i64))
|
|
386
|
-
.collect()
|
|
387
|
-
})
|
|
388
|
-
.unwrap_or_default(),
|
|
389
|
-
),
|
|
390
|
-
));
|
|
391
|
-
}
|
|
392
|
-
Json::Obj(fields).dumps()
|
|
393
|
-
} else {
|
|
394
|
-
let mut line =
|
|
395
|
-
compact_line(index, event, &result.names, args.width, false, args.uuids);
|
|
396
|
-
if args.with_result {
|
|
397
|
-
line.push_str(&result_suffix(event, &result));
|
|
398
|
-
}
|
|
399
|
-
line
|
|
400
|
-
};
|
|
401
|
-
emitter.emit(line, budget, cancel)?;
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
Ok(if result.quota_reached {
|
|
405
|
-
ScanControl::Stop {
|
|
406
|
-
source_complete: result.source_complete,
|
|
407
|
-
}
|
|
408
|
-
} else {
|
|
409
|
-
ScanControl::Continue
|
|
375
|
+
})
|
|
410
376
|
})
|
|
411
377
|
});
|
|
412
378
|
if outcome.complete && !reducer.complete() {
|
|
@@ -423,9 +389,18 @@ pub fn run(args: GrepArgs) -> Result<(), CliExit> {
|
|
|
423
389
|
} else {
|
|
424
390
|
String::new()
|
|
425
391
|
};
|
|
426
|
-
|
|
392
|
+
let validated = if session.budget.progress.validated_bytes > 0 {
|
|
393
|
+
format!(
|
|
394
|
+
" · re-read {} bytes for validation",
|
|
395
|
+
session.budget.progress.validated_bytes
|
|
396
|
+
)
|
|
397
|
+
} else {
|
|
398
|
+
String::new()
|
|
399
|
+
};
|
|
400
|
+
if let Err(error) = render.emitter.emit(
|
|
427
401
|
format!(
|
|
428
|
-
"{
|
|
402
|
+
"{} files, {} matches{note}{validated}",
|
|
403
|
+
render.files,
|
|
429
404
|
counts.iter().sum::<usize>()
|
|
430
405
|
),
|
|
431
406
|
&mut session.budget,
|
|
@@ -436,7 +411,85 @@ pub fn run(args: GrepArgs) -> Result<(), CliExit> {
|
|
|
436
411
|
}
|
|
437
412
|
outcome.progress = session.budget.progress.clone();
|
|
438
413
|
}
|
|
439
|
-
emitter.finish(&outcome, counts)
|
|
414
|
+
render.emitter.finish(&outcome, counts)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
struct Render<'a> {
|
|
418
|
+
args: &'a GrepArgs,
|
|
419
|
+
emitter: Emitter,
|
|
420
|
+
files: usize,
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
impl Render<'_> {
|
|
424
|
+
fn event(
|
|
425
|
+
&mut self,
|
|
426
|
+
path: &Path,
|
|
427
|
+
event: GrepEvent<'_>,
|
|
428
|
+
budget: &mut ScanBudget,
|
|
429
|
+
cancel: &Cancellation,
|
|
430
|
+
) -> Result<(), SnapshotError> {
|
|
431
|
+
let args = self.args;
|
|
432
|
+
let structured = args.json || args.scan_json;
|
|
433
|
+
if event.opens_source {
|
|
434
|
+
self.files += 1;
|
|
435
|
+
if !structured {
|
|
436
|
+
self.emitter
|
|
437
|
+
.emit(transcript_header(&path.to_string_lossy()), budget, cancel)?;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if !structured && args.context > 0 && event.opens_window && !event.opens_source {
|
|
441
|
+
self.emitter.emit("--".to_owned(), budget, cancel)?;
|
|
442
|
+
}
|
|
443
|
+
let _render_staging = event.preflight_render(budget, cancel)?;
|
|
444
|
+
let line = if structured {
|
|
445
|
+
let Json::Obj(mut fields) = event_json(event.index, event.entry) else {
|
|
446
|
+
unreachable!("event_json object")
|
|
447
|
+
};
|
|
448
|
+
fields.insert(
|
|
449
|
+
0,
|
|
450
|
+
(
|
|
451
|
+
"path".into(),
|
|
452
|
+
Json::Str(path.to_string_lossy().into_owned()),
|
|
453
|
+
),
|
|
454
|
+
);
|
|
455
|
+
if event.pattern_ids.is_none() {
|
|
456
|
+
fields.push(("context".into(), Json::Bool(true)));
|
|
457
|
+
}
|
|
458
|
+
if args.with_result {
|
|
459
|
+
let results = result_fields(event.entry, event.results);
|
|
460
|
+
if !results.is_empty() {
|
|
461
|
+
fields.push(("results".into(), Json::Obj(results)));
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
if args.scan_json {
|
|
465
|
+
fields.push(("generation".into(), Json::Str(event.generation.to_owned())));
|
|
466
|
+
fields.push((
|
|
467
|
+
"pattern_ids".into(),
|
|
468
|
+
Json::Arr(
|
|
469
|
+
event
|
|
470
|
+
.pattern_ids
|
|
471
|
+
.map(|ids| ids.iter().map(|id| Json::Int(*id as i64)).collect())
|
|
472
|
+
.unwrap_or_default(),
|
|
473
|
+
),
|
|
474
|
+
));
|
|
475
|
+
}
|
|
476
|
+
Json::Obj(fields).dumps()
|
|
477
|
+
} else {
|
|
478
|
+
let mut line = compact_line(
|
|
479
|
+
event.index,
|
|
480
|
+
event.entry,
|
|
481
|
+
event.names,
|
|
482
|
+
args.width,
|
|
483
|
+
false,
|
|
484
|
+
args.uuids,
|
|
485
|
+
);
|
|
486
|
+
if args.with_result {
|
|
487
|
+
line.push_str(&result_suffix(event.entry, event.results));
|
|
488
|
+
}
|
|
489
|
+
line
|
|
490
|
+
};
|
|
491
|
+
self.emitter.emit(line, budget, cancel)
|
|
492
|
+
}
|
|
440
493
|
}
|
|
441
494
|
|
|
442
495
|
fn run_over_corpus(
|
|
@@ -521,6 +574,25 @@ fn run_over_corpus(
|
|
|
521
574
|
emitter.finish(&outcome, counts)
|
|
522
575
|
}
|
|
523
576
|
|
|
577
|
+
fn checkpoints() -> GrepCheckpoints {
|
|
578
|
+
let exe = std::env::current_exe()
|
|
579
|
+
.and_then(std::fs::metadata)
|
|
580
|
+
.expect("current executable metadata");
|
|
581
|
+
GrepCheckpoints::new(
|
|
582
|
+
crate::target::home_dir()
|
|
583
|
+
.join(".claude")
|
|
584
|
+
.join("cc-transcript")
|
|
585
|
+
.join("scan"),
|
|
586
|
+
format!(
|
|
587
|
+
"{} {} {}.{}",
|
|
588
|
+
crate::pkg_version(),
|
|
589
|
+
exe.len(),
|
|
590
|
+
exe.mtime(),
|
|
591
|
+
exe.mtime_nsec()
|
|
592
|
+
),
|
|
593
|
+
)
|
|
594
|
+
}
|
|
595
|
+
|
|
524
596
|
fn failed_outcome(error: SnapshotError, budget: &ScanBudget) -> ScanOutcome {
|
|
525
597
|
ScanOutcome {
|
|
526
598
|
complete: false,
|
|
@@ -15,6 +15,7 @@ chrono = { version = "0.4", default-features = false, features = ["std", "serde"
|
|
|
15
15
|
memchr = "2.7"
|
|
16
16
|
once_cell = "1"
|
|
17
17
|
regex = "1"
|
|
18
|
+
regex-syntax = "0.8"
|
|
18
19
|
# Gated behind `command`: a real bash AST (rable) backs the command parser. The Swift/CI build
|
|
19
20
|
# takes core with default-features off, so this stays out of the python-free path.
|
|
20
21
|
rable = { version = "0.2.1", optional = true }
|
|
@@ -29,7 +29,11 @@ pub mod query;
|
|
|
29
29
|
pub mod render;
|
|
30
30
|
pub mod rng;
|
|
31
31
|
pub mod scan;
|
|
32
|
+
pub mod scan_checkpoint;
|
|
32
33
|
pub mod scan_grep;
|
|
34
|
+
pub mod scan_index;
|
|
35
|
+
pub mod scan_projection;
|
|
36
|
+
pub mod scan_stream;
|
|
33
37
|
#[cfg(feature = "sqlite")]
|
|
34
38
|
pub mod schema;
|
|
35
39
|
pub mod snapshot;
|
|
@@ -23,6 +23,8 @@ pub struct ScanProgress {
|
|
|
23
23
|
pub output_bytes: usize,
|
|
24
24
|
pub source_opens: usize,
|
|
25
25
|
pub cache_hits: usize,
|
|
26
|
+
pub cache_invalidations: usize,
|
|
27
|
+
pub validated_bytes: usize,
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
pub struct ScanBudget<'store> {
|
|
@@ -31,6 +33,7 @@ pub struct ScanBudget<'store> {
|
|
|
31
33
|
store: &'store NativeStore,
|
|
32
34
|
context: Value,
|
|
33
35
|
staging: ProjectionArena<'store>,
|
|
36
|
+
validation: usize,
|
|
34
37
|
}
|
|
35
38
|
|
|
36
39
|
pub type StagingReservation<'store> = crate::snapshot::ProjectionAllocation<'store>;
|
|
@@ -45,6 +48,7 @@ impl<'store> ScanBudget<'store> {
|
|
|
45
48
|
store,
|
|
46
49
|
staging: ProjectionArena::new(store, context.clone()),
|
|
47
50
|
context,
|
|
51
|
+
validation: store.scan_validate_bytes(),
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
54
|
|
|
@@ -148,6 +152,40 @@ impl<'store> ScanBudget<'store> {
|
|
|
148
152
|
Ok(())
|
|
149
153
|
}
|
|
150
154
|
|
|
155
|
+
pub fn validation_remaining(&self) -> usize {
|
|
156
|
+
self.validation
|
|
157
|
+
.saturating_sub(self.progress.validated_bytes)
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
pub fn charge_validation(&mut self, bytes: usize) {
|
|
161
|
+
self.progress.validated_bytes += bytes;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
pub fn charge_source(&mut self, bytes: usize) -> Result<(), SnapshotError> {
|
|
165
|
+
if bytes > self.remaining().max_source_read_bytes {
|
|
166
|
+
return Err(self.read_exhausted());
|
|
167
|
+
}
|
|
168
|
+
self.progress.source_bytes += bytes;
|
|
169
|
+
Ok(())
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
pub fn read_exhausted(&self) -> SnapshotError {
|
|
173
|
+
if self.progress.source_bytes >= self.limits.max_source_read_bytes {
|
|
174
|
+
crate::snapshot::source_read_limit()
|
|
175
|
+
} else {
|
|
176
|
+
incomplete("cumulative scan work budget exhausted")
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
pub fn charge_parse(&mut self, cancel: &Cancellation) -> Result<(), SnapshotError> {
|
|
181
|
+
self.checkpoint(cancel)?;
|
|
182
|
+
if self.remaining().max_events == 0 {
|
|
183
|
+
return Err(incomplete("cumulative scan work budget exhausted"));
|
|
184
|
+
}
|
|
185
|
+
self.progress.parsed_events += 1;
|
|
186
|
+
Ok(())
|
|
187
|
+
}
|
|
188
|
+
|
|
151
189
|
pub fn charge_output(
|
|
152
190
|
&mut self,
|
|
153
191
|
bytes: usize,
|
|
@@ -227,7 +265,10 @@ pub struct ScanOutcome {
|
|
|
227
265
|
|
|
228
266
|
pub enum ScanControl {
|
|
229
267
|
Continue,
|
|
230
|
-
Stop {
|
|
268
|
+
Stop {
|
|
269
|
+
source_complete: bool,
|
|
270
|
+
names_through: Option<u64>,
|
|
271
|
+
},
|
|
231
272
|
}
|
|
232
273
|
|
|
233
274
|
pub struct ScanSession<'a> {
|
|
@@ -401,6 +442,15 @@ impl<'a> ScanSession<'a> {
|
|
|
401
442
|
&mut ScanBudget<'a>,
|
|
402
443
|
&Cancellation,
|
|
403
444
|
) -> Result<ScanControl, SnapshotError>,
|
|
445
|
+
{
|
|
446
|
+
self.each_source(plan, |session, path| {
|
|
447
|
+
session.visit_snapshot(path, &mut visit)
|
|
448
|
+
})
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
pub fn each_source<F>(&mut self, plan: &ScanPlan, mut source: F) -> ScanOutcome
|
|
452
|
+
where
|
|
453
|
+
F: FnMut(&mut Self, &Path) -> Result<ScanControl, SnapshotError>,
|
|
404
454
|
{
|
|
405
455
|
let mut selected_sources = 0;
|
|
406
456
|
let mut available_sources = 0;
|
|
@@ -413,54 +463,28 @@ impl<'a> ScanSession<'a> {
|
|
|
413
463
|
return Err(incomplete("source budget exhausted"));
|
|
414
464
|
}
|
|
415
465
|
self.budget.progress.sources += 1;
|
|
416
|
-
let
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
return Err(error);
|
|
426
|
-
}
|
|
427
|
-
continue;
|
|
428
|
-
}
|
|
429
|
-
let guarded = ResponseGuard {
|
|
430
|
-
store: self.store,
|
|
431
|
-
context: &self.context,
|
|
432
|
-
response,
|
|
433
|
-
keep: false,
|
|
434
|
-
};
|
|
435
|
-
if guarded.response["status"].as_str() != Some("ok") {
|
|
436
|
-
return Err(response_error(&guarded.response));
|
|
437
|
-
}
|
|
438
|
-
let snapshot = self
|
|
439
|
-
.store
|
|
440
|
-
.pin_scope_for_work(
|
|
441
|
-
&guarded.response["data"]["description"]["handle"],
|
|
442
|
-
&self.context,
|
|
443
|
-
self.budget.limits.deadline_unix_ms,
|
|
444
|
-
)?
|
|
445
|
-
.0;
|
|
446
|
-
if snapshot.event_count > self.budget.remaining().max_events {
|
|
447
|
-
return Err(incomplete("preparation event budget exhausted"));
|
|
448
|
-
}
|
|
449
|
-
self.budget.progress.preparation_reserved_events += snapshot.event_count;
|
|
450
|
-
match visit(&path, &snapshot, &mut self.budget, &self.cancel)? {
|
|
451
|
-
ScanControl::Continue => {}
|
|
452
|
-
ScanControl::Stop { source_complete } => {
|
|
453
|
-
return Ok(source_complete && source_index + 1 == selected_sources)
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
break;
|
|
466
|
+
if let ScanControl::Stop {
|
|
467
|
+
source_complete,
|
|
468
|
+
names_through,
|
|
469
|
+
} = source(self, &path)?
|
|
470
|
+
{
|
|
471
|
+
return Ok((
|
|
472
|
+
source_complete && source_index + 1 == selected_sources,
|
|
473
|
+
names_through,
|
|
474
|
+
));
|
|
457
475
|
}
|
|
458
476
|
}
|
|
459
|
-
Ok(true)
|
|
477
|
+
Ok((true, None))
|
|
460
478
|
})();
|
|
461
479
|
let (complete, reason) = match result {
|
|
462
|
-
Ok(true) => (true, None),
|
|
463
|
-
Ok(false) => (false, Some("result_limit".to_owned())),
|
|
480
|
+
Ok((true, _)) => (true, None),
|
|
481
|
+
Ok((false, None)) => (false, Some("result_limit".to_owned())),
|
|
482
|
+
Ok((false, Some(through))) => (
|
|
483
|
+
false,
|
|
484
|
+
Some(format!(
|
|
485
|
+
"result_limit; tool names resolved through byte {through}"
|
|
486
|
+
)),
|
|
487
|
+
),
|
|
464
488
|
Err(error) => (
|
|
465
489
|
false,
|
|
466
490
|
Some(format!("{}: {}", error.status.as_str(), error.reason)),
|
|
@@ -474,6 +498,57 @@ impl<'a> ScanSession<'a> {
|
|
|
474
498
|
progress: self.budget.progress.clone(),
|
|
475
499
|
}
|
|
476
500
|
}
|
|
501
|
+
|
|
502
|
+
pub fn visit_snapshot<F>(
|
|
503
|
+
&mut self,
|
|
504
|
+
path: &Path,
|
|
505
|
+
visit: &mut F,
|
|
506
|
+
) -> Result<ScanControl, SnapshotError>
|
|
507
|
+
where
|
|
508
|
+
F: FnMut(
|
|
509
|
+
&Path,
|
|
510
|
+
&TranscriptSnapshot,
|
|
511
|
+
&mut ScanBudget<'a>,
|
|
512
|
+
&Cancellation,
|
|
513
|
+
) -> Result<ScanControl, SnapshotError>,
|
|
514
|
+
{
|
|
515
|
+
let mut request = self.bounded_request("acquire");
|
|
516
|
+
request.insert("path", json!(path.to_string_lossy().as_ref()));
|
|
517
|
+
request.insert("classifier", json!({"id":"native","version":"1"}));
|
|
518
|
+
loop {
|
|
519
|
+
let response = self.request(request)?;
|
|
520
|
+
if let Some(cursor) = response["cursor"].as_str() {
|
|
521
|
+
request = json!({"operation":"resume","cursor":cursor});
|
|
522
|
+
if let Err(error) = self.budget.checkpoint(&self.cancel) {
|
|
523
|
+
self.store.discard_response(&response, &self.context)?;
|
|
524
|
+
return Err(error);
|
|
525
|
+
}
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
let guarded = ResponseGuard {
|
|
529
|
+
store: self.store,
|
|
530
|
+
context: &self.context,
|
|
531
|
+
response,
|
|
532
|
+
keep: false,
|
|
533
|
+
};
|
|
534
|
+
if guarded.response["status"].as_str() != Some("ok") {
|
|
535
|
+
return Err(response_error(&guarded.response));
|
|
536
|
+
}
|
|
537
|
+
let snapshot = self
|
|
538
|
+
.store
|
|
539
|
+
.pin_scope_for_work(
|
|
540
|
+
&guarded.response["data"]["description"]["handle"],
|
|
541
|
+
&self.context,
|
|
542
|
+
self.budget.limits.deadline_unix_ms,
|
|
543
|
+
)?
|
|
544
|
+
.0;
|
|
545
|
+
if snapshot.event_count > self.budget.remaining().max_events {
|
|
546
|
+
return Err(incomplete("preparation event budget exhausted"));
|
|
547
|
+
}
|
|
548
|
+
self.budget.progress.preparation_reserved_events += snapshot.event_count;
|
|
549
|
+
return visit(path, &snapshot, &mut self.budget, &self.cancel);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
477
552
|
}
|
|
478
553
|
|
|
479
554
|
impl Drop for ScanSession<'_> {
|