src/lightspeed@ops@generator_harness.erl

-module(lightspeed@ops@generator_harness).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lightspeed/ops/generator_harness.gleam").
-export([snapshot_signature/0, run_scenario/1, run_matrix/0, scenario_label/1, pass_fail_label/1, signature/1, scenario/1, outcomes/1, failed_scenarios/1, report_signature/1, snapshot_report_markdown/0]).
-export_type([scenario/0, scenario_outcome/0, report/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(" Deterministic generator parity harness for M25.\n").

-type scenario() :: project_scaffold |
    live_resource_scaffold |
    html_resource_scaffold |
    json_resource_scaffold |
    auth_scaffold |
    full_stack_scaffold |
    snapshot_guard.

-type scenario_outcome() :: {scenario_outcome, scenario(), boolean(), binary()}.

-type report() :: {report, list(scenario_outcome()), integer()}.

-file("src/lightspeed/ops/generator_harness.gleam", 272).
-spec count_failed(list(scenario_outcome())) -> integer().
count_failed(Outcomes) ->
    case Outcomes of
        [] ->
            0;

        [Outcome | Rest] ->
            case erlang:element(3, Outcome) of
                true ->
                    count_failed(Rest);

                false ->
                    1 + count_failed(Rest)
            end
    end.

-file("src/lightspeed/ops/generator_harness.gleam", 291).
-spec int_to_string(integer()) -> binary().
int_to_string(Value) ->
    erlang:integer_to_binary(Value).

-file("src/lightspeed/ops/generator_harness.gleam", 101).
?DOC(" Deterministic snapshot signature over generator outputs.\n").
-spec snapshot_signature() -> binary().
snapshot_signature() ->
    <<<<<<"m25.snapshot.v"/utf8, (int_to_string(1))/binary>>/binary, "|"/utf8>>/binary,
        (lightspeed@tooling@generator:snapshot_signature())/binary>>.

-file("src/lightspeed/ops/generator_harness.gleam", 264).
-spec evaluate_snapshot_guard() -> scenario_outcome().
evaluate_snapshot_guard() ->
    First = snapshot_signature(),
    Second = snapshot_signature(),
    Passed = First =:= Second,
    {scenario_outcome, snapshot_guard, Passed, First}.

-file("src/lightspeed/ops/generator_harness.gleam", 244).
-spec evaluate_full_stack_scaffold() -> scenario_outcome().
evaluate_full_stack_scaffold() ->
    Project = begin
        _pipe = lightspeed@tooling@generator:new(<<"demo_app"/utf8>>),
        _pipe@1 = lightspeed@tooling@generator:generate_live(
            _pipe,
            <<"posts"/utf8>>
        ),
        _pipe@2 = lightspeed@tooling@generator:generate_html(
            _pipe@1,
            <<"posts"/utf8>>
        ),
        _pipe@3 = lightspeed@tooling@generator:generate_json(
            _pipe@2,
            <<"posts"/utf8>>
        ),
        lightspeed@tooling@generator:generate_auth(_pipe@3)
    end,
    Passed = (lightspeed@tooling@generator:production_contract(Project) andalso lightspeed@tooling@generator:resource_contract(
        Project,
        <<"posts"/utf8>>
    ))
    andalso lightspeed@tooling@generator:auth_contract(Project),
    {scenario_outcome,
        full_stack_scaffold,
        Passed,
        lightspeed@tooling@generator:fixture_signature(Project)}.

-file("src/lightspeed/ops/generator_harness.gleam", 229).
-spec evaluate_auth_scaffold() -> scenario_outcome().
evaluate_auth_scaffold() ->
    Project = begin
        _pipe = lightspeed@tooling@generator:new(<<"demo_app"/utf8>>),
        lightspeed@tooling@generator:generate_auth(_pipe)
    end,
    Passed = lightspeed@tooling@generator:production_contract(Project) andalso lightspeed@tooling@generator:auth_contract(
        Project
    ),
    {scenario_outcome,
        auth_scaffold,
        Passed,
        lightspeed@tooling@generator:fixture_signature(Project)}.

-file("src/lightspeed/ops/generator_harness.gleam", 208).
-spec evaluate_json_resource_scaffold() -> scenario_outcome().
evaluate_json_resource_scaffold() ->
    Project = begin
        _pipe = lightspeed@tooling@generator:new(<<"demo_app"/utf8>>),
        lightspeed@tooling@generator:generate_json(_pipe, <<"posts"/utf8>>)
    end,
    Passed = ((lightspeed@tooling@generator:production_contract(Project) andalso lightspeed@tooling@generator:has_file(
        Project,
        <<"src/demo_app/controllers/posts_json.gleam"/utf8>>
    ))
    andalso lightspeed@tooling@generator:has_file(
        Project,
        <<"src/demo_app/api/posts_serializer.gleam"/utf8>>
    ))
    andalso lightspeed@tooling@generator:has_file(
        Project,
        <<"test/demo_app/integration/posts_json_flow_test.gleam"/utf8>>
    ),
    {scenario_outcome,
        json_resource_scaffold,
        Passed,
        lightspeed@tooling@generator:fixture_signature(Project)}.

-file("src/lightspeed/ops/generator_harness.gleam", 188).
-spec evaluate_html_resource_scaffold() -> scenario_outcome().
evaluate_html_resource_scaffold() ->
    Project = begin
        _pipe = lightspeed@tooling@generator:new(<<"demo_app"/utf8>>),
        lightspeed@tooling@generator:generate_html(_pipe, <<"posts"/utf8>>)
    end,
    Passed = (lightspeed@tooling@generator:production_contract(Project) andalso lightspeed@tooling@generator:has_file(
        Project,
        <<"src/demo_app/controllers/posts_html.gleam"/utf8>>
    ))
    andalso lightspeed@tooling@generator:has_file(
        Project,
        <<"test/demo_app/integration/posts_html_flow_test.gleam"/utf8>>
    ),
    {scenario_outcome,
        html_resource_scaffold,
        Passed,
        lightspeed@tooling@generator:fixture_signature(Project)}.

-file("src/lightspeed/ops/generator_harness.gleam", 163).
-spec evaluate_live_resource_scaffold() -> scenario_outcome().
evaluate_live_resource_scaffold() ->
    Project = begin
        _pipe = lightspeed@tooling@generator:new(<<"demo_app"/utf8>>),
        lightspeed@tooling@generator:generate_live(_pipe, <<"posts"/utf8>>)
    end,
    Passed = (((lightspeed@tooling@generator:production_contract(Project)
    andalso lightspeed@tooling@generator:has_file(
        Project,
        <<"src/demo_app/live/posts_live.gleam"/utf8>>
    ))
    andalso lightspeed@tooling@generator:has_file(
        Project,
        <<"src/demo_app/data/posts_repository.gleam"/utf8>>
    ))
    andalso lightspeed@tooling@generator:has_file(
        Project,
        <<"priv/repo/migrations/20260508000000_create_posts.sql"/utf8>>
    ))
    andalso lightspeed@tooling@generator:has_file(
        Project,
        <<"test/demo_app/integration/posts_live_flow_test.gleam"/utf8>>
    ),
    {scenario_outcome,
        live_resource_scaffold,
        Passed,
        lightspeed@tooling@generator:fixture_signature(Project)}.

-file("src/lightspeed/ops/generator_harness.gleam", 152).
-spec evaluate_project_scaffold() -> scenario_outcome().
evaluate_project_scaffold() ->
    Project = lightspeed@tooling@generator:new(<<"demo_app"/utf8>>),
    Passed = lightspeed@tooling@generator:production_contract(Project),
    {scenario_outcome,
        project_scaffold,
        Passed,
        lightspeed@tooling@generator:fixture_signature(Project)}.

-file("src/lightspeed/ops/generator_harness.gleam", 47).
?DOC(" Run one scenario.\n").
-spec run_scenario(scenario()) -> scenario_outcome().
run_scenario(Scenario) ->
    case Scenario of
        project_scaffold ->
            evaluate_project_scaffold();

        live_resource_scaffold ->
            evaluate_live_resource_scaffold();

        html_resource_scaffold ->
            evaluate_html_resource_scaffold();

        json_resource_scaffold ->
            evaluate_json_resource_scaffold();

        auth_scaffold ->
            evaluate_auth_scaffold();

        full_stack_scaffold ->
            evaluate_full_stack_scaffold();

        snapshot_guard ->
            evaluate_snapshot_guard()
    end.

-file("src/lightspeed/ops/generator_harness.gleam", 31).
?DOC(" Run all M25 tooling scenarios.\n").
-spec run_matrix() -> report().
run_matrix() ->
    Scenarios = [project_scaffold,
        live_resource_scaffold,
        html_resource_scaffold,
        json_resource_scaffold,
        auth_scaffold,
        full_stack_scaffold,
        snapshot_guard],
    Outcomes = gleam@list:map(Scenarios, fun run_scenario/1),
    {report, Outcomes, count_failed(Outcomes)}.

-file("src/lightspeed/ops/generator_harness.gleam", 60).
?DOC(" Scenario label.\n").
-spec scenario_label(scenario()) -> binary().
scenario_label(Scenario) ->
    case Scenario of
        project_scaffold ->
            <<"project_scaffold"/utf8>>;

        live_resource_scaffold ->
            <<"live_resource_scaffold"/utf8>>;

        html_resource_scaffold ->
            <<"html_resource_scaffold"/utf8>>;

        json_resource_scaffold ->
            <<"json_resource_scaffold"/utf8>>;

        auth_scaffold ->
            <<"auth_scaffold"/utf8>>;

        full_stack_scaffold ->
            <<"full_stack_scaffold"/utf8>>;

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

-file("src/lightspeed/ops/generator_harness.gleam", 73).
?DOC(" Stable pass/fail label.\n").
-spec pass_fail_label(scenario_outcome()) -> binary().
pass_fail_label(Outcome) ->
    case erlang:element(3, Outcome) of
        true ->
            <<"pass"/utf8>>;

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

-file("src/lightspeed/ops/generator_harness.gleam", 81).
?DOC(" Scenario signature.\n").
-spec signature(scenario_outcome()) -> binary().
signature(Outcome) ->
    erlang:element(4, Outcome).

-file("src/lightspeed/ops/generator_harness.gleam", 86).
?DOC(" Scenario enum accessor.\n").
-spec scenario(scenario_outcome()) -> scenario().
scenario(Outcome) ->
    erlang:element(2, Outcome).

-file("src/lightspeed/ops/generator_harness.gleam", 91).
?DOC(" Outcomes accessor.\n").
-spec outcomes(report()) -> list(scenario_outcome()).
outcomes(Report) ->
    erlang:element(2, Report).

-file("src/lightspeed/ops/generator_harness.gleam", 96).
?DOC(" Failed scenario count.\n").
-spec failed_scenarios(report()) -> integer().
failed_scenarios(Report) ->
    erlang:element(3, Report).

-file("src/lightspeed/ops/generator_harness.gleam", 283).
-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/ops/generator_harness.gleam", 109).
?DOC(" Stable report signature for fixture baselines.\n").
-spec report_signature(report()) -> binary().
report_signature(Report) ->
    Entries = gleam@list:map(
        erlang:element(2, Report),
        fun(Outcome) ->
            <<<<<<<<(scenario_label(erlang:element(2, Outcome)))/binary,
                            "="/utf8>>/binary,
                        (pass_fail_label(Outcome))/binary>>/binary,
                    ":"/utf8>>/binary,
                (erlang:element(4, Outcome))/binary>>
        end
    ),
    join_with(<<";"/utf8>>, Entries).

-file("src/lightspeed/ops/generator_harness.gleam", 123).
?DOC(" Deterministic markdown report for snapshot drift scripts.\n").
-spec snapshot_report_markdown() -> binary().
snapshot_report_markdown() ->
    Report = run_matrix(),
    Failed = failed_scenarios(Report),
    Status = case Failed =:= 0 of
        true ->
            <<"OK"/utf8>>;

        false ->
            <<"FAIL"/utf8>>
    end,
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"# Generator Fixture Report\n\n"/utf8,
                                                                            "snapshot_version: "/utf8>>/binary,
                                                                        (int_to_string(
                                                                            1
                                                                        ))/binary>>/binary,
                                                                    "\n"/utf8>>/binary,
                                                                "fixture_version: "/utf8>>/binary,
                                                            (int_to_string(2))/binary>>/binary,
                                                        "\n"/utf8>>/binary,
                                                    "status: "/utf8>>/binary,
                                                Status/binary>>/binary,
                                            "\n"/utf8>>/binary,
                                        "failed_scenarios: "/utf8>>/binary,
                                    (int_to_string(Failed))/binary>>/binary,
                                "\n\n"/utf8>>/binary,
                            "snapshot_signature: "/utf8>>/binary,
                        (snapshot_signature())/binary>>/binary,
                    "\n\n"/utf8>>/binary,
                "report_signature: "/utf8>>/binary,
            (report_signature(Report))/binary>>/binary,
        "\n"/utf8>>.