cc-transcript 6.0.0__tar.gz → 7.0.1__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 (64) hide show
  1. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/PKG-INFO +2 -2
  2. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/extract/correct.py +4 -3
  3. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/judge/__init__.py +1 -1
  4. cc_transcript-7.0.1/cc_transcript/judge/llm.py +62 -0
  5. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/pyproject.toml +2 -2
  6. cc_transcript-6.0.0/cc_transcript/judge/llm.py +0 -99
  7. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/Cargo.lock +0 -0
  8. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/Cargo.toml +0 -0
  9. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/LICENSE +0 -0
  10. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/README.md +0 -0
  11. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/__init__.py +0 -0
  12. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/__main__.py +0 -0
  13. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/_parser_rs.pyi +0 -0
  14. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/activity.py +0 -0
  15. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/backend.py +0 -0
  16. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/builders.py +0 -0
  17. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/cli.py +0 -0
  18. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/context.py +0 -0
  19. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/corrections.py +0 -0
  20. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/corrections_cli.py +0 -0
  21. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/cost.py +0 -0
  22. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/decisions.py +0 -0
  23. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/discovery.py +0 -0
  24. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/disktruth.py +0 -0
  25. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/evidence.py +0 -0
  26. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/extract/__init__.py +0 -0
  27. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/filterspec.py +0 -0
  28. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/ids.py +0 -0
  29. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/judge/verdicts.py +0 -0
  30. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/messages.py +0 -0
  31. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/__init__.py +0 -0
  32. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/candidates.py +0 -0
  33. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/confidence.py +0 -0
  34. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/engine.py +0 -0
  35. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/filterspec.py +0 -0
  36. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/formats.py +0 -0
  37. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/signals.py +0 -0
  38. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/sourcekind.py +0 -0
  39. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/spec.py +0 -0
  40. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/mining/store.py +0 -0
  41. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/models.py +0 -0
  42. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/parser.py +0 -0
  43. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/py.typed +0 -0
  44. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/query.py +0 -0
  45. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/render.py +0 -0
  46. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/rust.py +0 -0
  47. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/sentiment/__init__.py +0 -0
  48. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/sentiment/buckets.py +0 -0
  49. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/sentiment/engine.py +0 -0
  50. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/sentiment/lexicon.py +0 -0
  51. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/sentiment/scorespec.py +0 -0
  52. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/store.py +0 -0
  53. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/cc_transcript/tools.py +0 -0
  54. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/Cargo.toml +0 -0
  55. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/data/afinn-en-165.tsv +0 -0
  56. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/data/domain_overrides.tsv +0 -0
  57. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/src/event.rs +0 -0
  58. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/src/filter.rs +0 -0
  59. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/src/lexicon.rs +0 -0
  60. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/src/lib.rs +0 -0
  61. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/src/mining.rs +0 -0
  62. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/src/model.rs +0 -0
  63. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/src/score.rs +0 -0
  64. {cc_transcript-6.0.0 → cc_transcript-7.0.1}/rust/src/value.rs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cc-transcript
3
- Version: 6.0.0
3
+ Version: 7.0.1
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -16,7 +16,7 @@ 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: spawnllm>=0.4.0 ; extra == 'llm'
19
+ Requires-Dist: spawnllm>=0.5.1,<0.6 ; extra == 'llm'
20
20
  Requires-Dist: spacy>=3.8 ; extra == 'sentiment'
21
21
  Requires-Dist: afinn>=0.1 ; extra == 'sentiment'
22
22
  Provides-Extra: dev
@@ -25,7 +25,6 @@ import anyio.to_thread
25
25
  from pydantic import BaseModel
26
26
 
27
27
  from cc_transcript.evidence import GitFix, harvest_pairs, lower_pair
28
- from cc_transcript.judge.llm import run_structured_on
29
28
  from cc_transcript.render import Budget, hunk_lines
30
29
 
31
30
  if TYPE_CHECKING:
@@ -138,10 +137,12 @@ def usable_backend() -> LlmBackend | None:
138
137
  async def choose_pair(
139
138
  pairs: Sequence[CandidatePair], *, feedback: str, anchor_turn: int, tier: TModel, backend: LlmBackend | None
140
139
  ) -> CandidatePair | None:
140
+ from spawnllm import extract
141
+
141
142
  if backend is None:
142
143
  return max(pairs, key=lambda pair: pair.overlap)
143
- pick = await run_structured_on(
144
- backend, build_pick_prompt(feedback, pairs, anchor_turn=anchor_turn), response_model=CorrectionPick, tier=tier
144
+ pick = await extract(
145
+ build_pick_prompt(feedback, pairs, anchor_turn=anchor_turn), CorrectionPick, backend=backend, model=tier
145
146
  )
146
147
  return pairs[pick.candidate - 1] if pick.candidate is not None and 1 <= pick.candidate <= len(pairs) else None
147
148
 
@@ -12,7 +12,7 @@ prompts, the verdict model, and any SQL views over the verdict table.
12
12
 
13
13
  from __future__ import annotations
14
14
 
15
- from cc_transcript.judge.llm import resolved_model, run_structured, run_structured_on, structured_judge
15
+ from cc_transcript.judge.llm import default_backend, resolved_model, structured_judge
16
16
  from cc_transcript.judge.verdicts import (
17
17
  AuditEstimate,
18
18
  AuditSample,
@@ -0,0 +1,62 @@
1
+ """Headless structured completions via spawnllm's first ready CLI backend.
2
+
3
+ The structured call comes from the shared ``spawnllm`` library;
4
+ :func:`spawnllm.extract` resolves a backend, runs the spawn, and validates the
5
+ response into the model. The backend is whichever of spawnllm's CLIs is
6
+ installed and authenticated (:func:`spawnllm.select_backend`), using the
7
+ caller's existing CLI auth — no API key, no pinned provider. ``spawnllm`` and
8
+ ``pydantic`` load lazily inside each function, so importing the judge package
9
+ needs no extra installed.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ from functools import cache
15
+ from typing import TYPE_CHECKING
16
+
17
+ if TYPE_CHECKING:
18
+ from collections.abc import Awaitable, Callable
19
+
20
+ from pydantic import BaseModel
21
+ from spawnllm import LlmBackend, TModel
22
+
23
+ LLM_TIMEOUT = 180
24
+
25
+
26
+ @cache
27
+ def default_backend() -> LlmBackend:
28
+ """The first installed, authenticated spawnllm backend, cached per process.
29
+
30
+ Raises:
31
+ spawnllm.BackendUnavailable: When no backend is installed and authenticated.
32
+ """
33
+ from spawnllm import select_backend
34
+
35
+ return select_backend()
36
+
37
+
38
+ def resolved_model(tier: TModel) -> str:
39
+ """The concrete model name the active backend runs for an abstract tier.
40
+
41
+ The verdict store keys on this string; it reflects whichever backend
42
+ :func:`spawnllm.select_backend` resolves, so a judged corpus stays coherent
43
+ within one backend environment.
44
+ """
45
+ return default_backend().models[tier]
46
+
47
+
48
+ def structured_judge[M: BaseModel](
49
+ response_model: type[M], *, tier: TModel, timeout: int = LLM_TIMEOUT
50
+ ) -> Callable[[str], Awaitable[M]]:
51
+ """Returns a prompt-to-verdict callable that plugs into :func:`run_verdicts`.
52
+
53
+ Each call runs one structured completion on the cached default backend via
54
+ :func:`spawnllm.extract`, which validates the response into ``response_model``.
55
+
56
+ Example:
57
+ >>> judge = structured_judge(Verdict, tier="medium")
58
+ >>> await run_verdicts(rows, prompt_for, judge, persist, concurrency=8)
59
+ """
60
+ from spawnllm import extract
61
+
62
+ return lambda prompt: extract(prompt, response_model, backend=default_backend(), model=tier, timeout=timeout)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cc-transcript"
3
- version = "6.0.0"
3
+ version = "7.0.1"
4
4
  description = "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."
5
5
  readme = "README.md"
6
6
  license = "PolyForm-Noncommercial-1.0.0"
@@ -46,7 +46,7 @@ sentiment = [
46
46
  "spacy>=3.8",
47
47
  "afinn>=0.1",
48
48
  ]
49
- llm = ["spawnllm>=0.4.0"]
49
+ llm = ["spawnllm>=0.5.1,<0.6"]
50
50
 
51
51
  [project.scripts]
52
52
  cc-transcript = "cc_transcript.cli:cli"
@@ -1,99 +0,0 @@
1
- """Headless structured completions via spawnllm's first ready CLI backend.
2
-
3
- Run dispatch and envelope parsing come from the shared ``spawnllm`` library;
4
- :func:`spawnllm.run` drives the spawn and built-in transient retry. The backend
5
- is whichever of spawnllm's CLIs is installed and authenticated
6
- (:func:`spawnllm.select_backend`), using the caller's existing CLI auth — no API
7
- key, no pinned provider. ``spawnllm`` and ``pydantic`` load lazily inside each
8
- function, so importing the judge package needs no extra installed.
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- from functools import cache
14
- from typing import TYPE_CHECKING, cast
15
-
16
- if TYPE_CHECKING:
17
- from collections.abc import Awaitable, Callable
18
-
19
- from pydantic import BaseModel
20
- from spawnllm import LlmBackend, TModel
21
-
22
- LLM_TIMEOUT = 180
23
-
24
-
25
- @cache
26
- def default_backend() -> LlmBackend:
27
- """The first installed, authenticated spawnllm backend, cached per process.
28
-
29
- Raises:
30
- spawnllm.BackendUnavailable: When no backend is installed and authenticated.
31
- """
32
- from spawnllm import select_backend
33
-
34
- return select_backend()
35
-
36
-
37
- def resolved_model(tier: TModel) -> str:
38
- """The concrete model name the active backend runs for an abstract tier.
39
-
40
- The verdict store keys on this string; it reflects whichever backend
41
- :func:`spawnllm.select_backend` resolves, so a judged corpus stays coherent
42
- within one backend environment.
43
- """
44
- return default_backend().models[tier]
45
-
46
-
47
- async def run_structured_on[M: BaseModel](
48
- backend: LlmBackend, prompt: str, *, response_model: type[M], tier: TModel, timeout: int = LLM_TIMEOUT
49
- ) -> M:
50
- """Runs one structured completion on an explicit ``backend``.
51
-
52
- A caller that resolves a backend once per pass passes it here, so a large pass
53
- probes auth once; :func:`run_structured` is the select-and-run convenience.
54
- :func:`spawnllm.run` retries transient failures with backoff before returning.
55
-
56
- Raises:
57
- subprocess.TimeoutExpired: If the backend CLI outlives ``timeout``.
58
- pydantic.ValidationError: If the response does not match the schema.
59
- """
60
- from spawnllm import RunSpec, run
61
-
62
- rr = await run(
63
- RunSpec(
64
- prompt=prompt,
65
- model=backend.models[tier],
66
- schema=backend.schema_for(response_model),
67
- timeout=timeout,
68
- ),
69
- backend=backend,
70
- )
71
- return cast(M, backend.parse_response(rr.stdout, response_model))
72
-
73
-
74
- async def run_structured[M: BaseModel](
75
- prompt: str, *, response_model: type[M], tier: TModel, timeout: int = LLM_TIMEOUT
76
- ) -> M:
77
- """Runs one structured completion on the first ready backend.
78
-
79
- The prompt is delivered to the CLI and the response forced into
80
- ``response_model``'s JSON schema. Backend selection is cached per process.
81
-
82
- Raises:
83
- spawnllm.BackendUnavailable: If no backend is installed and authenticated.
84
- subprocess.TimeoutExpired: If the backend CLI outlives ``timeout``.
85
- pydantic.ValidationError: If the response does not match the schema.
86
- """
87
- return await run_structured_on(default_backend(), prompt, response_model=response_model, tier=tier, timeout=timeout)
88
-
89
-
90
- def structured_judge[M: BaseModel](
91
- response_model: type[M], *, tier: TModel, timeout: int = LLM_TIMEOUT
92
- ) -> Callable[[str], Awaitable[M]]:
93
- """Returns a prompt-to-verdict callable that plugs into :func:`run_verdicts`.
94
-
95
- Example:
96
- >>> judge = structured_judge(Verdict, tier="medium")
97
- >>> await run_verdicts(rows, prompt_for, judge, persist, concurrency=8)
98
- """
99
- return lambda prompt: run_structured(prompt, response_model=response_model, tier=tier, timeout=timeout)
File without changes
File without changes
File without changes
File without changes