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:

CategoryMeaning
BlockersReproduced against source. Nothing here is speculative.
Open workGenuinely unfinished. Carried from the repo’s own tracker, with each item’s code status checked where it was cheap to check.
Evidence-blockedCode 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.

ItemGoalStatus
SFX-A1Cache generated ElevenLabs sound effects so identical descriptions are not re-billedOpen
SFX-B1Apply scene-context effects (cave, underwater, outdoor) from segment metadataOpen — needs an environment field on segment metadata first
SFX-C1One unified local search across the BBC library, custom SFX, and the Freesound cacheOpen
SFX-D1Character voice effects driven by character traitsOpen

🖼️ 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:

ItemGoalVerified status
Prompt includesMove long agent backstories out of YAML into file: includesHalf-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 toolsExtend the crew tool registry with envelope and ducking advisorsPresent 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 surfacingExpose crew-runner settings through config and CLINot started. No crew-runner settings class exists in the config models
Crew artifact consistencySave raw and parsed JSON for every crew under the run’s text artifactsCarried from the tracker; not independently verified here
Image-prompt hardeningGive the image-prompt crew a Pydantic output and run it through the runnerCarried from the tracker; blocked in practice by B5
Snapshot coverageSnapshot tests for plan, story and timeline JSONCarried 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.

ItemWhat was deliveredConfirmed at
Ambient SFX stemambient_sfx is built and exported as the fourth stem, alongside tts, music and impact_sfxstages/finalize_production.py
SFX duration configsfx_duration_seconds reaches the ElevenLabs SFX adapter instead of being hardcodedadapters/sfx/elevenlabs.py
Montage serializationSegment models serialize in JSON mode, killing the montage crash recorded in the raw error logservices/ffmpeg_montage.py
Audio-production fixturesRealigned to the refactored service signature; the affected module passestests/unit/application/services/test_audio_production_sfx_flag.py
Multi-task crew runnerThe runner exposes a per-task result type and a multi-task execution entry pointcrew/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.

ItemWhy it cannot be settled
Four-stem export verificationRequires inspecting the artifacts of a completed run; out/ is empty
SFX distribution across the timelineRequires a rendered timeline to inspect
Voice-casting crew behaviourWired in crew/voice_casting_crew.py, but its runtime behaviour is unobserved
Expressive audio tags reaching synthesisRequires synthesized audio to inspect
Music stem level, settings export, genre selectionAll three are “verify after fix” items awaiting a run
Orchestration adoption of the multi-task runnerThe entry point exists; whether the orchestration service uses it is unverified

📊 Measured state — 2026-08-02

SignalValue
Test suite12 errors · 18 skipped · 458 non-skipped · 391–393 passed across identical runs (~85.4–85.8%)
Failure clusteringThe failures reduce to four root causes — B4, B6, B7, B8 — plus one nondeterministic test, not 50-odd independent bugs
Lintruff check src/ tests/ reports 1160 findings, 848 of them autofixable
Undefined names18 in src/ (see B10)
Completed pipeline runs on this checkoutNone
Stages verified end-to-end5 of 9, unchanged since 2025-11-10
Blockers open11 — 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.

0 items under this folder.