Skip to content

Xilu018 Remove Episode

src.xil_pipeline.XILU018_remove_episode

xil-remove-episode — remove workspace files for a single episode.

Deletes every workspace artifact belonging to the named episode while leaving the source production script untouched. The following are removed:

  • configs/{slug}/cast_{tag}.json
  • configs/{slug}/sfx_{tag}.json
  • parsed/{slug}/parsed_{tag}.json (and .csv, orig_, pre_splice_, stem_verify_)
  • cues/{slug}/cues_{tag}.md + cues_manifest_{tag}.json
  • stems/{slug}/{tag}/ (directory)
  • daw/{slug}/{tag}/ (directory)
  • masters/{slug}/{tag}_*.mp3 (glob — date-tagged masters from xil-master)
  • posts/{slug}/{tag}_posts.md
  • voice_samples/{tag}/ (directory — from xil-sample)
  • legacy root files: cast_{slug}{tag}.json, sfx{slug}_{tag}.json
  • legacy parsed files in parsed/ (flat naming, pre-0.1.8 layout)

Shared assets (SFX/, logs/) and the source script (scripts/) are never touched.

Usage::

xil remove-episode S01E01 --dry-run
xil remove-episode S01E01 --yes
xil remove-episode S01E01 --show "Night Owls" --dry-run

logger module-attribute

logger = get_logger(__name__)

RemovalItem module-attribute

RemovalItem = _Dir | _File

get_parser

get_parser() -> argparse.ArgumentParser

Return the argument parser for xil-remove-episode.

Source code in src/xil_pipeline/XILU018_remove_episode.py
def get_parser() -> argparse.ArgumentParser:
    """Return the argument parser for xil-remove-episode."""
    parser = argparse.ArgumentParser(
        prog="xil-remove-episode",
        description=(
            "Remove all workspace files for a single episode. "
            "The source production script is never touched. "
            "Shared assets (SFX/, logs/) are never touched."
        ),
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog=(
            "Examples:\n"
            "  xil remove-episode S01E01 --dry-run\n"
            "  xil remove-episode S01E01 --yes\n"
            '  xil remove-episode S01E01 --show "Night Owls" --dry-run\n'
        ),
    )
    parser.add_argument(
        "episode",
        metavar="TAG",
        help="Episode tag to remove (e.g. S01E01)",
    )
    parser.add_argument(
        "--show", "-s",
        default=None,
        metavar="SHOW",
        help="Show name or slug (default: resolved from project.json / XIL_PROJECTROOT)",
    )
    parser.add_argument(
        "--dry-run", "-n",
        action="store_true",
        help="Show what would be removed without deleting anything",
    )
    parser.add_argument(
        "--yes", "-y",
        action="store_true",
        help="Skip the confirmation prompt",
    )
    return parser

main

main() -> None

CLI entry point for episode workspace removal.

Source code in src/xil_pipeline/XILU018_remove_episode.py
def main() -> None:
    """CLI entry point for episode workspace removal."""
    configure_logging()
    args = get_parser().parse_args()

    slug = resolve_slug(args.show)
    tag = args.episode
    items = _collect(slug, tag)

    total_files, total_bytes = _report(items, slug, tag, dry_run=args.dry_run)

    if args.dry_run:
        if total_files > 0:
            logger.info("")
            logger.info("Dry run — nothing deleted. Run without --dry-run to remove.")
        sys.exit(0)

    if total_files == 0:
        sys.exit(0)

    if not args.yes:
        logger.info("")
        confirm = input(
            f'⚠️  This will permanently delete {total_files} file(s) ({_fmt_bytes(total_bytes)}) '
            f'for episode "{tag}" (show "{slug}").\n'
            f'    Type "{tag}" to confirm (or Ctrl-C to abort): '
        ).strip()
        if confirm != tag:
            logger.info("Aborted — input did not match. Nothing deleted.")
            sys.exit(1)

    logger.info("")
    removed = _delete(items)
    logger.info("")
    logger.info(f"✓ Removed {removed} file(s) for episode '{tag}' (show '{slug}').")