src/lightspeed@ops@template_ergonomics_harness.erl

-module(lightspeed@ops@template_ergonomics_harness).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/lightspeed/ops/template_ergonomics_harness.gleam").
-export([run_scenario/1, run_matrix/0, scenario_label/1, pass_fail_label/1, signature/1, scenario/1, deterministic/1, outcomes/1, failed_scenarios/1, nondeterministic_failures/1, report_signature/1, snapshot_signature/0, snapshot_report_markdown/0]).
-export_type([card_assigns/0, 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 M39 template ergonomics conformance harness.\n").

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

-type scenario() :: routine_schema_boilerplate_reduction |
    alias_migration_path |
    ergonomic_diagnostic_hints |
    optional_accessor_workflow.

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

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

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

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

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

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 417).
-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/template_ergonomics_harness.gleam", 439).
-spec bool_label(boolean()) -> binary().
bool_label(Value) ->
    case Value of
        true ->
            <<"true"/utf8>>;

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

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 383).
-spec render_card(
    card_assigns(),
    list({binary(), lightspeed@component:rendered()})
) -> lightspeed@component:rendered().
render_card(Assigns, Slots) ->
    Body_html = case lightspeed@component@template_ergonomics:required_slot_html(
        Slots,
        <<"body"/utf8>>
    ) of
        {ok, Value} ->
            Value;

        {error, Reason} ->
            <<<<"<!--"/utf8, Reason/binary>>/binary, "-->"/utf8>>
    end,
    Footer_html = lightspeed@component@template_ergonomics:slot_html_or_empty(
        Slots,
        <<"footer"/utf8>>
    ),
    lightspeed@component:html(
        <<<<<<<<<<<<<<<<"<article data-highlighted=\""/utf8,
                                        (bool_label(erlang:element(3, Assigns)))/binary>>/binary,
                                    "\"><h1>"/utf8>>/binary,
                                (erlang:element(2, Assigns))/binary>>/binary,
                            "</h1><section>"/utf8>>/binary,
                        Body_html/binary>>/binary,
                    "</section><footer>"/utf8>>/binary,
                Footer_html/binary>>/binary,
            "</footer></article>"/utf8>>
    ).

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 354).
-spec card_schema() -> lightspeed@component@template_compiler:schema(card_assigns(), list({binary(),
    lightspeed@component:rendered()})).
card_schema() ->
    lightspeed@component@template_ergonomics:routine_schema(
        <<"card_ergonomic"/utf8>>,
        [lightspeed@component@template_compiler:required_string(
                <<"title"/utf8>>
            ),
            lightspeed@component@template_compiler:optional_bool(
                <<"highlighted"/utf8>>,
                {some, false}
            )],
        [lightspeed@component@template_compiler:required_slot(<<"body"/utf8>>),
            lightspeed@component@template_compiler:optional_slot(
                <<"footer"/utf8>>
            )],
        fun(Attrs) ->
            case {lightspeed@component@template_compiler:require_string(
                    Attrs,
                    <<"title"/utf8>>
                ),
                lightspeed@component@template_ergonomics:optional_bool(
                    Attrs,
                    <<"highlighted"/utf8>>,
                    false
                )} of
                {{ok, Title}, {ok, Highlighted}} ->
                    {ok, {card_assigns, Title, Highlighted}};

                {{error, Reason}, _} ->
                    {error, Reason};

                {_, {error, Reason@1}} ->
                    {error, Reason@1}
            end
        end,
        fun render_card/2
    ).

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 326).
-spec evaluate_optional_accessor_workflow() -> {boolean(), binary()}.
evaluate_optional_accessor_workflow() ->
    Ergonomic = lightspeed@component@template_ergonomics:ergonomic_schema(
        card_schema(),
        [],
        [lightspeed@component@template_ergonomics:slot_default_html(
                <<"footer"/utf8>>,
                <<"<p>default footer</p>"/utf8>>
            )]
    ),
    Result = lightspeed@component@template_ergonomics:compile(
        Ergonomic,
        [lightspeed@component@template_ergonomics:string_attr(
                <<"title"/utf8>>,
                <<"Ops"/utf8>>
            )],
        [lightspeed@component@template_ergonomics:slot_html(
                <<"body"/utf8>>,
                <<"<p>ok</p>"/utf8>>
            )]
    ),
    case Result of
        {ok, Compiled} ->
            Html = lightspeed@component@template_ergonomics:html(Compiled),
            Passed = Html =:= <<"<article data-highlighted=\"false\"><h1>Ops</h1><section><p>ok</p></section><footer><p>default footer</p></footer></article>"/utf8>>,
            {Passed,
                lightspeed@component@template_ergonomics:signature(Compiled)};

        {error, Diagnostics} ->
            {false,
                lightspeed@component@template_ergonomics:diagnostics_signature(
                    Diagnostics
                )}
    end.

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 293).
-spec evaluate_ergonomic_diagnostic_hints() -> {boolean(), binary()}.
evaluate_ergonomic_diagnostic_hints() ->
    Ergonomic = lightspeed@component@template_ergonomics:ergonomic_schema(
        card_schema(),
        [lightspeed@component@template_ergonomics:attr_alias(
                <<"headline"/utf8>>,
                <<"title"/utf8>>,
                <<"migrate old template attr `headline` to `title`"/utf8>>
            )],
        []
    ),
    Result = lightspeed@component@template_ergonomics:compile(
        Ergonomic,
        [lightspeed@component@template_ergonomics:string_attr(
                <<"titel"/utf8>>,
                <<"Inbox"/utf8>>
            )],
        []
    ),
    case Result of
        {ok, Compiled} ->
            {false,
                lightspeed@component@template_ergonomics:signature(Compiled)};

        {error, Diagnostics} ->
            Signature = lightspeed@component@template_ergonomics:diagnostics_signature(
                Diagnostics
            ),
            Passed = Signature =:= <<"unknown_attribute:unknown_attribute:card_ergonomic:titel:hint=unknown attr `titel`, did you mean `title`?;missing_attribute:missing_attribute:card_ergonomic:title:hint=provide required attr `title` or migrate from alias(es): headline;missing_slot:missing_slot:card_ergonomic:body:hint=add required slot `body`"/utf8>>,
            {Passed, Signature}
    end.

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 252).
-spec evaluate_alias_migration_path() -> {boolean(), binary()}.
evaluate_alias_migration_path() ->
    Ergonomic = lightspeed@component@template_ergonomics:ergonomic_schema(
        card_schema(),
        [lightspeed@component@template_ergonomics:attr_alias(
                <<"headline"/utf8>>,
                <<"title"/utf8>>,
                <<"migrate old template attr `headline` to `title`"/utf8>>
            )],
        [lightspeed@component@template_ergonomics:slot_default_html(
                <<"footer"/utf8>>,
                <<""/utf8>>
            )]
    ),
    Result = lightspeed@component@template_ergonomics:compile(
        Ergonomic,
        [lightspeed@component@template_ergonomics:string_attr(
                <<"headline"/utf8>>,
                <<"Inbox"/utf8>>
            ),
            lightspeed@component@template_ergonomics:bool_attr(
                <<"highlighted"/utf8>>,
                true
            )],
        [lightspeed@component@template_ergonomics:slot_html(
                <<"body"/utf8>>,
                <<"<p>migrated</p>"/utf8>>
            )]
    ),
    case Result of
        {ok, Compiled} ->
            Aliases = lightspeed@component@template_ergonomics:applied_aliases(
                Compiled
            ),
            Passed = (Aliases =:= [{<<"headline"/utf8>>, <<"title"/utf8>>}])
            andalso (lightspeed@component@template_ergonomics:html(Compiled) =:= <<"<article data-highlighted=\"true\"><h1>Inbox</h1><section><p>migrated</p></section><footer></footer></article>"/utf8>>),
            {Passed,
                lightspeed@component@template_ergonomics:signature(Compiled)};

        {error, Diagnostics} ->
            {false,
                lightspeed@component@template_ergonomics:diagnostics_signature(
                    Diagnostics
                )}
    end.

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 412).
-spec ergonomic_steps() -> integer().
ergonomic_steps() ->
    3.

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 406).
-spec baseline_steps() -> integer().
baseline_steps() ->
    4.

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 190).
-spec evaluate_routine_schema_boilerplate_reduction() -> {boolean(), binary()}.
evaluate_routine_schema_boilerplate_reduction() ->
    Schema = lightspeed@component@template_ergonomics:routine_schema(
        <<"card_ergonomic"/utf8>>,
        [lightspeed@component@template_compiler:required_string(
                <<"title"/utf8>>
            ),
            lightspeed@component@template_compiler:optional_bool(
                <<"highlighted"/utf8>>,
                {some, false}
            )],
        [lightspeed@component@template_compiler:required_slot(<<"body"/utf8>>),
            lightspeed@component@template_compiler:optional_slot(
                <<"footer"/utf8>>
            )],
        fun(Attrs) ->
            case {lightspeed@component@template_compiler:require_string(
                    Attrs,
                    <<"title"/utf8>>
                ),
                lightspeed@component@template_ergonomics:optional_bool(
                    Attrs,
                    <<"highlighted"/utf8>>,
                    false
                )} of
                {{ok, Title}, {ok, Highlighted}} ->
                    {ok, {card_assigns, Title, Highlighted}};

                {{error, Reason}, _} ->
                    {error, Reason};

                {_, {error, Reason@1}} ->
                    {error, Reason@1}
            end
        end,
        fun render_card/2
    ),
    Ergonomic = lightspeed@component@template_ergonomics:ergonomic_schema(
        Schema,
        [],
        [lightspeed@component@template_ergonomics:slot_default_html(
                <<"footer"/utf8>>,
                <<""/utf8>>
            )]
    ),
    Result = lightspeed@component@template_ergonomics:compile(
        Ergonomic,
        [lightspeed@component@template_ergonomics:string_attr(
                <<"title"/utf8>>,
                <<"Inbox"/utf8>>
            )],
        [lightspeed@component@template_ergonomics:slot_html(
                <<"body"/utf8>>,
                <<"<p>3 notifications</p>"/utf8>>
            )]
    ),
    case Result of
        {ok, Compiled} ->
            Html = lightspeed@component@template_ergonomics:html(Compiled),
            Signature = lightspeed@component@template_ergonomics:signature(
                Compiled
            ),
            Passed = ((Html =:= <<"<article data-highlighted=\"false\"><h1>Inbox</h1><section><p>3 notifications</p></section><footer></footer></article>"/utf8>>)
            andalso (erlang:length(
                lightspeed@component@template_ergonomics:applied_slot_defaults(
                    Compiled
                )
            )
            =:= 1))
            andalso (lightspeed@component@template_ergonomics:applied_aliases(
                Compiled
            )
            =:= []),
            {Passed,
                <<<<Signature/binary, "|boilerplate_delta="/utf8>>/binary,
                    (erlang:integer_to_binary(
                        baseline_steps() - ergonomic_steps()
                    ))/binary>>};

        {error, Diagnostics} ->
            {false,
                lightspeed@component@template_ergonomics:diagnostics_signature(
                    Diagnostics
                )}
    end.

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 180).
-spec evaluate(scenario()) -> {boolean(), binary()}.
evaluate(Scenario) ->
    case Scenario of
        routine_schema_boilerplate_reduction ->
            evaluate_routine_schema_boilerplate_reduction();

        alias_migration_path ->
            evaluate_alias_migration_path();

        ergonomic_diagnostic_hints ->
            evaluate_ergonomic_diagnostic_hints();

        optional_accessor_workflow ->
            evaluate_optional_accessor_workflow()
    end.

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 62).
?DOC(" Run one M39 scenario twice and require deterministic parity.\n").
-spec run_scenario(scenario()) -> scenario_outcome().
run_scenario(Scenario) ->
    {First_passed, First_signature} = evaluate(Scenario),
    {Second_passed, Second_signature} = evaluate(Scenario),
    Deterministic = (First_passed =:= Second_passed) andalso (First_signature
    =:= Second_signature),
    Passed = (First_passed andalso Second_passed) andalso Deterministic,
    {scenario_outcome, Scenario, Passed, Deterministic, First_signature}.

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 44).
?DOC(" Run all M39 conformance scenarios.\n").
-spec run_matrix() -> report().
run_matrix() ->
    Outcomes = begin
        _pipe = [routine_schema_boilerplate_reduction,
            alias_migration_path,
            ergonomic_diagnostic_hints,
            optional_accessor_workflow],
        gleam@list:map(_pipe, fun run_scenario/1)
    end,
    {report, Outcomes, count_failed(Outcomes), count_nondeterministic(Outcomes)}.

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

        alias_migration_path ->
            <<"alias_migration_path"/utf8>>;

        ergonomic_diagnostic_hints ->
            <<"ergonomic_diagnostic_hints"/utf8>>;

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

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 88).
?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/template_ergonomics_harness.gleam", 96).
?DOC(" Scenario signature accessor.\n").
-spec signature(scenario_outcome()) -> binary().
signature(Outcome) ->
    erlang:element(5, Outcome).

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

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 106).
?DOC(" Determinism accessor.\n").
-spec deterministic(scenario_outcome()) -> boolean().
deterministic(Outcome) ->
    erlang:element(4, Outcome).

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

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

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 121).
?DOC(" Nondeterministic failures count.\n").
-spec nondeterministic_failures(report()) -> integer().
nondeterministic_failures(Report) ->
    erlang:element(4, Report).

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 446).
-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/template_ergonomics_harness.gleam", 126).
?DOC(" Stable report signature.\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,
                            ":deterministic="/utf8>>/binary,
                        (bool_label(erlang:element(4, Outcome)))/binary>>/binary,
                    ":"/utf8>>/binary,
                (erlang:element(5, Outcome))/binary>>
        end
    ),
    join_with(<<";"/utf8>>, Entries).

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 142).
?DOC(" Deterministic snapshot signature for M39 drift gates.\n").
-spec snapshot_signature() -> binary().
snapshot_signature() ->
    <<<<<<"m39.snapshot.v"/utf8, (erlang:integer_to_binary(1))/binary>>/binary,
            "|"/utf8>>/binary,
        (report_signature(run_matrix()))/binary>>.

-file("src/lightspeed/ops/template_ergonomics_harness.gleam", 150).
?DOC(" Deterministic markdown report for M39 fixture scripts.\n").
-spec snapshot_report_markdown() -> binary().
snapshot_report_markdown() ->
    Report = run_matrix(),
    Failed = failed_scenarios(Report),
    Nondeterministic = nondeterministic_failures(Report),
    Status = case (Failed =:= 0) andalso (Nondeterministic =:= 0) of
        true ->
            <<"OK"/utf8>>;

        false ->
            <<"FAIL"/utf8>>
    end,
    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"# Template Ergonomics Fixture Report\n\n"/utf8,
                                                                            "snapshot_version: "/utf8>>/binary,
                                                                        (erlang:integer_to_binary(
                                                                            1
                                                                        ))/binary>>/binary,
                                                                    "\n"/utf8>>/binary,
                                                                "status: "/utf8>>/binary,
                                                            Status/binary>>/binary,
                                                        "\n"/utf8>>/binary,
                                                    "failed_scenarios: "/utf8>>/binary,
                                                (erlang:integer_to_binary(
                                                    Failed
                                                ))/binary>>/binary,
                                            "\n"/utf8>>/binary,
                                        "nondeterministic_failures: "/utf8>>/binary,
                                    (erlang:integer_to_binary(Nondeterministic))/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>>.