fix(pipelines): make the screen-demo manifest load - #472
Open
bbudaedu wants to merge 1 commit into
Open
Conversation
`pipeline_defs/screen-demo.yaml` carries a top-level `production_modes` block
that the manifest schema does not allow, so `load_pipeline("screen-demo")`
raises. The pipeline is marked `production` stability in AGENT_GUIDE.md.
lib/checkpoint.py degrades gracefully on an unloadable manifest, which is right
for a corrupt user manifest but means a manifest shipped in this repo is
silently ignored rather than loudly rejected. Both fallbacks then misfire:
_stage_requires_approval("screen-demo", "idea") -> None
(the manifest declares True; None means the caller's own flag wins)
get_pipeline_stages("screen-demo")
-> [research, proposal, idea, script, scene_plan, assets, edit,
compose, publish] # the canonical fallback
declared: [idea, script, scene_plan, assets, edit, compose, publish]
The stage-order fallback inserts `research` and `proposal` ahead of the real
first stage, so the opening checkpoint of every screen-demo run is rejected:
write_checkpoint(..., stage="idea", status="completed", human_approved=True)
CheckpointValidationError: PREREQUISITE VIOLATION: stage 'idea' cannot
advance; incomplete or missing: ['research', 'proposal']
The pipeline cannot start. Separately, all five of its declared gates
(idea, script, scene_plan, assets, publish) fall back to whatever the caller
passes, against AGENT_GUIDE.md's "the manifest value is binding".
`production_modes` is a documented, first-class feature rather than stray
YAML: skills/pipelines/screen-demo/idea-director.md builds its whole
real_capture vs synthetic_terminal decision table on it, and AGENT_GUIDE.md
routes agents to this manifest to choose between them. Nothing in Python reads
it — it is agent-facing declarative content like the rest of the manifest. So
the schema is what is stale, and it gains a typed definition for the block.
`extensions` was not a candidate home: it is a fixed set of four capability
booleans, not a free-form bucket.
Coverage iterates pipeline_defs/ instead of naming pipelines. Existing manifest
tests load talking-head, framework-smoke, animated-explainer and
documentary-montage by name, so the one broken manifest was never touched —
the same gap that hid this class of bug in the style playbooks. The new tests
assert every shipped manifest validates, that the stage order the checkpoint
writer uses is the one the manifest declares, and that every declared
human_approval_default is what `_stage_requires_approval` resolves.
Verified: the 3 screen-demo cases fail on the unfixed tree; full suite goes
964 -> 1004 passed with no regressions.
This was referenced Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The defect
pipeline_defs/screen-demo.yamlcarries a top-levelproduction_modesblock the manifest schema does not allow, soload_pipeline("screen-demo")raises. The pipeline is marked production stability in AGENT_GUIDE.md's table.lib/checkpoint.pydegrades gracefully when a manifest cannot be parsed. That is right for a corrupt user manifest, but it means a manifest shipped in this repo is silently ignored rather than loudly rejected — and both fallbacks then misfire.1. The pipeline cannot start
The stage-order fallback returns the canonical list, which inserts
researchandproposalahead of screen-demo's real first stage:So the opening checkpoint of every screen-demo run is rejected:
The other five
idea-first pipelines (talking-head,hybrid,clip-factory, …) clear that same check, which isolates the cause to the unloadable manifest rather than the prerequisite rule.2. Its approval gates fail open
Nonemeans the caller's ownhuman_approval_requiredflag wins. All five declared gates —idea,script,scene_plan,assets,publish— stop being binding, against AGENT_GUIDE.md:The repair
production_modesis a documented, first-class feature rather than stray YAML:skills/pipelines/screen-demo/idea-director.mdbuilds its entirereal_capturevssynthetic_terminaldecision table on it, down to which render runtimes each mode permits.pipeline_defs/screen-demo.yaml+skills/pipelines/screen-demo/idea-director.md."best_forandagent_skillselsewhere in the manifest.So the schema is what is stale, and it gains a typed definition for the block, following the shape of the existing
stagesentries.extensionswas considered as a home and rejected: it is a fixed set of four capability booleans (custom_scripts,custom_playbooks,custom_skills,custom_tools), not a free-form bucket.Coverage
Existing manifest tests load
talking-head,framework-smoke,animated-explaineranddocumentary-montageby name, so the one broken manifest was never touched — the same gap that hides this class of bug elsewhere in the repo.tests/contracts/test_pipeline_catalog.pyiteratespipeline_defs/and asserts three things, one per symptom above:human_approval_defaultis what_stage_requires_approvalresolvesVerification
screen-democases fail on the unfixed tree; all 40 pass after.make lint: passed.Independent of #468 and #469 — no overlapping files.
🤖 Generated with Claude Code