Skip to content

lasagnastack.stages.reel_pipeline.critique

lasagnastack.stages.reel_pipeline.critique

run

run(
    cut_list: CutList,
    inventories: list[ClipInventory],
    brief_path: Path,
    output_dir: Path,
    client: LLMClient | None = None,
    skill_path: Path | None = None,
    max_retries: int = _MAX_RETRIES_DEFAULT,
) -> CutList

Run the critique loop, replacing the cut list on revision until approved or capped.

Writes critique/iteration_N.json per iteration via io.write_json / io.critique_path.

Parameters:

Name Type Description Default
cut_list CutList

Initial cut list from Stage 3.

required
inventories list[ClipInventory]

Segment inventories (for context).

required
brief_path Path

Path to the creator brief.

required
output_dir Path

Pipeline root; critique JSONs written here.

required
client LLMClient | None

LLM client to use. Defaults to GeminiClient.

None
skill_path Path | None

Optional path to a Markdown skill file injected into the prompt before the creator brief.

None
max_retries int

Maximum critique iterations before shipping as-is.

_MAX_RETRIES_DEFAULT

Returns:

Type Description
CutList

The approved (or capped) CutList.

Source code in src/lasagnastack/stages/reel_pipeline/critique.py
def run(
    cut_list: CutList,
    inventories: list[ClipInventory],
    brief_path: Path,
    output_dir: Path,
    client: LLMClient | None = None,
    skill_path: Path | None = None,
    max_retries: int = _MAX_RETRIES_DEFAULT,
) -> CutList:
    """Run the critique loop, replacing the cut list on revision until approved or capped.

    Writes critique/iteration_N.json per iteration via io.write_json / io.critique_path.

    Args:
        cut_list: Initial cut list from Stage 3.
        inventories: Segment inventories (for context).
        brief_path: Path to the creator brief.
        output_dir: Pipeline root; critique JSONs written here.
        client: LLM client to use. Defaults to GeminiClient.
        skill_path: Optional path to a Markdown skill file injected into the
            prompt before the creator brief.
        max_retries: Maximum critique iterations before shipping as-is.

    Returns:
        The approved (or capped) CutList.
    """
    if client is None:
        client = GeminiClient()

    previous_issues: list[list[str]] = []
    for iteration in range(max_retries):
        result = _critique_once(
            cut_list,
            inventories,
            brief_path,
            client,
            iteration,
            previous_issues,
            skill_path,
        )
        io.write_json(result, io.critique_path(output_dir, iteration))

        if result.verdict == "approved" or result.cut_list_v2 is None:
            return cut_list

        log.info("critique_revising", iteration=iteration, issues=result.issues)
        previous_issues.append(result.issues)
        cut_list = result.cut_list_v2

    if max_retries > 0:
        log.warning("critique_cap_reached", max_retries=max_retries)
    return cut_list