cc-transcript 14.28.3__tar.gz → 14.28.5__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.28.3 → cc_transcript-14.28.5}/PKG-INFO +1 -1
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/pyproject.toml +1 -1
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/target.rs +39 -14
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/scan.rs +39 -1
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/scan_regressions.rs +36 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot.rs +492 -40
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_prepared_service.rs +9 -4
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_projection.rs +40 -6
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_root_warm.rs +1 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/Cargo.lock +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/Cargo.toml +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/LICENSE +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/README.md +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/__init__.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/__init__.pyi +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/_native.pyi +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/activity.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/activity_probe.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/builders.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/codex.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/command.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/context.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/corrections.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/cost.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/decision_store.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/decisions.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/discovery.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/disktruth.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/evidence.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/extract/__init__.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/extract/correct.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/facts.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/filterspec.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/heartbeats.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/ids.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/judge/__init__.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/judge/llm.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/judge/similar.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/judge/verdicts.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/ledger.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/literals.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/__init__.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/candidates.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/confidence.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/engine.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/formats.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/sampling.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/signals.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/sourcekind.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/spec.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/mining/store.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/models.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/nlp.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/notifications.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/parser.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/py.typed +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/query.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/render.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/sentiment/__init__.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/sentiment/buckets.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/sentiment/data/afinn-en-165.tsv +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/sentiment/data/domain_overrides.tsv +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/sentiment/data/en-ewt.udpipe +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/sentiment/engine.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/sentiment/lexicon.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/sentiment/scorespec.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/snapshot_schema/config.schema.json +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/snapshot_schema/context.schema.json +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/snapshot_schema/request.schema.json +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/snapshot_schema/response.schema.json +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/snapshot_schema/tool_registry.schema.json +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/snapshots.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/synthetic.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/tools.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/cc_transcript/watch.py +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/Cargo.toml +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/blame.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/corpus.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/corrections.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/digest.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/facts.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/grep.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/list.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/mod.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/scratchpad.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/show.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/slice.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/stats.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/commands/watch.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/lib.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/main.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/output.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/cli/src/timearg.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/Cargo.toml +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/benches/parse.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/benches/render.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/benches/toolcall.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/activity.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/actor.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/blame.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/buckets.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/codex/discovery.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/codex/lower.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/codex/mod.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/codex/parse.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/codex/probe.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/codex/protocol.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/codex/types.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/command.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/context.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/corrections.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/cost.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/discovery.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/facts.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/feedback.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/filter.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/gateway.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/ids.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/judge.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/lib.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/literals/command.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/literals/corrections.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/literals/feedback.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/literals/mining.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/literals/mod.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/literals/protocol.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/notifications.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/parse.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/protocol.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/pystr.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/query.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/render.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/rng.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/scan_grep.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/schema.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_activity.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_codec.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_codex_append.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_labels.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_memory.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_owned.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_prepared.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_prepared_disk.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_regressions.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/snapshot_text.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/sqlite.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/toolcall.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/types.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/value.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/core/src/watch.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/Cargo.toml +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/build.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/data/command_prefix_pins.tsv +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/actor_bridge.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/bin/stub_gen.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/codex.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/command.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/context.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/corrections.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/discovery.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/feedback.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/judge.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/lexicon.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/lib.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/mining.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/nlp.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/python.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/render.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/score.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/snapshot_decode.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/snapshots.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/sqlite.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/toolcall.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/attachment.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/blocks.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/command.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/convert.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/dunder.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/events.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/meta.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/mod.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/print.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/store.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/system.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/toolcall.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/toolresult.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/views/transcript.rs +0 -0
- {cc_transcript-14.28.3 → cc_transcript-14.28.5}/rust/crates/py/src/watch.rs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cc-transcript"
|
|
3
|
-
version = "14.28.
|
|
3
|
+
version = "14.28.5" # 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,6 +1,7 @@
|
|
|
1
1
|
//! Target discovery and parsing shared by every transcript command (cli.py's
|
|
2
2
|
//! discover / resolve_targets / parse_transcripts / scope_note plumbing).
|
|
3
3
|
|
|
4
|
+
use std::fs;
|
|
4
5
|
use std::path::{Path, PathBuf};
|
|
5
6
|
|
|
6
7
|
use cc_transcript_core::discovery::{find_in, mtime_secs};
|
|
@@ -26,23 +27,26 @@ pub struct Targets {
|
|
|
26
27
|
pub total: usize,
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
fn project_matches(path: &Path, root: &Path, project: Option<&str>) -> bool {
|
|
30
|
-
let Some(project) = project else { return true };
|
|
31
|
-
let Ok(rel) = path.strip_prefix(root) else {
|
|
32
|
-
return false;
|
|
33
|
-
};
|
|
34
|
-
let parts: Vec<_> = rel.components().collect();
|
|
35
|
-
parts[..parts.len().saturating_sub(1)]
|
|
36
|
-
.iter()
|
|
37
|
-
.any(|part| part.as_os_str().to_string_lossy().contains(project))
|
|
38
|
-
}
|
|
39
|
-
|
|
40
30
|
/// Newest-first discovery under `root` (cli.py discover): find_in order, project
|
|
41
31
|
/// filtered, stable-sorted by mtime descending.
|
|
42
32
|
pub fn discover(root: &Path, project: Option<&str>, contains: Option<&str>) -> Vec<(PathBuf, f64)> {
|
|
43
|
-
let
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
let roots = if let Some(project) = project {
|
|
34
|
+
fs::read_dir(root)
|
|
35
|
+
.map(|entries| {
|
|
36
|
+
entries
|
|
37
|
+
.flatten()
|
|
38
|
+
.filter(|entry| entry.file_type().is_ok_and(|kind| kind.is_dir()))
|
|
39
|
+
.filter(|entry| entry.file_name().to_string_lossy().contains(project))
|
|
40
|
+
.map(|entry| entry.path())
|
|
41
|
+
.collect()
|
|
42
|
+
})
|
|
43
|
+
.unwrap_or_default()
|
|
44
|
+
} else {
|
|
45
|
+
vec![root.to_path_buf()]
|
|
46
|
+
};
|
|
47
|
+
let mut found: Vec<(PathBuf, f64)> = roots
|
|
48
|
+
.iter()
|
|
49
|
+
.flat_map(|root| find_in(root, contains, None, None))
|
|
46
50
|
.collect();
|
|
47
51
|
found.sort_by(|a, b| b.1.partial_cmp(&a.1).expect("mtimes are finite"));
|
|
48
52
|
found
|
|
@@ -237,3 +241,24 @@ pub fn py_path(arg: &str) -> PathBuf {
|
|
|
237
241
|
};
|
|
238
242
|
PathBuf::from(text)
|
|
239
243
|
}
|
|
244
|
+
|
|
245
|
+
#[cfg(test)]
|
|
246
|
+
mod tests {
|
|
247
|
+
use super::discover;
|
|
248
|
+
|
|
249
|
+
#[test]
|
|
250
|
+
fn project_discovery_only_walks_matching_roots() {
|
|
251
|
+
let root = tempfile::tempdir().unwrap();
|
|
252
|
+
let wanted = root.path().join("wanted-project");
|
|
253
|
+
let other = root.path().join("other-project");
|
|
254
|
+
std::fs::create_dir(&wanted).unwrap();
|
|
255
|
+
std::fs::create_dir(&other).unwrap();
|
|
256
|
+
std::fs::write(wanted.join("match.jsonl"), "{}").unwrap();
|
|
257
|
+
std::fs::write(other.join("match.jsonl"), "{}").unwrap();
|
|
258
|
+
|
|
259
|
+
let found = discover(root.path(), Some("wanted"), None);
|
|
260
|
+
|
|
261
|
+
assert_eq!(found.len(), 1);
|
|
262
|
+
assert_eq!(found[0].0, wanted.join("match.jsonl"));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
@@ -292,8 +292,46 @@ impl<'a> ScanSession<'a> {
|
|
|
292
292
|
}
|
|
293
293
|
let canonical_root =
|
|
294
294
|
std::fs::canonicalize(&plan.root).map_err(|error| incomplete(error.to_string()))?;
|
|
295
|
+
let roots = if let Some(project) = &plan.project {
|
|
296
|
+
let mut roots = Vec::new();
|
|
297
|
+
for entry in
|
|
298
|
+
std::fs::read_dir(&plan.root).map_err(|error| incomplete(error.to_string()))?
|
|
299
|
+
{
|
|
300
|
+
self.budget.checkpoint(&self.cancel)?;
|
|
301
|
+
self.budget.progress.discovery_entries += 1;
|
|
302
|
+
if self.budget.progress.discovery_entries > self.budget.limits.max_discovery_entries
|
|
303
|
+
{
|
|
304
|
+
return Err(incomplete("project discovery budget exhausted"));
|
|
305
|
+
}
|
|
306
|
+
let entry = entry.map_err(|error| incomplete(error.to_string()))?;
|
|
307
|
+
if entry
|
|
308
|
+
.file_type()
|
|
309
|
+
.map_err(|error| incomplete(error.to_string()))?
|
|
310
|
+
.is_dir()
|
|
311
|
+
&& entry.file_name().to_string_lossy().contains(project)
|
|
312
|
+
{
|
|
313
|
+
roots.push(entry.path());
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
roots
|
|
317
|
+
} else {
|
|
318
|
+
vec![plan.root.clone()]
|
|
319
|
+
};
|
|
320
|
+
if roots.is_empty() {
|
|
321
|
+
return Ok((Vec::new(), 0));
|
|
322
|
+
}
|
|
295
323
|
let mut request = self.bounded_request("discover");
|
|
296
|
-
request.insert(
|
|
324
|
+
request.insert(
|
|
325
|
+
"roots",
|
|
326
|
+
json!(roots
|
|
327
|
+
.iter()
|
|
328
|
+
.map(|root| root.to_string_lossy().into_owned())
|
|
329
|
+
.collect::<Vec<_>>()),
|
|
330
|
+
);
|
|
331
|
+
request["limits"].insert(
|
|
332
|
+
"max_items",
|
|
333
|
+
json!(self.budget.remaining().max_discovery_entries),
|
|
334
|
+
);
|
|
297
335
|
request.insert("preserve_aliases", json!(true));
|
|
298
336
|
request.insert("follow_directory_symlinks", json!(false));
|
|
299
337
|
let mut paths = Vec::new();
|
|
@@ -85,6 +85,42 @@ fn exhausted_discovery_does_not_read_a_body() {
|
|
|
85
85
|
assert_eq!(result.progress.source_opens, 0);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
#[test]
|
|
89
|
+
fn project_filter_skips_other_directories_before_the_scan() {
|
|
90
|
+
let fixture = Fixture::new();
|
|
91
|
+
let wanted = fixture.0.join("wanted-project");
|
|
92
|
+
let other = fixture.0.join("other-project");
|
|
93
|
+
std::fs::create_dir(&wanted).unwrap();
|
|
94
|
+
std::fs::create_dir(&other).unwrap();
|
|
95
|
+
let event = "{\"type\":\"user\",\"uuid\":\"a\",\"sessionId\":\"s\",\"timestamp\":\"2026-01-01T00:00:00Z\",\"message\":{\"role\":\"user\",\"content\":\"match\"}}\n";
|
|
96
|
+
for name in ["first.jsonl", "second.jsonl"] {
|
|
97
|
+
std::fs::write(wanted.join(name), event).unwrap();
|
|
98
|
+
}
|
|
99
|
+
for index in 0..10 {
|
|
100
|
+
std::fs::write(other.join(format!("{index}.jsonl")), event).unwrap();
|
|
101
|
+
}
|
|
102
|
+
let mut bound = limits();
|
|
103
|
+
bound.max_items = 1;
|
|
104
|
+
bound.max_discovery_entries = 6;
|
|
105
|
+
let store = NativeStore::new(&json!({})).unwrap();
|
|
106
|
+
let mut scan = ScanSession::new(&store, bound, Cancellation::default());
|
|
107
|
+
let plan = ScanPlan {
|
|
108
|
+
project: Some("wanted".to_owned()),
|
|
109
|
+
..fixture.plan(vec![])
|
|
110
|
+
};
|
|
111
|
+
let mut visited = Vec::new();
|
|
112
|
+
let result = scan.run(&plan, |path, _, _, _| {
|
|
113
|
+
visited.push(path.file_name().unwrap().to_string_lossy().into_owned());
|
|
114
|
+
Ok(ScanControl::Continue)
|
|
115
|
+
});
|
|
116
|
+
assert!(result.complete, "{:?}", result.reason);
|
|
117
|
+
assert_eq!(result.selected_sources, 2);
|
|
118
|
+
assert_eq!(result.available_sources, 2);
|
|
119
|
+
assert!(result.progress.discovery_entries <= 6);
|
|
120
|
+
visited.sort();
|
|
121
|
+
assert_eq!(visited, ["first.jsonl", "second.jsonl"]);
|
|
122
|
+
}
|
|
123
|
+
|
|
88
124
|
#[test]
|
|
89
125
|
fn explicit_paths_keep_their_order() {
|
|
90
126
|
let fixture = Fixture::new();
|