cjm-transcript-decomp-core 0.0.9__tar.gz → 0.0.20__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.
- {cjm_transcript_decomp_core-0.0.9/cjm_transcript_decomp_core.egg-info → cjm_transcript_decomp_core-0.0.20}/PKG-INFO +63 -6
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/README.md +59 -3
- cjm_transcript_decomp_core-0.0.20/cjm_transcript_decomp_core/__init__.py +1 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core/alignment.py +50 -2
- cjm_transcript_decomp_core-0.0.20/cjm_transcript_decomp_core/cli.py +745 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core/graph.py +67 -5
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core/models.py +7 -1
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core/pipeline.py +108 -23
- cjm_transcript_decomp_core-0.0.20/cjm_transcript_decomp_core/respine.py +738 -0
- cjm_transcript_decomp_core-0.0.20/cjm_transcript_decomp_core/retire.py +531 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core/runs.py +19 -5
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20/cjm_transcript_decomp_core.egg-info}/PKG-INFO +63 -6
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core.egg-info/SOURCES.txt +5 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core.egg-info/requires.txt +3 -2
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/pyproject.toml +1 -1
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/tests/test_alignment.py +38 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/tests/test_batch_logic.py +21 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/tests/test_cli.py +14 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/tests/test_graph.py +73 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/tests/test_pipeline.py +85 -0
- cjm_transcript_decomp_core-0.0.20/tests/test_prompt_slots.py +25 -0
- cjm_transcript_decomp_core-0.0.20/tests/test_respine.py +293 -0
- cjm_transcript_decomp_core-0.0.20/tests/test_retire.py +245 -0
- cjm_transcript_decomp_core-0.0.9/cjm_transcript_decomp_core/__init__.py +0 -1
- cjm_transcript_decomp_core-0.0.9/cjm_transcript_decomp_core/cli.py +0 -266
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/LICENSE +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/MANIFEST.in +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core/discovery.py +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core/launch.py +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core/segments.py +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core/state.py +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core.egg-info/dependency_links.txt +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core.egg-info/entry_points.txt +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/cjm_transcript_decomp_core.egg-info/top_level.txt +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/setup.cfg +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/tests/test_models.py +0 -0
- {cjm_transcript_decomp_core-0.0.9 → cjm_transcript_decomp_core-0.0.20}/tests/test_segment_logic.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cjm-transcript-decomp-core
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.20
|
|
4
4
|
Summary: A frontend-agnostic core for the transcript decomposition workflow — composes isolated capability workers (forced alignment, VAD, graph storage) into a headless pipeline that decomposes transcription run manifests into a VAD-aligned context-graph spine with traceable provenance, and a CLI as its first driver.
|
|
5
5
|
Author-email: "Christian J. Mills" <9126128+cj-mills@users.noreply.github.com>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -14,8 +14,9 @@ Requires-Dist: cjm_substrate>=0.0.63
|
|
|
14
14
|
Requires-Dist: pyyaml
|
|
15
15
|
Requires-Dist: cjm_context_graph_primitives>=0.0.15
|
|
16
16
|
Requires-Dist: cjm_capability_primitives>=0.0.11
|
|
17
|
-
Requires-Dist: cjm-context-graph-layer>=0.0.
|
|
18
|
-
Requires-Dist: cjm-transcript-graph-schema>=0.0.
|
|
17
|
+
Requires-Dist: cjm-context-graph-layer>=0.0.13
|
|
18
|
+
Requires-Dist: cjm-transcript-graph-schema>=0.0.11
|
|
19
|
+
Requires-Dist: cjm-transcription-core>=0.0.21
|
|
19
20
|
Dynamic: license-file
|
|
20
21
|
|
|
21
22
|
# cjm-transcript-decomp-core
|
|
@@ -26,7 +27,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
26
27
|
|
|
27
28
|
## Modules
|
|
28
29
|
|
|
29
|
-
- **`cjm_transcript_decomp_core`**
|
|
30
|
+
- **`cjm_transcript_decomp_core.__init__`**
|
|
30
31
|
- **`cjm_transcript_decomp_core.alignment`** — Pure forced-alignment logic (no capability calls): map FA words back to character spans in the original text, assign words to VAD chunks by timestamp, and build one text segment per VAD chunk. Extracted from the page-centric ForcedAlignmentService (Tier-1 logic).
|
|
31
32
|
- **`cjm_transcript_decomp_core.cli`** — The CLI driver — the decomposition core's first (and currently only) frontend.
|
|
32
33
|
- **`cjm_transcript_decomp_core.discovery`** — Capability-role discovery by manifest surface match — the journaling-by-
|
|
@@ -34,6 +35,8 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
34
35
|
- **`cjm_transcript_decomp_core.launch`** — The shared launch surface every decomp shell drives through: the argument
|
|
35
36
|
- **`cjm_transcript_decomp_core.models`** — Lean data shapes for the transcript-decomposition pipeline: in-core mirrors of the forced-alignment / VAD / text DTOs (no FastHTML deps), run configuration, the committed graph-segment carrier, and the decomposition run manifest (proto-bundle).
|
|
36
37
|
- **`cjm_transcript_decomp_core.pipeline`** — The headless decomposition pipeline (stage 5: decomp is an EXTENDER). Load a transcription run manifest, verify the transcription-emitted graph root exists (the graph begins at transcription), then per source per pipeline-segment run VAD + per-transcriber forced alignment, build one aligned segment per VAD chunk with per-transcriber text variants, and attach the fine spine under the existing AudioSegment nodes via the layer's idempotent extend_graph — with HITL approval seams between alignment, commit, and the next source.
|
|
38
|
+
- **`cjm_transcript_decomp_core.respine`** — Chunk RESPINE — re-derive ONE coarse chunk of a LIVE spine from a landed external transcript (work item 7a5e9c84; design ruling 0b4d5cfa, amendment 4a7ec4f8).
|
|
39
|
+
- **`cjm_transcript_decomp_core.retire`** — Spine RETIREMENT + COMPACTION — safe removal of superseded decomposition spines (ruling a7617bd4, item eaefebd2).
|
|
37
40
|
- **`cjm_transcript_decomp_core.runs`** — Run-manifest indexes for the decomp-batch TUI (work item 0ff6bf0f): the
|
|
38
41
|
- **`cjm_transcript_decomp_core.segments`** — Fine-segment inspection for the decomp TUI (work item 166dd2b8, half a):
|
|
39
42
|
- **`cjm_transcript_decomp_core.state`** — Sidecar TUI state: last-used batch settings persisted across sessions (the
|
|
@@ -45,7 +48,9 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
45
48
|
- `assign_words_to_chunks` _function_ — Assign each FA word to a VAD chunk by timestamp overlap.
|
|
46
49
|
- `build_segments_from_alignment` _function_ — Build a TextSegment per VAD chunk by grouping words by chunk assignment.
|
|
47
50
|
- `carve_chunks_at_event_spans` _function_ — The event-carve stage (EVENT_SPLIT_POLICY, respine trial DEC 6cc10fb7):
|
|
51
|
+
- `collapse_newlines` _function_ — The stored-text form of a slice that still holds a newline: a retained
|
|
48
52
|
- `map_fa_words_to_text` _function_ — Map forced-alignment words back to character spans in the original text.
|
|
53
|
+
- `normalize_external_text` _function_ — Offset-preserving fold-input normalisation for EXTERNAL variants (finding
|
|
49
54
|
- `rescue_gap_words` _function_ — The word-rescue stage (WORD_RESCUE_POLICY, 96edc646 verdict bc7ece7b):
|
|
50
55
|
- `sentence_end_word_indices` _function_ — Map capability-delivered sentence boundaries onto FA words (B.5: the
|
|
51
56
|
- `split_chunks_at_sentence_gaps` _function_ — The sentence-split stage (SENTENCE_SPLIT_POLICY, DEC f1024568): refine the
|
|
@@ -53,10 +58,13 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
53
58
|
|
|
54
59
|
### `cjm_transcript_decomp_core.cli`
|
|
55
60
|
|
|
61
|
+
- `backfill_provenance_command` _function_ — Execute `backfill-provenance`: mint the Segment -> Transcript DERIVED_FROM
|
|
56
62
|
- `build_parser` _function_ — Build the CLI parser (subcommands: run).
|
|
57
63
|
- `load_capabilities` _function_ — Discover manifests + load each requested capability (default instance).
|
|
58
64
|
- `main` _function_ — CLI entry point (console script: `cjm-transcript-decomp-core`).
|
|
65
|
+
- `respine_chunk_command` _function_ — Execute `respine-chunk` (work item 7a5e9c84, ruling 0b4d5cfa; the machinery lives
|
|
59
66
|
- `run_command` _function_ — Execute the `run` subcommand: extend transcription-run manifest(s) with the fine spine.
|
|
67
|
+
- `spine_command` _function_ — The spine retirement + compaction verbs (ruling a7617bd4; the machinery lives in
|
|
60
68
|
|
|
61
69
|
### `cjm_transcript_decomp_core.discovery`
|
|
62
70
|
|
|
@@ -67,7 +75,9 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
67
75
|
|
|
68
76
|
- `SourceVerification` _class_ — Skeptical-lens verification of one Source's fine-spine extension under a
|
|
69
77
|
- `build_extension_payload` _function_ — Build the fine-spine EXTENSION payload (pure; no capability calls).
|
|
78
|
+
- `provenance_edges_from_segment_wire` _function_ — Derive a Segment's Transcript provenance edges from the node itself:
|
|
70
79
|
- `resolve_root_ids` _function_ — Recompute the transcription-emitted root node ids from manifest data.
|
|
80
|
+
- `segment_provenance_edges` _function_ — Text provenance as EDGES (finding 89b16be6, the references-must-be-edges
|
|
71
81
|
- `verify_source` _function_ — Verify a Source's committed extension via server-side AGGREGATES (D13/D19).
|
|
72
82
|
|
|
73
83
|
### `cjm_transcript_decomp_core.launch`
|
|
@@ -108,6 +118,52 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
108
118
|
- `submit_and_wait` _function_ — Submit one capability job, wait for it, and return its result (raise on failure).
|
|
109
119
|
- `vad_chunks_from_result` _function_ — Normalize a typed VAD result into segment-local VAD chunks.
|
|
110
120
|
|
|
121
|
+
### `cjm_transcript_decomp_core.respine`
|
|
122
|
+
|
|
123
|
+
- `bridge_edges` _function_ — Bridge NEXT from the previous live segment to the new first and from the new
|
|
124
|
+
- `build_respine_op` _function_ — ONE replayed property-update op (pure): superseded_by on the old segments, the
|
|
125
|
+
- `chunk_entry_for` _function_ — Resolve ONE coarse chunk of a source entry (pure): by manifest index, or by
|
|
126
|
+
- `classify_dependents` _function_ — Sort the chunk's dependents into the two transferable classes and the rest
|
|
127
|
+
- `decomp_config_from` _function_ — Rebuild the live spine's DecompConfig from its manifest snapshot (pure): the
|
|
128
|
+
- `describe_dependents` _function_ — The refusal / readout listing (pure).
|
|
129
|
+
- `find_decomp_manifest` _function_ — The decomp run that minted the live spine (pure): the newest manifest whose
|
|
130
|
+
- `live_chunk_segments` _function_ — The chunk's LIVE segments: PART_OF its rendition, on the spine, not superseded.
|
|
131
|
+
- `live_spine_index` _function_ — The whole live spine's (id, index) — the renumber plan's input.
|
|
132
|
+
- `plan_renumber` _function_ — The renumber plan (pure; 0b4d5cfa (4), the 'do it properly' ruling): the new
|
|
133
|
+
- `read_dependents` _function_ — What points at the old segments: every Correction with a CORRECTS edge into
|
|
134
|
+
- `render_chunk_prompt` _function_ — Mode one (--prompt): the chunk's escalation prompt WITH CONTEXT — no writes.
|
|
135
|
+
- `resolve_chunk_context` _function_ — Resolve the live spine -> its decomp manifest -> the transcription manifest it
|
|
136
|
+
- `respine_chunk` _function_ — Mode two (--text-file): land -> re-derive the chunk under the live policy ->
|
|
137
|
+
- `respine_op_id` _function_ — The op id `superseded_by` names: a function of (source, landed transcript).
|
|
138
|
+
- `source_entry_for` _function_ — The transcription manifest's entry for a Source, by recomputed identity (pure).
|
|
139
|
+
- `transfer_handler` _function_ — Discover the correction core's chunk-scoped transfer through the entry-point
|
|
140
|
+
|
|
141
|
+
### `cjm_transcript_decomp_core.retire`
|
|
142
|
+
|
|
143
|
+
- `annotate_spines` _function_ — Mark each spine row with its retirement state (pure; rows copied).
|
|
144
|
+
- `apply_spine_fact` _function_ — Replay handler for spine-retire / spine-compaction / chunk-respine: property merges
|
|
145
|
+
- `compact_retired` _function_ — The compact act over every retired, not-yet-compacted spine of the given sources:
|
|
146
|
+
- `default_live_spine` _function_ — Which spine opens by default (pure). Preference is a DECLARED fact, never creation order:
|
|
147
|
+
- `dependents_free` _function_
|
|
148
|
+
- `dependents_map` _function_ — Every spine's dependents in one raw read (see DEPENDENTS_SQL); a spine absent from
|
|
149
|
+
- `get_source` _function_ — The Source node as a dict (None when absent).
|
|
150
|
+
- `journal_spine_retire` _function_ — Apply + journal one retirement fact (write-side dual of apply_spine_fact).
|
|
151
|
+
- `list_sources` _function_ — Every Source (optionally one collection's members).
|
|
152
|
+
- `list_spines` _function_ — The source's coexisting spines, grouped by skeleton hash and annotated with the retirement map.
|
|
153
|
+
- `live_spines` _function_
|
|
154
|
+
- `plan_retire` _function_ — Rules (a) + successor validation as a pure plan; the graph write is `journal_spine_retire`.
|
|
155
|
+
- `plan_superseded` _function_ — The batch candidate list: every LIVE spine that is not the source's default (rule (c)) —
|
|
156
|
+
- `resolve_source_id` _function_ — Resolve a human selector to ONE Source (refuses with the candidates).
|
|
157
|
+
- `resolve_spine` _function_ — Resolve a picker-style selector to exactly one spine row (pure); refuses with the roster.
|
|
158
|
+
- `retire_spine` _function_ — The whole retire act: list -> plan (rules a) -> dependents gate (rule b) -> journaled fact.
|
|
159
|
+
- `retired_spines` _function_ — The Source's retirement map (pure): {spine key: {reason, successor, actor, ts[, compacted]}}.
|
|
160
|
+
- `source_rendition_ids` _function_ — Every AudioRendition under a Source (all chains — retirement is per skeleton, not per chain).
|
|
161
|
+
- `spine_dependents` _function_ — Rule (b)'s evidence: what on the graph points at the spine's segments.
|
|
162
|
+
- `spine_fact_handlers` _function_
|
|
163
|
+
- `spine_key` _function_
|
|
164
|
+
- `spine_label` _function_
|
|
165
|
+
- `spine_segment_ids` _function_
|
|
166
|
+
|
|
111
167
|
### `cjm_transcript_decomp_core.runs`
|
|
112
168
|
|
|
113
169
|
- `DecompIndex` _class_ — Decomp-core run manifests read back: coverage chips for the batch stage
|
|
@@ -115,6 +171,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
115
171
|
- `SourceRunIndex` _class_ — Transcription-core run manifests — the decomp workflow's SOURCES — plus
|
|
116
172
|
- `TrainingRunIndex` _class_ — Training-run manifests under the workspace training-runs/ dir — the
|
|
117
173
|
- `group_batches` _function_ — Fold an ordered batch selection into headless hand-off groups.
|
|
174
|
+
- `is_external_transcriber` _function_ — Whether a transcriber name is an external landing's (the `/manual` marker).
|
|
118
175
|
|
|
119
176
|
### `cjm_transcript_decomp_core.segments`
|
|
120
177
|
|
|
@@ -140,5 +197,5 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
140
197
|
|
|
141
198
|
## Dependencies
|
|
142
199
|
|
|
143
|
-
**Depends on:** `cjm-capability-primitives`, `cjm-context-graph-layer`, `cjm-context-graph-primitives`, `cjm-substrate`, `cjm-transcript-graph-schema`, `pyyaml`
|
|
144
|
-
**Used by:** `cjm-transcript-
|
|
200
|
+
**Depends on:** `cjm-capability-primitives`, `cjm-context-graph-layer`, `cjm-context-graph-primitives`, `cjm-substrate`, `cjm-transcript-graph-schema`, `cjm-transcription-core`, `pyyaml`
|
|
201
|
+
**Used by:** `cjm-transcript-correction-qt`, `cjm-transcript-decomp-qt`
|
|
@@ -6,7 +6,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
6
6
|
|
|
7
7
|
## Modules
|
|
8
8
|
|
|
9
|
-
- **`cjm_transcript_decomp_core`**
|
|
9
|
+
- **`cjm_transcript_decomp_core.__init__`**
|
|
10
10
|
- **`cjm_transcript_decomp_core.alignment`** — Pure forced-alignment logic (no capability calls): map FA words back to character spans in the original text, assign words to VAD chunks by timestamp, and build one text segment per VAD chunk. Extracted from the page-centric ForcedAlignmentService (Tier-1 logic).
|
|
11
11
|
- **`cjm_transcript_decomp_core.cli`** — The CLI driver — the decomposition core's first (and currently only) frontend.
|
|
12
12
|
- **`cjm_transcript_decomp_core.discovery`** — Capability-role discovery by manifest surface match — the journaling-by-
|
|
@@ -14,6 +14,8 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
14
14
|
- **`cjm_transcript_decomp_core.launch`** — The shared launch surface every decomp shell drives through: the argument
|
|
15
15
|
- **`cjm_transcript_decomp_core.models`** — Lean data shapes for the transcript-decomposition pipeline: in-core mirrors of the forced-alignment / VAD / text DTOs (no FastHTML deps), run configuration, the committed graph-segment carrier, and the decomposition run manifest (proto-bundle).
|
|
16
16
|
- **`cjm_transcript_decomp_core.pipeline`** — The headless decomposition pipeline (stage 5: decomp is an EXTENDER). Load a transcription run manifest, verify the transcription-emitted graph root exists (the graph begins at transcription), then per source per pipeline-segment run VAD + per-transcriber forced alignment, build one aligned segment per VAD chunk with per-transcriber text variants, and attach the fine spine under the existing AudioSegment nodes via the layer's idempotent extend_graph — with HITL approval seams between alignment, commit, and the next source.
|
|
17
|
+
- **`cjm_transcript_decomp_core.respine`** — Chunk RESPINE — re-derive ONE coarse chunk of a LIVE spine from a landed external transcript (work item 7a5e9c84; design ruling 0b4d5cfa, amendment 4a7ec4f8).
|
|
18
|
+
- **`cjm_transcript_decomp_core.retire`** — Spine RETIREMENT + COMPACTION — safe removal of superseded decomposition spines (ruling a7617bd4, item eaefebd2).
|
|
17
19
|
- **`cjm_transcript_decomp_core.runs`** — Run-manifest indexes for the decomp-batch TUI (work item 0ff6bf0f): the
|
|
18
20
|
- **`cjm_transcript_decomp_core.segments`** — Fine-segment inspection for the decomp TUI (work item 166dd2b8, half a):
|
|
19
21
|
- **`cjm_transcript_decomp_core.state`** — Sidecar TUI state: last-used batch settings persisted across sessions (the
|
|
@@ -25,7 +27,9 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
25
27
|
- `assign_words_to_chunks` _function_ — Assign each FA word to a VAD chunk by timestamp overlap.
|
|
26
28
|
- `build_segments_from_alignment` _function_ — Build a TextSegment per VAD chunk by grouping words by chunk assignment.
|
|
27
29
|
- `carve_chunks_at_event_spans` _function_ — The event-carve stage (EVENT_SPLIT_POLICY, respine trial DEC 6cc10fb7):
|
|
30
|
+
- `collapse_newlines` _function_ — The stored-text form of a slice that still holds a newline: a retained
|
|
28
31
|
- `map_fa_words_to_text` _function_ — Map forced-alignment words back to character spans in the original text.
|
|
32
|
+
- `normalize_external_text` _function_ — Offset-preserving fold-input normalisation for EXTERNAL variants (finding
|
|
29
33
|
- `rescue_gap_words` _function_ — The word-rescue stage (WORD_RESCUE_POLICY, 96edc646 verdict bc7ece7b):
|
|
30
34
|
- `sentence_end_word_indices` _function_ — Map capability-delivered sentence boundaries onto FA words (B.5: the
|
|
31
35
|
- `split_chunks_at_sentence_gaps` _function_ — The sentence-split stage (SENTENCE_SPLIT_POLICY, DEC f1024568): refine the
|
|
@@ -33,10 +37,13 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
33
37
|
|
|
34
38
|
### `cjm_transcript_decomp_core.cli`
|
|
35
39
|
|
|
40
|
+
- `backfill_provenance_command` _function_ — Execute `backfill-provenance`: mint the Segment -> Transcript DERIVED_FROM
|
|
36
41
|
- `build_parser` _function_ — Build the CLI parser (subcommands: run).
|
|
37
42
|
- `load_capabilities` _function_ — Discover manifests + load each requested capability (default instance).
|
|
38
43
|
- `main` _function_ — CLI entry point (console script: `cjm-transcript-decomp-core`).
|
|
44
|
+
- `respine_chunk_command` _function_ — Execute `respine-chunk` (work item 7a5e9c84, ruling 0b4d5cfa; the machinery lives
|
|
39
45
|
- `run_command` _function_ — Execute the `run` subcommand: extend transcription-run manifest(s) with the fine spine.
|
|
46
|
+
- `spine_command` _function_ — The spine retirement + compaction verbs (ruling a7617bd4; the machinery lives in
|
|
40
47
|
|
|
41
48
|
### `cjm_transcript_decomp_core.discovery`
|
|
42
49
|
|
|
@@ -47,7 +54,9 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
47
54
|
|
|
48
55
|
- `SourceVerification` _class_ — Skeptical-lens verification of one Source's fine-spine extension under a
|
|
49
56
|
- `build_extension_payload` _function_ — Build the fine-spine EXTENSION payload (pure; no capability calls).
|
|
57
|
+
- `provenance_edges_from_segment_wire` _function_ — Derive a Segment's Transcript provenance edges from the node itself:
|
|
50
58
|
- `resolve_root_ids` _function_ — Recompute the transcription-emitted root node ids from manifest data.
|
|
59
|
+
- `segment_provenance_edges` _function_ — Text provenance as EDGES (finding 89b16be6, the references-must-be-edges
|
|
51
60
|
- `verify_source` _function_ — Verify a Source's committed extension via server-side AGGREGATES (D13/D19).
|
|
52
61
|
|
|
53
62
|
### `cjm_transcript_decomp_core.launch`
|
|
@@ -88,6 +97,52 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
88
97
|
- `submit_and_wait` _function_ — Submit one capability job, wait for it, and return its result (raise on failure).
|
|
89
98
|
- `vad_chunks_from_result` _function_ — Normalize a typed VAD result into segment-local VAD chunks.
|
|
90
99
|
|
|
100
|
+
### `cjm_transcript_decomp_core.respine`
|
|
101
|
+
|
|
102
|
+
- `bridge_edges` _function_ — Bridge NEXT from the previous live segment to the new first and from the new
|
|
103
|
+
- `build_respine_op` _function_ — ONE replayed property-update op (pure): superseded_by on the old segments, the
|
|
104
|
+
- `chunk_entry_for` _function_ — Resolve ONE coarse chunk of a source entry (pure): by manifest index, or by
|
|
105
|
+
- `classify_dependents` _function_ — Sort the chunk's dependents into the two transferable classes and the rest
|
|
106
|
+
- `decomp_config_from` _function_ — Rebuild the live spine's DecompConfig from its manifest snapshot (pure): the
|
|
107
|
+
- `describe_dependents` _function_ — The refusal / readout listing (pure).
|
|
108
|
+
- `find_decomp_manifest` _function_ — The decomp run that minted the live spine (pure): the newest manifest whose
|
|
109
|
+
- `live_chunk_segments` _function_ — The chunk's LIVE segments: PART_OF its rendition, on the spine, not superseded.
|
|
110
|
+
- `live_spine_index` _function_ — The whole live spine's (id, index) — the renumber plan's input.
|
|
111
|
+
- `plan_renumber` _function_ — The renumber plan (pure; 0b4d5cfa (4), the 'do it properly' ruling): the new
|
|
112
|
+
- `read_dependents` _function_ — What points at the old segments: every Correction with a CORRECTS edge into
|
|
113
|
+
- `render_chunk_prompt` _function_ — Mode one (--prompt): the chunk's escalation prompt WITH CONTEXT — no writes.
|
|
114
|
+
- `resolve_chunk_context` _function_ — Resolve the live spine -> its decomp manifest -> the transcription manifest it
|
|
115
|
+
- `respine_chunk` _function_ — Mode two (--text-file): land -> re-derive the chunk under the live policy ->
|
|
116
|
+
- `respine_op_id` _function_ — The op id `superseded_by` names: a function of (source, landed transcript).
|
|
117
|
+
- `source_entry_for` _function_ — The transcription manifest's entry for a Source, by recomputed identity (pure).
|
|
118
|
+
- `transfer_handler` _function_ — Discover the correction core's chunk-scoped transfer through the entry-point
|
|
119
|
+
|
|
120
|
+
### `cjm_transcript_decomp_core.retire`
|
|
121
|
+
|
|
122
|
+
- `annotate_spines` _function_ — Mark each spine row with its retirement state (pure; rows copied).
|
|
123
|
+
- `apply_spine_fact` _function_ — Replay handler for spine-retire / spine-compaction / chunk-respine: property merges
|
|
124
|
+
- `compact_retired` _function_ — The compact act over every retired, not-yet-compacted spine of the given sources:
|
|
125
|
+
- `default_live_spine` _function_ — Which spine opens by default (pure). Preference is a DECLARED fact, never creation order:
|
|
126
|
+
- `dependents_free` _function_
|
|
127
|
+
- `dependents_map` _function_ — Every spine's dependents in one raw read (see DEPENDENTS_SQL); a spine absent from
|
|
128
|
+
- `get_source` _function_ — The Source node as a dict (None when absent).
|
|
129
|
+
- `journal_spine_retire` _function_ — Apply + journal one retirement fact (write-side dual of apply_spine_fact).
|
|
130
|
+
- `list_sources` _function_ — Every Source (optionally one collection's members).
|
|
131
|
+
- `list_spines` _function_ — The source's coexisting spines, grouped by skeleton hash and annotated with the retirement map.
|
|
132
|
+
- `live_spines` _function_
|
|
133
|
+
- `plan_retire` _function_ — Rules (a) + successor validation as a pure plan; the graph write is `journal_spine_retire`.
|
|
134
|
+
- `plan_superseded` _function_ — The batch candidate list: every LIVE spine that is not the source's default (rule (c)) —
|
|
135
|
+
- `resolve_source_id` _function_ — Resolve a human selector to ONE Source (refuses with the candidates).
|
|
136
|
+
- `resolve_spine` _function_ — Resolve a picker-style selector to exactly one spine row (pure); refuses with the roster.
|
|
137
|
+
- `retire_spine` _function_ — The whole retire act: list -> plan (rules a) -> dependents gate (rule b) -> journaled fact.
|
|
138
|
+
- `retired_spines` _function_ — The Source's retirement map (pure): {spine key: {reason, successor, actor, ts[, compacted]}}.
|
|
139
|
+
- `source_rendition_ids` _function_ — Every AudioRendition under a Source (all chains — retirement is per skeleton, not per chain).
|
|
140
|
+
- `spine_dependents` _function_ — Rule (b)'s evidence: what on the graph points at the spine's segments.
|
|
141
|
+
- `spine_fact_handlers` _function_
|
|
142
|
+
- `spine_key` _function_
|
|
143
|
+
- `spine_label` _function_
|
|
144
|
+
- `spine_segment_ids` _function_
|
|
145
|
+
|
|
91
146
|
### `cjm_transcript_decomp_core.runs`
|
|
92
147
|
|
|
93
148
|
- `DecompIndex` _class_ — Decomp-core run manifests read back: coverage chips for the batch stage
|
|
@@ -95,6 +150,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
95
150
|
- `SourceRunIndex` _class_ — Transcription-core run manifests — the decomp workflow's SOURCES — plus
|
|
96
151
|
- `TrainingRunIndex` _class_ — Training-run manifests under the workspace training-runs/ dir — the
|
|
97
152
|
- `group_batches` _function_ — Fold an ordered batch selection into headless hand-off groups.
|
|
153
|
+
- `is_external_transcriber` _function_ — Whether a transcriber name is an external landing's (the `/manual` marker).
|
|
98
154
|
|
|
99
155
|
### `cjm_transcript_decomp_core.segments`
|
|
100
156
|
|
|
@@ -120,5 +176,5 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
|
|
|
120
176
|
|
|
121
177
|
## Dependencies
|
|
122
178
|
|
|
123
|
-
**Depends on:** `cjm-capability-primitives`, `cjm-context-graph-layer`, `cjm-context-graph-primitives`, `cjm-substrate`, `cjm-transcript-graph-schema`, `pyyaml`
|
|
124
|
-
**Used by:** `cjm-transcript-
|
|
179
|
+
**Depends on:** `cjm-capability-primitives`, `cjm-context-graph-layer`, `cjm-context-graph-primitives`, `cjm-substrate`, `cjm-transcript-graph-schema`, `cjm-transcription-core`, `pyyaml`
|
|
180
|
+
**Used by:** `cjm-transcript-correction-qt`, `cjm-transcript-decomp-qt`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.20"
|
|
@@ -16,7 +16,50 @@ _PUNCT_RE = re.compile(r"[^\w\s]", re.UNICODE)
|
|
|
16
16
|
# authoritative text — the v1-v3 token heuristic (closer/abbreviation/stub
|
|
17
17
|
# lists) is RETIRED. The segmenter's identity (capability name + config hash)
|
|
18
18
|
# joins the skeleton-identity composite beside this tag.
|
|
19
|
-
|
|
19
|
+
# 'capability-v2' (finding efe88f17): the segmenter now reads EXTERNAL variants
|
|
20
|
+
# through `normalize_external_text` — a pasted landing's wordwrap newlines
|
|
21
|
+
# become spaces before the split, so pySBD (which splits at EVERY newline) no
|
|
22
|
+
# longer cuts the skeleton mid-sentence; a paragraph break keeps ONE newline
|
|
23
|
+
# and stays a boundary. Local transcriber text is untouched (it carries no
|
|
24
|
+
# newlines). The split input changed for those variants, so the tag bumps.
|
|
25
|
+
SENTENCE_SPLIT_POLICY = "sentence-split/capability-v2"
|
|
26
|
+
|
|
27
|
+
# A newline run: its LAST newline is retained for a paragraph break; everything
|
|
28
|
+
# else in the run becomes a space (length kept).
|
|
29
|
+
_NEWLINE_RUN_RE = re.compile(r"[\r\n]+")
|
|
30
|
+
_NEWLINE_INSIDE_RE = re.compile(r"[ \t]*[\r\n]+[ \t]*")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def normalize_external_text(
|
|
34
|
+
text: str, # An operator-landed external variant's text, verbatim as landed
|
|
35
|
+
) -> str: # The fold-input form: same length, wraps -> spaces, paragraph breaks -> one retained newline
|
|
36
|
+
"""Offset-preserving fold-input normalisation for EXTERNAL variants (finding
|
|
37
|
+
efe88f17): the AI Studio 'Copy as text' gesture hard-wraps the transcript, and
|
|
38
|
+
pySBD splits at every newline — so a wrap mid-sentence became a sentence end
|
|
39
|
+
and a skeleton cut. Every newline run becomes spaces, except that a run
|
|
40
|
+
holding TWO OR MORE '\\n' (a paragraph / speaker break the model wrote on
|
|
41
|
+
purpose) keeps ONE '\\n' as its last character so the segmenter still sees
|
|
42
|
+
the boundary. '\\r' counts as whitespace of the run. The length never changes,
|
|
43
|
+
so every char-slice ref into the verbatim Transcript text stays valid; the
|
|
44
|
+
Transcript node itself is never rewritten — this is the fold's reading of it."""
|
|
45
|
+
def _run(m: "re.Match[str]") -> str:
|
|
46
|
+
run = m.group(0)
|
|
47
|
+
if run.count("\n") >= 2:
|
|
48
|
+
return " " * (len(run) - 1) + "\n"
|
|
49
|
+
return " " * len(run)
|
|
50
|
+
return _NEWLINE_RUN_RE.sub(_run, text)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def collapse_newlines(
|
|
54
|
+
text: str, # A segment's sliced text (may still hold a retained paragraph newline)
|
|
55
|
+
) -> str: # The same words, every newline run (with its flanking blanks) as one space
|
|
56
|
+
"""The stored-text form of a slice that still holds a newline: a retained
|
|
57
|
+
paragraph break inside a segment (the split refused the cut, or no split ran)
|
|
58
|
+
is presentation, not content — it collapses to one space so the correction
|
|
59
|
+
app's <pre> walk lane never renders a ragged block. Slice refs are untouched
|
|
60
|
+
(they index the verbatim Transcript text, not this string)."""
|
|
61
|
+
return _NEWLINE_INSIDE_RE.sub(" ", text).strip()
|
|
62
|
+
|
|
20
63
|
|
|
21
64
|
# Event-carve policy tag (respine trial DEC 6cc10fb7): versioned for the same
|
|
22
65
|
# reason — it is a SKELETON IDENTITY input. 'v1' = cut-don't-label: model event
|
|
@@ -180,11 +223,14 @@ def build_segments_from_alignment(
|
|
|
180
223
|
num_chunks: int, # Total number of VAD chunks
|
|
181
224
|
source_id: Optional[str] = None, # Source row id for traceability
|
|
182
225
|
source_provider_id: Optional[str] = None, # Source provider identifier
|
|
226
|
+
collapse_newlines_in_text: bool = False, # External variants (efe88f17): a newline still inside a slice -> one space in the stored text
|
|
183
227
|
) -> List[TextSegment]: # One segment per VAD chunk
|
|
184
228
|
"""Build a TextSegment per VAD chunk by grouping words by chunk assignment.
|
|
185
229
|
|
|
186
230
|
Each chunk's text is the original (punctuated) slice from the first to the
|
|
187
|
-
last word assigned to it; chunks with no words become empty segments.
|
|
231
|
+
last word assigned to it; chunks with no words become empty segments. With
|
|
232
|
+
`collapse_newlines_in_text` (external variants) the STORED text collapses any
|
|
233
|
+
newline run to one space — the slice refs stay the verbatim offsets.
|
|
188
234
|
"""
|
|
189
235
|
chunk_spans: Dict[int, List[Tuple[int, int]]] = {}
|
|
190
236
|
for span, chunk_idx in zip(spans, assignments):
|
|
@@ -197,6 +243,8 @@ def build_segments_from_alignment(
|
|
|
197
243
|
seg_start = word_spans[0][0]
|
|
198
244
|
seg_end = word_spans[-1][1]
|
|
199
245
|
seg_text = text[seg_start:seg_end].strip()
|
|
246
|
+
if collapse_newlines_in_text:
|
|
247
|
+
seg_text = collapse_newlines(seg_text)
|
|
200
248
|
else:
|
|
201
249
|
seg_text = ""
|
|
202
250
|
seg_start = None
|