-module(lightspeed@tooling@generator). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/lightspeed/tooling/generator.gleam"). -export([parse/1, parse_error_label/1, generate_auth/1, new/1, generate_json/2, generate_html/2, generate_live/2, scaffold/1, app_name/1, module_name/1, files/1, features/1, has_file/2, file_content/2, fixture_signature/1, boot_ci_contract/1, production_contract/1, resource_contract/2, auth_contract/1, fixture_snapshots/0, snapshot_signature/0]). -export_type([command/0, parse_error/0, file/0, project/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 project and resource scaffold generator for M25.\n"). -type command() :: {new, binary()} | {gen_live, binary(), binary()} | {gen_html, binary(), binary()} | {gen_json, binary(), binary()} | {gen_auth, binary()}. -type parse_error() :: {missing_arguments, binary()} | {unsupported_command, binary()}. -type file() :: {file, binary(), binary()}. -opaque project() :: {project, binary(), binary(), list(file()), list(binary())}. -file("src/lightspeed/tooling/generator.gleam", 49). ?DOC( " Parse CLI-like command args.\n" "\n" " Supported shapes:\n" "\n" " - `[\"new\", \"\"]`\n" " - `[\"gen.live\", \"\", \"\"]`\n" " - `[\"gen.html\", \"\", \"\"]`\n" " - `[\"gen.json\", \"\", \"\"]`\n" " - `[\"gen.auth\", \"\"]`\n" ). -spec parse(list(binary())) -> {ok, command()} | {error, parse_error()}. parse(Args) -> case Args of [<<"new"/utf8>>, App_name] -> {ok, {new, App_name}}; [<<"gen.live"/utf8>>, App_name@1, Resource] -> {ok, {gen_live, App_name@1, Resource}}; [<<"gen.html"/utf8>>, App_name@2, Resource@1] -> {ok, {gen_html, App_name@2, Resource@1}}; [<<"gen.json"/utf8>>, App_name@3, Resource@2] -> {ok, {gen_json, App_name@3, Resource@2}}; [<<"gen.auth"/utf8>>, App_name@4] -> {ok, {gen_auth, App_name@4}}; [<<"new"/utf8>>] -> {error, {missing_arguments, <<"new"/utf8>>}}; [<<"gen.live"/utf8>>, _ | _] -> {error, {missing_arguments, <<"gen.live"/utf8>>}}; [<<"gen.html"/utf8>>, _ | _] -> {error, {missing_arguments, <<"gen.html"/utf8>>}}; [<<"gen.json"/utf8>>, _ | _] -> {error, {missing_arguments, <<"gen.json"/utf8>>}}; [<<"gen.auth"/utf8>>] -> {error, {missing_arguments, <<"gen.auth"/utf8>>}}; [] -> {error, {missing_arguments, <<"command"/utf8>>}}; [Command | _] -> {error, {unsupported_command, Command}} end. -file("src/lightspeed/tooling/generator.gleam", 70). ?DOC(" Stable parse-error label for fixtures.\n"). -spec parse_error_label(parse_error()) -> binary(). parse_error_label(Error) -> case Error of {missing_arguments, Command} -> <<"missing_arguments:"/utf8, Command/binary>>; {unsupported_command, Command@1} -> <<"unsupported_command:"/utf8, Command@1/binary>> end. -file("src/lightspeed/tooling/generator.gleam", 686). -spec contains(list(binary()), binary()) -> boolean(). contains(Values, Needle) -> case Values of [] -> false; [Value | Rest] -> case Value =:= Needle of true -> true; false -> contains(Rest, Needle) end end. -file("src/lightspeed/tooling/generator.gleam", 636). -spec add_feature(project(), binary()) -> project(). add_feature(Project, Feature) -> case contains(erlang:element(5, Project), Feature) of true -> Project; false -> {project, erlang:element(2, Project), erlang:element(3, Project), erlang:element(4, Project), [Feature | erlang:element(5, Project)]} end. -file("src/lightspeed/tooling/generator.gleam", 653). -spec remove_path(list(file()), binary()) -> list(file()). remove_path(Files_rev, Path) -> case Files_rev of [] -> []; [Entry | Rest] -> case erlang:element(2, Entry) =:= Path of true -> remove_path(Rest, Path); false -> [Entry | remove_path(Rest, Path)] end end. -file("src/lightspeed/tooling/generator.gleam", 649). -spec upsert_file(list(file()), file()) -> list(file()). upsert_file(Files_rev, Next) -> [Next | remove_path(Files_rev, erlang:element(2, Next))]. -file("src/lightspeed/tooling/generator.gleam", 643). -spec put_file(project(), binary(), binary()) -> project(). put_file(Project, Path, Content) -> Files_rev = upsert_file(erlang:element(4, Project), {file, Path, Content}), {project, erlang:element(2, Project), erlang:element(3, Project), Files_rev, erlang:element(5, Project)}. -file("src/lightspeed/tooling/generator.gleam", 380). ?DOC(" Generate a `phx.gen.auth`-style auth scaffold.\n"). -spec generate_auth(project()) -> project(). generate_auth(Project) -> App = erlang:element(2, Project), _pipe = Project, _pipe@1 = put_file( _pipe, <<<<"src/"/utf8, App/binary>>/binary, "/auth.gleam"/utf8>>, <<"pub type User {\n User(id: String, email: String, tenant_id: String)\n}\n"/utf8>> ), _pipe@2 = put_file( _pipe@1, <<<<"src/"/utf8, App/binary>>/binary, "/auth/password.gleam"/utf8>>, <<"import gleam/string\n\npub fn validate(password: String) -> Bool {\n string.length(password) >= 12\n && string.contains(password, \"0\")\n && string.contains(password, \"A\")\n}\n"/utf8>> ), _pipe@3 = put_file( _pipe@2, <<<<"src/"/utf8, App/binary>>/binary, "/auth/policy.gleam"/utf8>>, <<<<"import "/utf8, App/binary>>/binary, "/auth\n\npub fn can_impersonate(_user: auth.User) -> Bool {\n False\n}\n"/utf8>> ), _pipe@4 = put_file( _pipe@3, <<<<"src/"/utf8, App/binary>>/binary, "/auth/session.gleam"/utf8>>, <<<<"import "/utf8, App/binary>>/binary, "/auth\n\npub fn login(email: String, tenant_id: String) -> auth.User {\n auth.User(id: \"u-1\", email: email, tenant_id: tenant_id)\n}\n"/utf8>> ), _pipe@5 = put_file( _pipe@4, <<<<"test/"/utf8, App/binary>>/binary, "/auth_test.gleam"/utf8>>, <<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/auth/password\n\npub fn generated_auth_defaults_test() {\n password.validate(\"A1234567890x\")\n |> should.equal(True)\n\n password.validate(\"short\")\n |> should.equal(False)\n}\n"/utf8>> ), _pipe@6 = put_file( _pipe@5, <<<<"test/"/utf8, App/binary>>/binary, "/auth_policy_test.gleam"/utf8>>, <<<<<<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/auth\nimport "/utf8>>/binary, App/binary>>/binary, "/auth/policy\n\npub fn generated_auth_policy_test() {\n let user = auth.User(id: \"u-1\", email: \"a@example.com\", tenant_id: \"t-1\")\n policy.can_impersonate(user)\n |> should.equal(False)\n}\n"/utf8>> ), _pipe@7 = put_file( _pipe@6, <<<<"test/"/utf8, App/binary>>/binary, "/integration/auth_flow_test.gleam"/utf8>>, <<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/auth/session\n\npub fn generated_auth_session_flow_test() {\n session.login(\"a@example.com\", \"t-1\")\n |> should.equal(session.login(\"a@example.com\", \"t-1\"))\n}\n"/utf8>> ), _pipe@8 = put_file( _pipe@7, <<"examples/auth/README.md"/utf8>>, <<"# Auth Example\n\nGenerated auth fixture with password, policy, and session scaffolding.\n"/utf8>> ), add_feature(_pipe@8, <<"gen.auth"/utf8>>). -file("src/lightspeed/tooling/generator.gleam", 697). -spec normalize_name(binary()) -> binary(). normalize_name(Value) -> _pipe = Value, _pipe@1 = string:lowercase(_pipe), _pipe@2 = gleam@string:replace(_pipe@1, <<"-"/utf8>>, <<"_"/utf8>>), gleam@string:replace(_pipe@2, <<" "/utf8>>, <<"_"/utf8>>). -file("src/lightspeed/tooling/generator.gleam", 728). -spec join_with(binary(), list(binary())) -> binary(). join_with(Separator, Values) -> case Values of [] -> <<""/utf8>>; [Value] -> Value; [Value@1 | Rest] -> <<<>/binary, (join_with(Separator, Rest))/binary>> end. -file("src/lightspeed/tooling/generator.gleam", 721). -spec capitalize(binary()) -> binary(). capitalize(Value) -> case gleam_stdlib:string_pop_grapheme(Value) of {error, _} -> <<""/utf8>>; {ok, {First, Rest}} -> <<(string:uppercase(First))/binary, Rest/binary>> end. -file("src/lightspeed/tooling/generator.gleam", 714). -spec capitalize_parts(list(binary()), list(binary())) -> list(binary()). capitalize_parts(Parts, Rev) -> case Parts of [] -> lists:reverse(Rev); [Part | Rest] -> capitalize_parts(Rest, [capitalize(Part) | Rev]) end. -file("src/lightspeed/tooling/generator.gleam", 704). -spec to_module_name(binary()) -> binary(). to_module_name(Value) -> Parts = begin _pipe = Value, _pipe@1 = normalize_name(_pipe), _pipe@2 = gleam@string:split(_pipe@1, <<"_"/utf8>>), capitalize_parts(_pipe@2, []) end, join_with(<<""/utf8>>, Parts). -file("src/lightspeed/tooling/generator.gleam", 103). ?DOC( " Build a new project scaffold comparable to `phx.new`.\n" "\n" " M25 baseline deepens output toward production defaults:\n" " - data scope contracts\n" " - migration-ready directory layout\n" " - integration-test scaffolds\n" " - governance/testing defaults\n" ). -spec new(binary()) -> project(). new(App_name) -> Module_name = to_module_name(App_name), App = normalize_name(App_name), _pipe = {project, App, Module_name, [], []}, _pipe@1 = put_file( _pipe, <<".tool-versions"/utf8>>, <<"erlang 28.5\ngleam 1.16.0\nrebar 3.27.0\n"/utf8>> ), _pipe@2 = put_file( _pipe@1, <<".gitignore"/utf8>>, <<"build/\n*.beam\nerl_crash.dump\n"/utf8>> ), _pipe@3 = put_file( _pipe@2, <<"gleam.toml"/utf8>>, <<<<"name = \""/utf8, App/binary>>/binary, "\"\nversion = \"0.1.0\"\ndescription = \"Generated by lightspeed tooling\"\nlicences = [\"Unlicense\"]\ntarget = \"erlang\"\ngleam = \">= 1.16.0\"\n\n[dependencies]\ngleam_stdlib = \">= 1.0.0 and < 2.0.0\"\ngleam_otp = \">= 1.2.0 and < 2.0.0\"\n\n[dev-dependencies]\ngleeunit = \">= 1.10.0 and < 2.0.0\"\n"/utf8>> ), _pipe@4 = put_file( _pipe@3, <<"Makefile"/utf8>>, <<"setup:\n\tgleam deps download\n\nfmt:\n\tgleam format src test\n\nfmt-check:\n\tgleam format --check src test\n\ncheck:\n\tgleam check --target erlang\n\ntest:\n\tgleam test --target erlang\n\nci: fmt-check check test\n"/utf8>> ), _pipe@5 = put_file( _pipe@4, <<"AGENTS.md"/utf8>>, <<"# AGENTS\n\nGenerated project policy:\n\n1. Follow Gleam best practices.\n2. Add tests for every code change.\n3. Require RFC + ADR for every code change.\n4. Prefer simplicity first, then performance.\n"/utf8>> ), _pipe@6 = put_file( _pipe@5, <<"README.md"/utf8>>, <<<<"# "/utf8, Module_name/binary>>/binary, "\n\nGenerated by Lightspeed M25 scaffold.\n\n## Commands\n\n- make setup\n- make ci\n\n## Governance\n\nEvery code change requires an RFC and ADR.\n"/utf8>> ), _pipe@7 = put_file( _pipe@6, <<"docs/testing.md"/utf8>>, <<"# Testing\n\nRun `make ci` before commit.\nAdd tests for every new or changed behavior.\n"/utf8>> ), _pipe@8 = put_file( _pipe@7, <<"docs/data_policy.md"/utf8>>, <<"# Data Policy\n\nAll repository operations must be scoped by tenant context.\n"/utf8>> ), _pipe@9 = put_file( _pipe@8, <<"docs/migration_playbook.md"/utf8>>, <<"# Migration Playbook\n\nAdd one migration per resource and keep rollback notes beside each migration.\n"/utf8>> ), _pipe@10 = put_file( _pipe@9, <<"rfcs/0000-template.md"/utf8>>, <<"# RFC-0000 Template\n"/utf8>> ), _pipe@11 = put_file( _pipe@10, <<"adrs/0000-template.md"/utf8>>, <<"# ADR-0000 Template\n"/utf8>> ), _pipe@12 = put_file( _pipe@11, <<"priv/repo/migrations/.keep"/utf8>>, <<""/utf8>> ), _pipe@13 = put_file(_pipe@12, <<"priv/static/.keep"/utf8>>, <<""/utf8>>), _pipe@14 = put_file( _pipe@13, <<<<"src/"/utf8, App/binary>>/binary, ".gleam"/utf8>>, <<<<"pub fn banner() -> String {\n \""/utf8, Module_name/binary>>/binary, "\"\n}\n"/utf8>> ), _pipe@15 = put_file( _pipe@14, <<<<"src/"/utf8, App/binary>>/binary, "/app.gleam"/utf8>>, <<<<<<<<"import "/utf8, App/binary>>/binary, "\n\npub fn start() -> String {\n "/utf8>>/binary, App/binary>>/binary, ".banner()\n}\n"/utf8>> ), _pipe@16 = put_file( _pipe@15, <<<<"src/"/utf8, App/binary>>/binary, "/web/router.gleam"/utf8>>, <<"pub fn routes() -> List(#(String, String)) {\n [#(\"GET\", \"/health\"), #(\"GET\", \"/\")]\n}\n"/utf8>> ), _pipe@17 = put_file( _pipe@16, <<<<"src/"/utf8, App/binary>>/binary, "/web/endpoint.gleam"/utf8>>, <<<<"import "/utf8, App/binary>>/binary, "/web/router\n\npub fn route_count() -> Int {\n list.length(router.routes())\n}\n"/utf8>> ), _pipe@18 = put_file( _pipe@17, <<<<"src/"/utf8, App/binary>>/binary, "/data/scope.gleam"/utf8>>, <<"pub type Role {\n Reader\n Editor\n Admin\n}\n\npub type Scope {\n Scope(tenant_id: String, role: Role)\n}\n\npub fn can_write(scope: Scope) -> Bool {\n case scope.role {\n Editor -> True\n Admin -> True\n Reader -> False\n }\n}\n"/utf8>> ), _pipe@19 = put_file( _pipe@18, <<<<"src/"/utf8, App/binary>>/binary, "/data/repository.gleam"/utf8>>, <<<<"import "/utf8, App/binary>>/binary, "/data/scope\n\npub fn authorize_read(_scope: scope.Scope, _tenant_id: String) -> Bool {\n True\n}\n\npub fn authorize_write(scope: scope.Scope, tenant_id: String) -> Bool {\n scope.tenant_id == tenant_id && scope.can_write(scope)\n}\n"/utf8>> ), _pipe@20 = put_file( _pipe@19, <<<<"test/"/utf8, App/binary>>/binary, "_test.gleam"/utf8>>, <<<<<<<<<<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "\n\npub fn generated_banner_test() {\n "/utf8>>/binary, App/binary>>/binary, ".banner()\n |> should.equal(\""/utf8>>/binary, Module_name/binary>>/binary, "\")\n}\n"/utf8>> ), _pipe@21 = put_file( _pipe@20, <<<<"test/"/utf8, App/binary>>/binary, "/integration/app_boot_test.gleam"/utf8>>, <<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/web/endpoint\n\npub fn generated_boot_routes_test() {\n endpoint.route_count()\n |> should.equal(2)\n}\n"/utf8>> ), _pipe@22 = put_file( _pipe@21, <<<<"test/"/utf8, App/binary>>/binary, "/integration/scope_policy_test.gleam"/utf8>>, <<<<<<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/data/repository\nimport "/utf8>>/binary, App/binary>>/binary, "/data/scope\n\npub fn generated_scope_policy_test() {\n let reader = scope.Scope(tenant_id: \"t-1\", role: scope.Reader)\n let editor = scope.Scope(tenant_id: \"t-1\", role: scope.Editor)\n\n repository.authorize_write(reader, \"t-1\")\n |> should.equal(False)\n\n repository.authorize_write(editor, \"t-1\")\n |> should.equal(True)\n\n repository.authorize_write(editor, \"t-2\")\n |> should.equal(False)\n}\n"/utf8>> ), add_feature(_pipe@22, <<"new"/utf8>>). -file("src/lightspeed/tooling/generator.gleam", 327). ?DOC(" Generate a `phx.gen.json`-style resource scaffold.\n"). -spec generate_json(project(), binary()) -> project(). generate_json(Project, Resource) -> App = erlang:element(2, Project), Name = normalize_name(Resource), _pipe = Project, _pipe@1 = put_file( _pipe, <<<<<<<<"src/"/utf8, App/binary>>/binary, "/api/"/utf8>>/binary, Name/binary>>/binary, "_serializer.gleam"/utf8>>, <<<<<<<<"pub fn encode_list() -> String {\n \"{\\\"data\\\":[],\\\"resource\\\":\\\""/utf8, Name/binary>>/binary, "\\\"}\"\n}\n\npub fn encode_item(id: String) -> String {\n \"{\\\"data\\\":{\\\"id\\\":\\\"\" <> id <> \"\\\"},\\\"resource\\\":\\\""/utf8>>/binary, Name/binary>>/binary, "\\\"}\"\n}\n"/utf8>> ), _pipe@2 = put_file( _pipe@1, <<<<<<<<"src/"/utf8, App/binary>>/binary, "/controllers/"/utf8>>/binary, Name/binary>>/binary, "_json.gleam"/utf8>>, <<<<<<<<<<<<<<<<"import "/utf8, App/binary>>/binary, "/api/"/utf8>>/binary, Name/binary>>/binary, "_serializer\n\npub fn index() -> String {\n "/utf8>>/binary, Name/binary>>/binary, "_serializer.encode_list()\n}\n\npub fn show(id: String) -> String {\n "/utf8>>/binary, Name/binary>>/binary, "_serializer.encode_item(id)\n}\n"/utf8>> ), _pipe@3 = put_file( _pipe@2, <<<<<<<<"test/"/utf8, App/binary>>/binary, "/"/utf8>>/binary, Name/binary>>/binary, "_json_test.gleam"/utf8>>, <<<<<<<<<<<<<<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/controllers/"/utf8>>/binary, Name/binary>>/binary, "_json\n\npub fn generated_json_resource_test() {\n "/utf8>>/binary, Name/binary>>/binary, "_json.index()\n |> should.equal(\"{\\\"data\\\":[],\\\"resource\\\":\\\""/utf8>>/binary, Name/binary>>/binary, "\\\"}\")\n}\n"/utf8>> ), _pipe@4 = put_file( _pipe@3, <<<<<<<<"test/"/utf8, App/binary>>/binary, "/integration/"/utf8>>/binary, Name/binary>>/binary, "_json_flow_test.gleam"/utf8>>, <<<<<<<<<<<<<<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/controllers/"/utf8>>/binary, Name/binary>>/binary, "_json\n\npub fn generated_json_show_test() {\n "/utf8>>/binary, Name/binary>>/binary, "_json.show(\"42\")\n |> should.equal(\"{\\\"data\\\":{\\\"id\\\":\\\"42\\\"},\\\"resource\\\":\\\""/utf8>>/binary, Name/binary>>/binary, "\\\"}\")\n}\n"/utf8>> ), add_feature(_pipe@4, <<"gen.json:"/utf8, Name/binary>>). -file("src/lightspeed/tooling/generator.gleam", 281). ?DOC(" Generate a `phx.gen.html`-style resource scaffold.\n"). -spec generate_html(project(), binary()) -> project(). generate_html(Project, Resource) -> App = erlang:element(2, Project), Name = normalize_name(Resource), Module_name = to_module_name(Name), _pipe = Project, _pipe@1 = put_file( _pipe, <<<<<<<<"src/"/utf8, App/binary>>/binary, "/controllers/"/utf8>>/binary, Name/binary>>/binary, "_html.gleam"/utf8>>, <<<<<<<<"pub fn index() -> String {\n \"

"/utf8, Module_name/binary>>/binary, " Index

\"\n}\n\npub fn show(id: String) -> String {\n \"
id <> \"\\\">"/utf8>>/binary, Module_name/binary>>/binary, " Show
\"\n}\n"/utf8>> ), _pipe@2 = put_file( _pipe@1, <<<<"priv/templates/"/utf8, Name/binary>>/binary, "/index.html"/utf8>>, <<<<"

"/utf8, Module_name/binary>>/binary, " Index

\n"/utf8>> ), _pipe@3 = put_file( _pipe@2, <<<<<<<<"test/"/utf8, App/binary>>/binary, "/"/utf8>>/binary, Name/binary>>/binary, "_html_test.gleam"/utf8>>, <<<<<<<<<<<<<<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/controllers/"/utf8>>/binary, Name/binary>>/binary, "_html\n\npub fn generated_html_resource_test() {\n "/utf8>>/binary, Name/binary>>/binary, "_html.index()\n |> should.equal(\"

"/utf8>>/binary, Module_name/binary>>/binary, " Index

\")\n}\n"/utf8>> ), _pipe@4 = put_file( _pipe@3, <<<<<<<<"test/"/utf8, App/binary>>/binary, "/integration/"/utf8>>/binary, Name/binary>>/binary, "_html_flow_test.gleam"/utf8>>, <<<<<<<<<<<<<<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/controllers/"/utf8>>/binary, Name/binary>>/binary, "_html\n\npub fn generated_html_show_test() {\n "/utf8>>/binary, Name/binary>>/binary, "_html.show(\"42\")\n |> should.equal(\"
"/utf8>>/binary, Module_name/binary>>/binary, " Show
\")\n}\n"/utf8>> ), add_feature(_pipe@4, <<"gen.html:"/utf8, Name/binary>>). -file("src/lightspeed/tooling/generator.gleam", 211). ?DOC(" Generate a `phx.gen.live`-style resource scaffold.\n"). -spec generate_live(project(), binary()) -> project(). generate_live(Project, Resource) -> App = erlang:element(2, Project), Name = normalize_name(Resource), Module_name = to_module_name(Name), _pipe = Project, _pipe@1 = put_file( _pipe, <<<<<<<<"src/"/utf8, App/binary>>/binary, "/live/"/utf8>>/binary, Name/binary>>/binary, "_live.gleam"/utf8>>, <<<<<<<<"pub type Model {\n Model(count: Int)\n}\n\npub type Msg {\n Increment\n Decrement\n}\n\npub fn init() -> Model {\n Model(count: 0)\n}\n\npub fn update(model: Model, msg: Msg) -> Model {\n case msg {\n Increment -> Model(..model, count: model.count + 1)\n Decrement -> Model(..model, count: model.count - 1)\n }\n}\n\npub fn render(model: Model) -> String {\n \"
>/binary, "\\\">

"/utf8>>/binary, Module_name/binary>>/binary, "

\" <> int.to_string(model.count) <> \"
\"\n}\n"/utf8>> ), _pipe@2 = put_file( _pipe@1, <<<<<<<<"src/"/utf8, App/binary>>/binary, "/data/"/utf8>>/binary, Name/binary>>/binary, "_repository.gleam"/utf8>>, <<<<<<<<"import "/utf8, App/binary>>/binary, "/data/repository\nimport "/utf8>>/binary, App/binary>>/binary, "/data/scope\n\npub fn list(scope scope: scope.Scope) -> Result(List(String), String) {\n case repository.authorize_read(scope, scope.tenant_id) {\n True -> Ok([])\n False -> Error(\"forbidden\")\n }\n}\n\npub fn insert(scope scope: scope.Scope, tenant_id: String, _attrs: String) -> Result(String, String) {\n case repository.authorize_write(scope, tenant_id) {\n True -> Ok(\"created\")\n False -> Error(\"forbidden\")\n }\n}\n"/utf8>> ), _pipe@3 = put_file( _pipe@2, <<<<"priv/repo/migrations/20260508000000_create_"/utf8, Name/binary>>/binary, ".sql"/utf8>>, <<<<<<<<"-- up\n-- create table "/utf8, Name/binary>>/binary, " (\n-- id text primary key,\n-- tenant_id text not null,\n-- inserted_at text not null\n-- );\n\n-- down\n-- drop table "/utf8>>/binary, Name/binary>>/binary, ";\n"/utf8>> ), _pipe@4 = put_file( _pipe@3, <<<<<<<<"test/"/utf8, App/binary>>/binary, "/"/utf8>>/binary, Name/binary>>/binary, "_live_test.gleam"/utf8>>, <<<<<<<<<<<<<<<<<<<<<<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/live/"/utf8>>/binary, Name/binary>>/binary, "_live\n\npub fn generated_live_render_test() {\n "/utf8>>/binary, Name/binary>>/binary, "_live.init()\n |> "/utf8>>/binary, Name/binary>>/binary, "_live.render\n |> should.equal("/utf8>>/binary, Name/binary>>/binary, "_live.init() |> "/utf8>>/binary, Name/binary>>/binary, "_live.render)\n}\n"/utf8>> ), _pipe@5 = put_file( _pipe@4, <<<<<<<<"test/"/utf8, App/binary>>/binary, "/integration/"/utf8>>/binary, Name/binary>>/binary, "_live_flow_test.gleam"/utf8>>, <<<<<<<<<<<<<<<<<<<<"import gleeunit/should\nimport "/utf8, App/binary>>/binary, "/data/"/utf8>>/binary, Name/binary>>/binary, "_repository\nimport "/utf8>>/binary, App/binary>>/binary, "/data/scope\n\npub fn generated_live_resource_scope_test() {\n let scope_reader = scope.Scope(tenant_id: \"t-1\", role: scope.Reader)\n let scope_editor = scope.Scope(tenant_id: \"t-1\", role: scope.Editor)\n\n "/utf8>>/binary, Name/binary>>/binary, "_repository.insert(scope_reader, \"t-1\", \"{}\")\n |> should.equal(Error(\"forbidden\"))\n\n "/utf8>>/binary, Name/binary>>/binary, "_repository.insert(scope_editor, \"t-1\", \"{}\")\n |> should.equal(Ok(\"created\"))\n}\n"/utf8>> ), _pipe@6 = put_file( _pipe@5, <<<<"examples/crud/"/utf8, Name/binary>>/binary, ".md"/utf8>>, <<<<"# CRUD Example "/utf8, Module_name/binary>>/binary, "\n\nGenerated live resource fixture with scope-aware repository and migration scaffold.\n"/utf8>> ), add_feature(_pipe@6, <<"gen.live:"/utf8, Name/binary>>). -file("src/lightspeed/tooling/generator.gleam", 78). ?DOC(" Execute one command into a generated project tree.\n"). -spec scaffold(command()) -> project(). scaffold(Command) -> case Command of {new, App_name} -> new(App_name); {gen_live, App_name@1, Resource} -> _pipe = new(App_name@1), generate_live(_pipe, Resource); {gen_html, App_name@2, Resource@1} -> _pipe@1 = new(App_name@2), generate_html(_pipe@1, Resource@1); {gen_json, App_name@3, Resource@2} -> _pipe@2 = new(App_name@3), generate_json(_pipe@2, Resource@2); {gen_auth, App_name@4} -> _pipe@3 = new(App_name@4), generate_auth(_pipe@3) end. -file("src/lightspeed/tooling/generator.gleam", 432). ?DOC(" Generated app name.\n"). -spec app_name(project()) -> binary(). app_name(Project) -> erlang:element(2, Project). -file("src/lightspeed/tooling/generator.gleam", 437). ?DOC(" Generated module name.\n"). -spec module_name(project()) -> binary(). module_name(Project) -> erlang:element(3, Project). -file("src/lightspeed/tooling/generator.gleam", 442). ?DOC(" Generated files in stable order.\n"). -spec files(project()) -> list(file()). files(Project) -> lists:reverse(erlang:element(4, Project)). -file("src/lightspeed/tooling/generator.gleam", 447). ?DOC(" Generated feature labels in stable order.\n"). -spec features(project()) -> list(binary()). features(Project) -> lists:reverse(erlang:element(5, Project)). -file("src/lightspeed/tooling/generator.gleam", 664). -spec has_file_in(list(file()), binary()) -> boolean(). has_file_in(Files_rev, Path) -> case Files_rev of [] -> false; [Entry | Rest] -> case erlang:element(2, Entry) =:= Path of true -> true; false -> has_file_in(Rest, Path) end end. -file("src/lightspeed/tooling/generator.gleam", 452). ?DOC(" Check for a generated file.\n"). -spec has_file(project(), binary()) -> boolean(). has_file(Project, Path) -> has_file_in(erlang:element(4, Project), Path). -file("src/lightspeed/tooling/generator.gleam", 675). -spec read_file(list(file()), binary()) -> gleam@option:option(binary()). read_file(Files_rev, Path) -> case Files_rev of [] -> none; [Entry | Rest] -> case erlang:element(2, Entry) =:= Path of true -> {some, erlang:element(3, Entry)}; false -> read_file(Rest, Path) end end. -file("src/lightspeed/tooling/generator.gleam", 457). ?DOC(" Read generated file content when present.\n"). -spec file_content(project(), binary()) -> gleam@option:option(binary()). file_content(Project, Path) -> read_file(erlang:element(4, Project), Path). -file("src/lightspeed/tooling/generator.gleam", 629). -spec file_paths(list(file())) -> list(binary()). file_paths(Files) -> case Files of [] -> []; [{file, Path, _} | Rest] -> [Path | file_paths(Rest)] end. -file("src/lightspeed/tooling/generator.gleam", 462). ?DOC(" Stable fixture signature for reproducible generator outputs.\n"). -spec fixture_signature(project()) -> binary(). fixture_signature(Project) -> <<<<<<<<<<<<<<"m25.v"/utf8, (erlang:integer_to_binary(2))/binary>>/binary, "|app="/utf8>>/binary, (erlang:element(2, Project))/binary>>/binary, "|features="/utf8>>/binary, (join_with(<<","/utf8>>, features(Project)))/binary>>/binary, "|files="/utf8>>/binary, (join_with(<<","/utf8>>, file_paths(files(Project))))/binary>>. -file("src/lightspeed/tooling/generator.gleam", 622). -spec all_paths(list(binary()), project()) -> boolean(). all_paths(Paths, Project) -> case Paths of [] -> true; [Path | Rest] -> has_file(Project, Path) andalso all_paths(Rest, Project) end. -file("src/lightspeed/tooling/generator.gleam", 614). -spec has_rfc_adr_mentions(project()) -> boolean(). has_rfc_adr_mentions(Project) -> case file_content(Project, <<"README.md"/utf8>>) of none -> false; {some, Content} -> gleam_stdlib:contains_string(Content, <<"RFC"/utf8>>) andalso gleam_stdlib:contains_string( Content, <<"ADR"/utf8>> ) end. -file("src/lightspeed/tooling/generator.gleam", 601). -spec makefile_has_targets(project()) -> boolean(). makefile_has_targets(Project) -> case file_content(Project, <<"Makefile"/utf8>>) of none -> false; {some, Content} -> ((((gleam_stdlib:contains_string(Content, <<"setup:"/utf8>>) andalso gleam_stdlib:contains_string( Content, <<"fmt:"/utf8>> )) andalso gleam_stdlib:contains_string(Content, <<"fmt-check:"/utf8>>)) andalso gleam_stdlib:contains_string(Content, <<"check:"/utf8>>)) andalso gleam_stdlib:contains_string(Content, <<"test:"/utf8>>)) andalso gleam_stdlib:contains_string(Content, <<"ci:"/utf8>>) end. -file("src/lightspeed/tooling/generator.gleam", 474). ?DOC(" Validate that generated project satisfies baseline boot/CI constraints.\n"). -spec boot_ci_contract(project()) -> boolean(). boot_ci_contract(Project) -> App = erlang:element(2, Project), Required_files = [<<".tool-versions"/utf8>>, <<".gitignore"/utf8>>, <<"gleam.toml"/utf8>>, <<"Makefile"/utf8>>, <<"AGENTS.md"/utf8>>, <<"README.md"/utf8>>, <<"docs/testing.md"/utf8>>, <<"docs/data_policy.md"/utf8>>, <<"docs/migration_playbook.md"/utf8>>, <<"rfcs/0000-template.md"/utf8>>, <<"adrs/0000-template.md"/utf8>>, <<<<"src/"/utf8, App/binary>>/binary, ".gleam"/utf8>>, <<<<"src/"/utf8, App/binary>>/binary, "/data/scope.gleam"/utf8>>, <<<<"src/"/utf8, App/binary>>/binary, "/data/repository.gleam"/utf8>>, <<<<"test/"/utf8, App/binary>>/binary, "_test.gleam"/utf8>>, <<<<"test/"/utf8, App/binary>>/binary, "/integration/app_boot_test.gleam"/utf8>>, <<<<"test/"/utf8, App/binary>>/binary, "/integration/scope_policy_test.gleam"/utf8>>], Required_targets = makefile_has_targets(Project), Governance = has_rfc_adr_mentions(Project), (all_paths(Required_files, Project) andalso Required_targets) andalso Governance. -file("src/lightspeed/tooling/generator.gleam", 596). -spec has_migration_ready_layout(project()) -> boolean(). has_migration_ready_layout(Project) -> has_file(Project, <<"priv/repo/migrations/.keep"/utf8>>) andalso has_file( Project, <<"docs/migration_playbook.md"/utf8>> ). -file("src/lightspeed/tooling/generator.gleam", 579). -spec has_data_scope_controls(project()) -> boolean(). has_data_scope_controls(Project) -> App = erlang:element(2, Project), case {file_content( Project, <<<<"src/"/utf8, App/binary>>/binary, "/data/scope.gleam"/utf8>> ), file_content( Project, <<<<"src/"/utf8, App/binary>>/binary, "/data/repository.gleam"/utf8>> )} of {{some, Scope_file}, {some, Repo_file}} -> ((gleam_stdlib:contains_string( Scope_file, <<"pub type Scope"/utf8>> ) andalso gleam_stdlib:contains_string( Scope_file, <<"pub fn can_write"/utf8>> )) andalso gleam_stdlib:contains_string( Repo_file, <<"authorize_write"/utf8>> )) andalso gleam_stdlib:contains_string( Repo_file, <<"scope.tenant_id == tenant_id"/utf8>> ); {_, _} -> false end. -file("src/lightspeed/tooling/generator.gleam", 502). ?DOC(" Validate production-ready scaffold defaults from M25.\n"). -spec production_contract(project()) -> boolean(). production_contract(Project) -> (boot_ci_contract(Project) andalso has_data_scope_controls(Project)) andalso has_migration_ready_layout( Project ). -file("src/lightspeed/tooling/generator.gleam", 509). ?DOC(" Validate that generated resource files include migration/integration scaffolds.\n"). -spec resource_contract(project(), binary()) -> boolean(). resource_contract(Project, Resource) -> App = erlang:element(2, Project), Name = normalize_name(Resource), ((((has_file( Project, <<<<<<<<"src/"/utf8, App/binary>>/binary, "/live/"/utf8>>/binary, Name/binary>>/binary, "_live.gleam"/utf8>> ) andalso has_file( Project, <<<<<<<<"src/"/utf8, App/binary>>/binary, "/data/"/utf8>>/binary, Name/binary>>/binary, "_repository.gleam"/utf8>> )) andalso has_file( Project, <<<<"priv/repo/migrations/20260508000000_create_"/utf8, Name/binary>>/binary, ".sql"/utf8>> )) andalso has_file( Project, <<<<<<<<"test/"/utf8, App/binary>>/binary, "/integration/"/utf8>>/binary, Name/binary>>/binary, "_live_flow_test.gleam"/utf8>> )) andalso has_file( Project, <<<<<<<<"test/"/utf8, App/binary>>/binary, "/integration/"/utf8>>/binary, Name/binary>>/binary, "_html_flow_test.gleam"/utf8>> )) andalso has_file( Project, <<<<<<<<"test/"/utf8, App/binary>>/binary, "/integration/"/utf8>>/binary, Name/binary>>/binary, "_json_flow_test.gleam"/utf8>> ). -file("src/lightspeed/tooling/generator.gleam", 534). ?DOC(" Validate auth scaffold defaults from M25.\n"). -spec auth_contract(project()) -> boolean(). auth_contract(Project) -> App = erlang:element(2, Project), (((has_file( Project, <<<<"src/"/utf8, App/binary>>/binary, "/auth/password.gleam"/utf8>> ) andalso has_file( Project, <<<<"src/"/utf8, App/binary>>/binary, "/auth/policy.gleam"/utf8>> )) andalso has_file( Project, <<<<"src/"/utf8, App/binary>>/binary, "/auth/session.gleam"/utf8>> )) andalso has_file( Project, <<<<"test/"/utf8, App/binary>>/binary, "/auth_policy_test.gleam"/utf8>> )) andalso has_file( Project, <<<<"test/"/utf8, App/binary>>/binary, "/integration/auth_flow_test.gleam"/utf8>> ). -file("src/lightspeed/tooling/generator.gleam", 545). ?DOC(" Deterministic fixture snapshots used by drift guards.\n"). -spec fixture_snapshots() -> list({binary(), binary()}). fixture_snapshots() -> Project = new(<<"demo_app"/utf8>>), Full_stack = begin _pipe = Project, _pipe@1 = generate_live(_pipe, <<"posts"/utf8>>), _pipe@2 = generate_html(_pipe@1, <<"posts"/utf8>>), _pipe@3 = generate_json(_pipe@2, <<"posts"/utf8>>), generate_auth(_pipe@3) end, Auth_only = begin _pipe@4 = Project, generate_auth(_pipe@4) end, [{<<"project"/utf8>>, fixture_signature(Project)}, {<<"auth_only"/utf8>>, fixture_signature(Auth_only)}, {<<"full_stack"/utf8>>, fixture_signature(Full_stack)}]. -file("src/lightspeed/tooling/generator.gleam", 565). ?DOC(" Deterministic snapshot signature over M25 generator fixtures.\n"). -spec snapshot_signature() -> binary(). snapshot_signature() -> Entries = begin _pipe = fixture_snapshots(), gleam@list:map( _pipe, fun(Entry) -> {Name, Signature} = Entry, <<<>/binary, "|"/utf8>>/binary, (join_with(<<";"/utf8>>, Entries))/binary>>.