Skip to content

fix(pipelines): make the screen-demo manifest load - #472

Open
bbudaedu wants to merge 1 commit into
calesthio:mainfrom
bbudaedu:fix/screen-demo-manifest-schema
Open

fix(pipelines): make the screen-demo manifest load#472
bbudaedu wants to merge 1 commit into
calesthio:mainfrom
bbudaedu:fix/screen-demo-manifest-schema

Conversation

@bbudaedu

@bbudaedu bbudaedu commented Aug 4, 2026

Copy link
Copy Markdown

The defect

pipeline_defs/screen-demo.yaml carries a top-level production_modes block the manifest schema does not allow, so load_pipeline("screen-demo") raises. The pipeline is marked production stability in AGENT_GUIDE.md's table.

lib/checkpoint.py degrades 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 research and proposal ahead of screen-demo's real first stage:

get_pipeline_stages("screen-demo")
  ->  [research, proposal, idea, script, scene_plan, assets, edit, compose, publish]
manifest declares
  ->  [idea, script, scene_plan, assets, edit, compose, publish]

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 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

_stage_requires_approval("screen-demo", "idea")  ->  None      # manifest declares True

None means the caller's own human_approval_required flag wins. All five declared gates — idea, script, scene_plan, assets, publish — stop being binding, against AGENT_GUIDE.md:

Read human_approval_default from the pipeline manifest per stage. The manifest value is binding — never re-judge it.

The repair

production_modes is a documented, first-class feature rather than stray YAML:

  • skills/pipelines/screen-demo/idea-director.md builds its entire real_capture vs synthetic_terminal decision table on it, down to which render runtimes each mode permits.
  • AGENT_GUIDE.md routes agents to this manifest to make that choice: "Picking a screen-recording mode (real capture vs synthetic terminal)? → pipeline_defs/screen-demo.yaml + skills/pipelines/screen-demo/idea-director.md."
  • Nothing in Python reads it — it is agent-facing declarative content, like best_for and agent_skills elsewhere 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 stages entries.

extensions was 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-explainer and documentary-montage by 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.py iterates pipeline_defs/ and asserts three things, one per symptom above:

  • every shipped manifest validates
  • the stage order the checkpoint writer actually uses equals the one the manifest declares
  • every declared human_approval_default is what _stage_requires_approval resolves

Verification

  • The 3 screen-demo cases fail on the unfixed tree; all 40 pass after.
  • Full suite: 964 → 1004 passed, 10 skipped, no regressions.
  • make lint: passed.

Independent of #468 and #469 — no overlapping files.

🤖 Generated with Claude Code

`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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant