digraph reference_template {
    graph [
        goal="$goal",
        rankdir=LR,
        default_max_retries=3,
        retry_target="implement",
        fallback_retry_target="debate_consolidate",
        provenance_version="1",
        model_stylesheet="
            * { model: DEFAULT_MODEL; provider: DEFAULT_PROVIDER; }
            .hard { model: HARD_MODEL; provider: HARD_PROVIDER; }
            .verify { model: VERIFY_MODEL; provider: VERIFY_PROVIDER; }
            .branch-a { model: BRANCH_A_MODEL; provider: BRANCH_A_PROVIDER; }
            .branch-b { model: BRANCH_B_MODEL; provider: BRANCH_B_PROVIDER; }
            .branch-c { model: BRANCH_C_MODEL; provider: BRANCH_C_PROVIDER; }
        "
    ]

    // =======================================================================
    // TEMPLATE USAGE
    //
    // This template defines TOPOLOGY ONLY: node shapes, edges, routing,
    // and structural patterns. It contains NO prompt text.
    //
    // The ingestor must compose every prompt from scratch based on the
    // actual project spec, DoD, and repo contents. Prompt requirements
    // are listed in comments above each shape=box node. See Phase 4 of
    // the create-dotfile skill for the full prompt contract.
    //
    // Common requirements for ALL shape=box prompts (do not repeat per node):
    //   - Reference $goal
    //   - Full status contract: write to $KILROY_STAGE_STATUS_PATH,
    //     fall back to $KILROY_STAGE_STATUS_FALLBACK_PATH, do not write
    //     nested status.json after cd, use schema {"status":"..."}
    //   - For status=fail or status=retry: include failure_reason, details,
    //     and failure_class
    // =======================================================================

    exit  [shape=Msquare, label="Exit"]

    subgraph cluster_bootstrap {
        label="Bootstrap"
        start [shape=Mdiamond, label="Start"]

        // Toolchain gate — fail fast before LLM stages.
        // Replace script with project-specific checks.
        check_toolchain [
            shape=parallelogram,
            max_retries=0,
            script="echo 'Replace with project-specific toolchain checks'; exit 0"
        ]

        // PROMPT: expand_spec
        // Role: create or reuse canonical spec at .ai/spec.md
        // Must address:
        //   - Reuse existing .ai/spec.md or repo spec if adequate
        //   - Copy user-declared verbatim specs without rewriting
        //   - Expand from $goal only when no adequate spec exists
        //   - Spec must include: scope, constraints, assumptions, acceptance
        //     criteria, verification approach, non-goals
        // Reads: $goal, existing .ai/spec.md (if any), repo docs
        // Writes: .ai/spec.md
        // Note: auto_status=true — no explicit status write needed
        expand_spec [
            shape=box,
            auto_status=true
        ]

        // PROMPT: check_dod
        // Role: determine if .ai/definition_of_done.md is adequate
        // Must address:
        //   - Check file existence and content (not placeholder)
        //   - Apply DoD rubric: scope, deliverables, AC, verification,
        //     quality/safety gates, non-goals
        //   - Apply coverage checklist: build, tests, lint, docs,
        //     compatibility, security, ops, perf
        // Reads: .ai/definition_of_done.md
        // Outcomes: has_dod or needs_dod
        check_dod [
            shape=box,
            label="DoD exists?"
        ]
    }

    subgraph cluster_dod {
        label="DoD Fanout"
        node [shape=box]

        dod_fanout [shape=component, label="DoD Fan-Out"]

        // PROMPT: dod_a, dod_b, dod_c
        // (identical prompt — diversity comes from different models)
        // Role: propose a project DoD from the spec
        // Must address:
        //   - Read .ai/spec.md
        //   - DoD is outcomes/evidence, not a plan
        //   - Each item verifiable (pass/fail)
        //   - Don't prescribe implementation approach
        //   - Include: scope, deliverables, AC, verification, non-goals
        //   - Apply coverage checklist
        // Writes: .ai/dod_a.md (or _b, _c)
        dod_a [class="branch-a"]
        dod_b [class="branch-b"]
        dod_c [class="branch-c"]

        // PROMPT: consolidate_dod
        // Role: synthesize dod_a/b/c into consensus DoD
        // Must address:
        //   - Review every branch result in parallel.results from prompt context
        //   - Read branch files from the shared checkout
        //   - Read .ai/spec.md for context
        //   - Resolve contradictions, apply DoD rubric + coverage checklist
        // Writes: .ai/definition_of_done.md
        consolidate_dod [auto_status=true]
    }

    subgraph cluster_planning {
        label="Planning Fanout"
        node [shape=box]

        plan_fanout [shape=component, label="Plan Fan-Out"]

        // PROMPT: plan_a, plan_b, plan_c
        // (identical prompt — diversity comes from different models)
        // Role: create implementation plan from spec + DoD
        // Must address:
        //   - Read .ai/spec.md and .ai/definition_of_done.md
        //   - If .ai/postmortem_latest.md exists, incorporate its lessons
        //   - Plan must cover all deliverables and acceptance criteria
        //     from the DoD, with project-specific implementation detail
        //   - Plan must be grounded in the actual project domain,
        //     technology stack, and repo structure
        // Writes: .ai/plan_a.md (or _b, _c)
        plan_a [class="branch-a"]
        plan_b [class="branch-b"]
        plan_c [class="branch-c"]

        // PROMPT: debate_consolidate
        // Role: synthesize plan_a/b/c into best-of-breed final plan
        // Must address:
        //   - Review every branch result in parallel.results from prompt context
        //   - Read branch files from the shared checkout
        //   - If .ai/postmortem_latest.md exists, verify plan addresses
        //     every identified issue
        //   - Resolve conflicts, ensure dependency order
        // Writes: .ai/plan_final.md
        debate_consolidate [auto_status=true]
    }

    // OPTIONAL: For porting/reading-existing-source tasks — add analyze cluster here.
    // analyze_fanout [shape=component, label="Analyze Fan-Out"]
    // analyze_module_a [shape=box, auto_status=true, prompt="...read source, write .ai/design_a.md..."]
    // analyze_module_b [shape=box, auto_status=true, prompt="..."]
    // merge_analysis   [shape=box, auto_status=true, prompt="...verify all design docs..."]
    // See reference_template.dot OPTIONAL stubs below for pattern.

    // OPTIONAL: For 5+ discrete deliverable files — use worker pool instead of flat fan-out.
    // plan_work          [shape=box, auto_status=true, label="Plan Work Queue", prompt="...write .ai/work_queue.json..."]
    // work_pool          [shape=component, label="Worker Pool"]
    // worker_0           [shape=box, auto_status=true, label="Worker 0", prompt="...id%3==0..."]
    // worker_1           [shape=box, auto_status=true, label="Worker 1", prompt="...id%3==1..."]
    // worker_2           [shape=box, auto_status=true, label="Worker 2", prompt="...id%3==2..."]
    // check_work_complete [shape=box, auto_status=true, label="Work Complete?", prompt="...pass counter..."]

    subgraph cluster_implement_verify {
        label="Implement And Verify"

        // PROMPT: implement
        // Role: single-writer code implementation (fresh or repair)
        // Must address:
        //   - REPAIR FIRST: if .ai/postmortem_latest.md exists, read it
        //     FIRST, fix ONLY identified gaps, do NOT regenerate working
        //     systems, preserve all passing code and tests
        //   - FRESH: if no postmortem, execute .ai/plan_final.md
        //   - Read .ai/spec.md and .ai/definition_of_done.md
        //   - Implementation instructions must be specific to the project's
        //     deliverables, domain, technology, and constraints — derived
        //     from the ingestor's reading of the spec and DoD
        //   - Incremental implementation: each module complete before next
        //   - Log progress to .ai/implementation_log.md
        // Failure: also include failure_signature in meta
        implement [
            shape=box,
            class="hard",
            max_retries=2
        ]
        check_implement [shape=diamond, label="Implement OK?"]

        // Auto-fix formatting before verify gate.
        // Replace script with project-specific auto-formatter.
        fix_fmt [
            shape=parallelogram,
            max_retries=0,
            script="echo 'Replace with project-specific auto-formatter'; exit 0"
        ]

        // Replace script with project-specific formatter check.
        verify_fmt [
            shape=parallelogram,
            max_retries=0,
            script="echo 'Replace with project-specific formatter check'; exit 0"
        ]
        check_fmt [shape=diamond, label="Fmt OK?"]

        // Replace script with project-specific build command.
        verify_build [
            shape=parallelogram,
            script="echo 'Replace with project-specific build check'; exit 0"
        ]
        check_build [shape=diamond, label="Build OK?"]

        // Replace script with project-specific test command.
        verify_test [
            shape=parallelogram,
            script="echo 'Replace with project-specific test check'; exit 0"
        ]
        check_test [shape=diamond, label="Tests OK?"]

        // Replace script with artifact hygiene check.
        // Confirm deliverables meet their interface contract (exports, endpoints,
        // CLI behavior, observable outputs); file existence alone is insufficient.
        verify_artifacts [
            shape=parallelogram,
            max_retries=0,
            script="echo 'Replace with artifact hygiene check'; exit 0"
        ]
        check_artifacts [shape=diamond, label="Artifacts OK?"]

        // PROMPT: verify_fidelity
        // Role: semantic review after all deterministic checks pass
        // Must address:
        //   - Read implementation outputs and verify against
        //     .ai/definition_of_done.md and .ai/spec.md
        //   - Verification must be specific to the project's acceptance
        //     criteria — enumerate the actual areas to check, derived from
        //     the ingestor's reading of the DoD
        //   - Write results to .ai/verify_fidelity.md
        // Failure: also include failure_signature in meta — sorted
        //   comma-separated list of specific failed criteria identifiers
        verify_fidelity [
            shape=box,
            class="verify"
        ]
        check_impl [shape=diamond, label="Impl OK?"]
    }

    subgraph cluster_review {
        label="Review Fanout"
        node [shape=box]

        review_fanout [shape=component, label="Review Fan-Out"]

        // PROMPT: review_a, review_b, review_c
        // (identical prompt — diversity comes from different models)
        // Role: review implementation against DoD
        // Must address:
        //   - Read .ai/definition_of_done.md for acceptance criteria
        //   - Read implementation outputs
        //   - Check build, completeness, correctness, tests against all
        //     DoD criteria — enumerate what to check, derived from the
        //     ingestor's reading of the DoD
        //   - Verdict: APPROVED or REJECTED with specific evidence
        // Failure: include specific gaps with criteria identifiers
        // Writes: .ai/review_a.md (or _b, _c)
        review_a [class="branch-a"]
        review_b [class="branch-b"]
        review_c [class="branch-c"]

        // PROMPT: review_consensus
        // Role: synthesize reviews into consensus verdict
        // Must address:
        //   - Review every branch result in parallel.results from prompt context
        //   - Read branch files from the shared checkout
        //   - Read .ai/definition_of_done.md for criteria
        //   - Consensus: 2+ APPROVED with no critical gaps -> success;
        //     otherwise -> retry with specific issues
        // Writes: .ai/review_consensus.md
        review_consensus [auto_status=true, goal_gate=true, retry_target="postmortem"]
    }

    subgraph cluster_postmortem {
        label="Postmortem"
        node [shape=box]

        // PROMPT: postmortem
        // Role: analyze failure and guide next repair iteration
        // Must address:
        //   - Read .ai/review_consensus.md (if review stage reached)
        //   - Read .ai/verify_fidelity.md (if semantic verify ran)
        //   - Review branch status and context updates in parallel.results
        //     from prompt context if available
        //   - Read .ai/implementation_log.md
        //   - Output: root causes, what worked (preserve), what failed
        //     (fix), concrete next changes
        //   - Must NOT direct from-scratch restart — preserve working code
        // Outcome classification (recovery routing):
        //   - impl_repair: code repair needed; plan/toolchain still valid
        //   - needs_replan: plan/approach is inadequate; regenerate plan branches
        //   - needs_toolchain: environment/bootstrap/toolchain issue detected
        //   - When uncertain, default to impl_repair
        // Writes: .ai/postmortem_latest.md (overwrite previous)
        // Note: status reflects analysis completion, not implementation state
        postmortem [auto_status=true]
    }

    // =========================================================================
    // Flow
    // =========================================================================

    // Linear start: toolchain gate -> spec -> DoD check
    start -> check_toolchain
    check_toolchain -> expand_spec [condition="outcome=succeeded"]
    check_toolchain -> check_toolchain [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
    check_toolchain -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
    check_toolchain -> postmortem
    expand_spec -> check_dod

    // DoD fan-out (if needed)
    check_dod -> dod_fanout [condition="outcome=needs_dod"]
    check_dod -> dod_fanout
    dod_fanout -> dod_a
    dod_fanout -> dod_b
    dod_fanout -> dod_c
    dod_a -> consolidate_dod
    dod_b -> consolidate_dod
    dod_c -> consolidate_dod
    consolidate_dod -> plan_fanout

    // Skip to planning if DoD exists
    check_dod -> plan_fanout [condition="outcome=has_dod"]

    // Planning fan-in -> debate -> implement
    plan_fanout -> plan_a
    plan_fanout -> plan_b
    plan_fanout -> plan_c
    plan_a -> debate_consolidate
    plan_b -> debate_consolidate
    plan_c -> debate_consolidate
    debate_consolidate -> implement

    // Verify/check inner loop (tool gates first, semantic review last)
    implement -> check_implement
    check_implement -> fix_fmt [condition="outcome=succeeded"]
    fix_fmt -> verify_fmt
    check_implement -> implement  [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
    check_implement -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
    check_implement -> postmortem
    verify_fmt -> check_fmt
    check_fmt -> verify_build [condition="outcome=succeeded"]
    check_fmt -> implement    [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
    check_fmt -> postmortem   [condition="outcome=failed && context.failure_class!=transient_infra"]
    check_fmt -> postmortem

    verify_build -> check_build
    check_build -> verify_test  [condition="outcome=succeeded"]
    check_build -> implement    [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
    check_build -> postmortem   [condition="outcome=failed && context.failure_class!=transient_infra"]
    check_build -> postmortem

    verify_test -> check_test
    check_test -> verify_artifacts [condition="outcome=succeeded"]
    check_test -> implement        [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
    check_test -> postmortem       [condition="outcome=failed && context.failure_class!=transient_infra"]
    check_test -> postmortem

    verify_artifacts -> check_artifacts
    check_artifacts -> verify_fidelity [condition="outcome=succeeded"]
    check_artifacts -> implement       [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
    check_artifacts -> postmortem      [condition="outcome=failed && context.failure_class!=transient_infra"]
    check_artifacts -> postmortem

    verify_fidelity -> check_impl
    check_impl -> review_fanout [condition="outcome=succeeded"]
    review_fanout -> review_a
    review_fanout -> review_b
    review_fanout -> review_c
    check_impl -> implement  [condition="outcome=failed && context.failure_class=transient_infra", loop_restart=true]
    check_impl -> postmortem [condition="outcome=failed && context.failure_class!=transient_infra"]
    check_impl -> postmortem

    // Review fan-in -> consensus
    review_a -> review_consensus
    review_b -> review_consensus
    review_c -> review_consensus

    // Consensus routing: success -> exit, anything else -> postmortem
    review_consensus -> exit [condition="outcome=succeeded"]
    review_consensus -> postmortem

    // Domain-routed recovery: classify failure and choose the right re-entry
    postmortem -> check_toolchain [condition="outcome=failed && context.failure_class=transient_infra"]
    postmortem -> implement [condition="outcome=impl_repair"]
    postmortem -> plan_fanout [condition="outcome=needs_replan"]
    postmortem -> check_toolchain [condition="outcome=needs_toolchain"]
    postmortem -> implement
}
