This page separates six focused blocker contracts closed by 2026-08-03 evidence from B2–B12, the flaky suite, structural work, and evidence-blocked items. B13–B16 were discovered during the 2026-08-02 wiki audit; B17 was found during the 2026-08-03 closure-plan review.
🧭 How to read this page
Three categories, and the difference between them is the whole point:
| Category | Meaning |
|---|---|
| Blockers | Reproduced against source. Nothing here is speculative. |
| Open work | Genuinely unfinished. Carried from the repo’s own tracker, with each item’s code status checked where it was cheap to check. |
| Evidence-blocked | Code exists, ticked by a previous author, but unprovable here because no pipeline run can complete on this checkout. Not the same as undone. |
Every blocker has a stable anchor (#b1 … #b17) so 🚑 Troubleshooting and the 🧾 Claim Registry can point at it directly.
🔴 P0 — runtime-fatal
These stop the headline command or silently corrupt its behaviour.
B1
Closed at the named boundary on 2026-08-03. The local SFX adapter defers optional imports and resource probing; focused minimal-startup and local-SFX evidence demonstrates import-safe startup with the SFX path enabled. Full generation and artifacts remain evidence-blocked (src/storymatrix/infrastructure/adapters/sfx/local.py).
B2
The legacy story-crew fallback raises NameError the moment it is entered. _create_legacy_story_crew_inline() takes an LLM service parameter, but its body tests and assigns a bare llm name that was never defined in that scope. Any fallback into this path dies immediately. Details on 🤖 CrewAI Agents.
B3
The agentic timeline path has never once run, and nothing reports it. The agentic timeline adapter calls a logger at six sites inside its response-parsing hot path, but imports no logger at all. The NameError that follows is caught by the deterministic-timeline fallback, so the stage reports success while the agentic path silently never executes.
This is the single most misleading defect in the codebase: it makes a broken feature look like a working one, and it explains why verifying the timeline guardrails has never succeeded. See 🎞️ Production Pipeline.
B4
The documented mock image service cannot be instantiated. MockImageService implements only one of the two abstract methods its interface declares, leaving generate_image_for_scene abstract, so constructing it raises TypeError: Can't instantiate abstract class. That breaks the documented offline escape hatch and takes the dependency-injection gating test with it.
B5
Mock mode always fails the image-prompt crew. The crew assigns a sentinel model string of the form mock-provider/mock-response and hands it to litellm, which rejects it with BadRequestError: LLM Provider NOT provided. The failure is captured verbatim in the repo’s raw error log and the code path is unchanged since.
B14
Closed at the named boundary on 2026-08-03. API authentication/rate-limit dependencies now use config.services.api, and one explicit /health contract plus /metrics reach their handlers in focused request dispatch (src/storymatrix/interfaces/api/main.py).
B15
Closed at the named boundary on 2026-08-03. Typed CLI overrides now resolve above YAML, environment/.env, and defaults; focused precedence and offline/low-resource evidence demonstrates no paid-provider construction or requests (src/storymatrix/cli/main.py, src/storymatrix/config/config.py).
🟠 P1 — broken contracts
B6
An async conversion was applied to the media-asset repository but never propagated to its callers. FileSystemMediaAssetRepository’s save and friends are coroutines; callers and tests still use their results as if they were plain objects, producing AttributeError: 'coroutine' object has no attribute 'id' across eleven tests. A spent helper script at the repo root performed the rewrite; auditing every call site is a prerequisite to deleting it.
B7
The golden-path fixture no longer satisfies its own schema. background_music is required and omitted, so integration setup fails with a validation error. It needs a fixture refresh only after a real verification run; B1 is no longer the reason this remains evidence-blocked.
B8
The container-wiring fixture passes a str where a Path is required, so both wiring tests error during setup with AttributeError: 'str' object has no attribute 'exists'.
B9
A repository annotates a type it never imports. The SQLite content repository refers to sessionmaker in an annotation with no corresponding import. from __future__ import annotations defers the failure, so this is latent — it bites whenever annotations are resolved at runtime.
B10
Eighteen undefined-name diagnostics in src/. B2, B3 and B9 are the live ones; the remainder are annotation-only types that were never imported (VoiceFilter, StoryPlan, Voice, CharacterMappingService, Scene, CharacterDTO, GenerateStoryRequest). Enumerate them with ruff check src/ --select F821 --output-format concise.
B13
Closed at the named boundary on 2026-08-03. WebSettings now declares typed title, dark_mode, and reload, and focused startup evidence demonstrates those values resolve without paid-provider construction (src/storymatrix/config/models.py, src/storymatrix/interfaces/web/main.py).
B17
Closed at the named boundary on 2026-08-03. The status handler accepts only job_id and returns the declared StoryStatusResponse; focused pending and ready states are schema-valid without a live broker (src/storymatrix/interfaces/api/main.py). This was found during the closure-plan review after the 2026-08-02 audit.
🟡 P2 — hygiene and drift
B11
Debris at the repository root. A spent migration script (see B6), a throwaway import smoke test, and a raw error log sit untracked alongside the package. Worth noting for accuracy: the second error recorded in that log is fixed — montage serialization now uses JSON mode.
B12
AGENTS.md is wrong about where output goes. It names outputs/ as the active write target and calls out/ legacy. The application setting and the shipped YAML both select out/, and outputs/ does not exist. The fix belongs in the document, not the code — this wiki publishes out/ throughout. See 🏃 Runbook.
B16
Closed at the named boundary on 2026-08-03. The unconditional provider-strategy stdout print was removed from load_config(); focused loader/CLI evidence shows no replacement noise (src/storymatrix/config/config.py).
🧪 Test-suite integrity
Flaky suite
One test makes the suite’s exact pass count irreproducible. Three identical runs on 2026-08-02 returned 392, 391 and 392 passing tests. The only test that changed verdict between them was a memory-stability check in tests/performance/test_audio_processing.py, which is inherently nondeterministic.
Stable across all three runs: 12 errors, 18 skipped, 458 non-skipped. Variable: 391–393 passed, 53–55 failed, a pass rate of roughly 85.4–85.8%. Any document quoting a single exact pass count — including this project’s older notes — is quoting one sample from that band. Either make the test deterministic or mark it so it stops polluting the headline number. Full breakdown on 🧪 Testing.
🔊 Open work — SFX and audio
Carried from the repo’s task tracker. Renamed with an SFX- prefix because the tracker’s original A1/B1/C1/D1 labels collide with the blocker ids above.
| Item | Goal | Status |
|---|---|---|
SFX-A1 | Cache generated ElevenLabs sound effects so identical descriptions are not re-billed | Open |
SFX-B1 | Apply scene-context effects (cave, underwater, outdoor) from segment metadata | Open — needs an environment field on segment metadata first |
SFX-C1 | One unified local search across the BBC library, custom SFX, and the Freesound cache | Open |
SFX-D1 | Character voice effects driven by character traits | Open |
🖼️ Open work — the image bottleneck
The image-prompt crew takes upwards of ten minutes for two scenes, and the full pipeline times out before reaching timeline generation — stage six of nine. This is the practical reason the later stages have no verification, and it compounds B1.
Note that the documented workaround — switch to the mock image provider for development — is itself broken by B4.
🧱 Open work — structural
Carried from the tracker’s oldest section. Each status below was checked against source in this pass:
| Item | Goal | Verified status |
|---|---|---|
| Prompt includes | Move long agent backstories out of YAML into file: includes | Half-done, and currently dead code. The include mechanism exists in the crew factory and three prompt files exist, but no config uses the file: prefix — all six story backstories are still inline, so those files are unreachable |
| Deterministic tools | Extend the crew tool registry with envelope and ducking advisors | Present but stubbed. Every tool in the registry returns a constant; the conflict resolver is an explicit no-op and the segmentation analyser returns fixed values. And the factory never passes tools into constructed agents, so the registry is populated but not wired either |
| Runner config surfacing | Expose crew-runner settings through config and CLI | Not started. No crew-runner settings class exists in the config models |
| Crew artifact consistency | Save raw and parsed JSON for every crew under the run’s text artifacts | Carried from the tracker; not independently verified here |
| Image-prompt hardening | Give the image-prompt crew a Pydantic output and run it through the runner | Carried from the tracker; blocked in practice by B5 |
| Snapshot coverage | Snapshot tests for plan, story and timeline JSON | Carried from the tracker; see B7 for the existing snapshot’s state |
✅ Verified done
Ticked, and confirmed against source in this pass. These are not open, and any document still listing them as outstanding is stale.
| Item | What was delivered | Confirmed at |
|---|---|---|
| Ambient SFX stem | ambient_sfx is built and exported as the fourth stem, alongside tts, music and impact_sfx | stages/finalize_production.py |
| SFX duration config | sfx_duration_seconds reaches the ElevenLabs SFX adapter instead of being hardcoded | adapters/sfx/elevenlabs.py |
| Montage serialization | Segment models serialize in JSON mode, killing the montage crash recorded in the raw error log | services/ffmpeg_montage.py |
| Audio-production fixtures | Realigned to the refactored service signature; the affected module passes | tests/unit/application/services/test_audio_production_sfx_flag.py |
| Multi-task crew runner | The runner exposes a per-task result type and a multi-task execution entry point | crew/runner.py |
🚧 Evidence-blocked, not undone
Code exists for all of these. None can be proven on this checkout, because completing a pipeline run is a precondition and B1 prevents one. Listing them as incomplete work would be as wrong as listing them as finished.
| Item | Why it cannot be settled |
|---|---|
| Four-stem export verification | Requires inspecting the artifacts of a completed run; out/ is empty |
| SFX distribution across the timeline | Requires a rendered timeline to inspect |
| Voice-casting crew behaviour | Wired in crew/voice_casting_crew.py, but its runtime behaviour is unobserved |
| Expressive audio tags reaching synthesis | Requires synthesized audio to inspect |
| Music stem level, settings export, genre selection | All three are “verify after fix” items awaiting a run |
| Orchestration adoption of the multi-task runner | The entry point exists; whether the orchestration service uses it is unverified |
📊 Measured state — 2026-08-02
| Signal | Value |
|---|---|
| Test suite | 12 errors · 18 skipped · 458 non-skipped · 391–393 passed across identical runs (~85.4–85.8%) |
| Failure clustering | The failures reduce to four root causes — B4, B6, B7, B8 — plus one nondeterministic test, not 50-odd independent bugs |
| Lint | ruff check src/ tests/ reports 1160 findings, 848 of them autofixable |
| Undefined names | 18 in src/ (see B10) |
| Completed pipeline runs on this checkout | None |
| Stages verified end-to-end | 5 of 9, unchanged since 2025-11-10 |
| Blockers open | 11 — B2–B12 remain open; B1 and B13–B17 are closed at named boundaries |
The clustering line matters more than the raw count: the failures reduce to four known root causes and one flaky test, so the raw failure count does not represent 50-odd independent defects.
🔗 Related
- 🚑 Troubleshooting — the same blockers keyed by the error message you will actually see
- 🧪 Testing — suite layout, markers, and the full failure breakdown
- 🧾 Claim Registry — machine-checked form of every claim on this page
- 🔥 Incident Log — what has already gone wrong, and what it cost