Table of Contents - Overview - Command Options - Required TodoWrite Items - Phase 1: Discovery ( )) - Step 1.1: Locate Tutorial Assets - Step 1.2: Parse Manifests - Step 1.3: Handle Options - Phase 1.5: Validation ( )) - Step 1.5.1: VHS Syntax Validation - Step 1.5.2: Extract and Validate CLI Commands - Step 1.5.3: Verify Demo Data Exists - Step 1.5.4: Test Commands Locally - Validation Flags - Validation Exit Criteria - Phase 1.6: Binary Rebuild ( )) - Step 1.6.1: Detect Build System - Step 1.6.2: Check Binary Freshness - Step 1.6.3: Rebuild Binary - Step 1.6.4: Verify Binary Accessibility -…

| \\\n grep -v '^

Table of Contents - Overview - Command Options - Required TodoWrite Items - Phase 1: Discovery ( )) - Step 1.1: Locate Tutorial Assets - Step 1.2: Parse Manifests - Step 1.3: Handle Options - Phase 1.5: Validation ( )) - Step 1.5.1: VHS Syntax Validation - Step 1.5.2: Extract and Validate CLI Commands - Step 1.5.3: Verify Demo Data Exists - Step 1.5.4: Test Commands Locally - Validation Flags - Validation Exit Criteria - Phase 1.6: Binary Rebuild ( )) - Step 1.6.1: Detect Build System - Step 1.6.2: Check Binary Freshness - Step 1.6.3: Rebuild Binary - Step 1.6.4: Verify Binary Accessibility -…

\n}\n```\n\n**Example**:\n```vhs\nType \"skrills validate --errors-only\"\n```\nExtracts: `skrills validate --errors-only`\n\n### 3. CLI Flag Validation\n\nFor each extracted command, validate flags exist:\n\n```bash\nvalidate_command_flags() {\n local cmd=\"$1\"\n local line_num=\"$2\"\n\n # Extract the base command (e.g., \"skrills validate\")\n local base_cmd=$(echo \"$cmd\" | awk '{print $1, $2}')\n\n # Get help output for flag discovery\n local help_output=$($base_cmd --help 2>&1)\n\n # Extract flags from the command\n local flags=$(echo \"$cmd\" | grep -oE '\\-\\-[a-zA-Z0-9-]+')\n\n for flag in $flags; do\n if ! echo \"$help_output\" | grep -q -- \"$flag\"; then\n echo \"ERROR: Invalid flag '$flag' at line $line_num\"\n echo \" Command: $cmd\"\n echo \" Run '$base_cmd --help' to see available flags\"\n fi\n done\n}\n```\n\n**Example validation**:\n```bash\n# Command from tape line 12\nskrills create demo --sample basic\n\n# Validation\n$ skrills create --help | grep -- '--sample'\n# (no output - flag doesn't exist)\n\n# Error output\nERROR: Invalid flag '--sample' at line 12\n Command: skrills create demo --sample basic\n Run 'skrills create --help' to see available flags\n```\n\n### 4. Demo Data Verification\n\nCheck that demo directories and skills exist:\n\n```bash\nverify_demo_data() {\n local tape_file=\"$1\"\n\n # Extract Env SKRILLS_SKILL_DIR if set\n local skill_dir=$(grep '^Env SKRILLS_SKILL_DIR' \"$tape_file\" | \\\n sed 's/.*\"\\(.*\\)\"/\\1/')\n\n if [ -n \"$skill_dir\" ]; then\n if [ ! -d \"$skill_dir\" ]; then\n echo \"ERROR: Demo skill directory does not exist: $skill_dir\"\n return 1\n fi\n\n # Check it has content\n local skill_count=$(find \"$skill_dir\" -name \"SKILL.md\" 2>/dev/null | wc -l)\n if [ \"$skill_count\" -eq 0 ]; then\n echo \"ERROR: Demo skill directory is empty: $skill_dir\"\n echo \" Expected at least one SKILL.md file\"\n return 1\n fi\n\n echo \"OK: Demo skills found: $skill_count skills in $skill_dir\"\n fi\n\n # Check for other referenced directories\n grep '^Type.*mkdir\\|^Type.*cp\\|^Type.*cd' \"$tape_file\" | while read -r line; do\n # Extract directory paths and verify parent exists\n # This is optional - catches obvious path errors\n true\n done\n}\n```\n\n### 5. Expected Output Verification\n\nFor commands that should produce visible output, verify they will:\n\n```bash\nverify_expected_output() {\n local cmd=\"$1\"\n\n # Skip echo commands (always produce output)\n echo \"$cmd\" | grep -q '^echo ' && return 0\n\n # For skrills commands, do a dry-run to verify output\n if echo \"$cmd\" | grep -q '^skrills '; then\n # Run with --help to verify command exists\n local base=$(echo \"$cmd\" | awk '{print $1, $2}')\n if ! $base --help &>/dev/null; then\n echo \"WARNING: Command may not produce output: $cmd\"\n fi\n fi\n}\n```\n\n## Complete Validation Script\n\n```bash\n#!/bin/bash\n# validate_tape.sh - Pre-flight validation for VHS tape files\n\nvalidate_tape() {\n local tape_file=\"$1\"\n local errors=0\n\n echo \"=== Validating: $tape_file ===\"\n\n # Phase 1: Syntax\n echo \"Phase 1: VHS Syntax...\"\n if ! grep -q '^Output ' \"$tape_file\"; then\n echo \" ERROR: Missing Output directive\"\n ((errors++))\n else\n echo \" OK: Output directive found\"\n fi\n\n # Phase 2: Extract commands\n echo \"Phase 2: Extracting commands...\"\n local line_num=0\n local cmd_count=0\n while IFS= read -r line; do\n ((line_num++))\n if [[ \"$line\" =~ ^Type\\ \\\" ]]; then\n cmd=$(echo \"$line\" | sed 's/^Type \"//' | sed 's/\"$//')\n ((cmd_count++))\n\n # Phase 3: Validate CLI flags\n if [[ \"$cmd\" =~ ^skrills ]]; then\n base_cmd=$(echo \"$cmd\" | awk '{print $1, $2}')\n flags=$(echo \"$cmd\" | grep -oE '\\-\\-[a-zA-Z0-9-]+' || true)\n\n if [ -n \"$flags\" ]; then\n help_output=$($base_cmd --help 2>&1 || echo \"\")\n for flag in $flags; do\n if ! echo \"$help_output\" | grep -q -- \"$flag\"; then\n echo \" ERROR: Invalid flag '$flag' at line $line_num\"\n echo \" Command: $cmd\"\n ((errors++))\n fi\n done\n fi\n fi\n fi\n done \u003c \"$tape_file\"\n echo \" Extracted $cmd_count commands\"\n\n # Phase 4: Demo data\n echo \"Phase 4: Demo data verification...\"\n skill_dir=$(grep '^Env SKRILLS_SKILL_DIR' \"$tape_file\" | sed 's/.*\"\\(.*\\)\"/\\1/' || true)\n if [ -n \"$skill_dir\" ]; then\n if [ ! -d \"$skill_dir\" ]; then\n echo \" ERROR: Demo skill directory missing: $skill_dir\"\n ((errors++))\n else\n skill_count=$(find \"$skill_dir\" -name \"SKILL.md\" 2>/dev/null | wc -l)\n if [ \"$skill_count\" -eq 0 ]; then\n echo \" ERROR: No skills in demo directory: $skill_dir\"\n ((errors++))\n else\n echo \" OK: Found $skill_count demo skills\"\n fi\n fi\n fi\n\n # Summary\n echo \"=== Validation Complete ===\"\n if [ \"$errors\" -eq 0 ]; then\n echo \"PASSED: No errors found\"\n return 0\n else\n echo \"FAILED: $errors error(s) found\"\n return 1\n fi\n}\n\n# Run if called directly\nif [ -n \"$1\" ]; then\n validate_tape \"$1\"\nfi\n```\n\n## Integration with Workflow\n\nBefore running VHS, execute validation:\n\n```bash\n# In the tutorial-updates skill Phase 1.5\nvalidate_tape \"$tape_file\"\nif [ $? -ne 0 ]; then\n echo \"Validation failed. Fix errors before running VHS.\"\n exit 1\nfi\n\n# Proceed to VHS recording\nvhs \"$tape_file\"\n```\n\n## Flags\n\n### `--validate-only`\n\nRun validation without generating GIF:\n\n```bash\n# Validate all tapes without recording\nfor tape in assets/tapes/*.tape; do\n validate_tape \"$tape\"\ndone\n```\n\n### `--skip-validation`\n\nBypass validation for rapid regeneration:\n\n```bash\n# Skip validation when commands are known-good\nif [ \"$SKIP_VALIDATION\" != \"true\" ]; then\n validate_tape \"$tape_file\" || exit 1\nfi\nvhs \"$tape_file\"\n```\n\n## Exit Codes\n\n| Code | Meaning |\n|------|---------|\n| 0 | Validation passed |\n| 1 | Validation failed (errors found) |\n| 2 | Validation skipped (--skip-validation) |\n\n## Error Message Format\n\nStandardized format for actionable errors:\n\n```\nERROR: \u003cshort-description> at line \u003cnumber>\n Command: \u003cfull-command>\n \u003chint-or-available-options>\n```\n\nExample:\n```\nERROR: Invalid flag '--sample' at line 12\n Command: skrills validate --sample 5\n Run 'skrills validate --help' to see available flags\n```\n","content_type":"text/markdown; charset=utf-8","language":"markdown","size":9405,"content_sha256":"bc956bc21e96992125db662e605885c44febf44cc794191e9ee2062b96d09d93"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":2},"content":[{"text":"Table of Contents","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Overview","type":"text","marks":[{"type":"link","attrs":{"href":"#overview","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Command Options","type":"text","marks":[{"type":"link","attrs":{"href":"#command-options","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Required TodoWrite Items","type":"text","marks":[{"type":"link","attrs":{"href":"#required-todowrite-items","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Phase 1: Discovery (","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-1:-discovery-(tutorial-updates:discovery)","title":null}}]},{"text":"tutorial-updates:discovery","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-1:-discovery-(tutorial-updates:discovery)","title":null}},{"type":"code_inline"}]},{"text":")","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-1:-discovery-(tutorial-updates:discovery)","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.1: Locate Tutorial Assets","type":"text","marks":[{"type":"link","attrs":{"href":"#step-11:-locate-tutorial-assets","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.2: Parse Manifests","type":"text","marks":[{"type":"link","attrs":{"href":"#step-12:-parse-manifests","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.3: Handle Options","type":"text","marks":[{"type":"link","attrs":{"href":"#step-13:-handle-options","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Phase 1.5: Validation (","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-15:-validation-(tutorial-updates:validation)","title":null}}]},{"text":"tutorial-updates:validation","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-15:-validation-(tutorial-updates:validation)","title":null}},{"type":"code_inline"}]},{"text":")","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-15:-validation-(tutorial-updates:validation)","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.5.1: VHS Syntax Validation","type":"text","marks":[{"type":"link","attrs":{"href":"#step-151:-vhs-syntax-validation","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.5.2: Extract and Validate CLI Commands","type":"text","marks":[{"type":"link","attrs":{"href":"#step-152:-extract-and-validate-cli-commands","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.5.3: Verify Demo Data Exists","type":"text","marks":[{"type":"link","attrs":{"href":"#step-153:-verify-demo-data-exists","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.5.4: Test Commands Locally","type":"text","marks":[{"type":"link","attrs":{"href":"#step-154:-test-commands-locally","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validation Flags","type":"text","marks":[{"type":"link","attrs":{"href":"#validation-flags","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validation Exit Criteria","type":"text","marks":[{"type":"link","attrs":{"href":"#validation-exit-criteria","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Phase 1.6: Binary Rebuild (","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-16:-binary-rebuild-(tutorial-updates:rebuild)","title":null}}]},{"text":"tutorial-updates:rebuild","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-16:-binary-rebuild-(tutorial-updates:rebuild)","title":null}},{"type":"code_inline"}]},{"text":")","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-16:-binary-rebuild-(tutorial-updates:rebuild)","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.6.1: Detect Build System","type":"text","marks":[{"type":"link","attrs":{"href":"#step-161:-detect-build-system","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.6.2: Check Binary Freshness","type":"text","marks":[{"type":"link","attrs":{"href":"#step-162:-check-binary-freshness","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.6.3: Rebuild Binary","type":"text","marks":[{"type":"link","attrs":{"href":"#step-163:-rebuild-binary","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 1.6.4: Verify Binary Accessibility","type":"text","marks":[{"type":"link","attrs":{"href":"#step-164:-verify-binary-accessibility","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Rebuild Flags","type":"text","marks":[{"type":"link","attrs":{"href":"#rebuild-flags","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Rebuild Exit Criteria","type":"text","marks":[{"type":"link","attrs":{"href":"#rebuild-exit-criteria","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Phase 2: Recording (","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-2:-recording-(tutorial-updates:recording)","title":null}}]},{"text":"tutorial-updates:recording","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-2:-recording-(tutorial-updates:recording)","title":null}},{"type":"code_inline"}]},{"text":")","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-2:-recording-(tutorial-updates:recording)","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 2.1: Process Tape Components","type":"text","marks":[{"type":"link","attrs":{"href":"#step-21:-process-tape-components","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 2.2: Process Browser Components","type":"text","marks":[{"type":"link","attrs":{"href":"#step-22:-process-browser-components","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 2.3: Handle Multi-Component Tutorials","type":"text","marks":[{"type":"link","attrs":{"href":"#step-23:-handle-multi-component-tutorials","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Phase 3: Generation (","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-3:-generation-(tutorial-updates:generation)","title":null}}]},{"text":"tutorial-updates:generation","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-3:-generation-(tutorial-updates:generation)","title":null}},{"type":"code_inline"}]},{"text":")","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-3:-generation-(tutorial-updates:generation)","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 3.1: Parse Tape Annotations","type":"text","marks":[{"type":"link","attrs":{"href":"#step-31:-parse-tape-annotations","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 3.2: Generate Dual-Tone Markdown","type":"text","marks":[{"type":"link","attrs":{"href":"#step-32:-generate-dual-tone-markdown","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 3.3: Generate README Demo Section","type":"text","marks":[{"type":"link","attrs":{"href":"#step-33:-generate-readme-demo-section","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Demos","type":"text","marks":[{"type":"link","attrs":{"href":"#demos","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Quickstart","type":"text","marks":[{"type":"link","attrs":{"href":"#quickstart","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Phase 4: Integration (","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-4:-integration-(tutorial-updates:integration)","title":null}}]},{"text":"tutorial-updates:integration","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-4:-integration-(tutorial-updates:integration)","title":null}},{"type":"code_inline"}]},{"text":")","type":"text","marks":[{"type":"link","attrs":{"href":"#phase-4:-integration-(tutorial-updates:integration)","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 4.1: Verify All Outputs","type":"text","marks":[{"type":"link","attrs":{"href":"#step-41:-verify-all-outputs","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 4.2: Update SUMMARY.md (Book)","type":"text","marks":[{"type":"link","attrs":{"href":"#step-42:-update-summarymd-(book)","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Step 4.3: Report Results","type":"text","marks":[{"type":"link","attrs":{"href":"#step-43:-report-results","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Exit Criteria","type":"text","marks":[{"type":"link","attrs":{"href":"#exit-criteria","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Error Handling","type":"text","marks":[{"type":"link","attrs":{"href":"#error-handling","title":null}}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Scaffold Mode","type":"text","marks":[{"type":"link","attrs":{"href":"#scaffold-mode","title":null}}]}]}]}]},{"type":"heading","attrs":{"level":1},"content":[{"text":"Tutorial Updates Skill","type":"text"}]},{"type":"paragraph","content":[{"text":"Orchestrate tutorial generation with GIF recordings from VHS tape files and Playwright browser specs.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When To Use","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generating or updating user-facing tutorials","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Creating VHS and Playwright tutorial recordings","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"When NOT To Use","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Internal documentation without user-facing tutorials","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"API reference docs - use scribe:doc-generator instead","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"paragraph","content":[{"text":"This skill coordinates the complete tutorial generation pipeline:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Discover tape files and manifests in the project","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validate tape commands and check binary freshness","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Rebuild binaries if stale so demos reflect latest code","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Record terminal sessions using VHS (scry:vhs-recording)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Record browser sessions using Playwright (scry:browser-recording)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generate optimized GIFs (scry:gif-generation)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Compose multi-component tutorials (scry:media-composition)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Generate dual-tone markdown for docs/ and book/","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Command Options","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"/update-tutorial quickstart # Single tutorial by name\n/update-tutorial sync mcp # Multiple tutorials\n/update-tutorial --all # All tutorials with manifests\n/update-tutorial --list # Show available tutorials\n/update-tutorial --scaffold # Create structure without recording","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Required TodoWrite Items","type":"text"}]},{"type":"paragraph","content":[{"text":"Create todos with these prefixes for progress tracking:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"**Verification:** Run the command with `--help` flag to verify availability.\n- tutorial-updates:discovery\n- tutorial-updates:validation\n- tutorial-updates:rebuild\n- tutorial-updates:recording\n- tutorial-updates:generation\n- tutorial-updates:integration","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 1: Discovery (","type":"text"},{"text":"tutorial-updates:discovery","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.1: Locate Tutorial Assets","type":"text"}]},{"type":"paragraph","content":[{"text":"Find tape files and manifests in the project:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Find manifest files\nfind . -name \"*.manifest.yaml\" -type f \\\n -not -path \"*/.venv/*\" -not -path \"*/__pycache__/*\" \\\n -not -path \"*/node_modules/*\" -not -path \"*/.git/*\" \\\n 2>/dev/null | head -20\n\n# Find tape files\nfind . -name \"*.tape\" -type f \\\n -not -path \"*/.venv/*\" -not -path \"*/__pycache__/*\" \\\n -not -path \"*/node_modules/*\" -not -path \"*/.git/*\" \\\n 2>/dev/null | head -20\n\n# Find browser specs\nfind . -name \"*.spec.ts\" -path \"*/browser/*\" -type f \\\n -not -path \"*/.venv/*\" -not -path \"*/__pycache__/*\" \\\n -not -path \"*/node_modules/*\" -not -path \"*/.git/*\" \\\n 2>/dev/null | head -20","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.2: Parse Manifests","type":"text"}]},{"type":"paragraph","content":[{"text":"For each manifest file, extract:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Tutorial name and title","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Component list (tape files, playwright specs)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Output paths for GIFs","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Composition rules (layout, combine options)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"modules/manifest-parsing.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for manifest schema details.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.3: Handle Options","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Option","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Behavior","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--list","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Display discovered tutorials and exit","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--all","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Process all discovered manifests","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--scaffold","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Create directory structure and empty files without recording","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"\u003cnames>","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Process only specified tutorials","type":"text"}]}]}]}]},{"type":"paragraph","content":[{"text":"When ","type":"text"},{"text":"--list","type":"text","marks":[{"type":"code_inline"}]},{"text":" is specified:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"**Verification:** Run the command with `--help` flag to verify availability.\nAvailable tutorials:\n quickstart assets/tapes/quickstart.tape\n sync assets/tapes/sync.tape (manifest)\n mcp assets/tapes/mcp.manifest.yaml (terminal + browser)\n skill-debug assets/tapes/skill-debug.tape","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 1.5: Validation (","type":"text"},{"text":"tutorial-updates:validation","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"paragraph","content":[{"text":"CRITICAL","type":"text","marks":[{"type":"strong"}]},{"text":": Validate tape commands BEFORE running VHS to avoid expensive regeneration cycles.","type":"text"}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"modules/tape-validation.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for detailed validation logic.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.5.1: VHS Syntax Validation","type":"text"}]},{"type":"paragraph","content":[{"text":"Check each tape file for valid VHS syntax:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Required: Output directive exists\ngrep -q '^Output ' \"$tape_file\" || echo \"ERROR: Missing Output directive\"\n\n# Check for balanced quotes in Type directives\ngrep '^Type ' \"$tape_file\" | while read -r line; do\n quote_count=$(echo \"$line\" | tr -cd '\"' | wc -c)\n if [ $((quote_count % 2)) -ne 0 ]; then\n echo \"ERROR: Unbalanced quotes: $line\"\n fi\ndone","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.5.2: Extract and Validate CLI Commands","type":"text"}]},{"type":"paragraph","content":[{"text":"For each ","type":"text"},{"text":"Type","type":"text","marks":[{"type":"code_inline"}]},{"text":" directive, extract the command and validate flags:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Extract commands from Type directives\ngrep '^Type ' \"$tape_file\" | sed 's/^Type \"//' | sed 's/\"$//' | while read -r cmd; do\n # Skip comments, clear, and echo commands\n [[ \"$cmd\" =~ ^# ]] && continue\n [[ \"$cmd\" == \"clear\" ]] && continue\n\n # For skrills commands, validate flags exist\n if [[ \"$cmd\" =~ ^skrills ]]; then\n base_cmd=$(echo \"$cmd\" | awk '{print $1, $2}')\n flags=$(echo \"$cmd\" | grep -oE '\\-\\-[a-zA-Z0-9-]+' || true)\n\n for flag in $flags; do\n if ! $base_cmd --help 2>&1 | grep -q -- \"$flag\"; then\n echo \"ERROR: Invalid flag '$flag' in command: $cmd\"\n fi\n done\n fi\ndone","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.5.3: Verify Demo Data Exists","type":"text"}]},{"type":"paragraph","content":[{"text":"If the tape uses demo data, verify it exists and is populated:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check SKRILLS_SKILL_DIR if set\nskill_dir=$(grep '^Env SKRILLS_SKILL_DIR' \"$tape_file\" | sed 's/.*\"\\(.*\\)\"/\\1/')\nif [ -n \"$skill_dir\" ]; then\n if [ ! -d \"$skill_dir\" ]; then\n echo \"ERROR: Demo skill directory missing: $skill_dir\"\n else\n skill_count=$(find \"$skill_dir\" -name \"SKILL.md\" 2>/dev/null | wc -l)\n if [ \"$skill_count\" -eq 0 ]; then\n echo \"ERROR: No skills in demo directory: $skill_dir\"\n else\n echo \"OK: Found $skill_count demo skills in $skill_dir\"\n fi\n fi\nfi","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.5.4: Test Commands Locally","type":"text"}]},{"type":"paragraph","content":[{"text":"CRITICAL","type":"text","marks":[{"type":"strong"}]},{"text":": Run each extracted command locally to verify it produces expected output:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# For each command in the tape, do a quick sanity check\n# This catches issues like:\n# - Commands that exit with non-zero status\n# - Commands that produce no output (won't show anything in GIF)\n# - Commands that require user input (will hang VHS)\n\nfor cmd in $(extract_commands \"$tape_file\"); do\n # Run with timeout to catch hanging commands\n if ! timeout 5s bash -c \"$cmd\" &>/dev/null; then\n echo \"WARNING: Command may fail or hang: $cmd\"\n fi\ndone","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Validation Flags","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flag","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Behavior","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--validate-only","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Run validation without generating GIF","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--skip-validation","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Bypass validation for rapid regeneration","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Validation Exit Criteria","type":"text"}]},{"type":"checkbox_list","attrs":{"id":null},"content":[{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"VHS tape syntax is valid (Output directive, balanced quotes)","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"All CLI flags in commands are valid (verified against --help)","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Demo data directories exist and are populated","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Commands execute successfully with expected output","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"If validation fails","type":"text","marks":[{"type":"strong"}]},{"text":": Stop immediately, report errors, and do NOT proceed to VHS recording.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 1.6: Binary Rebuild (","type":"text"},{"text":"tutorial-updates:rebuild","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"paragraph","content":[{"text":"CRITICAL","type":"text","marks":[{"type":"strong"}]},{"text":": Ensure the binary being tested in tapes matches the latest source code. Stale binaries produce misleading demos.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.6.1: Detect Build System","type":"text"}]},{"type":"paragraph","content":[{"text":"Identify the project's build system:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check for Cargo (Rust)\nif [ -f \"Cargo.toml\" ]; then\n BUILD_SYSTEM=\"cargo\"\n BINARY_NAME=$(grep '^name = ' Cargo.toml | head -1 | sed 's/.*\"\\(.*\\)\"/\\1/')\n echo \"Detected Cargo project: $BINARY_NAME\"\n# Check for Makefile\nelif [ -f \"Makefile\" ]; then\n BUILD_SYSTEM=\"make\"\n echo \"Detected Make project\"\n# Unknown\nelse\n echo \"WARNING: Unknown build system, skipping binary check\"\n BUILD_SYSTEM=\"unknown\"\nfi","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run ","type":"text"},{"text":"make --dry-run","type":"text","marks":[{"type":"code_inline"}]},{"text":" to verify build configuration.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.6.2: Check Binary Freshness","type":"text"}]},{"type":"paragraph","content":[{"text":"Compare binary modification time against Git HEAD:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"check_binary_freshness() {\n local binary_name=\"$1\"\n\n # Locate binary (check cargo install location first, then PATH)\n local binary_path=$(which \"$binary_name\" 2>/dev/null)\n\n if [ -z \"$binary_path\" ]; then\n echo \"WARNING: Binary '$binary_name' not found in PATH\"\n return 1\n fi\n\n # Get binary modification time (Linux/macOS compatible)\n local binary_mtime\n if command -v stat >/dev/null 2>&1; then\n # Linux\n binary_mtime=$(stat -c %Y \"$binary_path\" 2>/dev/null || \\\n # macOS\n stat -f %m \"$binary_path\" 2>/dev/null)\n else\n echo \"WARNING: stat command not available, skipping freshness check\"\n return 2\n fi\n\n # Get Git HEAD commit time\n local git_head_time=$(git log -1 --format=%ct 2>/dev/null)\n\n if [ -z \"$git_head_time\" ]; then\n echo \"WARNING: Not a git repository, skipping freshness check\"\n return 2\n fi\n\n # Compare timestamps\n if [ \"$binary_mtime\" -lt \"$git_head_time\" ]; then\n echo \"STALE: Binary is older than Git HEAD\"\n echo \" Binary: $(date -d @$binary_mtime 2>/dev/null || date -r $binary_mtime)\"\n echo \" HEAD: $(date -d @$git_head_time 2>/dev/null || date -r $git_head_time)\"\n return 1\n else\n echo \"OK: Binary is up-to-date\"\n return 0\n fi\n}","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run ","type":"text"},{"text":"git status","type":"text","marks":[{"type":"code_inline"}]},{"text":" to confirm working tree state.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.6.3: Rebuild Binary","type":"text"}]},{"type":"paragraph","content":[{"text":"Rebuild using the detected build system:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"rebuild_binary() {\n local build_system=\"$1\"\n local binary_name=\"$2\"\n\n case \"$build_system\" in\n cargo)\n echo \"Rebuilding with Cargo...\"\n # Use cargo install for CLI binaries\n if [ -d \"crates/cli\" ]; then\n cargo install --path crates/cli --locked --quiet\n else\n cargo install --path . --locked --quiet\n fi\n ;;\n make)\n echo \"Rebuilding with Make...\"\n make build --quiet\n ;;\n *)\n echo \"ERROR: Cannot rebuild, unknown build system\"\n return 1\n ;;\n esac\n\n echo \"Build complete: $binary_name\"\n}","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run ","type":"text"},{"text":"make --dry-run","type":"text","marks":[{"type":"code_inline"}]},{"text":" to verify build configuration.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 1.6.4: Verify Binary Accessibility","type":"text"}]},{"type":"paragraph","content":[{"text":"Ensure the rebuilt binary is accessible:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"verify_binary() {\n local binary_name=\"$1\"\n\n if ! command -v \"$binary_name\" >/dev/null 2>&1; then\n echo \"ERROR: Binary '$binary_name' not found after rebuild\"\n echo \" Check PATH includes: $HOME/.cargo/bin\"\n return 1\n fi\n\n # Test binary can execute\n if ! \"$binary_name\" --version >/dev/null 2>&1; then\n echo \"WARNING: Binary exists but --version failed\"\n else\n echo \"OK: Binary is accessible and functional\"\n \"$binary_name\" --version\n fi\n}","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run ","type":"text"},{"text":"pytest -v","type":"text","marks":[{"type":"code_inline"}]},{"text":" to verify tests pass.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Rebuild Flags","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Flag","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Behavior","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--skip-rebuild","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Skip binary freshness check and rebuild","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--force-rebuild","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Force rebuild even if binary is fresh","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Rebuild Exit Criteria","type":"text"}]},{"type":"checkbox_list","attrs":{"id":null},"content":[{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Build system detected (Cargo, Make, or explicitly skipped)","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Binary freshness checked against Git HEAD","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Binary rebuilt if stale (or forced)","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Rebuilt binary is accessible in PATH","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Binary executes successfully (--version test)","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"If rebuild fails","type":"text","marks":[{"type":"strong"}]},{"text":": Stop immediately, report build errors, and do NOT proceed to tape validation or VHS recording.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 2: Recording (","type":"text"},{"text":"tutorial-updates:recording","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2.1: Process Tape Components","type":"text"}]},{"type":"paragraph","content":[{"text":"For each tape file component:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Parse tape file for metadata annotations (@step, @docs-brief, @book-detail)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Validate Output directive exists","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Invoke ","type":"text"},{"text":"Skill(scry:vhs-recording)","type":"text","marks":[{"type":"code_inline"}]},{"text":" with tape file path","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify GIF output was created","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2.2: Process Browser Components","type":"text"}]},{"type":"paragraph","content":[{"text":"For each playwright spec component:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Check ","type":"text"},{"text":"requires","type":"text","marks":[{"type":"code_inline"}]},{"text":" field for prerequisite commands (e.g., start server)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Launch any required background processes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Invoke ","type":"text"},{"text":"Skill(scry:browser-recording)","type":"text","marks":[{"type":"code_inline"}]},{"text":" with spec path","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Stop background processes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Invoke ","type":"text"},{"text":"Skill(scry:gif-generation)","type":"text","marks":[{"type":"code_inline"}]},{"text":" to convert WebM to GIF","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 2.3: Handle Multi-Component Tutorials","type":"text"}]},{"type":"paragraph","content":[{"text":"For manifests with ","type":"text"},{"text":"combine","type":"text","marks":[{"type":"code_inline"}]},{"text":" section:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify all component GIFs exist","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Invoke ","type":"text"},{"text":"Skill(scry:media-composition)","type":"text","marks":[{"type":"code_inline"}]},{"text":" with manifest","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Verify combined output was created","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 3: Generation (","type":"text"},{"text":"tutorial-updates:generation","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3.1: Parse Tape Annotations","type":"text"}]},{"type":"paragraph","content":[{"text":"Extract documentation content from tape files:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"tape"},"content":[{"text":"# @step Install skrills\n# @docs-brief Install via cargo\n# @book-detail The recommended installation method uses cargo...\nType \"cargo install skrills\"","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"paragraph","content":[{"text":"Annotations:","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@step","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Step title/heading","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@docs-brief","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Concise text for project docs (docs/ directory)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"@book-detail","type":"text","marks":[{"type":"code_inline"}]},{"text":" - Extended text for technical book (book/ directory)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3.2: Generate Dual-Tone Markdown","type":"text"}]},{"type":"paragraph","content":[{"text":"Generate two versions of each tutorial:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Project docs","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"docs/tutorials/\u003cname>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Brief, action-oriented","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Uses @docs-brief content","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Focuses on commands and quick results","type":"text"}]}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Technical book","type":"text","marks":[{"type":"strong"}]},{"text":" (","type":"text"},{"text":"book/src/tutorials/\u003cname>.md","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Detailed, educational","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Uses @book-detail content","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Explains concepts and rationale","type":"text"}]}]}]}]}]},{"type":"paragraph","content":[{"text":"See ","type":"text"},{"text":"modules/markdown-generation.md","type":"text","marks":[{"type":"code_inline"}]},{"text":" for formatting details.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 3.3: Generate README Demo Section","type":"text"}]},{"type":"paragraph","content":[{"text":"Create or update demo section in README.md:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"## Demos\n\n### Quickstart\n![Quickstart demo](assets/gifs/quickstart.gif)\n*Install, validate, analyze, and serve in under a minute. [Full tutorial](docs/tutorials/quickstart.md)*","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Phase 4: Integration (","type":"text"},{"text":"tutorial-updates:integration","type":"text","marks":[{"type":"code_inline"}]},{"text":")","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4.1: Verify All Outputs","type":"text"}]},{"type":"paragraph","content":[{"text":"Confirm all expected files exist:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Check GIF files\nfor gif in assets/gifs/*.gif; do\n if [[ -f \"$gif\" ]]; then\n echo \"OK: $gif ($(du -h \"$gif\" | cut -f1))\"\n else\n echo \"MISSING: $gif\"\n fi\ndone\n\n# Check markdown files\nls -la docs/tutorials/*.md 2>/dev/null\nls -la book/src/tutorials/*.md 2>/dev/null","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4.2: Update SUMMARY.md (Book)","type":"text"}]},{"type":"paragraph","content":[{"text":"If the project has an mdBook structure, update ","type":"text"},{"text":"book/src/SUMMARY.md","type":"text","marks":[{"type":"code_inline"}]},{"text":":","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"markdown"},"content":[{"text":"- [Tutorials](./tutorials/README.md)\n - [Quickstart](./tutorials/quickstart.md)\n - [Sync Workflow](./tutorials/sync.md)\n - [MCP Integration](./tutorials/mcp.md)\n - [Skill Debugging](./tutorials/skill-debug.md)","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Step 4.3: Report Results","type":"text"}]},{"type":"paragraph","content":[{"text":"Summarize the update:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":""},"content":[{"text":"**Verification:** Run the command with `--help` flag to verify availability.\nTutorial Update Complete\n========================\nTutorials processed: 4\nGIFs generated: 5\n - quickstart.gif (1.2MB)\n - sync.gif (980KB)\n - mcp-terminal.gif (1.5MB)\n - mcp-browser.gif (2.1MB)\n - skill-debug.gif (890KB)\n\nMarkdown generated:\n - docs/tutorials/ (4 files)\n - book/src/tutorials/ (4 files)\n\nREADME demo section updated","type":"text"}]},{"type":"paragraph","content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Exit Criteria","type":"text"}]},{"type":"checkbox_list","attrs":{"id":null},"content":[{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"All specified tutorials processed (or all if --all)","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"GIF files created at manifest-specified paths","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Dual-tone markdown generated for each tutorial","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"README demo section updated with GIF embeds","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"Book SUMMARY.md updated (if applicable)","type":"text"}]}]},{"type":"checkbox_item","attrs":{"checked":false},"content":[{"type":"paragraph","content":[{"text":"All TodoWrite items completed","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Error Handling","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Error","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Resolution","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"VHS not installed","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"go install github.com/charmbracelet/vhs@latest","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Playwright not installed","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"npm install -D @playwright/test && npx playwright install chromium","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tape file missing Output","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Add ","type":"text"},{"text":"Output assets/gifs/\u003cname>.gif","type":"text","marks":[{"type":"code_inline"}]},{"text":" directive","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Browser spec requires server","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Start server before running spec","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"GIF too large","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Adjust fps/scale in gif-generation","type":"text"}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Scaffold Mode","type":"text"}]},{"type":"paragraph","content":[{"text":"When ","type":"text"},{"text":"--scaffold","type":"text","marks":[{"type":"code_inline"}]},{"text":" is specified, create structure without recording:","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create ","type":"text"},{"text":"assets/tapes/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create ","type":"text"},{"text":"assets/gifs/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create ","type":"text"},{"text":"assets/browser/","type":"text","marks":[{"type":"code_inline"}]},{"text":" directory (if browser tutorials planned)","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create template tape file with metadata annotations","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create template manifest file","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Create empty markdown files in docs/tutorials/ and book/src/tutorials/","type":"text"}]}]}]},{"type":"paragraph","content":[{"text":"Template tape file:","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"tape"},"content":[{"text":"# @title: Tutorial Name\n# @description: Brief description of the tutorial\n\nOutput assets/gifs/tutorial-name.gif\nSet FontSize 14\nSet Width 1200\nSet Height 600\nSet Theme \"Catppuccin Mocha\"\n\n# @step Step 1 Title\n# @docs-brief Brief docs text\n# @book-detail Extended book text with more context and explanation\nType \"command here\"\nEnter\nSleep 2s","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Verification:","type":"text","marks":[{"type":"strong"}]},{"text":" Run the command with ","type":"text"},{"text":"--help","type":"text","marks":[{"type":"code_inline"}]},{"text":" flag to verify availability.","type":"text"}]}]},"metadata":{"date":"2026-06-05","name":"tutorial-updates","tags":["tutorial","gif","vhs","playwright","documentation","demo"],"tools":[],"author":"@skillopedia","source":{"stars":298,"repo_name":"claude-night-market","origin_url":"https://github.com/athola/claude-night-market/blob/HEAD/plugins/sanctum/skills/tutorial-updates/SKILL.md","repo_owner":"athola","body_sha256":"2b0ed0e65006be3cf8ac58c9cbec1b7dc1cc12647017ab25988b9a155e0b4695","cluster_key":"4d4911352b4b6e7b8231e709c4b3b9a809069279703133003a17111c68b606dc","clean_bundle":{"format":"clean-skill-bundle-v1","source":"athola/claude-night-market/plugins/sanctum/skills/tutorial-updates/SKILL.md","attachments":[{"id":"4c0ee5f2-9d1d-5104-bbcf-5328fe6788fa","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/4c0ee5f2-9d1d-5104-bbcf-5328fe6788fa/attachment.md","path":"modules/manifest-parsing.md","size":8831,"sha256":"7d6465c96ae0481cd61db1dfdab677c5984f17d5a4e38215395cc0bcfd0825ad","contentType":"text/markdown; charset=utf-8"},{"id":"c0d7b4da-5a6a-5505-a3c0-a5eb4a29dd06","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/c0d7b4da-5a6a-5505-a3c0-a5eb4a29dd06/attachment.md","path":"modules/markdown-generation.md","size":10011,"sha256":"d9e55c10707065af51eb3e3533cab82a744c380e5e57344854b04f8d5d4f3ef8","contentType":"text/markdown; charset=utf-8"},{"id":"3321b02e-4854-55fc-b0ab-b82ae72e5406","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/3321b02e-4854-55fc-b0ab-b82ae72e5406/attachment.md","path":"modules/tape-validation.md","size":9405,"sha256":"bc956bc21e96992125db662e605885c44febf44cc794191e9ee2062b96d09d93","contentType":"text/markdown; charset=utf-8"}],"bundle_sha256":"ec740f441fa0e70ae7cc623082a2b39778ef4f43e6238e41e0684ce143a880ac","attachment_count":3,"text_attachments":3,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"plugins/sanctum/skills/tutorial-updates/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"testing-qa","category_label":"Testing"},"exact_dupes_collapsed_into_this":0},"modules":["modules/manifest-parsing.md","modules/markdown-generation.md","modules/tape-validation.md"],"version":"v1","category":"testing-qa","complexity":"high","import_tag":"clean-skills-v1","model_hint":"deep","alwaysApply":false,"description":"Generates or updates tutorials from VHS tapes and Playwright specs with dual-tone markdown and GIF recording. Use when tutorial assets need refreshing.","dependencies":["sanctum:shared","sanctum:git-workspace-review","scry:vhs-recording","scry:browser-recording","scry:gif-generation","scry:media-composition"],"estimated_tokens":1100,"progressive_loading":true}},"renderedAt":1782979265699}

Table of Contents - Overview - Command Options - Required TodoWrite Items - Phase 1: Discovery ( )) - Step 1.1: Locate Tutorial Assets - Step 1.2: Parse Manifests - Step 1.3: Handle Options - Phase 1.5: Validation ( )) - Step 1.5.1: VHS Syntax Validation - Step 1.5.2: Extract and Validate CLI Commands - Step 1.5.3: Verify Demo Data Exists - Step 1.5.4: Test Commands Locally - Validation Flags - Validation Exit Criteria - Phase 1.6: Binary Rebuild ( )) - Step 1.6.1: Detect Build System - Step 1.6.2: Check Binary Freshness - Step 1.6.3: Rebuild Binary - Step 1.6.4: Verify Binary Accessibility -…