cjm-transcript-decomp-core 0.0.2__tar.gz → 0.0.4__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 (26) hide show
  1. {cjm_transcript_decomp_core-0.0.2/cjm_transcript_decomp_core.egg-info → cjm_transcript_decomp_core-0.0.4}/PKG-INFO +7 -5
  2. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/README.md +3 -1
  3. cjm_transcript_decomp_core-0.0.4/cjm_transcript_decomp_core/__init__.py +1 -0
  4. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/cjm_transcript_decomp_core/cli.py +60 -18
  5. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/cjm_transcript_decomp_core/models.py +9 -2
  6. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/cjm_transcript_decomp_core/pipeline.py +17 -2
  7. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4/cjm_transcript_decomp_core.egg-info}/PKG-INFO +7 -5
  8. cjm_transcript_decomp_core-0.0.4/cjm_transcript_decomp_core.egg-info/entry_points.txt +5 -0
  9. cjm_transcript_decomp_core-0.0.4/cjm_transcript_decomp_core.egg-info/requires.txt +5 -0
  10. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/pyproject.toml +4 -1
  11. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/tests/test_cli.py +14 -1
  12. cjm_transcript_decomp_core-0.0.2/cjm_transcript_decomp_core/__init__.py +0 -1
  13. cjm_transcript_decomp_core-0.0.2/cjm_transcript_decomp_core.egg-info/entry_points.txt +0 -2
  14. cjm_transcript_decomp_core-0.0.2/cjm_transcript_decomp_core.egg-info/requires.txt +0 -5
  15. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/LICENSE +0 -0
  16. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/MANIFEST.in +0 -0
  17. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/cjm_transcript_decomp_core/alignment.py +0 -0
  18. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/cjm_transcript_decomp_core/graph.py +0 -0
  19. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/cjm_transcript_decomp_core.egg-info/SOURCES.txt +0 -0
  20. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/cjm_transcript_decomp_core.egg-info/dependency_links.txt +0 -0
  21. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/cjm_transcript_decomp_core.egg-info/top_level.txt +0 -0
  22. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/setup.cfg +0 -0
  23. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/tests/test_alignment.py +0 -0
  24. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/tests/test_graph.py +0 -0
  25. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/tests/test_models.py +0 -0
  26. {cjm_transcript_decomp_core-0.0.2 → cjm_transcript_decomp_core-0.0.4}/tests/test_pipeline.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cjm-transcript-decomp-core
3
- Version: 0.0.2
3
+ Version: 0.0.4
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
@@ -10,10 +10,10 @@ Classifier: Programming Language :: Python :: 3 :: Only
10
10
  Requires-Python: >=3.12
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: cjm_substrate>=0.0.51
14
- Requires-Dist: cjm_context_graph_primitives>=0.0.12
13
+ Requires-Dist: cjm_substrate>=0.0.57
14
+ Requires-Dist: cjm_context_graph_primitives>=0.0.15
15
15
  Requires-Dist: cjm_capability_primitives>=0.0.10
16
- Requires-Dist: cjm-context-graph-layer>=0.0.10
16
+ Requires-Dist: cjm-context-graph-layer>=0.0.11
17
17
  Requires-Dist: cjm-transcript-graph-schema>=0.0.7
18
18
  Dynamic: license-file
19
19
 
@@ -45,7 +45,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
45
45
  - `build_parser` _function_ — Build the CLI parser (subcommands: run).
46
46
  - `load_capabilities` _function_ — Discover manifests + load each requested capability (default instance).
47
47
  - `main` _function_ — CLI entry point (console script: `cjm-transcript-decomp-core`).
48
- - `run_command` _function_ — Execute the `run` subcommand: extend a transcription-emitted root with the fine spine.
48
+ - `run_command` _function_ — Execute the `run` subcommand: extend transcription-run manifest(s) with the fine spine.
49
49
 
50
50
  ### `cjm_transcript_decomp_core.graph`
51
51
 
@@ -71,6 +71,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
71
71
  - `build_alignment_composition` _function_ — Build the whole-source M×(VAD ∥ T×FA) composition (D8 fan-in, stage-5 variants).
72
72
  - `collect_capability_info` _function_ — Record capability identity + data-DB pointers for the run manifest (provenance).
73
73
  - `confirm_seam` _function_ — HITL approval seam in its cheapest viable form (log + optional CLI prompt).
74
+ - `decomp_replay_handlers` _function_ — The decomp core's replay vocabulary (DEC 426658f1, replay stays DOMAIN-OWNED).
74
75
  - `decompose_source` _function_ — Decompose one source into aligned fine segments with per-transcriber variants.
75
76
  - `fa_words_from_result` _function_ — Normalize a typed forced-alignment result into FA words (pure; stage 3).
76
77
  - `load_source_manifest` _function_ — Load + lightly validate a transcription-core run manifest.
@@ -81,3 +82,4 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
81
82
  ## Dependencies
82
83
 
83
84
  **Depends on:** `cjm-capability-primitives`, `cjm-context-graph-layer`, `cjm-context-graph-primitives`, `cjm-substrate`, `cjm-transcript-graph-schema`
85
+ **Used by:** `cjm-transcript-decomp-tui`
@@ -26,7 +26,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
26
26
  - `build_parser` _function_ — Build the CLI parser (subcommands: run).
27
27
  - `load_capabilities` _function_ — Discover manifests + load each requested capability (default instance).
28
28
  - `main` _function_ — CLI entry point (console script: `cjm-transcript-decomp-core`).
29
- - `run_command` _function_ — Execute the `run` subcommand: extend a transcription-emitted root with the fine spine.
29
+ - `run_command` _function_ — Execute the `run` subcommand: extend transcription-run manifest(s) with the fine spine.
30
30
 
31
31
  ### `cjm_transcript_decomp_core.graph`
32
32
 
@@ -52,6 +52,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
52
52
  - `build_alignment_composition` _function_ — Build the whole-source M×(VAD ∥ T×FA) composition (D8 fan-in, stage-5 variants).
53
53
  - `collect_capability_info` _function_ — Record capability identity + data-DB pointers for the run manifest (provenance).
54
54
  - `confirm_seam` _function_ — HITL approval seam in its cheapest viable form (log + optional CLI prompt).
55
+ - `decomp_replay_handlers` _function_ — The decomp core's replay vocabulary (DEC 426658f1, replay stays DOMAIN-OWNED).
55
56
  - `decompose_source` _function_ — Decompose one source into aligned fine segments with per-transcriber variants.
56
57
  - `fa_words_from_result` _function_ — Normalize a typed forced-alignment result into FA words (pure; stage 3).
57
58
  - `load_source_manifest` _function_ — Load + lightly validate a transcription-core run manifest.
@@ -62,3 +63,4 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
62
63
  ## Dependencies
63
64
 
64
65
  **Depends on:** `cjm-capability-primitives`, `cjm-context-graph-layer`, `cjm-context-graph-primitives`, `cjm-substrate`, `cjm-transcript-graph-schema`
66
+ **Used by:** `cjm-transcript-decomp-tui`
@@ -0,0 +1 @@
1
+ __version__ = "0.0.4"
@@ -10,9 +10,11 @@ Prerequisite runtime (once, from the repo root):
10
10
  cjm-ctl --cjm-config cjm.yaml setup-runtime
11
11
  cjm-ctl --cjm-config cjm.yaml install-all --capabilities capabilities_test.yaml --force
12
12
 
13
- Then decompose a transcription-core run manifest:
13
+ Then decompose transcription-core run manifest(s) — a multi-manifest batch
14
+ shares ONE loaded capability stack (models load once, per-manifest runs):
14
15
 
15
16
  cjm-transcript-decomp-core run path/to/transcription-run.json --yes
17
+ cjm-transcript-decomp-core run runs/run_a.json runs/run_b.json --yes
16
18
  # GPU runs: opt into CR-7 GPU subtree attribution
17
19
  cjm-transcript-decomp-core run run.json --yes --sysmon-capability cjm-capability-monitor-nvidia
18
20
  """
@@ -21,11 +23,13 @@ import argparse
21
23
  import asyncio
22
24
  import getpass
23
25
  import logging
26
+ import os
24
27
  from pathlib import Path
25
28
  from typing import Any, Dict, List, Optional
26
29
 
27
30
  from cjm_substrate.core.manager import CapabilityManager
28
31
  from cjm_substrate.core.queue import JobQueue
32
+ from cjm_substrate.core.workspace import resolve_workspace
29
33
  from cjm_transcript_decomp_core.models import DecompConfig
30
34
  from cjm_transcript_decomp_core.pipeline import load_source_manifest, run_decomp
31
35
 
@@ -41,7 +45,8 @@ def build_parser() -> argparse.ArgumentParser: # Configured CLI parser
41
45
  sub = parser.add_subparsers(dest="command", required=True)
42
46
 
43
47
  run = sub.add_parser("run", help="Extend a transcription-emitted graph root with the fine spine")
44
- run.add_argument("manifest", help="Transcription-core run manifest JSON (the source to decompose)")
48
+ run.add_argument("manifests", nargs="+",
49
+ help="Transcription-core run manifest JSON(s) — a batch shares ONE loaded capability stack")
45
50
  run.add_argument("--manifests-dir", default=".cjm/manifests", help="Capability manifests directory")
46
51
  run.add_argument("--vad-capability", default="cjm-capability-silero-vad", help="VAD capability name")
47
52
  run.add_argument("--fa-capability", default="cjm-capability-qwen3-forced-aligner", help="Forced-alignment capability name")
@@ -56,7 +61,15 @@ def build_parser() -> argparse.ArgumentParser: # Configured CLI parser
56
61
  run.add_argument("--language", default="English", help="Forced-alignment language")
57
62
  run.add_argument("--force", action="store_true", help="Bypass capability-side caches (VAD + FA)")
58
63
  run.add_argument("-y", "--yes", action="store_true", help="Auto-accept HITL seams (headless mode)")
59
- run.add_argument("--output", default=None, help="Decomp-manifest output path (default: runs/<run_id>.json)")
64
+ run.add_argument("--output", default=None, help="Decomp-manifest output path (single-manifest runs only; default: <output-dir>/<run_id>.json)")
65
+ run.add_argument("--output-dir", default=None,
66
+ help="Decomp-manifest output directory (callers with a shared runs dir "
67
+ "pass it so manifests land beside their sources; default: the "
68
+ "workspace's runs/ when one is active, else runs/ under the cwd)")
69
+ run.add_argument("--workspace", default=None,
70
+ help="Workspace root (5daadfc4; default: CJM_WORKSPACE env, else upward walk "
71
+ "from cwd). Supplies the --output-dir default and is exported so "
72
+ "substrate config + capability workers resolve workspace-scoped paths")
60
73
  run.add_argument("--actor", default=None,
61
74
  help="Journal attribution for who/what initiated this run (default: cli:<username>)")
62
75
  run.add_argument("-v", "--verbose", action="store_true", help="DEBUG-level logging")
@@ -85,11 +98,31 @@ def load_capabilities(
85
98
 
86
99
  async def run_command(
87
100
  args: argparse.Namespace, # Parsed CLI arguments for the `run` subcommand
88
- ) -> int: # Process exit code (0 = all sources extended + verified)
89
- """Execute the `run` subcommand: extend a transcription-emitted root with the fine spine."""
90
- manifest_path = str(Path(args.manifest).resolve())
91
- if not Path(manifest_path).exists():
92
- raise SystemExit(f"source manifest not found: {manifest_path}")
101
+ ) -> int: # Process exit code (0 = every manifest fully extended + verified)
102
+ """Execute the `run` subcommand: extend transcription-run manifest(s) with the fine spine.
103
+
104
+ Batch shape (decomp-TUI demand, work item 0ff6bf0f): N manifests ride ONE
105
+ capability stack — the models load once and every manifest reuses them,
106
+ where N CLI invocations would pay N model loads. Each manifest keeps its
107
+ own run_id, decomp manifest, and RUN_STARTED/RUN_FINISHED journal bracket,
108
+ so a batch member is indistinguishable from a solo run downstream. A failed
109
+ member records and the batch continues (unattended queueing must not sink
110
+ the rest); the exit code aggregates across members.
111
+ """
112
+ # 5daadfc4 workspace: resolve BEFORE any substrate config loads; export so
113
+ # the process tree (substrate config, capability workers) is workspace-scoped.
114
+ ws = resolve_workspace(explicit=getattr(args, "workspace", None))
115
+ if ws is not None:
116
+ os.environ["CJM_WORKSPACE"] = str(ws.root)
117
+ output_dir = (Path(args.output_dir) if args.output_dir
118
+ else (ws.runs_dir if ws is not None else Path("runs")))
119
+ manifest_paths = [str(Path(m).resolve()) for m in args.manifests]
120
+ missing = [m for m in manifest_paths if not Path(m).exists()]
121
+ if missing:
122
+ raise SystemExit(f"source manifest(s) not found: {', '.join(missing)}")
123
+ if args.output and len(manifest_paths) > 1:
124
+ raise SystemExit("--output names ONE decomp manifest — omit it for batch runs "
125
+ "(each lands at runs/<run_id>.json)")
93
126
 
94
127
  cfg = DecompConfig(
95
128
  vad_capability=args.vad_capability,
@@ -118,11 +151,28 @@ async def run_command(
118
151
 
119
152
  queue = JobQueue(deps=manager, sysmon_capability_name=args.sysmon_capability)
120
153
  await queue.start()
154
+ all_ok = True
121
155
  try:
122
156
  # CR-14 follow-up: actor attribution (operator identity by default;
123
157
  # agents/services pass --actor explicitly).
124
158
  actor = args.actor or f"cli:{getpass.getuser()}"
125
- manifest = await run_decomp(manager, queue, cfg, manifest_path, actor=actor)
159
+ for mp in manifest_paths:
160
+ try:
161
+ manifest = await run_decomp(manager, queue, cfg, mp, actor=actor)
162
+ except Exception as e: # One member's failure must not sink the batch
163
+ logger.error(f"decomp failed for {mp}: {e}")
164
+ print(f"FAILED {mp}: {e}")
165
+ all_ok = False
166
+ continue
167
+ out = (Path(args.output) if args.output
168
+ else output_dir / f"{manifest.run_id}.json")
169
+ manifest.save(out, workspace=ws)
170
+ n_manifest_sources = len(load_source_manifest(mp).get("sources", []) or [])
171
+ n_sources = len(manifest.sources)
172
+ n_segs = sum(s.segment_count for s in manifest.sources)
173
+ print(f"decomp manifest: {out}")
174
+ print(f"sources extended: {n_sources}/{n_manifest_sources} segment nodes: {n_segs}")
175
+ all_ok = all_ok and (n_sources == n_manifest_sources)
126
176
  finally:
127
177
  await queue.stop()
128
178
  for iid in reversed(load_order): # Reverse load order; the monitor unloads last
@@ -130,15 +180,7 @@ async def run_command(
130
180
  manager.unload_capability(iid)
131
181
  except Exception as e: # Best-effort teardown; never mask the run's outcome
132
182
  logger.warning(f"unload {iid} failed: {e}")
133
-
134
- out = Path(args.output) if args.output else Path("runs") / f"{manifest.run_id}.json"
135
- manifest.save(out)
136
- n_manifest_sources = len(load_source_manifest(manifest_path).get("sources", []) or [])
137
- n_sources = len(manifest.sources)
138
- n_segs = sum(s.segment_count for s in manifest.sources)
139
- print(f"decomp manifest: {out}")
140
- print(f"sources extended: {n_sources}/{n_manifest_sources} segment nodes: {n_segs}")
141
- return 0 if n_sources == n_manifest_sources else 1
183
+ return 0 if all_ok else 1
142
184
 
143
185
 
144
186
  def main(
@@ -7,6 +7,8 @@ from dataclasses import asdict, dataclass, field
7
7
  from pathlib import Path
8
8
  from typing import Any, Dict, List, Optional, Union
9
9
 
10
+ from cjm_substrate.core.workspace import relativize_recorded
11
+
10
12
 
11
13
  @dataclass
12
14
  class FAWord:
@@ -173,11 +175,16 @@ class DecompManifest:
173
175
  def save(
174
176
  self,
175
177
  path: Union[str, Path], # Destination JSON file (parent dirs created)
178
+ workspace=None, # Active Workspace; owned paths record as ${WS}/<rel> (5daadfc4 rung f)
176
179
  ) -> Path: # The written path
177
- """Write the manifest as pretty-printed JSON."""
180
+ """Write the manifest as pretty-printed JSON.
181
+
182
+ With `workspace`, recorded paths under its root take the ${WS}/ token
183
+ form (relativize_recorded), so the manifest relocates with the
184
+ workspace; readers resolve via resolve_recorded_tree at load."""
178
185
  out = Path(path)
179
186
  out.parent.mkdir(parents=True, exist_ok=True)
180
- out.write_text(json.dumps(self.to_dict(), indent=2))
187
+ out.write_text(json.dumps(relativize_recorded(self.to_dict(), workspace), indent=2))
181
188
  return out
182
189
 
183
190
 
@@ -10,13 +10,14 @@ from typing import Any, Dict, List, Optional, Tuple
10
10
  from cjm_capability_primitives.forced_alignment import ForcedAlignResult
11
11
  from cjm_capability_primitives.vad import VADResult
12
12
  from cjm_context_graph_layer.declare import Derivation, derivation_to_graph
13
- from cjm_context_graph_layer.journal import journal_extend, sidecar_journal_path
13
+ from cjm_context_graph_layer.journal import journal_extend, sidecar_journal_path, wires_handlers
14
14
  from cjm_context_graph_layer.ops import graph_task
15
15
  from cjm_substrate.core.empirical_store import compute_config_hash
16
16
  from cjm_substrate.core.journal_store import JournalEvent, SubstrateEventType
17
17
  from cjm_substrate.core.manager import CapabilityManager
18
18
  from cjm_substrate.core.ports import Composition, CompositionNode, NodeState
19
19
  from cjm_substrate.core.queue import JobQueue, JobStatus
20
+ from cjm_substrate.core.workspace import resolve_recorded_tree
20
21
  from cjm_transcript_decomp_core.alignment import (assign_words_to_chunks,
21
22
  build_segments_from_alignment,
22
23
  map_fa_words_to_text, tier1_alignment_checks)
@@ -59,8 +60,11 @@ def load_source_manifest(
59
60
 
60
61
  Consumed as untyped JSON — the format/version tags are the only interchange
61
62
  contract (no shared schema type across cores; manifest-as-interchange, CR-20).
63
+ ${WS}/ recorded paths (5daadfc4 rung f) resolve to absolute here, anchored
64
+ at the manifest's own location (active workspace as fallback), so all
65
+ downstream consumers keep seeing absolute paths.
62
66
  """
63
- data = json.loads(Path(path).read_text())
67
+ data = resolve_recorded_tree(json.loads(Path(path).read_text()), Path(path))
64
68
  fmt = data.get("format", "")
65
69
  if "transcription-core" not in fmt:
66
70
  logger.warning(f"unexpected source manifest format: {fmt!r} (continuing)")
@@ -486,3 +490,14 @@ async def run_decomp(
486
490
  "segments": sum(s.segment_count for s in manifest.sources),
487
491
  })
488
492
  return manifest
493
+
494
+
495
+ def decomp_replay_handlers() -> Dict[str, Any]: # verb -> async handler(queue, graph_id, op)
496
+ """The decomp core's replay vocabulary (DEC 426658f1, replay stays DOMAIN-OWNED).
497
+
498
+ Exported through the `cjm_context_graph_layer.replay` entry-point group and
499
+ unioned by `composed_replay_handlers`. Both verbs are `journal_extend` ops —
500
+ wire-carrying by construction — so they register the layer's shared
501
+ `apply_wires` (identity-comparable across cores: transcription also emits
502
+ `derivation`, and the shared handler keeps that collision legal)."""
503
+ return wires_handlers("spine-extension", "derivation")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cjm-transcript-decomp-core
3
- Version: 0.0.2
3
+ Version: 0.0.4
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
@@ -10,10 +10,10 @@ Classifier: Programming Language :: Python :: 3 :: Only
10
10
  Requires-Python: >=3.12
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: cjm_substrate>=0.0.51
14
- Requires-Dist: cjm_context_graph_primitives>=0.0.12
13
+ Requires-Dist: cjm_substrate>=0.0.57
14
+ Requires-Dist: cjm_context_graph_primitives>=0.0.15
15
15
  Requires-Dist: cjm_capability_primitives>=0.0.10
16
- Requires-Dist: cjm-context-graph-layer>=0.0.10
16
+ Requires-Dist: cjm-context-graph-layer>=0.0.11
17
17
  Requires-Dist: cjm-transcript-graph-schema>=0.0.7
18
18
  Dynamic: license-file
19
19
 
@@ -45,7 +45,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
45
45
  - `build_parser` _function_ — Build the CLI parser (subcommands: run).
46
46
  - `load_capabilities` _function_ — Discover manifests + load each requested capability (default instance).
47
47
  - `main` _function_ — CLI entry point (console script: `cjm-transcript-decomp-core`).
48
- - `run_command` _function_ — Execute the `run` subcommand: extend a transcription-emitted root with the fine spine.
48
+ - `run_command` _function_ — Execute the `run` subcommand: extend transcription-run manifest(s) with the fine spine.
49
49
 
50
50
  ### `cjm_transcript_decomp_core.graph`
51
51
 
@@ -71,6 +71,7 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
71
71
  - `build_alignment_composition` _function_ — Build the whole-source M×(VAD ∥ T×FA) composition (D8 fan-in, stage-5 variants).
72
72
  - `collect_capability_info` _function_ — Record capability identity + data-DB pointers for the run manifest (provenance).
73
73
  - `confirm_seam` _function_ — HITL approval seam in its cheapest viable form (log + optional CLI prompt).
74
+ - `decomp_replay_handlers` _function_ — The decomp core's replay vocabulary (DEC 426658f1, replay stays DOMAIN-OWNED).
74
75
  - `decompose_source` _function_ — Decompose one source into aligned fine segments with per-transcriber variants.
75
76
  - `fa_words_from_result` _function_ — Normalize a typed forced-alignment result into FA words (pure; stage 3).
76
77
  - `load_source_manifest` _function_ — Load + lightly validate a transcription-core run manifest.
@@ -81,3 +82,4 @@ A frontend-agnostic core for the transcript decomposition workflow — composes
81
82
  ## Dependencies
82
83
 
83
84
  **Depends on:** `cjm-capability-primitives`, `cjm-context-graph-layer`, `cjm-context-graph-primitives`, `cjm-substrate`, `cjm-transcript-graph-schema`
85
+ **Used by:** `cjm-transcript-decomp-tui`
@@ -0,0 +1,5 @@
1
+ [cjm_context_graph_layer.replay]
2
+ decomp = cjm_transcript_decomp_core.pipeline:decomp_replay_handlers
3
+
4
+ [console_scripts]
5
+ cjm-transcript-decomp-core = cjm_transcript_decomp_core.cli:main
@@ -0,0 +1,5 @@
1
+ cjm_substrate>=0.0.57
2
+ cjm_context_graph_primitives>=0.0.15
3
+ cjm_capability_primitives>=0.0.10
4
+ cjm-context-graph-layer>=0.0.11
5
+ cjm-transcript-graph-schema>=0.0.7
@@ -14,7 +14,7 @@ classifiers = [
14
14
  "Programming Language :: Python :: 3",
15
15
  "Programming Language :: Python :: 3 :: Only",
16
16
  ]
17
- dependencies = ['cjm_substrate>=0.0.51', 'cjm_context_graph_primitives>=0.0.12', 'cjm_capability_primitives>=0.0.10', 'cjm-context-graph-layer>=0.0.10', 'cjm-transcript-graph-schema>=0.0.7']
17
+ dependencies = ['cjm_substrate>=0.0.57', 'cjm_context_graph_primitives>=0.0.15', 'cjm_capability_primitives>=0.0.10', 'cjm-context-graph-layer>=0.0.11', 'cjm-transcript-graph-schema>=0.0.7']
18
18
 
19
19
  [project.urls]
20
20
  Repository = "https://github.com/cj-mills/cjm-transcript-decomp-core"
@@ -22,6 +22,9 @@ Repository = "https://github.com/cj-mills/cjm-transcript-decomp-core"
22
22
  [project.scripts]
23
23
  cjm-transcript-decomp-core = "cjm_transcript_decomp_core.cli:main"
24
24
 
25
+ [project.entry-points."cjm_context_graph_layer.replay"]
26
+ decomp = "cjm_transcript_decomp_core.pipeline:decomp_replay_handlers"
27
+
25
28
  [tool.setuptools.dynamic]
26
29
  version = {attr = "cjm_transcript_decomp_core.__version__"}
27
30
 
@@ -8,12 +8,16 @@ def test_run_defaults():
8
8
  p = build_parser()
9
9
  args = p.parse_args(["run", "m.json", "--yes", "--language", "English"])
10
10
  assert args.command == "run"
11
- assert args.manifest == "m.json"
11
+ assert args.manifests == ["m.json"] # single manifest = a batch of one
12
12
  assert args.yes is True
13
13
  assert args.fa_capability == "cjm-capability-qwen3-forced-aligner"
14
14
  assert args.graph_capability == "cjm-capability-graph-sqlite"
15
15
  assert args.text_from is None # authority defaults to the manifest's sole transcriber
16
16
  assert args.sysmon_capability is None
17
+ # 5daadfc4: None sentinel — run_command resolves the workspace's runs/ when
18
+ # one is active, else the legacy cwd-relative runs/; TUIs pin their browsed dir
19
+ assert args.output_dir is None
20
+ assert args.workspace is None
17
21
 
18
22
 
19
23
  def test_text_from_and_sysmon_flags():
@@ -22,3 +26,12 @@ def test_text_from_and_sysmon_flags():
22
26
  "--sysmon-capability", "cjm-capability-monitor-nvidia"])
23
27
  assert args.text_from == "cjm-capability-voxtral-hf"
24
28
  assert args.sysmon_capability == "cjm-capability-monitor-nvidia"
29
+
30
+
31
+ def test_batch_manifests():
32
+ # Batch shape (work item 0ff6bf0f): N manifests, one invocation, one stack.
33
+ p = build_parser()
34
+ args = p.parse_args(["run", "a.json", "b.json", "c.json", "--yes",
35
+ "--text-from", "cjm-capability-voxtral-hf"])
36
+ assert args.manifests == ["a.json", "b.json", "c.json"]
37
+ assert args.text_from == "cjm-capability-voxtral-hf"
@@ -1 +0,0 @@
1
- __version__ = "0.0.2"
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- cjm-transcript-decomp-core = cjm_transcript_decomp_core.cli:main
@@ -1,5 +0,0 @@
1
- cjm_substrate>=0.0.51
2
- cjm_context_graph_primitives>=0.0.12
3
- cjm_capability_primitives>=0.0.10
4
- cjm-context-graph-layer>=0.0.10
5
- cjm-transcript-graph-schema>=0.0.7