{"record":{"id":"44e52bae7e8dee3f","repo":"calesthio/OpenMontage","slug":"unknown-step-kind-k-r","errorCode":null,"errorMessage":"Unknown step kind: {k!r}","messagePattern":"Unknown step kind: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/verify_scene_pacing.py","lineNumber":49,"sourceCode":"\n\ndef step_duration(step: dict[str, Any], fps: int = 30) -> float:\n    \"\"\"Return the cursor-advancement for a single step (frame-accurate).\n\n    Pills DO NOT advance the cursor — they're non-blocking overlays.\n    \"\"\"\n    k = step[\"kind\"]\n    if k == \"cmd\":\n        type_frames = math.ceil(len(step[\"text\"]) * step.get(\"typeSpeed\", 0.035) * fps)\n        return type_frames / fps + step.get(\"holdSeconds\", 0.3)\n    if k == \"out\":\n        reveal_frames = max(2, math.ceil(0.08 * fps))\n        return reveal_frames / fps + step.get(\"holdSeconds\", 0.15)\n    if k == \"pause\":\n        return float(step[\"seconds\"])\n    if k == \"pill\":\n        return 0.0\n    raise ValueError(f\"Unknown step kind: {k!r}\")\n\n\n@dataclass\nclass Landmark:\n    video_time: float\n    kind: str\n    text: str\n\n\ndef trace(steps: list[dict[str, Any]], scene_start: float = 0.0, fps: int = 30, *, quiet: bool = False) -> list[Landmark]:\n    \"\"\"Walk the step list and print a video-time landmark for each visible event.\n\n    Returns the list of landmarks (useful for alignment checks).\n    \"\"\"\n    cursor = 0.0\n    out: list[Landmark] = []\n    for s in steps:\n        k = s[\"kind\"]","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/calesthio/OpenMontage/blob/95e1c3d0ab93482159818560f6a8c8e866b9139f/lib/verify_scene_pacing.py#L31-L67","documentation":"Raised by lib/verify_scene_pacing.py's step_duration() when a scene step dict has a 'kind' value other than the four supported kinds: 'cmd', 'out', 'pause', 'pill'. Each kind has its own duration model — 'cmd' types text at typeSpeed (default 0.035s/char) plus holdSeconds (default 0.3), 'out' is a reveal of ~0.08s plus holdSeconds (default 0.15), 'pause' is its explicit seconds, 'pill' is instant (0.0). An unknown kind means the pacing verifier cannot compute the timeline and refuses to guess.","triggerScenarios":"Feeding assert_alignment()/trace() a steps list containing a step like {'kind': 'wait', 'seconds': 2} or a typo like {'kind': 'cmdd'}; generating steps with a template or LLM that invents kind values; using a new step kind added to the renderer but not to this verifier.","commonSituations":"Hand-written or machine-generated scene step YAML with kind typos; renderer and verifier drifting out of sync when a new step kind is introduced; copy-pasting steps from a different scene format.","solutions":["Correct the step to one of the four kinds: cmd, out, pause, pill (use 'pause' with seconds for waits).","Validate kinds before tracing: assert all(s['kind'] in {'cmd','out','pause','pill'} for s in steps).","If you added a new kind to the renderer, add a matching duration branch to step_duration() in lib/verify_scene_pacing.py."],"exampleFix":"# before\nsteps = [{\"kind\": \"wait\", \"seconds\": 2.0}]\n\n# after\nsteps = [{\"kind\": \"pause\", \"seconds\": 2.0}]","handlingStrategy":"type-guard","validationCode":"VALID_KINDS = {\"cmd\", \"out\", \"pause\", \"pill\"}\nbad = [i for i, s in enumerate(steps) if s.get(\"kind\") not in VALID_KINDS]\nif bad:\n    raise ValueError(f\"Invalid step kind at indices {bad}; valid kinds: {sorted(VALID_KINDS)}\")","typeGuard":"from typing import Literal\nStepKind = Literal[\"cmd\", \"out\", \"pause\", \"pill\"]\n\ndef steps_are_valid(steps: list[dict]) -> bool:\n    return all(s.get(\"kind\") in {\"cmd\", \"out\", \"pause\", \"pill\"} for s in steps)","tryCatchPattern":"try:\n    trace(steps, scene_start, fps)\nexcept ValueError as e:\n    if \"Unknown step kind\" in str(e):\n        # bad generated steps — regenerate or repair before verifying pacing\n        raise SceneStepError(str(e)) from e\n    raise","preventionTips":["Validate the kind vocabulary immediately after generating or loading scene steps.","Use 'pause' with an explicit seconds field for any wait step.","When adding a renderer step kind, update step_duration() in the same change."],"tags":["scene","pacing","validation","video"],"backgroundTag":null,"analyzedSha":"95e1c3d0ab93482159818560f6a8c8e866b9139f","analyzedAt":"2026-08-15T06:31:20.014Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}