cc-transcript 14.45.12__tar.gz → 14.45.13__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.45.12 → cc_transcript-14.45.13}/PKG-INFO +1 -1
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/pyproject.toml +1 -1
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot.rs +160 -55
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_activity.rs +160 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_ledger_tests.rs +71 -10
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_prepared_service.rs +16 -12
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_projection.rs +81 -60
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_root_warm.rs +2 -2
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/Cargo.lock +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/Cargo.toml +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/LICENSE +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/README.md +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/__init__.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/__init__.pyi +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/_native.pyi +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/activity.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/activity_probe.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/builders.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/codex.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/command.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/context.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/corrections.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/cost.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/decision_store.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/decisions.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/discovery.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/disktruth.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/evidence.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/extract/__init__.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/extract/correct.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/facts.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/filterspec.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/heartbeats.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/ids.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/judge/__init__.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/judge/llm.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/judge/similar.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/judge/verdicts.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/ledger.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/literals.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/__init__.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/candidates.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/confidence.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/engine.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/formats.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/sampling.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/signals.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/sourcekind.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/spec.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/mining/store.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/models.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/nlp.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/notifications.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/parser.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/py.typed +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/query.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/render.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/sentiment/__init__.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/sentiment/buckets.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/sentiment/data/afinn-en-165.tsv +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/sentiment/data/domain_overrides.tsv +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/sentiment/data/en-ewt.udpipe +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/sentiment/engine.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/sentiment/lexicon.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/sentiment/scorespec.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/snapshot_schema/config.schema.json +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/snapshot_schema/context.schema.json +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/snapshot_schema/request.schema.json +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/snapshot_schema/response.schema.json +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/snapshot_schema/tool_registry.schema.json +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/snapshots.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/synthetic.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/tools.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/cc_transcript/watch.py +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/Cargo.toml +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/blame.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/corpus.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/corrections.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/digest.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/facts.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/grep.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/list.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/mod.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/scratchpad.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/show.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/slice.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/stats.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/commands/watch.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/lib.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/output.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/target.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/cli/src/timearg.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/Cargo.toml +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/benches/parse.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/benches/render.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/benches/toolcall.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/build.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/activity.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/actor.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/blame.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/buckets.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/codex/discovery.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/codex/lower.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/codex/mod.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/codex/parse.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/codex/probe.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/codex/protocol.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/codex/types.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/command.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/context.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/corrections.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/cost.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/discovery.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/facts.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/feedback.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/filter.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/gateway.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/ids.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/judge.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/lib.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/literals/command.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/literals/corrections.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/literals/feedback.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/literals/mining.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/literals/mod.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/literals/protocol.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/notifications.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/parse.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/protocol.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/pystr.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/query.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/render.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/rng.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/scan.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/scan_checkpoint.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/scan_grep.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/scan_grep_stream.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/scan_grep_stream_tests.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/scan_index.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/scan_projection.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/scan_regressions.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/scan_stream.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/schema.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_codec.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_codex_append.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_labels.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_ledger.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_memory.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_owned.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_prepared.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_prepared_disk.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_regressions.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/snapshot_text.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/sqlite.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/toolcall.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/types.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/value.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/src/watch.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/tests/sonic_arena_model.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/core/tests/std_allocation_model.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/Cargo.toml +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/build.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/data/command_prefix_pins.tsv +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/actor_bridge.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/bin/stub_gen.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/codex.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/command.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/context.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/corrections.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/discovery.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/feedback.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/judge.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/lexicon.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/lib.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/mining.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/nlp.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/python.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/render.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/score.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/snapshot_decode.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/snapshots.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/sqlite.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/toolcall.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/attachment.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/blocks.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/command.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/convert.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/dunder.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/events.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/meta.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/mod.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/print.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/store.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/system.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/toolcall.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/toolresult.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/views/transcript.rs +0 -0
- {cc_transcript-14.45.12 → cc_transcript-14.45.13}/rust/crates/py/src/watch.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cc-transcript"
|
|
3
|
-
version = "14.45.
|
|
3
|
+
version = "14.45.13" # 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"
|
|
@@ -32,7 +32,9 @@ use crate::snapshot_memory::{
|
|
|
32
32
|
use crate::snapshot_prepared::FactsNeed;
|
|
33
33
|
use crate::snapshot_prepared_disk::PreparedDiskKey;
|
|
34
34
|
use crate::snapshot_projection::JSON_LITERAL_OBJECT_CAPACITY;
|
|
35
|
-
use crate::types::
|
|
35
|
+
use crate::types::Entry;
|
|
36
|
+
#[cfg(test)]
|
|
37
|
+
use crate::types::SYNTHETIC_MODEL;
|
|
36
38
|
|
|
37
39
|
pub const SCHEMA: &str = "cc-transcript.snapshot/1";
|
|
38
40
|
pub const PARSER_VERSION: &str = "cc-transcript.snapshot/1";
|
|
@@ -375,23 +377,15 @@ impl TranscriptSnapshot {
|
|
|
375
377
|
if self.window_start == 0 {
|
|
376
378
|
return None;
|
|
377
379
|
}
|
|
378
|
-
self.
|
|
379
|
-
.iter()
|
|
380
|
-
.flat_map(|chunk| chunk.entries.iter())
|
|
381
|
-
.find_map(Entry::meta)
|
|
382
|
-
.map(|meta| meta.timestamp.timestamp_millis())
|
|
380
|
+
self.activity.started_unix_ms()
|
|
383
381
|
}
|
|
384
382
|
|
|
385
383
|
pub fn model(&self) -> Option<&str> {
|
|
386
|
-
self.
|
|
387
|
-
.
|
|
388
|
-
.
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
Entry::Assistant(assistant) if assistant.model != SYNTHETIC_MODEL => {
|
|
392
|
-
Some(assistant.model.as_str())
|
|
393
|
-
}
|
|
394
|
-
_ => None,
|
|
384
|
+
self.activity
|
|
385
|
+
.last_model_event()
|
|
386
|
+
.map(|position| match self.entry(position) {
|
|
387
|
+
Entry::Assistant(assistant) => assistant.model.as_str(),
|
|
388
|
+
_ => unreachable!("indexed model is an assistant event"),
|
|
395
389
|
})
|
|
396
390
|
}
|
|
397
391
|
|
|
@@ -533,11 +527,10 @@ struct Lease {
|
|
|
533
527
|
registry: Arc<crate::toolcall::ToolRegistrySnapshot>,
|
|
534
528
|
}
|
|
535
529
|
|
|
536
|
-
struct
|
|
530
|
+
struct LeasedScope {
|
|
537
531
|
snapshot: Arc<TranscriptSnapshot>,
|
|
538
532
|
classifier: Value,
|
|
539
533
|
expires: u64,
|
|
540
|
-
description_bytes: usize,
|
|
541
534
|
}
|
|
542
535
|
|
|
543
536
|
// Sized exactly like an acquire reply's re-serialized copy, whose bytes admit graph members.
|
|
@@ -2889,6 +2882,8 @@ pub struct NativeStore {
|
|
|
2889
2882
|
#[cfg(test)]
|
|
2890
2883
|
pub(crate) fact_builds: AtomicUsize,
|
|
2891
2884
|
#[cfg(test)]
|
|
2885
|
+
pub(crate) description_builds: AtomicUsize,
|
|
2886
|
+
#[cfg(test)]
|
|
2892
2887
|
pub(crate) fact_lookups: AtomicUsize,
|
|
2893
2888
|
#[cfg(test)]
|
|
2894
2889
|
pub(crate) fact_read_waits: AtomicUsize,
|
|
@@ -3372,6 +3367,8 @@ impl NativeStore {
|
|
|
3372
3367
|
#[cfg(test)]
|
|
3373
3368
|
fact_builds: AtomicUsize::new(0),
|
|
3374
3369
|
#[cfg(test)]
|
|
3370
|
+
description_builds: AtomicUsize::new(0),
|
|
3371
|
+
#[cfg(test)]
|
|
3375
3372
|
fact_lookups: AtomicUsize::new(0),
|
|
3376
3373
|
#[cfg(test)]
|
|
3377
3374
|
fact_read_waits: AtomicUsize::new(0),
|
|
@@ -3520,7 +3517,7 @@ impl NativeStore {
|
|
|
3520
3517
|
deadline: u64,
|
|
3521
3518
|
) -> Result<u64, SnapshotError> {
|
|
3522
3519
|
for handle in handles {
|
|
3523
|
-
self.
|
|
3520
|
+
self.pin_record(handle, context)?;
|
|
3524
3521
|
}
|
|
3525
3522
|
let state = self.lock_state();
|
|
3526
3523
|
let mut expires = (now_ms() + self.config.ttl).min(deadline);
|
|
@@ -3955,11 +3952,9 @@ impl NativeStore {
|
|
|
3955
3952
|
mut bounds: WorkLimits,
|
|
3956
3953
|
) -> Result<Value, SnapshotError> {
|
|
3957
3954
|
cancel.check(bounds.deadline_unix_ms)?;
|
|
3958
|
-
let (
|
|
3959
|
-
|
|
3960
|
-
bounds.deadline_unix_ms = bounds
|
|
3961
|
-
.deadline_unix_ms
|
|
3962
|
-
.min(number(&description, "lease_expires_unix_ms")? as u64);
|
|
3955
|
+
let scope = self.renew_scope_for_work(handle, context, bounds.deadline_unix_ms)?;
|
|
3956
|
+
let source = scope.snapshot;
|
|
3957
|
+
bounds.deadline_unix_ms = bounds.deadline_unix_ms.min(scope.expires);
|
|
3963
3958
|
bounds.deadline_unix_ms = bounds
|
|
3964
3959
|
.deadline_unix_ms
|
|
3965
3960
|
.min(now_ms() + self.config.preparation);
|
|
@@ -4983,6 +4978,29 @@ impl NativeStore {
|
|
|
4983
4978
|
|
|
4984
4979
|
#[cfg(test)]
|
|
4985
4980
|
fn audit_snapshot_allocations(snapshot: &Arc<TranscriptSnapshot>) -> Vec<(usize, usize)> {
|
|
4981
|
+
let started = if snapshot.window_start == 0 {
|
|
4982
|
+
None
|
|
4983
|
+
} else {
|
|
4984
|
+
snapshot
|
|
4985
|
+
.chunks
|
|
4986
|
+
.iter()
|
|
4987
|
+
.flat_map(|chunk| chunk.entries.iter())
|
|
4988
|
+
.find_map(Entry::meta)
|
|
4989
|
+
.map(|meta| meta.timestamp.timestamp_millis())
|
|
4990
|
+
};
|
|
4991
|
+
assert_eq!(snapshot.window_started_unix_ms(), started);
|
|
4992
|
+
let model = snapshot
|
|
4993
|
+
.chunks
|
|
4994
|
+
.iter()
|
|
4995
|
+
.rev()
|
|
4996
|
+
.flat_map(|chunk| chunk.entries.iter().rev())
|
|
4997
|
+
.find_map(|entry| match entry {
|
|
4998
|
+
Entry::Assistant(assistant) if assistant.model != SYNTHETIC_MODEL => {
|
|
4999
|
+
Some(assistant.model.as_str())
|
|
5000
|
+
}
|
|
5001
|
+
_ => None,
|
|
5002
|
+
});
|
|
5003
|
+
assert_eq!(snapshot.model(), model);
|
|
4986
5004
|
let TranscriptSnapshot {
|
|
4987
5005
|
ledger: _,
|
|
4988
5006
|
id,
|
|
@@ -5863,6 +5881,8 @@ impl NativeStore {
|
|
|
5863
5881
|
lease: &str,
|
|
5864
5882
|
expires: u64,
|
|
5865
5883
|
) -> Value {
|
|
5884
|
+
#[cfg(test)]
|
|
5885
|
+
self.description_builds.fetch_add(1, Ordering::Relaxed);
|
|
5866
5886
|
json!({"handle": LeaseHandle {owner_epoch: &self.owner_epoch, snapshot_id: &snapshot.id, generation: &snapshot.id, lease_id: lease},
|
|
5867
5887
|
"canonical_path": snapshot.canonical_path.to_string_lossy().as_ref(),
|
|
5868
5888
|
"source_id": format!("{}:{}", snapshot.stamp.identity.device, snapshot.stamp.identity.inode),
|
|
@@ -5879,8 +5899,7 @@ impl NativeStore {
|
|
|
5879
5899
|
handle: &Value,
|
|
5880
5900
|
context: &Value,
|
|
5881
5901
|
) -> Result<Arc<TranscriptSnapshot>, SnapshotError> {
|
|
5882
|
-
self.
|
|
5883
|
-
.map(|(snapshot, _)| snapshot)
|
|
5902
|
+
self.pin_record(handle, context).map(|scope| scope.snapshot)
|
|
5884
5903
|
}
|
|
5885
5904
|
|
|
5886
5905
|
pub fn validate_scope(&self, handle: &Value, context: &Value) -> Result<(), SnapshotError> {
|
|
@@ -5893,23 +5912,36 @@ impl NativeStore {
|
|
|
5893
5912
|
handle: &Value,
|
|
5894
5913
|
context: &Value,
|
|
5895
5914
|
) -> Result<(Arc<TranscriptSnapshot>, Value), SnapshotError> {
|
|
5915
|
+
let scope = self.capture_scope(handle, context)?;
|
|
5916
|
+
let description = self.description(
|
|
5917
|
+
&scope.snapshot,
|
|
5918
|
+
&scope.classifier,
|
|
5919
|
+
str_field(handle, "lease_id")?,
|
|
5920
|
+
scope.expires,
|
|
5921
|
+
);
|
|
5922
|
+
self.authority(context, Some(&scope.snapshot.canonical_path))?;
|
|
5923
|
+
Ok((scope.snapshot, description))
|
|
5924
|
+
}
|
|
5925
|
+
|
|
5926
|
+
fn pin_record(&self, handle: &Value, context: &Value) -> Result<LeasedScope, SnapshotError> {
|
|
5927
|
+
let scope = self.capture_scope(handle, context)?;
|
|
5928
|
+
self.authority(context, Some(&scope.snapshot.canonical_path))?;
|
|
5929
|
+
Ok(scope)
|
|
5930
|
+
}
|
|
5931
|
+
|
|
5932
|
+
fn capture_scope(&self, handle: &Value, context: &Value) -> Result<LeasedScope, SnapshotError> {
|
|
5896
5933
|
self.authority(context, None)?;
|
|
5897
|
-
let
|
|
5934
|
+
let scope = {
|
|
5898
5935
|
let mut state = self.lock_state();
|
|
5899
5936
|
Self::prune(&mut state);
|
|
5900
5937
|
let lease = self.lease(&state, handle, context)?;
|
|
5901
|
-
|
|
5902
|
-
Arc::clone(&lease.snapshot),
|
|
5903
|
-
|
|
5904
|
-
|
|
5905
|
-
|
|
5906
|
-
str_field(handle, "lease_id")?,
|
|
5907
|
-
lease.expires,
|
|
5908
|
-
),
|
|
5909
|
-
)
|
|
5938
|
+
LeasedScope {
|
|
5939
|
+
snapshot: Arc::clone(&lease.snapshot),
|
|
5940
|
+
classifier: lease.classifier.clone(),
|
|
5941
|
+
expires: lease.expires,
|
|
5942
|
+
}
|
|
5910
5943
|
};
|
|
5911
|
-
|
|
5912
|
-
Ok((snapshot, description))
|
|
5944
|
+
Ok(scope)
|
|
5913
5945
|
}
|
|
5914
5946
|
|
|
5915
5947
|
pub fn pin_scope_for_work(
|
|
@@ -5933,7 +5965,7 @@ impl NativeStore {
|
|
|
5933
5965
|
handle: &Value,
|
|
5934
5966
|
context: &Value,
|
|
5935
5967
|
deadline: u64,
|
|
5936
|
-
) -> Result<
|
|
5968
|
+
) -> Result<LeasedScope, SnapshotError> {
|
|
5937
5969
|
#[cfg(test)]
|
|
5938
5970
|
{
|
|
5939
5971
|
let hook = self.pin_hook.lock().expect("pin hook").clone();
|
|
@@ -5950,7 +5982,7 @@ impl NativeStore {
|
|
|
5950
5982
|
"borrow deadline expired",
|
|
5951
5983
|
));
|
|
5952
5984
|
}
|
|
5953
|
-
let
|
|
5985
|
+
let scope = self.pin_record(handle, context)?;
|
|
5954
5986
|
let mut state = self.lock_state();
|
|
5955
5987
|
let lease = self.lease(&state, handle, context)?;
|
|
5956
5988
|
let expires = lease.expires.max(deadline.min(lease.absolute_deadline));
|
|
@@ -5960,11 +5992,10 @@ impl NativeStore {
|
|
|
5960
5992
|
.get_mut(str_field(handle, "lease_id")?)
|
|
5961
5993
|
.expect("validated lease")
|
|
5962
5994
|
.expires = expires;
|
|
5963
|
-
Ok(
|
|
5964
|
-
snapshot,
|
|
5995
|
+
Ok(LeasedScope {
|
|
5996
|
+
snapshot: scope.snapshot,
|
|
5965
5997
|
classifier,
|
|
5966
5998
|
expires,
|
|
5967
|
-
description_bytes: value_bytes(&probe),
|
|
5968
5999
|
})
|
|
5969
6000
|
}
|
|
5970
6001
|
|
|
@@ -8764,6 +8795,12 @@ impl NativeStore {
|
|
|
8764
8795
|
let claimant = str_field(context, "claimant")?;
|
|
8765
8796
|
let lease_id = str_field(root_handle, "lease_id")?;
|
|
8766
8797
|
let root_path = scope.snapshot.canonical_path.as_os_str().len();
|
|
8798
|
+
let description_bytes = value_bytes(&self.description(
|
|
8799
|
+
&scope.snapshot,
|
|
8800
|
+
&scope.classifier,
|
|
8801
|
+
lease_id,
|
|
8802
|
+
scope.expires,
|
|
8803
|
+
));
|
|
8767
8804
|
let mut reservation = self.reserve_projection(
|
|
8768
8805
|
context,
|
|
8769
8806
|
size_of::<GraphCursor>()
|
|
@@ -8773,7 +8810,7 @@ impl NativeStore {
|
|
|
8773
8810
|
+ value_bytes(root_handle)
|
|
8774
8811
|
+ size_of::<GraphNode>()
|
|
8775
8812
|
+ root_path
|
|
8776
|
-
+
|
|
8813
|
+
+ description_bytes
|
|
8777
8814
|
+ set_growth(&HashSet::<SourceIdentity>::new(), 1)
|
|
8778
8815
|
+ task_count * size_of::<GraphTask>()
|
|
8779
8816
|
+ attachment_bytes
|
|
@@ -8781,7 +8818,7 @@ impl NativeStore {
|
|
|
8781
8818
|
)?;
|
|
8782
8819
|
#[cfg(test)]
|
|
8783
8820
|
self.graph_records.fetch_add(1, Ordering::Relaxed);
|
|
8784
|
-
let
|
|
8821
|
+
let LeasedScope {
|
|
8785
8822
|
snapshot: root,
|
|
8786
8823
|
classifier,
|
|
8787
8824
|
expires,
|
|
@@ -9097,7 +9134,7 @@ impl NativeStore {
|
|
|
9097
9134
|
usage: &mut [u64; 20],
|
|
9098
9135
|
) -> Result<GraphYield, SnapshotError> {
|
|
9099
9136
|
cancel.check(graph.remaining.deadline_unix_ms)?;
|
|
9100
|
-
self.
|
|
9137
|
+
self.renew_scope_for_work(
|
|
9101
9138
|
&graph.root_handle,
|
|
9102
9139
|
&graph.context,
|
|
9103
9140
|
graph.remaining.deadline_unix_ms,
|
|
@@ -9538,12 +9575,10 @@ impl NativeStore {
|
|
|
9538
9575
|
let handle = view
|
|
9539
9576
|
.get("handle")
|
|
9540
9577
|
.ok_or_else(|| invalid("missing view handle"))?;
|
|
9541
|
-
let (
|
|
9542
|
-
|
|
9543
|
-
bound.deadline_unix_ms = bound
|
|
9544
|
-
|
|
9545
|
-
.min(number(&description, "lease_expires_unix_ms")? as u64);
|
|
9546
|
-
if !classifier_eq(&view["classifier"], &description["classifier"])? {
|
|
9578
|
+
let scope = self.renew_scope_for_work(handle, context, bound.deadline_unix_ms)?;
|
|
9579
|
+
let snapshot = scope.snapshot;
|
|
9580
|
+
bound.deadline_unix_ms = bound.deadline_unix_ms.min(scope.expires);
|
|
9581
|
+
if !classifier_eq(&view["classifier"], &scope.classifier)? {
|
|
9547
9582
|
return Err(invalid("view classifier differs from leased generation"));
|
|
9548
9583
|
}
|
|
9549
9584
|
let mut page = bound;
|
|
@@ -9671,16 +9706,15 @@ impl NativeStore {
|
|
|
9671
9706
|
.ok_or_else(|| invalid("missing windows_json"))?;
|
|
9672
9707
|
let mut sessions = HashMap::new();
|
|
9673
9708
|
for handle in handles.iter() {
|
|
9674
|
-
let
|
|
9709
|
+
let scope = self.renew_scope_for_work(
|
|
9675
9710
|
handle
|
|
9676
9711
|
.get("handle")
|
|
9677
9712
|
.ok_or_else(|| invalid("missing handle"))?,
|
|
9678
9713
|
context,
|
|
9679
9714
|
bound.deadline_unix_ms,
|
|
9680
9715
|
)?;
|
|
9681
|
-
|
|
9682
|
-
|
|
9683
|
-
.min(number(&description, "lease_expires_unix_ms")? as u64);
|
|
9716
|
+
let snapshot = scope.snapshot;
|
|
9717
|
+
bound.deadline_unix_ms = bound.deadline_unix_ms.min(scope.expires);
|
|
9684
9718
|
let session = str_field(handle, "session_id")?;
|
|
9685
9719
|
if session != snapshot.session_id {
|
|
9686
9720
|
return Err(invalid("hydration session differs from handle"));
|
|
@@ -16144,6 +16178,77 @@ mod tests {
|
|
|
16144
16178
|
store.assert_conserved();
|
|
16145
16179
|
}
|
|
16146
16180
|
|
|
16181
|
+
#[test]
|
|
16182
|
+
fn repeated_root_predicates_keep_scope_metadata_typed() {
|
|
16183
|
+
let skill = json!({"type":"assistant","uuid":"skill","sessionId":"s","timestamp":"2026-01-02T03:04:06Z","message":{"model":"m","content":[{"type":"tool_use","id":"skill","name":"Skill","input":{"skill":"skill-4"}}]}});
|
|
16184
|
+
let source = Source::new(&format!("{}\n{skill}\n", user_text("prompt", "ready")));
|
|
16185
|
+
let store = fact_budget_store(16 * 1024 * 1024);
|
|
16186
|
+
let owner = context("a");
|
|
16187
|
+
let template = acquire(&source.path);
|
|
16188
|
+
let root = finish(
|
|
16189
|
+
&store,
|
|
16190
|
+
store.request(&template, &owner, &Cancellation::default()),
|
|
16191
|
+
&owner,
|
|
16192
|
+
);
|
|
16193
|
+
let graph = finish(
|
|
16194
|
+
&store,
|
|
16195
|
+
store.request(&json!({"schema":SCHEMA,"id":"prepare","operation":"prepare_graph","view":{"handle":handle(&root),"classifier":{"id":"native","version":"1"},"selectors":[],"attachments":[]},"thread_ids":[],"roots":[],"direct_paths":[],"deadline_unix_ms":template["deadline_unix_ms"],"limits":template["limits"]}), &owner, &Cancellation::default()),
|
|
16196
|
+
&owner,
|
|
16197
|
+
);
|
|
16198
|
+
assert_eq!(graph["status"].as_str(), Some("ok"), "{graph:?}");
|
|
16199
|
+
let before = store.description_builds.load(Ordering::Relaxed);
|
|
16200
|
+
for index in 0..24 {
|
|
16201
|
+
let request = prepared_graph_request(
|
|
16202
|
+
&graph,
|
|
16203
|
+
&template,
|
|
16204
|
+
json!([]),
|
|
16205
|
+
json!({"kind":"has_skill","values":[format!("skill-{index}")],"subagents":true}),
|
|
16206
|
+
None,
|
|
16207
|
+
);
|
|
16208
|
+
let answer = single_step(store.request(&request, &owner, &Cancellation::default()));
|
|
16209
|
+
assert_eq!(value_of(&answer), Some(index == 4), "{answer:?}");
|
|
16210
|
+
}
|
|
16211
|
+
assert_eq!(store.description_builds.load(Ordering::Relaxed), before);
|
|
16212
|
+
let (_, description) = store
|
|
16213
|
+
.pin_scope_for_work(
|
|
16214
|
+
&handle(&root),
|
|
16215
|
+
&owner,
|
|
16216
|
+
template["deadline_unix_ms"].as_u64().unwrap(),
|
|
16217
|
+
)
|
|
16218
|
+
.unwrap();
|
|
16219
|
+
assert_eq!(store.description_builds.load(Ordering::Relaxed), before + 1);
|
|
16220
|
+
assert_eq!(
|
|
16221
|
+
description["classifier"],
|
|
16222
|
+
json!({"id":"native","version":"1"})
|
|
16223
|
+
);
|
|
16224
|
+
assert_eq!(description["model"].as_str(), Some("m"));
|
|
16225
|
+
assert_eq!(
|
|
16226
|
+
description["canonical_path"].as_str(),
|
|
16227
|
+
std::fs::canonicalize(&source.path).unwrap().to_str()
|
|
16228
|
+
);
|
|
16229
|
+
let later = json!({"type":"assistant","uuid":"later","sessionId":"s","timestamp":"2026-01-02T03:04:07Z","message":{"model":"later","content":[]}});
|
|
16230
|
+
std::fs::OpenOptions::new()
|
|
16231
|
+
.append(true)
|
|
16232
|
+
.open(&source.path)
|
|
16233
|
+
.unwrap()
|
|
16234
|
+
.write_all(format!("{later}\n").as_bytes())
|
|
16235
|
+
.unwrap();
|
|
16236
|
+
let newer = finish(
|
|
16237
|
+
&store,
|
|
16238
|
+
store.request(&acquire(&source.path), &owner, &Cancellation::default()),
|
|
16239
|
+
&owner,
|
|
16240
|
+
);
|
|
16241
|
+
assert_eq!(
|
|
16242
|
+
store.pin(&handle(&root), &owner).unwrap().model(),
|
|
16243
|
+
Some("m")
|
|
16244
|
+
);
|
|
16245
|
+
assert_eq!(
|
|
16246
|
+
store.pin(&handle(&newer), &owner).unwrap().model(),
|
|
16247
|
+
Some("later")
|
|
16248
|
+
);
|
|
16249
|
+
store.assert_conserved();
|
|
16250
|
+
}
|
|
16251
|
+
|
|
16147
16252
|
#[test]
|
|
16148
16253
|
fn selected_root_slices_answer_has_override_within_their_view() {
|
|
16149
16254
|
let source = Source::new(&format!(
|
|
@@ -4,6 +4,7 @@ use std::ops::Range;
|
|
|
4
4
|
use std::sync::Arc;
|
|
5
5
|
|
|
6
6
|
use crate::activity::{lift_session_index_tail, lower_edit, Hunk, LiftedSession, ToolUse, Turn};
|
|
7
|
+
use crate::parse::pushed_capacity;
|
|
7
8
|
#[cfg(test)]
|
|
8
9
|
use crate::snapshot::NativeStore;
|
|
9
10
|
#[cfg(test)]
|
|
@@ -53,12 +54,77 @@ pub(crate) struct ResultPosition {
|
|
|
53
54
|
charge: MemoryCharge,
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
|
58
|
+
pub(crate) struct ActivityShape {
|
|
59
|
+
pub calls: usize,
|
|
60
|
+
pub call_name_bytes: usize,
|
|
61
|
+
pub paths: usize,
|
|
62
|
+
pub path_bytes: usize,
|
|
63
|
+
pub edits: usize,
|
|
64
|
+
pub edit_path_bytes: usize,
|
|
65
|
+
pub commands: usize,
|
|
66
|
+
pub command_bytes: usize,
|
|
67
|
+
pub skills: usize,
|
|
68
|
+
pub skill_bytes: usize,
|
|
69
|
+
pub prose_bytes: usize,
|
|
70
|
+
pub tool_name_slots: usize,
|
|
71
|
+
pub tool_name_bytes: usize,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
impl ActivityShape {
|
|
75
|
+
fn include_entry(&mut self, entry: &Entry) {
|
|
76
|
+
match entry {
|
|
77
|
+
Entry::User(user) => {
|
|
78
|
+
self.prose_bytes += user.content.text_len()
|
|
79
|
+
+ user
|
|
80
|
+
.tool_results()
|
|
81
|
+
.map(|result| result.content.len())
|
|
82
|
+
.sum::<usize>();
|
|
83
|
+
}
|
|
84
|
+
Entry::Assistant(assistant) => {
|
|
85
|
+
self.prose_bytes += crate::types::joined_text_len(&assistant.blocks);
|
|
86
|
+
self.tool_name_slots += pushed_capacity(entry.tool_uses().count());
|
|
87
|
+
self.tool_name_bytes +=
|
|
88
|
+
entry.tool_uses().map(|tool| tool.name.len()).sum::<usize>();
|
|
89
|
+
}
|
|
90
|
+
Entry::System(system) => {
|
|
91
|
+
self.prose_bytes += system.content.as_ref().map_or(0, String::len);
|
|
92
|
+
}
|
|
93
|
+
_ => {}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
fn include_call(&mut self, call: &ToolCall, edits: &[(String, Vec<Hunk>)]) {
|
|
98
|
+
let paths = call.file_paths();
|
|
99
|
+
self.calls += 1;
|
|
100
|
+
self.call_name_bytes += call.name().len();
|
|
101
|
+
self.paths += paths.len();
|
|
102
|
+
self.path_bytes += paths.iter().map(|path| path.len()).sum::<usize>();
|
|
103
|
+
self.edits += edits.len();
|
|
104
|
+
self.edit_path_bytes += edits.iter().map(|(path, _)| path.len()).sum::<usize>();
|
|
105
|
+
match call {
|
|
106
|
+
ToolCall::Bash(bash) => {
|
|
107
|
+
self.commands += 1;
|
|
108
|
+
self.command_bytes += bash.command.len();
|
|
109
|
+
}
|
|
110
|
+
ToolCall::Skill(skill) => {
|
|
111
|
+
self.skills += 1;
|
|
112
|
+
self.skill_bytes += skill.skill.len();
|
|
113
|
+
}
|
|
114
|
+
_ => {}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
56
119
|
#[derive(Debug, Clone, Default)]
|
|
57
120
|
pub struct ActivityIndex {
|
|
58
121
|
entries: usize,
|
|
59
122
|
turns: Arc<Vec<Arc<CachedTurn>>>,
|
|
60
123
|
uuids: Arc<HashMap<String, usize>>,
|
|
61
124
|
results: Arc<HashMap<String, ResultPosition>>,
|
|
125
|
+
shape: ActivityShape,
|
|
126
|
+
started_unix_ms: Option<i64>,
|
|
127
|
+
last_model_event: Option<usize>,
|
|
62
128
|
work: ActivityWork,
|
|
63
129
|
}
|
|
64
130
|
|
|
@@ -101,8 +167,12 @@ impl ActivityIndex {
|
|
|
101
167
|
..ActivityWork::default()
|
|
102
168
|
};
|
|
103
169
|
for (local, entry) in entries.iter().enumerate() {
|
|
170
|
+
next.shape.include_entry(entry);
|
|
104
171
|
let event = first_new_index + local;
|
|
105
172
|
if let Some(meta) = entry.meta() {
|
|
173
|
+
if next.started_unix_ms.is_none() {
|
|
174
|
+
next.started_unix_ms = Some(meta.timestamp.timestamp_millis());
|
|
175
|
+
}
|
|
106
176
|
if !next.uuids.contains_key(&meta.uuid) {
|
|
107
177
|
if Arc::strong_count(&next.uuids) > 1 {
|
|
108
178
|
next.work.copied_index_entries += next.uuids.len();
|
|
@@ -110,6 +180,10 @@ impl ActivityIndex {
|
|
|
110
180
|
Arc::make_mut(&mut next.uuids).insert(meta.uuid.clone(), event);
|
|
111
181
|
}
|
|
112
182
|
}
|
|
183
|
+
if matches!(entry, Entry::Assistant(assistant) if assistant.model != crate::types::SYNTHETIC_MODEL)
|
|
184
|
+
{
|
|
185
|
+
next.last_model_event = Some(event);
|
|
186
|
+
}
|
|
113
187
|
if let Entry::User(user) = entry {
|
|
114
188
|
for (ordinal, block) in user.blocks().iter().enumerate() {
|
|
115
189
|
let ContentBlock::ToolResult(result) = block else {
|
|
@@ -149,6 +223,7 @@ impl ActivityIndex {
|
|
|
149
223
|
};
|
|
150
224
|
let call = parse_tool_call(&tool.name, &tool.input);
|
|
151
225
|
let edits = lower_edit(&call);
|
|
226
|
+
next.shape.include_call(&call, &edits);
|
|
152
227
|
let id = tool.id.clone();
|
|
153
228
|
let accounted_bytes = size_of::<CachedCall>()
|
|
154
229
|
+ id.capacity()
|
|
@@ -204,6 +279,18 @@ impl ActivityIndex {
|
|
|
204
279
|
self.entries
|
|
205
280
|
}
|
|
206
281
|
|
|
282
|
+
pub(crate) fn shape(&self) -> ActivityShape {
|
|
283
|
+
self.shape
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
pub(crate) fn started_unix_ms(&self) -> Option<i64> {
|
|
287
|
+
self.started_unix_ms
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
pub(crate) fn last_model_event(&self) -> Option<usize> {
|
|
291
|
+
self.last_model_event
|
|
292
|
+
}
|
|
293
|
+
|
|
207
294
|
pub fn turn_count(&self) -> usize {
|
|
208
295
|
self.turns.len()
|
|
209
296
|
}
|
|
@@ -436,6 +523,9 @@ impl ActivityIndex {
|
|
|
436
523
|
turns,
|
|
437
524
|
uuids,
|
|
438
525
|
results,
|
|
526
|
+
shape: _,
|
|
527
|
+
started_unix_ms: _,
|
|
528
|
+
last_model_event: _,
|
|
439
529
|
work: _,
|
|
440
530
|
} = self;
|
|
441
531
|
let mut allocations = vec![
|
|
@@ -1084,11 +1174,14 @@ mod tests {
|
|
|
1084
1174
|
#[test]
|
|
1085
1175
|
fn every_append_boundary_matches_full_lift() {
|
|
1086
1176
|
let entries = [
|
|
1177
|
+
entry(r#"{"type":"mode","sessionId":"s","mode":"plan"}"#),
|
|
1087
1178
|
tools(),
|
|
1088
1179
|
user("u", "first"),
|
|
1089
1180
|
tools(),
|
|
1090
1181
|
user("v", "second"),
|
|
1091
1182
|
results(),
|
|
1183
|
+
entry(&sonic_rs::json!({"type":"assistant","uuid":"synthetic","sessionId":"s","timestamp":"2026-01-02T03:04:08Z","message":{"model":crate::types::SYNTHETIC_MODEL,"content":[{"type":"text","text":"synthetic"}]}}).to_string()),
|
|
1184
|
+
user("tail", "trailing prose"),
|
|
1092
1185
|
];
|
|
1093
1186
|
let refs: Vec<_> = entries.iter().collect();
|
|
1094
1187
|
for boundary in 0..=refs.len() {
|
|
@@ -1096,9 +1189,69 @@ mod tests {
|
|
|
1096
1189
|
let next = prior.append(&refs, boundary, None);
|
|
1097
1190
|
parity(&next, &refs, None);
|
|
1098
1191
|
parity(&prior, &refs[..boundary], None);
|
|
1192
|
+
assert_eq!(next.shape(), ActivityIndex::new(&refs, None).shape());
|
|
1193
|
+
assert_eq!(
|
|
1194
|
+
next.started_unix_ms(),
|
|
1195
|
+
refs.iter()
|
|
1196
|
+
.find_map(|entry| entry.meta())
|
|
1197
|
+
.map(|meta| meta.timestamp.timestamp_millis())
|
|
1198
|
+
);
|
|
1199
|
+
assert_eq!(
|
|
1200
|
+
next.last_model_event(),
|
|
1201
|
+
refs.iter().rposition(|entry| matches!(entry, Entry::Assistant(assistant) if assistant.model != crate::types::SYNTHETIC_MODEL))
|
|
1202
|
+
);
|
|
1203
|
+
assert_eq!(
|
|
1204
|
+
prior.started_unix_ms(),
|
|
1205
|
+
refs[..boundary]
|
|
1206
|
+
.iter()
|
|
1207
|
+
.find_map(|entry| entry.meta())
|
|
1208
|
+
.map(|meta| meta.timestamp.timestamp_millis())
|
|
1209
|
+
);
|
|
1210
|
+
assert_eq!(
|
|
1211
|
+
prior.last_model_event(),
|
|
1212
|
+
refs[..boundary].iter().rposition(|entry| matches!(entry, Entry::Assistant(assistant) if assistant.model != crate::types::SYNTHETIC_MODEL))
|
|
1213
|
+
);
|
|
1214
|
+
assert_eq!(
|
|
1215
|
+
prior.shape(),
|
|
1216
|
+
ActivityIndex::new(&refs[..boundary], None).shape()
|
|
1217
|
+
);
|
|
1099
1218
|
}
|
|
1100
1219
|
}
|
|
1101
1220
|
|
|
1221
|
+
#[test]
|
|
1222
|
+
fn metadata_is_local_to_each_window_and_immutable_prefix() {
|
|
1223
|
+
let entries = [
|
|
1224
|
+
sonic_rs::json!({"type":"user","uuid":"outside","sessionId":"s","timestamp":"2026-01-02T03:04:01Z","message":{"content":"outside"}}),
|
|
1225
|
+
sonic_rs::json!({"type":"assistant","uuid":"before","sessionId":"s","timestamp":"2026-01-02T03:04:02Z","message":{"model":"before","content":[]}}),
|
|
1226
|
+
sonic_rs::json!({"type":"mode","sessionId":"s","mode":"plan"}),
|
|
1227
|
+
sonic_rs::json!({"type":"user","uuid":"inside","sessionId":"s","timestamp":"2026-01-02T03:04:08Z","message":{"content":"inside"}}),
|
|
1228
|
+
sonic_rs::json!({"type":"assistant","uuid":"model","sessionId":"s","timestamp":"2026-01-02T03:04:09Z","message":{"model":"inside","content":[]}}),
|
|
1229
|
+
sonic_rs::json!({"type":"user","uuid":"tail","sessionId":"s","timestamp":"2026-01-02T03:04:10Z","message":{"content":"tail"}}),
|
|
1230
|
+
sonic_rs::json!({"type":"assistant","uuid":"after","sessionId":"s","timestamp":"2026-01-02T03:04:11Z","message":{"model":"after","content":[]}}),
|
|
1231
|
+
].map(|value| entry(&value.to_string()));
|
|
1232
|
+
let refs: Vec<_> = entries.iter().collect();
|
|
1233
|
+
let global = ActivityIndex::new(&refs, None);
|
|
1234
|
+
for range in [0..5, 2..6, 3..6, 2..4] {
|
|
1235
|
+
let window = &refs[range.clone()];
|
|
1236
|
+
let first = window
|
|
1237
|
+
.iter()
|
|
1238
|
+
.find_map(|entry| entry.meta())
|
|
1239
|
+
.map(|meta| meta.timestamp.timestamp_millis());
|
|
1240
|
+
let model = window.iter().rposition(|entry| matches!(entry, Entry::Assistant(assistant) if assistant.model != crate::types::SYNTHETIC_MODEL));
|
|
1241
|
+
for boundary in 0..=window.len() {
|
|
1242
|
+
let prior = ActivityIndex::new(&window[..boundary], None);
|
|
1243
|
+
let next = prior.append(window, boundary, None);
|
|
1244
|
+
assert_eq!(next.started_unix_ms(), first, "{range:?} {boundary}");
|
|
1245
|
+
assert_eq!(next.last_model_event(), model, "{range:?} {boundary}");
|
|
1246
|
+
assert_eq!(prior.last_model_event(), window[..boundary].iter().rposition(|entry| matches!(entry, Entry::Assistant(assistant) if assistant.model != crate::types::SYNTHETIC_MODEL)));
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
let window = ActivityIndex::new(&refs[2..6], None);
|
|
1250
|
+
assert_ne!(window.started_unix_ms(), global.started_unix_ms());
|
|
1251
|
+
assert_eq!(window.last_model_event(), Some(2));
|
|
1252
|
+
assert_eq!(global.last_model_event(), Some(6));
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1102
1255
|
#[test]
|
|
1103
1256
|
fn custom_classifier_and_empty_append_preserve_semantics() {
|
|
1104
1257
|
let entries = [user("u", "first"), tools(), user("v", "second"), results()];
|
|
@@ -1109,6 +1262,13 @@ mod tests {
|
|
|
1109
1262
|
parity(&next, &refs, Some(&flags));
|
|
1110
1263
|
let unchanged = next.append(&refs, refs.len(), Some(&flags));
|
|
1111
1264
|
assert_eq!(unchanged.work(), ActivityWork::default());
|
|
1265
|
+
assert_eq!(unchanged.shape(), next.shape());
|
|
1266
|
+
assert_eq!(unchanged.started_unix_ms(), next.started_unix_ms());
|
|
1267
|
+
assert_eq!(unchanged.last_model_event(), next.last_model_event());
|
|
1268
|
+
assert_eq!(
|
|
1269
|
+
next.shape(),
|
|
1270
|
+
ActivityIndex::new(&refs, Some(&flags)).shape()
|
|
1271
|
+
);
|
|
1112
1272
|
assert!(Arc::ptr_eq(&next.turns[0], &unchanged.turns[0]));
|
|
1113
1273
|
assert!(Arc::ptr_eq(&next.uuids, &unchanged.uuids));
|
|
1114
1274
|
assert!(Arc::ptr_eq(&next.results, &unchanged.results));
|