src/lightspeed@tooling@ai_workflow.erl

-module(lightspeed@tooling@ai_workflow).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lightspeed/tooling/ai_workflow.gleam").
-export([scaffold_plan/2, refactor_plan/2, template_plan/2, kind_label/1, boundary_label/1, guardrail_label/1, plan_signature/1, evidence_label/1, evaluate/1, passed/1, quality_score/1, policy_score/1, violations/1, evidence/1, signature/1, track_label/1, required_evidence/1, satisfies_track_requirements/3]).
-export_type([workflow_kind/0, review_boundary/0, plan/0, guardrail/0, artifact/0, evidence/0, evaluation/0, verification_track/0, candidate/0]).

-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.

?MODULEDOC(" AI-native workflow contracts and guardrails for M44.\n").

-type workflow_kind() :: scaffold_generation |
    refactor_generation |
    template_refinement.

-type review_boundary() :: {review_boundary,
        binary(),
        boolean(),
        binary(),
        binary()}.

-type plan() :: {plan,
        binary(),
        workflow_kind(),
        binary(),
        list(binary()),
        list(review_boundary())}.

-type guardrail() :: tests_required |
    rfc_adr_required |
    deterministic_evidence_required |
    human_review_required_for_refactor |
    forbidden_token_ban.

-type artifact() :: {artifact, binary(), binary()}.

-type evidence() :: {evidence, binary(), binary()}.

-type evaluation() :: {evaluation,
        plan(),
        boolean(),
        integer(),
        integer(),
        list(binary()),
        list(evidence()),
        binary()}.

-type verification_track() :: generator_track | template_track.

-type candidate() :: {candidate, list(artifact()), list(evidence()), binary()}.

-file("src/lightspeed/tooling/ai_workflow.gleam", 682).
-spec normalize_label(binary()) -> binary().
normalize_label(Value) ->
    _pipe = Value,
    _pipe@1 = string:lowercase(_pipe),
    _pipe@2 = gleam@string:replace(_pipe@1, <<"/"/utf8>>, <<"_"/utf8>>),
    _pipe@3 = gleam@string:replace(_pipe@2, <<"-"/utf8>>, <<"_"/utf8>>),
    _pipe@4 = gleam@string:replace(_pipe@3, <<"."/utf8>>, <<"_"/utf8>>),
    gleam@string:replace(_pipe@4, <<" "/utf8>>, <<"_"/utf8>>).

-file("src/lightspeed/tooling/ai_workflow.gleam", 84).
?DOC(" Build one scaffolding-focused AI plan.\n").
-spec scaffold_plan(binary(), binary()) -> plan().
scaffold_plan(App_name, Resource) ->
    {plan,
        <<"ai_scaffold_"/utf8, (normalize_label(Resource))/binary>>,
        scaffold_generation,
        <<<<<<<<"Generate live scaffold for "/utf8, App_name/binary>>/binary,
                    " resource "/utf8>>/binary,
                Resource/binary>>/binary,
            " with policy-compliant defaults."/utf8>>,
        [<<"gen.live"/utf8>>, App_name, Resource],
        [{review_boundary,
                <<"prompt_review"/utf8>>,
                true,
                <<"application_owner"/utf8>>,
                <<"confirm product scope and tenancy constraints"/utf8>>},
            {review_boundary,
                <<"policy_review"/utf8>>,
                true,
                <<"reviewer"/utf8>>,
                <<"verify generated scaffold satisfies governance contracts"/utf8>>}]}.

-file("src/lightspeed/tooling/ai_workflow.gleam", 112).
?DOC(" Build one refactor-focused AI plan.\n").
-spec refactor_plan(binary(), binary()) -> plan().
refactor_plan(Module_path, Change_summary) ->
    {plan,
        <<"ai_refactor_"/utf8, (normalize_label(Module_path))/binary>>,
        refactor_generation,
        <<<<<<"Refactor "/utf8, Module_path/binary>>/binary,
                " while preserving behavior and adding required tests: "/utf8>>/binary,
            Change_summary/binary>>,
        [],
        [{review_boundary,
                <<"human_review"/utf8>>,
                true,
                <<"senior_reviewer"/utf8>>,
                <<"review semantic risk and regression surface"/utf8>>},
            {review_boundary,
                <<"policy_review"/utf8>>,
                true,
                <<"reviewer"/utf8>>,
                <<"verify RFC/ADR/test obligations and deterministic evidence"/utf8>>}]}.

-file("src/lightspeed/tooling/ai_workflow.gleam", 139).
?DOC(" Build one template-refinement AI plan.\n").
-spec template_plan(binary(), binary()) -> plan().
template_plan(Component_name, Change_summary) ->
    {plan,
        <<"ai_template_"/utf8, (normalize_label(Component_name))/binary>>,
        template_refinement,
        <<<<<<"Refine template ergonomics for "/utf8, Component_name/binary>>/binary,
                " with backward-compatible hints and test updates: "/utf8>>/binary,
            Change_summary/binary>>,
        [],
        [{review_boundary,
                <<"human_review"/utf8>>,
                true,
                <<"template_owner"/utf8>>,
                <<"validate rendering semantics and migration guidance"/utf8>>},
            {review_boundary,
                <<"policy_review"/utf8>>,
                true,
                <<"reviewer"/utf8>>,
                <<"enforce deterministic workflow and governance compliance"/utf8>>}]}.

-file("src/lightspeed/tooling/ai_workflow.gleam", 166).
?DOC(" Workflow kind label.\n").
-spec kind_label(workflow_kind()) -> binary().
kind_label(Kind) ->
    case Kind of
        scaffold_generation ->
            <<"scaffold_generation"/utf8>>;

        refactor_generation ->
            <<"refactor_generation"/utf8>>;

        template_refinement ->
            <<"template_refinement"/utf8>>
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 717).
-spec bool_label(boolean()) -> binary().
bool_label(Value) ->
    case Value of
        true ->
            <<"true"/utf8>>;

        false ->
            <<"false"/utf8>>
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 175).
?DOC(" Review boundary label.\n").
-spec boundary_label(review_boundary()) -> binary().
boundary_label(Boundary) ->
    <<<<<<<<(erlang:element(2, Boundary))/binary, ":required="/utf8>>/binary,
                (bool_label(erlang:element(3, Boundary)))/binary>>/binary,
            ":owner="/utf8>>/binary,
        (erlang:element(4, Boundary))/binary>>.

-file("src/lightspeed/tooling/ai_workflow.gleam", 184).
?DOC(" Guardrail label.\n").
-spec guardrail_label(guardrail()) -> binary().
guardrail_label(Guardrail) ->
    case Guardrail of
        tests_required ->
            <<"tests_required"/utf8>>;

        rfc_adr_required ->
            <<"rfc_adr_required"/utf8>>;

        deterministic_evidence_required ->
            <<"deterministic_evidence_required"/utf8>>;

        human_review_required_for_refactor ->
            <<"human_review_required_for_refactor"/utf8>>;

        forbidden_token_ban ->
            <<"forbidden_token_ban"/utf8>>
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 691).
-spec join_with(binary(), list(binary())) -> binary().
join_with(Separator, Values) ->
    case Values of
        [] ->
            <<""/utf8>>;

        [Value] ->
            Value;

        [Value@1 | Rest] ->
            <<<<Value@1/binary, Separator/binary>>/binary,
                (join_with(Separator, Rest))/binary>>
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 195).
?DOC(" Stable plan signature.\n").
-spec plan_signature(plan()) -> binary().
plan_signature(Plan) ->
    <<<<<<<<<<<<<<<<<<"id="/utf8, (erlang:element(2, Plan))/binary>>/binary,
                                    "|kind="/utf8>>/binary,
                                (kind_label(erlang:element(3, Plan)))/binary>>/binary,
                            "|prompt="/utf8>>/binary,
                        (erlang:element(4, Plan))/binary>>/binary,
                    "|command_args="/utf8>>/binary,
                (join_with(<<","/utf8>>, erlang:element(5, Plan)))/binary>>/binary,
            "|boundaries="/utf8>>/binary,
        (join_with(
            <<";"/utf8>>,
            gleam@list:map(erlang:element(6, Plan), fun boundary_label/1)
        ))/binary>>.

-file("src/lightspeed/tooling/ai_workflow.gleam", 334).
?DOC(" Stable evidence entry label.\n").
-spec evidence_label(evidence()) -> binary().
evidence_label(Entry) ->
    <<<<(erlang:element(2, Entry))/binary, "="/utf8>>/binary,
        (erlang:element(3, Entry))/binary>>.

-file("src/lightspeed/tooling/ai_workflow.gleam", 518).
-spec evaluation_signature(
    plan(),
    boolean(),
    integer(),
    integer(),
    list(binary()),
    list(evidence())
) -> binary().
evaluation_signature(
    Plan,
    Passed,
    Quality_score,
    Policy_score,
    Violations,
    Evidence
) ->
    <<<<<<<<<<<<<<<<<<<<(plan_signature(Plan))/binary, "|passed="/utf8>>/binary,
                                        (bool_label(Passed))/binary>>/binary,
                                    "|quality="/utf8>>/binary,
                                (erlang:integer_to_binary(Quality_score))/binary>>/binary,
                            "|policy="/utf8>>/binary,
                        (erlang:integer_to_binary(Policy_score))/binary>>/binary,
                    "|violations="/utf8>>/binary,
                (join_with(<<","/utf8>>, Violations))/binary>>/binary,
            "|evidence="/utf8>>/binary,
        (join_with(<<";"/utf8>>, gleam@list:map(Evidence, fun evidence_label/1)))/binary>>.

-file("src/lightspeed/tooling/ai_workflow.gleam", 706).
-spec clamp(integer(), integer(), integer()) -> integer().
clamp(Value, Min, Max) ->
    case Value < Min of
        true ->
            Min;

        false ->
            case Value > Max of
                true ->
                    Max;

                false ->
                    Value
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 699).
-spec min_int(integer(), integer()) -> integer().
min_int(Left, Right) ->
    case Left =< Right of
        true ->
            Left;

        false ->
            Right
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 556).
-spec score_quality(integer(), integer(), integer()) -> integer().
score_quality(Artifact_count, Evidence_count, Violation_count) ->
    Base = 60,
    Artifact_bonus = min_int(25, Artifact_count * 3),
    Evidence_bonus = min_int(15, Evidence_count * 3),
    Penalty = Violation_count * 20,
    clamp(((Base + Artifact_bonus) + Evidence_bonus) - Penalty, 0, 100).

-file("src/lightspeed/tooling/ai_workflow.gleam", 549).
-spec score_policy(integer(), integer()) -> integer().
score_policy(Passed_guardrails, Total_guardrails) ->
    case Total_guardrails =< 0 of
        true ->
            0;

        false ->
            case Total_guardrails of
                0 -> 0;
                Gleam@denominator -> Passed_guardrails * 100 div Gleam@denominator
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 628).
-spec content_contains_any(binary(), list(binary())) -> boolean().
content_contains_any(Content, Tokens) ->
    case Tokens of
        [] ->
            false;

        [Token | Rest] ->
            case gleam_stdlib:contains_string(Content, Token) of
                true ->
                    true;

                false ->
                    content_contains_any(Content, Rest)
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 614).
-spec has_forbidden_token_with_list(list(artifact()), list(binary())) -> boolean().
has_forbidden_token_with_list(Artifacts, Forbidden_tokens) ->
    case Artifacts of
        [] ->
            false;

        [Artifact | Rest] ->
            case content_contains_any(
                erlang:element(3, Artifact),
                Forbidden_tokens
            ) of
                true ->
                    true;

                false ->
                    has_forbidden_token_with_list(Rest, Forbidden_tokens)
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 606).
-spec has_forbidden_token(list(artifact())) -> boolean().
has_forbidden_token(Artifacts) ->
    has_forbidden_token_with_list(
        Artifacts,
        [<<"unsafe-inline-script"/utf8>>,
            <<"eval("/utf8>>,
            <<"shell_exec("/utf8>>]
    ).

-file("src/lightspeed/tooling/ai_workflow.gleam", 595).
-spec has_human_review_boundary(list(review_boundary())) -> boolean().
has_human_review_boundary(Boundaries) ->
    case Boundaries of
        [] ->
            false;

        [Boundary | Rest] ->
            case (erlang:element(2, Boundary) =:= <<"human_review"/utf8>>)
            andalso erlang:element(3, Boundary) of
                true ->
                    true;

                false ->
                    has_human_review_boundary(Rest)
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 639).
-spec evidence_contains(list(evidence()), binary()) -> boolean().
evidence_contains(Evidence, Label) ->
    case Evidence of
        [] ->
            false;

        [Entry | Rest] ->
            case erlang:element(2, Entry) =:= Label of
                true ->
                    true;

                false ->
                    evidence_contains(Rest, Label)
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 584).
-spec has_artifact_path(list(artifact()), binary()) -> boolean().
has_artifact_path(Artifacts, Path) ->
    case Artifacts of
        [] ->
            false;

        [Artifact | Rest] ->
            case erlang:element(2, Artifact) =:= Path of
                true ->
                    true;

                false ->
                    has_artifact_path(Rest, Path)
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 579).
-spec has_governance_artifacts(list(artifact())) -> boolean().
has_governance_artifacts(Artifacts) ->
    has_artifact_path(Artifacts, <<"rfcs/0000-template.md"/utf8>>) andalso has_artifact_path(
        Artifacts,
        <<"adrs/0000-template.md"/utf8>>
    ).

-file("src/lightspeed/tooling/ai_workflow.gleam", 568).
-spec has_test_artifact(list(artifact())) -> boolean().
has_test_artifact(Artifacts) ->
    case Artifacts of
        [] ->
            false;

        [Artifact | Rest] ->
            case gleam_stdlib:string_starts_with(
                erlang:element(2, Artifact),
                <<"test/"/utf8>>
            ) of
                true ->
                    true;

                false ->
                    has_test_artifact(Rest)
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 473).
-spec guardrail_violation(plan(), candidate(), guardrail()) -> gleam@option:option(binary()).
guardrail_violation(Plan, Candidate, Guardrail) ->
    case Guardrail of
        tests_required ->
            case has_test_artifact(erlang:element(2, Candidate)) of
                true ->
                    none;

                false ->
                    {some, <<"missing_test_artifacts"/utf8>>}
            end;

        rfc_adr_required ->
            case has_governance_artifacts(erlang:element(2, Candidate)) of
                true ->
                    none;

                false ->
                    {some, <<"missing_governance_artifacts"/utf8>>}
            end;

        deterministic_evidence_required ->
            case (erlang:element(4, Candidate) /= <<""/utf8>>) andalso evidence_contains(
                erlang:element(3, Candidate),
                <<"deterministic_signature"/utf8>>
            ) of
                true ->
                    none;

                false ->
                    {some, <<"missing_deterministic_evidence"/utf8>>}
            end;

        human_review_required_for_refactor ->
            case erlang:element(3, Plan) of
                refactor_generation ->
                    case has_human_review_boundary(erlang:element(6, Plan)) of
                        true ->
                            none;

                        false ->
                            {some, <<"missing_human_review_boundary"/utf8>>}
                    end;

                template_refinement ->
                    case has_human_review_boundary(erlang:element(6, Plan)) of
                        true ->
                            none;

                        false ->
                            {some, <<"missing_human_review_boundary"/utf8>>}
                    end;

                scaffold_generation ->
                    none
            end;

        forbidden_token_ban ->
            case has_forbidden_token(erlang:element(2, Candidate)) of
                true ->
                    {some, <<"forbidden_tokens_present"/utf8>>};

                false ->
                    none
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 439).
-spec evaluate_guardrails(
    plan(),
    candidate(),
    list(guardrail()),
    list(binary()),
    integer(),
    integer()
) -> {list(binary()), integer(), integer()}.
evaluate_guardrails(
    Plan,
    Candidate,
    Guardrails,
    Violations_rev,
    Passed_guardrails,
    Total_guardrails
) ->
    case Guardrails of
        [] ->
            {lists:reverse(Violations_rev), Passed_guardrails, Total_guardrails};

        [Guardrail | Rest] ->
            case guardrail_violation(Plan, Candidate, Guardrail) of
                none ->
                    evaluate_guardrails(
                        Plan,
                        Candidate,
                        Rest,
                        Violations_rev,
                        Passed_guardrails + 1,
                        Total_guardrails
                    );

                {some, Violation} ->
                    evaluate_guardrails(
                        Plan,
                        Candidate,
                        Rest,
                        [Violation | Violations_rev],
                        Passed_guardrails,
                        Total_guardrails
                    )
            end
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 539).
-spec default_guardrails() -> list(guardrail()).
default_guardrails() ->
    [tests_required,
        rfc_adr_required,
        deterministic_evidence_required,
        human_review_required_for_refactor,
        forbidden_token_ban].

-file("src/lightspeed/tooling/ai_workflow.gleam", 677).
-spec extract_template_target(binary()) -> binary().
extract_template_target(Plan_id) ->
    _pipe = gleam@string:replace(Plan_id, <<"ai_template_"/utf8>>, <<""/utf8>>),
    gleam@string:replace(_pipe, <<"_"/utf8>>, <<"/"/utf8>>).

-file("src/lightspeed/tooling/ai_workflow.gleam", 405).
-spec template_candidate(plan()) -> candidate().
template_candidate(Plan) ->
    Component_target = extract_template_target(erlang:element(2, Plan)),
    Deterministic = <<"template_signature:"/utf8, Component_target/binary>>,
    Artifacts = [{artifact,
            <<<<"src/lightspeed/component/"/utf8, Component_target/binary>>/binary,
                ".gleam"/utf8>>,
            <<"pub fn template_marker() -> String {\n  \"ai_template\"\n}\n"/utf8>>},
        {artifact,
            <<<<"test/lightspeed/"/utf8,
                    (normalize_label(Component_target))/binary>>/binary,
                "_template_test.gleam"/utf8>>,
            <<"pub fn template_regression_test() -> Bool {\n  True\n}\n"/utf8>>},
        {artifact,
            <<"rfcs/0000-template.md"/utf8>>,
            <<"# RFC placeholder\n"/utf8>>},
        {artifact,
            <<"adrs/0000-template.md"/utf8>>,
            <<"# ADR placeholder\n"/utf8>>}],
    Evidence = [{evidence, <<"deterministic_signature"/utf8>>, Deterministic},
        {evidence, <<"template_workflow_signature"/utf8>>, Deterministic},
        {evidence,
            <<"template_guardrail_profile"/utf8>>,
            <<"aliases+defaults+hints"/utf8>>},
        {evidence, <<"template_migration_contract"/utf8>>, <<"enforced"/utf8>>}],
    {candidate, Artifacts, Evidence, Deterministic}.

-file("src/lightspeed/tooling/ai_workflow.gleam", 672).
-spec extract_refactor_target(binary()) -> binary().
extract_refactor_target(Plan_id) ->
    _pipe = gleam@string:replace(Plan_id, <<"ai_refactor_"/utf8>>, <<""/utf8>>),
    gleam@string:replace(_pipe, <<"_"/utf8>>, <<"/"/utf8>>).

-file("src/lightspeed/tooling/ai_workflow.gleam", 375).
-spec refactor_candidate(plan()) -> candidate().
refactor_candidate(Plan) ->
    Module_target = extract_refactor_target(erlang:element(2, Plan)),
    Deterministic = <<"refactor_signature:"/utf8, Module_target/binary>>,
    Artifacts = [{artifact,
            <<<<"src/lightspeed/"/utf8, Module_target/binary>>/binary,
                ".gleam"/utf8>>,
            <<"pub fn refactor_marker() -> String {\n  \"ai_refactor\"\n}\n"/utf8>>},
        {artifact,
            <<<<"test/lightspeed/"/utf8,
                    (normalize_label(Module_target))/binary>>/binary,
                "_test.gleam"/utf8>>,
            <<"pub fn refactor_regression_test() -> Bool {\n  True\n}\n"/utf8>>},
        {artifact,
            <<"rfcs/0000-template.md"/utf8>>,
            <<"# RFC placeholder\n"/utf8>>},
        {artifact,
            <<"adrs/0000-template.md"/utf8>>,
            <<"# ADR placeholder\n"/utf8>>}],
    Evidence = [{evidence, <<"deterministic_signature"/utf8>>, Deterministic},
        {evidence, <<"human_review_boundary"/utf8>>, <<"required"/utf8>>},
        {evidence,
            <<"policy_profile"/utf8>>,
            <<"tests+rfc+adr+determinism"/utf8>>}],
    {candidate, Artifacts, Evidence, Deterministic}.

-file("src/lightspeed/tooling/ai_workflow.gleam", 658).
-spec project_artifacts(
    list(lightspeed@tooling@generator:file()),
    list(artifact())
) -> list(artifact()).
project_artifacts(Files, Artifacts_rev) ->
    case Files of
        [] ->
            lists:reverse(Artifacts_rev);

        [File | Rest] ->
            project_artifacts(
                Rest,
                [{artifact, erlang:element(2, File), erlang:element(3, File)} |
                    Artifacts_rev]
            )
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 346).
-spec scaffold_candidate(plan()) -> {ok, candidate()} | {error, binary()}.
scaffold_candidate(Plan) ->
    case lightspeed@tooling@generator:parse(erlang:element(5, Plan)) of
        {error, Error} ->
            {error,
                <<"parse_error:"/utf8,
                    (lightspeed@tooling@generator:parse_error_label(Error))/binary>>};

        {ok, Command} ->
            Project = lightspeed@tooling@generator:scaffold(Command),
            Artifacts = project_artifacts(
                lightspeed@tooling@generator:files(Project),
                []
            ),
            Deterministic = lightspeed@tooling@generator:fixture_signature(
                Project
            ),
            Evidence = [{evidence,
                    <<"generator_fixture_signature"/utf8>>,
                    Deterministic},
                {evidence,
                    <<"generator_snapshot_signature"/utf8>>,
                    lightspeed@tooling@generator:snapshot_signature()},
                {evidence,
                    <<"generator_contract"/utf8>>,
                    bool_label(
                        lightspeed@tooling@generator:production_contract(
                            Project
                        )
                    )},
                {evidence, <<"deterministic_signature"/utf8>>, Deterministic}],
            {ok, {candidate, Artifacts, Evidence, Deterministic}}
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 338).
-spec generate_candidate(plan()) -> {ok, candidate()} | {error, binary()}.
generate_candidate(Plan) ->
    case erlang:element(3, Plan) of
        scaffold_generation ->
            scaffold_candidate(Plan);

        refactor_generation ->
            {ok, refactor_candidate(Plan)};

        template_refinement ->
            {ok, template_candidate(Plan)}
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 209).
?DOC(" Evaluate one AI workflow plan against deterministic guardrails.\n").
-spec evaluate(plan()) -> evaluation().
evaluate(Plan) ->
    case generate_candidate(Plan) of
        {error, Reason} ->
            {evaluation,
                Plan,
                false,
                0,
                0,
                [Reason],
                [],
                evaluation_signature(Plan, false, 0, 0, [Reason], [])};

        {ok, Candidate} ->
            Guardrails = default_guardrails(),
            {Violations, Passed_guardrails, Total_guardrails} = evaluate_guardrails(
                Plan,
                Candidate,
                Guardrails,
                [],
                0,
                erlang:length(Guardrails)
            ),
            Policy = score_policy(Passed_guardrails, Total_guardrails),
            Quality = score_quality(
                erlang:length(erlang:element(2, Candidate)),
                erlang:length(erlang:element(3, Candidate)),
                erlang:length(Violations)
            ),
            Passed = ((Violations =:= []) andalso (Policy >= 80)) andalso (Quality
            >= 80),
            {evaluation,
                Plan,
                Passed,
                Quality,
                Policy,
                Violations,
                erlang:element(3, Candidate),
                evaluation_signature(
                    Plan,
                    Passed,
                    Quality,
                    Policy,
                    Violations,
                    erlang:element(3, Candidate)
                )}
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 263).
?DOC(" Evaluation pass/fail accessor.\n").
-spec passed(evaluation()) -> boolean().
passed(Evaluation) ->
    erlang:element(3, Evaluation).

-file("src/lightspeed/tooling/ai_workflow.gleam", 268).
?DOC(" Evaluation quality score accessor.\n").
-spec quality_score(evaluation()) -> integer().
quality_score(Evaluation) ->
    erlang:element(4, Evaluation).

-file("src/lightspeed/tooling/ai_workflow.gleam", 273).
?DOC(" Evaluation policy score accessor.\n").
-spec policy_score(evaluation()) -> integer().
policy_score(Evaluation) ->
    erlang:element(5, Evaluation).

-file("src/lightspeed/tooling/ai_workflow.gleam", 278).
?DOC(" Evaluation violations accessor.\n").
-spec violations(evaluation()) -> list(binary()).
violations(Evaluation) ->
    erlang:element(6, Evaluation).

-file("src/lightspeed/tooling/ai_workflow.gleam", 283).
?DOC(" Evaluation evidence accessor.\n").
-spec evidence(evaluation()) -> list(evidence()).
evidence(Evaluation) ->
    erlang:element(7, Evaluation).

-file("src/lightspeed/tooling/ai_workflow.gleam", 288).
?DOC(" Evaluation signature accessor.\n").
-spec signature(evaluation()) -> binary().
signature(Evaluation) ->
    erlang:element(8, Evaluation).

-file("src/lightspeed/tooling/ai_workflow.gleam", 293).
?DOC(" Verification track label.\n").
-spec track_label(verification_track()) -> binary().
track_label(Track) ->
    case Track of
        generator_track ->
            <<"generator_track"/utf8>>;

        template_track ->
            <<"template_track"/utf8>>
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 301).
?DOC(" Required evidence labels for one verification track.\n").
-spec required_evidence(verification_track()) -> list(binary()).
required_evidence(Track) ->
    case Track of
        generator_track ->
            [<<"generator_fixture_signature"/utf8>>,
                <<"generator_snapshot_signature"/utf8>>,
                <<"generator_contract"/utf8>>];

        template_track ->
            [<<"template_workflow_signature"/utf8>>,
                <<"template_guardrail_profile"/utf8>>,
                <<"template_migration_contract"/utf8>>]
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 650).
-spec has_all_evidence(list(evidence()), list(binary())) -> boolean().
has_all_evidence(Evidence, Labels) ->
    case Labels of
        [] ->
            true;

        [Label | Rest] ->
            evidence_contains(Evidence, Label) andalso has_all_evidence(
                Evidence,
                Rest
            )
    end.

-file("src/lightspeed/tooling/ai_workflow.gleam", 317).
?DOC(" True when one evaluation satisfies required evidence and external signature.\n").
-spec satisfies_track_requirements(evaluation(), verification_track(), binary()) -> boolean().
satisfies_track_requirements(Evaluation, Track, External_signature) ->
    Requirements = required_evidence(Track),
    Has_required = has_all_evidence(erlang:element(7, Evaluation), Requirements),
    External_ok = case Track of
        generator_track ->
            gleam_stdlib:string_starts_with(
                External_signature,
                <<"m25.snapshot.v"/utf8>>
            );

        template_track ->
            gleam_stdlib:string_starts_with(
                External_signature,
                <<"m39.snapshot.v"/utf8>>
            )
    end,
    Has_required andalso External_ok.