cc-transcript 0.9.0__tar.gz → 3.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/PKG-INFO +10 -10
  2. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/README.md +8 -6
  3. cc_transcript-3.0.0/cc_transcript/__init__.py +570 -0
  4. cc_transcript-3.0.0/cc_transcript/activity.py +329 -0
  5. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/cli.py +98 -2
  6. cc_transcript-3.0.0/cc_transcript/context.py +252 -0
  7. cc_transcript-3.0.0/cc_transcript/corrections.py +231 -0
  8. cc_transcript-3.0.0/cc_transcript/decisions.py +229 -0
  9. cc_transcript-3.0.0/cc_transcript/discovery.py +145 -0
  10. cc_transcript-3.0.0/cc_transcript/disktruth.py +167 -0
  11. cc_transcript-3.0.0/cc_transcript/evidence.py +303 -0
  12. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/filterspec.py +1 -0
  13. cc_transcript-3.0.0/cc_transcript/ids.py +144 -0
  14. cc_transcript-3.0.0/cc_transcript/judge/__init__.py +33 -0
  15. {cc_transcript-0.9.0/cc_transcript/domains/mining → cc_transcript-3.0.0/cc_transcript/judge}/llm.py +1 -1
  16. {cc_transcript-0.9.0/cc_transcript/domains/mining → cc_transcript-3.0.0/cc_transcript/judge}/verdicts.py +42 -12
  17. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/messages.py +3 -3
  18. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/mining/__init__.py +19 -55
  19. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/mining/candidates.py +11 -14
  20. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/mining/confidence.py +1 -8
  21. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/mining/filterspec.py +9 -21
  22. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/mining/signals.py +90 -27
  23. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/mining/store.py +12 -16
  24. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/models.py +20 -5
  25. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/parser.py +3 -3
  26. cc_transcript-3.0.0/cc_transcript/query.py +516 -0
  27. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/render.py +113 -2
  28. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/sentiment/__init__.py +6 -5
  29. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/sentiment/engine.py +3 -3
  30. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/sentiment/scorespec.py +2 -2
  31. cc_transcript-3.0.0/cc_transcript/tools.py +389 -0
  32. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/pyproject.toml +2 -4
  33. cc_transcript-0.9.0/cc_transcript/__init__.py +0 -69
  34. cc_transcript-0.9.0/cc_transcript/discovery.py +0 -72
  35. cc_transcript-0.9.0/cc_transcript/domains/__init__.py +0 -9
  36. cc_transcript-0.9.0/cc_transcript/domains/mining/context.py +0 -217
  37. cc_transcript-0.9.0/cc_transcript/domains/mining/markers.py +0 -11
  38. cc_transcript-0.9.0/cc_transcript/domains/mining/nav.py +0 -90
  39. cc_transcript-0.9.0/cc_transcript/filters.py +0 -109
  40. cc_transcript-0.9.0/cc_transcript/sentiment/__init__.py +0 -39
  41. cc_transcript-0.9.0/cc_transcript/sentiment/buckets.py +0 -17
  42. cc_transcript-0.9.0/cc_transcript/sentiment/lexicon.py +0 -7
  43. cc_transcript-0.9.0/cc_transcript/sentiment/messages.py +0 -13
  44. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/Cargo.lock +0 -0
  45. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/Cargo.toml +0 -0
  46. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/LICENSE +0 -0
  47. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/__main__.py +0 -0
  48. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/_parser_rs.pyi +0 -0
  49. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/backend.py +0 -0
  50. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/builders.py +0 -0
  51. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/mining/formats.py +0 -0
  52. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/mining/sourcekind.py +0 -0
  53. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/py.typed +0 -0
  54. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/rust.py +0 -0
  55. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/sentiment/buckets.py +0 -0
  56. {cc_transcript-0.9.0/cc_transcript/domains → cc_transcript-3.0.0/cc_transcript}/sentiment/lexicon.py +0 -0
  57. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/cc_transcript/store.py +0 -0
  58. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/Cargo.toml +0 -0
  59. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/data/afinn-en-165.tsv +0 -0
  60. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/data/domain_overrides.tsv +0 -0
  61. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/src/event.rs +0 -0
  62. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/src/filter.rs +0 -0
  63. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/src/lexicon.rs +0 -0
  64. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/src/lib.rs +0 -0
  65. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/src/model.rs +0 -0
  66. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/src/score.rs +0 -0
  67. {cc_transcript-0.9.0 → cc_transcript-3.0.0}/rust/src/value.rs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cc-transcript
3
- Version: 0.9.0
3
+ Version: 3.0.0
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -16,16 +16,14 @@ Requires-Dist: orjson>=3.10
16
16
  Requires-Dist: pytest>=8.0 ; extra == 'dev'
17
17
  Requires-Dist: ty>=0.0.44 ; extra == 'dev'
18
18
  Requires-Dist: ruff>=0.8 ; extra == 'dev'
19
- Requires-Dist: cc-transcript[sentiment] ; extra == 'lexicon'
20
19
  Requires-Dist: spawnllm>=0.1.3 ; extra == 'llm'
21
20
  Requires-Dist: spacy>=3.8 ; extra == 'sentiment'
22
21
  Requires-Dist: afinn>=0.1 ; extra == 'sentiment'
23
22
  Provides-Extra: dev
24
- Provides-Extra: lexicon
25
23
  Provides-Extra: llm
26
24
  Provides-Extra: sentiment
27
25
  License-File: LICENSE
28
- Summary: Typed, non-lossy events for Claude Code transcripts: a superset JSONL parser (Rust fast path, Python reference), sentiment and feedback-mining domains, and a transcript-investigation CLI.
26
+ Summary: The Claude Code session-activity platform: a superset JSONL parser (Rust fast path, Python reference), typed tool calls with a cross-language content digest, turns/edits/evidence over one spine, context windows with labeled fidelity, unified decision and correction ledgers, LLM judging, and a transcript-investigation CLI.
29
27
  Keywords: claude-code,claude,anthropic,transcripts,jsonl,parser,cli,agents,sentiment,feedback-mining
30
28
  Author-email: Yasyf Mohamedali <yasyfm@gmail.com>
31
29
  License-Expression: PolyForm-Noncommercial-1.0.0
@@ -39,7 +37,7 @@ Project-URL: Repository, https://github.com/yasyf/cc-transcript
39
37
 
40
38
  # cc-transcript
41
39
 
42
- ![cc-transcript banner](https://github.com/yasyf/cc-transcript/raw/main/docs/assets/readme-banner.png)
40
+ ![cc-transcript banner](https://github.com/yasyf/cc-transcript/raw/main/docs/assets/readme-banner.webp)
43
41
 
44
42
  [![PyPI](https://img.shields.io/pypi/v/cc-transcript.svg)](https://pypi.org/project/cc-transcript/)
45
43
  [![Python](https://img.shields.io/pypi/pyversions/cc-transcript.svg)](https://pypi.org/project/cc-transcript/)
@@ -88,12 +86,11 @@ clean = list(apply_spec(events, spec))
88
86
  ```
89
87
 
90
88
  `NOISE_SPEC` is a ready-made spec for the universal structural noise (system reminders,
91
- local-command output, skill banners). For flag-style filtering, `FilterConfig` is also
92
- available — every rule is off by default, so a bare `FilterConfig()` passes everything through.
89
+ local-command output, skill banners).
93
90
 
94
91
  ## The CLI
95
92
 
96
- Four commands — `list`, `show`, `grep`, `stats` — and every one runs as `uvx cc-transcript ...`, no install step. `list` finds transcripts, newest first:
93
+ Six commands — `list`, `show`, `grep`, `stats`, `slice`, `digest` — and every one runs as `uvx cc-transcript ...`, no install step. `list` finds transcripts, newest first:
97
94
 
98
95
  ```console
99
96
  $ uvx cc-transcript list --limit 3
@@ -145,6 +142,8 @@ $ uvx cc-transcript grep -i "filterspec" --kind user --max-matches 3 ~/.claude/p
145
142
 
146
143
  The output is compact by design — one line per event, hard truncation — so an agent triages a session in a few hundred tokens instead of paging through megabytes of JSONL.
147
144
 
145
+ The last two verbs serve programs, not people: `slice` emits per-tool-call JSONL for a session UUID and time window (the language-neutral bridge cc-review consumes), and `digest` generates and checks the cross-language fixture corpus for the tool-digest contract.
146
+
148
147
  ## Claude Code plugin
149
148
 
150
149
  Install the bundled plugin from inside Claude Code:
@@ -159,10 +158,11 @@ The plugin's skill teaches Claude to answer questions about its own history —
159
158
  ## What problems does this solve?
160
159
 
161
160
  - **One faithful parse.** Anything reading Claude Code transcripts re-implements the same JSONL quirks (str-or-list content, tool results nested two ways, envelope-less mode markers). This is that parser, written once and typed strictly.
162
- - **Non-lossy by design.** The event model is a superset: sidechains, `<synthetic>` turns, thinking blocks, and unrecognized entry types all survive parsing. You decide what to drop, via composable filter specs (`build_spec`) or `FilterConfig`.
161
+ - **Non-lossy by design.** The event model is a superset: sidechains, `<synthetic>` turns, thinking blocks, and unrecognized entry types all survive parsing. You decide what to drop, via composable filter specs (`build_spec`).
163
162
  - **Incremental ingestion.** `FileStateStore` tracks per-file mtimes in SQLite (WAL, safe across concurrent tasks) so re-runs only reparse changed files, and you compose your own writes in the same transaction.
164
163
  - **Two engines, one contract.** A single `Backend` protocol with two implementations: `RustBackend` (PyO3 + rayon) is the default fast path, and `PythonBackend` is the readable reference — parity-asserted against each other. Filter specs are portable, so a spec built in Python runs Rust-side without giving up the fast path.
165
- - **Analysis domains.** `domains.sentiment` scores conversational sentiment per time-bucketed conversation window; `domains.mining` mines transcripts for user feedback detectors, confidence calibration, candidate filtering, and verdicts.
164
+ - **One activity spine.** `SessionActivity` lifts parsed events into turns, typed tool calls, and first-class edits; `ContextWindow` persists `EventRef`s plus labeled previews and hydrates back to full fidelity while the transcript lives; rendering is `Budget`-bounded in exactly one place.
165
+ - **Mining, judging, and sentiment.** `cc_transcript.mining` mines transcripts for user feedback — detectors, confidence calibration, candidate filtering, and the feedback store; `cc_transcript.judge` runs fidelity-aware LLM verdict passes over the mined corpus; `cc_transcript.sentiment` scores conversational sentiment per time-bucketed conversation window.
166
166
  - **Transcript investigation for agents.** The CLI answers "what happened in that session" in a few hundred tokens, which is what makes the Claude Code plugin viable.
167
167
 
168
168
  ## Docs
@@ -1,6 +1,6 @@
1
1
  # cc-transcript
2
2
 
3
- ![cc-transcript banner](https://github.com/yasyf/cc-transcript/raw/main/docs/assets/readme-banner.png)
3
+ ![cc-transcript banner](https://github.com/yasyf/cc-transcript/raw/main/docs/assets/readme-banner.webp)
4
4
 
5
5
  [![PyPI](https://img.shields.io/pypi/v/cc-transcript.svg)](https://pypi.org/project/cc-transcript/)
6
6
  [![Python](https://img.shields.io/pypi/pyversions/cc-transcript.svg)](https://pypi.org/project/cc-transcript/)
@@ -49,12 +49,11 @@ clean = list(apply_spec(events, spec))
49
49
  ```
50
50
 
51
51
  `NOISE_SPEC` is a ready-made spec for the universal structural noise (system reminders,
52
- local-command output, skill banners). For flag-style filtering, `FilterConfig` is also
53
- available — every rule is off by default, so a bare `FilterConfig()` passes everything through.
52
+ local-command output, skill banners).
54
53
 
55
54
  ## The CLI
56
55
 
57
- Four commands — `list`, `show`, `grep`, `stats` — and every one runs as `uvx cc-transcript ...`, no install step. `list` finds transcripts, newest first:
56
+ Six commands — `list`, `show`, `grep`, `stats`, `slice`, `digest` — and every one runs as `uvx cc-transcript ...`, no install step. `list` finds transcripts, newest first:
58
57
 
59
58
  ```console
60
59
  $ uvx cc-transcript list --limit 3
@@ -106,6 +105,8 @@ $ uvx cc-transcript grep -i "filterspec" --kind user --max-matches 3 ~/.claude/p
106
105
 
107
106
  The output is compact by design — one line per event, hard truncation — so an agent triages a session in a few hundred tokens instead of paging through megabytes of JSONL.
108
107
 
108
+ The last two verbs serve programs, not people: `slice` emits per-tool-call JSONL for a session UUID and time window (the language-neutral bridge cc-review consumes), and `digest` generates and checks the cross-language fixture corpus for the tool-digest contract.
109
+
109
110
  ## Claude Code plugin
110
111
 
111
112
  Install the bundled plugin from inside Claude Code:
@@ -120,10 +121,11 @@ The plugin's skill teaches Claude to answer questions about its own history —
120
121
  ## What problems does this solve?
121
122
 
122
123
  - **One faithful parse.** Anything reading Claude Code transcripts re-implements the same JSONL quirks (str-or-list content, tool results nested two ways, envelope-less mode markers). This is that parser, written once and typed strictly.
123
- - **Non-lossy by design.** The event model is a superset: sidechains, `<synthetic>` turns, thinking blocks, and unrecognized entry types all survive parsing. You decide what to drop, via composable filter specs (`build_spec`) or `FilterConfig`.
124
+ - **Non-lossy by design.** The event model is a superset: sidechains, `<synthetic>` turns, thinking blocks, and unrecognized entry types all survive parsing. You decide what to drop, via composable filter specs (`build_spec`).
124
125
  - **Incremental ingestion.** `FileStateStore` tracks per-file mtimes in SQLite (WAL, safe across concurrent tasks) so re-runs only reparse changed files, and you compose your own writes in the same transaction.
125
126
  - **Two engines, one contract.** A single `Backend` protocol with two implementations: `RustBackend` (PyO3 + rayon) is the default fast path, and `PythonBackend` is the readable reference — parity-asserted against each other. Filter specs are portable, so a spec built in Python runs Rust-side without giving up the fast path.
126
- - **Analysis domains.** `domains.sentiment` scores conversational sentiment per time-bucketed conversation window; `domains.mining` mines transcripts for user feedback detectors, confidence calibration, candidate filtering, and verdicts.
127
+ - **One activity spine.** `SessionActivity` lifts parsed events into turns, typed tool calls, and first-class edits; `ContextWindow` persists `EventRef`s plus labeled previews and hydrates back to full fidelity while the transcript lives; rendering is `Budget`-bounded in exactly one place.
128
+ - **Mining, judging, and sentiment.** `cc_transcript.mining` mines transcripts for user feedback — detectors, confidence calibration, candidate filtering, and the feedback store; `cc_transcript.judge` runs fidelity-aware LLM verdict passes over the mined corpus; `cc_transcript.sentiment` scores conversational sentiment per time-bucketed conversation window.
127
129
  - **Transcript investigation for agents.** The CLI answers "what happened in that session" in a few hundred tokens, which is what makes the Claude Code plugin viable.
128
130
 
129
131
  ## Docs
@@ -0,0 +1,570 @@
1
+ """The cc-family session-activity platform.
2
+
3
+ One spine: parse Claude Code transcript JSONL into typed events, lift them
4
+ into a :class:`~cc_transcript.activity.SessionActivity` of turns, tool calls,
5
+ and edits — and every higher capability (context windows, evidence harvest,
6
+ queries, the decision ledger, LLM judging) is a pure function or thin store
7
+ over that spine.
8
+
9
+ The package root is lazy (PEP 562): importing ``cc_transcript.ids`` or
10
+ ``cc_transcript.tools`` pulls the standard library only, so the hook hot path
11
+ pays nothing for the parser or any heavy dependency.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ from importlib import import_module
17
+ from typing import TYPE_CHECKING
18
+
19
+ EXPORTS: dict[str, str] = {
20
+ name: module
21
+ for module, names in {
22
+ "cc_transcript.ids": (
23
+ "EventRef",
24
+ "EventUuid",
25
+ "SessionId",
26
+ "ToolDigest",
27
+ "ToolUseId",
28
+ "canonical_json",
29
+ "tool_digest",
30
+ ),
31
+ "cc_transcript.tools": (
32
+ "TOOL_ALIASES",
33
+ "BashCall",
34
+ "EditCall",
35
+ "EditSpan",
36
+ "ExitPlanModeCall",
37
+ "GlobCall",
38
+ "GrepCall",
39
+ "Hunk",
40
+ "MultiEditCall",
41
+ "NotebookEditCall",
42
+ "OtherCall",
43
+ "ReadCall",
44
+ "SkillCall",
45
+ "TaskCall",
46
+ "TaskCreateCall",
47
+ "TaskUpdateCall",
48
+ "ToolCall",
49
+ "ToolCallBase",
50
+ "ToolInputError",
51
+ "WriteCall",
52
+ "expand_tool_names",
53
+ "file_path_of",
54
+ "hunks_of",
55
+ "parse_tool_call",
56
+ "tool_name_matches",
57
+ ),
58
+ "cc_transcript.models": (
59
+ "AssistantEvent",
60
+ "CcVersion",
61
+ "ContentBlock",
62
+ "EntryMeta",
63
+ "ModeEvent",
64
+ "OtherEvent",
65
+ "SystemEvent",
66
+ "TextBlock",
67
+ "ThinkingBlock",
68
+ "ToolResultBlock",
69
+ "ToolUseBlock",
70
+ "TranscriptEvent",
71
+ "UserEvent",
72
+ ),
73
+ "cc_transcript.parser": (
74
+ "TranscriptParser",
75
+ "parse_event",
76
+ "parse_events_async",
77
+ "parse_events_from_bytes",
78
+ ),
79
+ "cc_transcript.backend": ("Backend", "ParsedTranscript"),
80
+ "cc_transcript.discovery": (
81
+ "CLAUDE_PROJECTS_DIR",
82
+ "TranscriptDiscovery",
83
+ "TranscriptExpiredError",
84
+ "find_transcript",
85
+ "find_transcript_sync",
86
+ "subagent_paths",
87
+ ),
88
+ "cc_transcript.activity": (
89
+ "Edit",
90
+ "SessionActivity",
91
+ "ToolUse",
92
+ "Turn",
93
+ "UserClassifier",
94
+ "hunk_overlap",
95
+ "native_user_classifier",
96
+ ),
97
+ "cc_transcript.evidence": (
98
+ "EXTRACTOR_VERSION",
99
+ "CandidatePair",
100
+ "GitFix",
101
+ "git_corrections",
102
+ "harvest_pairs",
103
+ "match_corrections",
104
+ "record_harvest",
105
+ ),
106
+ "cc_transcript.corrections": (
107
+ "CORRECTIONS_DDL",
108
+ "Correction",
109
+ "CorrectionLog",
110
+ "Origin",
111
+ ),
112
+ "cc_transcript.context": (
113
+ "ContextWindow",
114
+ "Fidelity",
115
+ "HydratedWindow",
116
+ "SchemaError",
117
+ "TurnRef",
118
+ "capture_window",
119
+ ),
120
+ "cc_transcript.render": ("Budget", "render_session", "render_tool_call", "render_turn"),
121
+ "cc_transcript.query": ("FileRef", "Session", "SubagentIndex", "SubagentSession", "ToolCallQuery"),
122
+ "cc_transcript.decisions": ("DECISIONS_DDL", "Action", "Decision", "DecisionLog"),
123
+ "cc_transcript.disktruth": (
124
+ "AttributionRange",
125
+ "DiskTruth",
126
+ "FileAttribution",
127
+ "TreeTurn",
128
+ "export_activity",
129
+ "load_export",
130
+ ),
131
+ "cc_transcript.filterspec": (
132
+ "ASSISTANTS",
133
+ "INTERRUPT_MARKER_RE",
134
+ "JUNK_USER_MESSAGE_RE",
135
+ "RESUME_PHRASE_SET",
136
+ "STOP_HOOK_RE",
137
+ "STRUCTURAL_NOISE_RE",
138
+ "TRIVIAL_ACK_SET",
139
+ "USERS",
140
+ "FilterSpec",
141
+ "annotate_spec",
142
+ "apply_spec",
143
+ "keep",
144
+ "labels_for",
145
+ ),
146
+ "cc_transcript.builders": (
147
+ "NOISE_SPEC",
148
+ "build_spec",
149
+ "drop_compacted",
150
+ "drop_empty",
151
+ "drop_entrypoints",
152
+ "drop_junk",
153
+ "drop_meta_flag",
154
+ "drop_phrases",
155
+ "drop_short",
156
+ "drop_sidechain",
157
+ "drop_synthetic",
158
+ "keep_only",
159
+ ),
160
+ "cc_transcript.messages": (
161
+ "AssistantMessage",
162
+ "BaseMessage",
163
+ "MessageToolCall",
164
+ "TranscriptMessage",
165
+ "UserMessage",
166
+ ),
167
+ "cc_transcript.store": ("FileStateStore",),
168
+ }.items()
169
+ for name in names
170
+ }
171
+
172
+
173
+ def __getattr__(name: str) -> object:
174
+ if module := EXPORTS.get(name):
175
+ return getattr(import_module(module), name)
176
+ raise AttributeError(f"module 'cc_transcript' has no attribute {name!r}")
177
+
178
+
179
+ def __dir__() -> list[str]:
180
+ return sorted(EXPORTS)
181
+
182
+
183
+ if TYPE_CHECKING:
184
+ from cc_transcript.activity import (
185
+ Edit as Edit,
186
+ )
187
+ from cc_transcript.activity import (
188
+ SessionActivity as SessionActivity,
189
+ )
190
+ from cc_transcript.activity import (
191
+ ToolUse as ToolUse,
192
+ )
193
+ from cc_transcript.activity import (
194
+ Turn as Turn,
195
+ )
196
+ from cc_transcript.activity import (
197
+ UserClassifier as UserClassifier,
198
+ )
199
+ from cc_transcript.activity import (
200
+ hunk_overlap as hunk_overlap,
201
+ )
202
+ from cc_transcript.activity import (
203
+ native_user_classifier as native_user_classifier,
204
+ )
205
+ from cc_transcript.backend import Backend as Backend
206
+ from cc_transcript.backend import ParsedTranscript as ParsedTranscript
207
+ from cc_transcript.builders import (
208
+ NOISE_SPEC as NOISE_SPEC,
209
+ )
210
+ from cc_transcript.builders import (
211
+ build_spec as build_spec,
212
+ )
213
+ from cc_transcript.builders import (
214
+ drop_compacted as drop_compacted,
215
+ )
216
+ from cc_transcript.builders import (
217
+ drop_empty as drop_empty,
218
+ )
219
+ from cc_transcript.builders import (
220
+ drop_entrypoints as drop_entrypoints,
221
+ )
222
+ from cc_transcript.builders import (
223
+ drop_junk as drop_junk,
224
+ )
225
+ from cc_transcript.builders import (
226
+ drop_meta_flag as drop_meta_flag,
227
+ )
228
+ from cc_transcript.builders import (
229
+ drop_phrases as drop_phrases,
230
+ )
231
+ from cc_transcript.builders import (
232
+ drop_short as drop_short,
233
+ )
234
+ from cc_transcript.builders import (
235
+ drop_sidechain as drop_sidechain,
236
+ )
237
+ from cc_transcript.builders import (
238
+ drop_synthetic as drop_synthetic,
239
+ )
240
+ from cc_transcript.builders import (
241
+ keep_only as keep_only,
242
+ )
243
+ from cc_transcript.context import (
244
+ ContextWindow as ContextWindow,
245
+ )
246
+ from cc_transcript.context import (
247
+ Fidelity as Fidelity,
248
+ )
249
+ from cc_transcript.context import (
250
+ HydratedWindow as HydratedWindow,
251
+ )
252
+ from cc_transcript.context import (
253
+ SchemaError as SchemaError,
254
+ )
255
+ from cc_transcript.context import (
256
+ TurnRef as TurnRef,
257
+ )
258
+ from cc_transcript.context import (
259
+ capture_window as capture_window,
260
+ )
261
+ from cc_transcript.corrections import (
262
+ CORRECTIONS_DDL as CORRECTIONS_DDL,
263
+ )
264
+ from cc_transcript.corrections import (
265
+ Correction as Correction,
266
+ )
267
+ from cc_transcript.corrections import (
268
+ CorrectionLog as CorrectionLog,
269
+ )
270
+ from cc_transcript.corrections import (
271
+ Origin as Origin,
272
+ )
273
+ from cc_transcript.decisions import (
274
+ DECISIONS_DDL as DECISIONS_DDL,
275
+ )
276
+ from cc_transcript.decisions import (
277
+ Action as Action,
278
+ )
279
+ from cc_transcript.decisions import (
280
+ Decision as Decision,
281
+ )
282
+ from cc_transcript.decisions import (
283
+ DecisionLog as DecisionLog,
284
+ )
285
+ from cc_transcript.discovery import (
286
+ CLAUDE_PROJECTS_DIR as CLAUDE_PROJECTS_DIR,
287
+ )
288
+ from cc_transcript.discovery import (
289
+ TranscriptDiscovery as TranscriptDiscovery,
290
+ )
291
+ from cc_transcript.discovery import (
292
+ TranscriptExpiredError as TranscriptExpiredError,
293
+ )
294
+ from cc_transcript.discovery import (
295
+ find_transcript as find_transcript,
296
+ )
297
+ from cc_transcript.discovery import (
298
+ find_transcript_sync as find_transcript_sync,
299
+ )
300
+ from cc_transcript.discovery import (
301
+ subagent_paths as subagent_paths,
302
+ )
303
+ from cc_transcript.disktruth import (
304
+ AttributionRange as AttributionRange,
305
+ )
306
+ from cc_transcript.disktruth import (
307
+ DiskTruth as DiskTruth,
308
+ )
309
+ from cc_transcript.disktruth import (
310
+ FileAttribution as FileAttribution,
311
+ )
312
+ from cc_transcript.disktruth import (
313
+ TreeTurn as TreeTurn,
314
+ )
315
+ from cc_transcript.disktruth import (
316
+ export_activity as export_activity,
317
+ )
318
+ from cc_transcript.disktruth import (
319
+ load_export as load_export,
320
+ )
321
+ from cc_transcript.evidence import (
322
+ EXTRACTOR_VERSION as EXTRACTOR_VERSION,
323
+ )
324
+ from cc_transcript.evidence import (
325
+ CandidatePair as CandidatePair,
326
+ )
327
+ from cc_transcript.evidence import (
328
+ GitFix as GitFix,
329
+ )
330
+ from cc_transcript.evidence import (
331
+ git_corrections as git_corrections,
332
+ )
333
+ from cc_transcript.evidence import (
334
+ harvest_pairs as harvest_pairs,
335
+ )
336
+ from cc_transcript.evidence import (
337
+ match_corrections as match_corrections,
338
+ )
339
+ from cc_transcript.evidence import (
340
+ record_harvest as record_harvest,
341
+ )
342
+ from cc_transcript.filterspec import (
343
+ ASSISTANTS as ASSISTANTS,
344
+ )
345
+ from cc_transcript.filterspec import (
346
+ INTERRUPT_MARKER_RE as INTERRUPT_MARKER_RE,
347
+ )
348
+ from cc_transcript.filterspec import (
349
+ JUNK_USER_MESSAGE_RE as JUNK_USER_MESSAGE_RE,
350
+ )
351
+ from cc_transcript.filterspec import (
352
+ RESUME_PHRASE_SET as RESUME_PHRASE_SET,
353
+ )
354
+ from cc_transcript.filterspec import (
355
+ STOP_HOOK_RE as STOP_HOOK_RE,
356
+ )
357
+ from cc_transcript.filterspec import (
358
+ STRUCTURAL_NOISE_RE as STRUCTURAL_NOISE_RE,
359
+ )
360
+ from cc_transcript.filterspec import (
361
+ TRIVIAL_ACK_SET as TRIVIAL_ACK_SET,
362
+ )
363
+ from cc_transcript.filterspec import (
364
+ USERS as USERS,
365
+ )
366
+ from cc_transcript.filterspec import (
367
+ FilterSpec as FilterSpec,
368
+ )
369
+ from cc_transcript.filterspec import (
370
+ annotate_spec as annotate_spec,
371
+ )
372
+ from cc_transcript.filterspec import (
373
+ apply_spec as apply_spec,
374
+ )
375
+ from cc_transcript.filterspec import (
376
+ keep as keep,
377
+ )
378
+ from cc_transcript.filterspec import (
379
+ labels_for as labels_for,
380
+ )
381
+ from cc_transcript.ids import (
382
+ EventRef as EventRef,
383
+ )
384
+ from cc_transcript.ids import (
385
+ EventUuid as EventUuid,
386
+ )
387
+ from cc_transcript.ids import (
388
+ SessionId as SessionId,
389
+ )
390
+ from cc_transcript.ids import (
391
+ ToolDigest as ToolDigest,
392
+ )
393
+ from cc_transcript.ids import (
394
+ ToolUseId as ToolUseId,
395
+ )
396
+ from cc_transcript.ids import (
397
+ canonical_json as canonical_json,
398
+ )
399
+ from cc_transcript.ids import (
400
+ tool_digest as tool_digest,
401
+ )
402
+ from cc_transcript.messages import (
403
+ AssistantMessage as AssistantMessage,
404
+ )
405
+ from cc_transcript.messages import (
406
+ BaseMessage as BaseMessage,
407
+ )
408
+ from cc_transcript.messages import (
409
+ MessageToolCall as MessageToolCall,
410
+ )
411
+ from cc_transcript.messages import (
412
+ TranscriptMessage as TranscriptMessage,
413
+ )
414
+ from cc_transcript.messages import (
415
+ UserMessage as UserMessage,
416
+ )
417
+ from cc_transcript.models import (
418
+ AssistantEvent as AssistantEvent,
419
+ )
420
+ from cc_transcript.models import (
421
+ CcVersion as CcVersion,
422
+ )
423
+ from cc_transcript.models import (
424
+ ContentBlock as ContentBlock,
425
+ )
426
+ from cc_transcript.models import (
427
+ EntryMeta as EntryMeta,
428
+ )
429
+ from cc_transcript.models import (
430
+ ModeEvent as ModeEvent,
431
+ )
432
+ from cc_transcript.models import (
433
+ OtherEvent as OtherEvent,
434
+ )
435
+ from cc_transcript.models import (
436
+ SystemEvent as SystemEvent,
437
+ )
438
+ from cc_transcript.models import (
439
+ TextBlock as TextBlock,
440
+ )
441
+ from cc_transcript.models import (
442
+ ThinkingBlock as ThinkingBlock,
443
+ )
444
+ from cc_transcript.models import (
445
+ ToolResultBlock as ToolResultBlock,
446
+ )
447
+ from cc_transcript.models import (
448
+ ToolUseBlock as ToolUseBlock,
449
+ )
450
+ from cc_transcript.models import (
451
+ TranscriptEvent as TranscriptEvent,
452
+ )
453
+ from cc_transcript.models import (
454
+ UserEvent as UserEvent,
455
+ )
456
+ from cc_transcript.parser import (
457
+ TranscriptParser as TranscriptParser,
458
+ )
459
+ from cc_transcript.parser import (
460
+ parse_event as parse_event,
461
+ )
462
+ from cc_transcript.parser import (
463
+ parse_events_async as parse_events_async,
464
+ )
465
+ from cc_transcript.parser import (
466
+ parse_events_from_bytes as parse_events_from_bytes,
467
+ )
468
+ from cc_transcript.query import (
469
+ FileRef as FileRef,
470
+ )
471
+ from cc_transcript.query import (
472
+ Session as Session,
473
+ )
474
+ from cc_transcript.query import (
475
+ SubagentIndex as SubagentIndex,
476
+ )
477
+ from cc_transcript.query import (
478
+ SubagentSession as SubagentSession,
479
+ )
480
+ from cc_transcript.query import (
481
+ ToolCallQuery as ToolCallQuery,
482
+ )
483
+ from cc_transcript.render import (
484
+ Budget as Budget,
485
+ )
486
+ from cc_transcript.render import (
487
+ render_session as render_session,
488
+ )
489
+ from cc_transcript.render import (
490
+ render_tool_call as render_tool_call,
491
+ )
492
+ from cc_transcript.render import (
493
+ render_turn as render_turn,
494
+ )
495
+ from cc_transcript.store import FileStateStore as FileStateStore
496
+ from cc_transcript.tools import (
497
+ TOOL_ALIASES as TOOL_ALIASES,
498
+ )
499
+ from cc_transcript.tools import (
500
+ BashCall as BashCall,
501
+ )
502
+ from cc_transcript.tools import (
503
+ EditCall as EditCall,
504
+ )
505
+ from cc_transcript.tools import (
506
+ EditSpan as EditSpan,
507
+ )
508
+ from cc_transcript.tools import (
509
+ ExitPlanModeCall as ExitPlanModeCall,
510
+ )
511
+ from cc_transcript.tools import (
512
+ GlobCall as GlobCall,
513
+ )
514
+ from cc_transcript.tools import (
515
+ GrepCall as GrepCall,
516
+ )
517
+ from cc_transcript.tools import (
518
+ Hunk as Hunk,
519
+ )
520
+ from cc_transcript.tools import (
521
+ MultiEditCall as MultiEditCall,
522
+ )
523
+ from cc_transcript.tools import (
524
+ NotebookEditCall as NotebookEditCall,
525
+ )
526
+ from cc_transcript.tools import (
527
+ OtherCall as OtherCall,
528
+ )
529
+ from cc_transcript.tools import (
530
+ ReadCall as ReadCall,
531
+ )
532
+ from cc_transcript.tools import (
533
+ SkillCall as SkillCall,
534
+ )
535
+ from cc_transcript.tools import (
536
+ TaskCall as TaskCall,
537
+ )
538
+ from cc_transcript.tools import (
539
+ TaskCreateCall as TaskCreateCall,
540
+ )
541
+ from cc_transcript.tools import (
542
+ TaskUpdateCall as TaskUpdateCall,
543
+ )
544
+ from cc_transcript.tools import (
545
+ ToolCall as ToolCall,
546
+ )
547
+ from cc_transcript.tools import (
548
+ ToolCallBase as ToolCallBase,
549
+ )
550
+ from cc_transcript.tools import (
551
+ ToolInputError as ToolInputError,
552
+ )
553
+ from cc_transcript.tools import (
554
+ WriteCall as WriteCall,
555
+ )
556
+ from cc_transcript.tools import (
557
+ expand_tool_names as expand_tool_names,
558
+ )
559
+ from cc_transcript.tools import (
560
+ file_path_of as file_path_of,
561
+ )
562
+ from cc_transcript.tools import (
563
+ hunks_of as hunks_of,
564
+ )
565
+ from cc_transcript.tools import (
566
+ parse_tool_call as parse_tool_call,
567
+ )
568
+ from cc_transcript.tools import (
569
+ tool_name_matches as tool_name_matches,
570
+ )