Skip to content

Commit e867780

Browse files
chore(reflaxe): normalize exception std override layout
1 parent fd9aaa3 commit e867780

22 files changed

Lines changed: 213 additions & 139 deletions

File tree

.beads/issues.jsonl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@
260260
{"_type":"issue","id":"haxe.elixir-cje","title":"Generate or implement Phoenix.SafePubSub module","description":"MISSING MODULE: Phoenix.SafePubSub has 5 undefined functions used in TodoPubSub (lib/reflaxe_runtime/server/pubsub/todo_pub_sub.ex): subscribe_topic/1 (line 9), broadcast_topic_payload/2 (line 13), parse_with_converter/2 (line 17), add_timestamp/1 (line 41), is_valid_message/1 (line 45). This is a type-safe wrapper around Phoenix.PubSub. Implement in std/phoenix/ or integrate into existing PubSub extern.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-03T00:00:44Z","updated_at":"2025-12-08T17:23:08Z","closed_at":"2025-12-08T11:23:08Z","dependency_count":0,"dependent_count":2,"comment_count":0}
261261
{"_type":"issue","id":"haxe.elixir-n6u","title":"Generate or implement Phoenix.Sorting module","description":"MISSING MODULE: Phoenix.Sorting.by/2 is undefined. Used in TodoLive.filter_and_sort_todos/5 at lib/todo_app_web/todo_live.ex:723. This appears to be a sorting utility that should sort a list by a given key. Either implement in std/phoenix/ or remove reference if not needed.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-03T00:00:37Z","updated_at":"2025-12-08T17:23:08Z","closed_at":"2025-12-08T11:23:08Z","dependency_count":0,"dependent_count":2,"comment_count":0}
262262
{"_type":"issue","id":"haxe.elixir-ml4","title":"Generate or implement TodoApp.ChangesetTools module","description":"MISSING MODULE: TodoApp.ChangesetTools.cast_with_string_fields/3 is undefined. Used in TodoLive.create_todo/2 at lib/todo_app_web/todo_live.ex:82. Either: (1) Create a Haxe class in std that generates this module, (2) Add it to the todo-app src_haxe, or (3) Remove the reference if dead code. The function appears to handle casting changeset fields from string params.","status":"closed","priority":1,"issue_type":"bug","created_at":"2025-12-03T00:00:30Z","updated_at":"2025-12-08T17:23:08Z","closed_at":"2025-12-08T11:23:08Z","dependency_count":0,"dependent_count":2,"comment_count":0}
263+
{"_type":"issue","id":"haxe.elixir.codex-cue","title":"Normalize haxe.Exception Reflaxe source layout","description":"Move the authored Elixir haxe.Exception override from src/haxe/Exception.cross.hx to std/elixir/_std/haxe/Exception.hx without changing executable code or target semantics. Keep source development wired through scoped HXML, let Reflaxe build generate packaged .cross.hx, update guards/docs/changelog, and validate compiler, package, PhoenixHx, examples, stdlib, snapshots, and todo-app QA.","acceptance_criteria":"No checked-in src/**/*.cross.hx remains; source-mode haxe.Exception resolves from std/elixir/_std; built package contains src/haxe/Exception.cross.hx; generated Elixir is unchanged except source-map path metadata; full local CI parity and async Playwright QA pass; latest pushed workflows are green.","status":"closed","priority":2,"issue_type":"task","owner":"boss@fullofcaffeine.com","created_at":"2026-07-09T19:54:10Z","created_by":"Marcelo Serpa","updated_at":"2026-07-09T21:04:42Z","started_at":"2026-07-09T19:54:15Z","closed_at":"2026-07-09T21:04:42Z","close_reason":"Moved haxe.Exception into the conventional std/elixir/_std source layout without executable-code or target-semantic changes; fixed and guarded complete scoped HXML classpaths, documented source/package consumption, and passed full snapshots, stdlib/runtime, examples/WAE, package smoke, Mix, npm test, and async todo-app Playwright QA.","labels":["packaging","reflaxe","stdlib"],"dependency_count":0,"dependent_count":0,"comment_count":0}
263264
{"_type":"issue","id":"haxe.elixir.codex-o4h","title":"Guard installed package CLI entrypoint","description":"Extend the haxelib package smoke to validate the installed package CLI entrypoint and fix the package layout issue it exposed: BEAM sys.* replacements must be authored under std/elixir/_std/sys so Reflaxe packages them as .cross.hx instead of shadowing host/eval sys.* during CLI runs.","acceptance_criteria":"BEAM sys.* replacements live under std/elixir/_std/sys; the layout guard rejects new plain std/sys modules; package smoke asserts packaged sys.* files are .cross.hx, runs the installed Run version command with the pinned Haxe binary, documents the convention in changelog/docs, and local package/layout/example checks pass.","status":"closed","priority":2,"issue_type":"chore","owner":"boss@fullofcaffeine.com","created_at":"2026-07-09T16:29:08Z","created_by":"Marcelo Serpa","updated_at":"2026-07-09T16:54:04Z","started_at":"2026-07-09T16:29:18Z","closed_at":"2026-07-09T16:54:04Z","close_reason":"Moved BEAM sys.* std replacements into std/elixir/_std/sys, guarded plain std/sys, validated package CLI/artifact behavior, full snapshots, stdlib runtime, examples, Mix fast, and async todo-app Playwright sentinel.","labels":["packaging","reflaxe"],"dependency_count":0,"dependent_count":0,"comment_count":0}
264265
{"_type":"issue","id":"haxe.elixir.codex-qz1","title":"Guard Reflaxe package artifact layout","description":"Strengthen haxelib package smoke coverage so the installed artifact keeps using Reflaxe build flattening instead of source-only std layouts or hand-rolled package structure.","acceptance_criteria":"Package smoke asserts source-only std/elixir/_std and haxelib reflaxe metadata are absent from installed artifacts while flattened .cross.hx overrides remain present; docs/changelog record the release-validation convention; local package/layout guards pass.","status":"closed","priority":2,"issue_type":"chore","owner":"boss@fullofcaffeine.com","created_at":"2026-07-09T15:53:29Z","created_by":"Marcelo Serpa","updated_at":"2026-07-09T15:55:49Z","started_at":"2026-07-09T15:53:39Z","closed_at":"2026-07-09T15:55:49Z","close_reason":"Implemented package artifact layout guard; validated stdlib layout, docs links, diff check, and haxelib package smoke.","labels":["packaging","reflaxe"],"dependency_count":0,"dependent_count":0,"comment_count":0}
265266
{"_type":"issue","id":"haxe.elixir.codex-7es","title":"Enable upstream Date and DateTools stdlib runtime specs","status":"closed","priority":2,"issue_type":"task","created_at":"2026-07-07T17:02:09Z","updated_at":"2026-07-07T17:56:26Z","closed_at":"2026-07-07T17:56:26Z","close_reason":"Enabled upstream Date and DateTools unitstd runtime specs, fixed Date/Date_Impl_ BEAM semantics, updated docs/snapshots/examples, and verified stdlib/runtime/examples/QA sentinel.","labels":["stdlib","testing"],"dependency_count":0,"dependent_count":0,"comment_count":0}

AGENTS.md

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -711,17 +711,17 @@ Examples
711711
- Repo root/runtime shims and any `*.ex` such as: `reflect.ex`, `std.ex`, `string_buf.ex`, `type.ex`, `int_iterator.ex`
712712
- Snapshot outputs under `test/snapshot/**/out/**/*.ex`
713713
- Make all behavior changes in the source-of-truth instead:
714-
- Standard library Haxe sources: `std/**/*.cross.hx`, target-owned `std/**/*.hx`, and early dual-mode `src/haxe/**`
714+
- Standard library Haxe sources: `std/elixir/_std/**/*.hx`, target-owned `std/**/*.hx`, and early plain dual-mode `src/haxe/**`
715715
- Compiler pipeline: `src/reflaxe/elixir/ast/**` (Builder → Transformer → Printer)
716716
- Only edit a `.ex` under `std/` directly if it is explicitly documented as the canonical runtime source (no corresponding `.hx` exists). If unsure, assume it is generated and fix upstream.
717-
- Example: Reflect.compare/2 — do not touch `reflect.ex`; change `std/Reflect.cross.hx` and re-run snapshots.
717+
- Example: Reflect.compare/2 — do not touch `reflect.ex`; change its authored `_std` Haxe source and re-run snapshots.
718718
- No band-aids: Do not “clean up” outputs or add runtime-only conditionals to mask upstream issues. Fix the transform or std source.
719719
- Pre-merge checks for std/behavior fixes:
720-
- `rg` should show diffs only in `std/**/*.cross.hx`, target-owned `std/**/*.hx`, early dual-mode `src/haxe/**`, or `src/reflaxe/elixir/**`.
720+
- `rg` should show diffs only in `std/elixir/_std/**/*.hx`, target-owned `std/**/*.hx`, early plain dual-mode `src/haxe/**`, or `src/reflaxe/elixir/**`.
721721
- No diffs to `reflect.ex`, `std.ex`, `string_buf.ex`, `type.ex`, `int_iterator.ex`, or `test/snapshot/**/out/**` unless accompanied by matching upstream `.hx` changes and a note explaining why the `.ex` is canonical.
722722
- Temporary runtime edits for debugging are allowed only if clearly annotated “DEBUG ONLY” and removed in the same PR after the proper upstream fix lands.
723723
- CI/WAE hygiene for stdlib overrides:
724-
- When adding/overriding a stdlib module in `std/**/*.cross.hx`, keep the public API (signatures + overloads) identical to upstream Haxe stdlib.
724+
- When adding/overriding a stdlib module in `std/elixir/_std/**/*.hx`, keep the public API (signatures + overloads) identical to upstream Haxe stdlib.
725725
- Avoid adding `@:coreApi` unless the upstream module is `@:coreApi` (core types get special treatment).
726726
- Verify locally before pushing: `npm run test:quick` + `npm run test:mix-fast` + `npm run test:examples-elixir` (WAE gate).
727727
- CI/WAE hygiene for `Examples (Elixir WAE)`:
@@ -885,16 +885,25 @@ Checklist before merging a transform:
885885
886886
### What lives where
887887
888-
- `std/**/*.cross.hx`
889-
- Cross-platform override files selected by Haxe when compiling in `cross` mode (Reflaxe targets on Haxe 4).
890-
- These shadow upstream Haxe stdlib by classpath precedence (Elixir builds only).
888+
- `std/elixir/_std/**/*.hx`
889+
- Authored upstream-colliding Elixir stdlib overrides, including `haxe.Exception`.
890+
- Reflaxe package builds flatten these into generated `src/**/*.cross.hx`; never check those generated files into the source tree.
891891
- Plain `std/**/*.hx`
892-
- Target-owned APIs/support modules such as `phoenix.*`, `ecto.*`, `elixir.*`, and BEAM-backed `sys.*`.
893-
- These are also visible only when bootstrap adds `std/` for Elixir builds.
892+
- Target-owned APIs/support modules such as `phoenix.*`, `ecto.*`, and `elixir.*`.
893+
- Upstream `haxe.*` and `sys.*` replacements belong under `std/elixir/_std`.
894894
- `src/haxe/**`
895-
- Rare early dual-mode stdlib overrides that must be available before bootstrap can add `std/`.
895+
- Rare early plain `.hx` dual-mode stdlib overrides that must be available to macro/eval before bootstrap can add `std/`.
896896
- Use `#if macro` for eval-safe host behavior and `#else` extern/target behavior when needed.
897897
898+
### Source checkout contract
899+
900+
- Repo-local, GitHub, and Lix development must resolve `-lib reflaxe.elixir` through the scoped `haxe_libraries/reflaxe.elixir.hxml`, which adds `std`, then `std/elixir/_std`, before typing.
901+
- An app-local `haxe_libraries/reflaxe.elixir.hxml` overrides the repository entry instead of extending it. It must repeat the complete `src`, `std`, then `std/elixir/_std` contract; `npm run guard:stdlib-layout` audits every checked-in scoped entry.
902+
- Direct compiler HXML files that bypass `-lib reflaxe.elixir` must add those same classpaths explicitly.
903+
- Do not point bare global `haxelib dev` at the unbuilt checkout for compiler testing: haxelib exposes only the single `src` classpath, so early upstream-colliding `_std` modules may already be cached before a macro can add the path.
904+
- To test through haxelib, build/install the package artifact first. Reflaxe then places generated `.cross.hx` files inside the package `src` classpath.
905+
- Keep `extraParams.hxml` cwd-agnostic. Relative `-cp` entries there resolve from the consumer project, not this library.
906+
898907
### How gating works
899908
900909
- Consumer installs rely on `extraParams.hxml`, which runs:
@@ -1573,6 +1582,7 @@ haxe.elixir/ # Project root (Reflaxe convention)
15731582
│ ├── ElixirCompiler.hx # Main compiler extending GenericCompiler<ElixirAST>
15741583
│ └── ast/ # AST builder, transformer, and printer
15751584
├── std/ # 📚 STANDARD LIBRARY (compile-time classpath)
1585+
│ ├── elixir/_std/ # Authored upstream std overrides; packaged as .cross.hx
15761586
│ ├── elixir/ # Elixir stdlib externs (IO, File, etc.)
15771587
│ ├── phoenix/ # Phoenix framework externs
15781588
│ └── ecto/ # Ecto ORM externs
@@ -1604,7 +1614,7 @@ haxe.elixir/ # Project root (Reflaxe convention)
16041614
- This is where ElixirCompiler.hx lives - the actual transpiler
16051615
- Only exists at macro-time, not in generated output
16061616
1607-
2. **`std/`** - Standard library (added to the classpath by `CompilerInit.Start()` for Elixir builds)
1617+
2. **`std/`** - Standard library (added by scoped HXML before typing, with bootstrap fallback for Elixir builds)
16081618
- Provides Haxe externs for Elixir/Phoenix/Ecto functionality
16091619
- Available to all user code during compilation
16101620
- Similar to how Reflaxe.CPP has `std/` for C++ standard library
@@ -3662,12 +3672,12 @@ See also: docs/03-compiler-development/transformers-overview.md (updated with th
36623672

36633673
- Do not land a temporary “unblocker” if the correct long‑term solution is known and in scope. Implement the proper solution even if it takes longer.
36643674
- Prefer earliest, architectural fixes over late compensating passes:
3665-
- stdlib behavior/shape → use `.cross.hx` overrides with typed externs and `__elixir__()`; avoid transformer overrides for stdlib.
3675+
- stdlib behavior/shape → author `_std` overrides with typed externs and `__elixir__()`; let Reflaxe generate package `.cross.hx` files and avoid transformer overrides for stdlib.
36663676
- Code generation issues → fix in Builder/AST generation rather than printer or post‑hoc transformer hacks.
36673677
- Classpath/availability → use target‑conditional classpath gating (CompilerInit.Start), never global inclusion.
36683678
- Exception: short‑lived debug instrumentation (behind `-D debug_*` flags) solely to investigate an issue and removed in the same PR as the permanent fix. No “temporary” hacks are allowed to merge into main.
36693679
- Review gate: PRs proposing stopgaps must include the proper fix in the same PR. Otherwise, reject the PR.
3670-
- Example: Implement Reflect.* and Type.* via `std/Reflect.cross.hx` and `std/Type.cross.hx` rather than overriding them in `StdHaxeRuntimeOverrideTransforms`.
3680+
- Example: Implement Reflect.* and Type.* in their `std/elixir/_std` Haxe sources rather than overriding them in `StdHaxeRuntimeOverrideTransforms`.
36713681
## Testing Discipline: No Test-Only Behavior Gates
36723682

36733683
- Tests must validate the exact behavior we ship. Do not add compiler conditionals, flags, or alternate code paths whose sole purpose is to make tests pass.

CHANGELOG.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44

55
* **reflaxe:** align stdlib override sources with the Reflaxe `_std` layout; source-tree and GitHub/Lix builds now load `std/elixir/_std` before target-owned `std` APIs so PhoenixHx/examples keep using the Elixir stdlib overrides in dev mode.
66
* **reflaxe:** move remaining upstream-colliding `std/haxe/**` replacement modules into `std/elixir/_std`, leaving plain `std/haxe/**` for target-owned support surfaces.
7+
* **reflaxe:** move the authored `haxe.Exception` override into `std/elixir/_std/haxe/Exception.hx`; Reflaxe now creates `src/haxe/Exception.cross.hx` only in built release packages, matching the Rust and OCaml target layout without changing exception semantics.
78
* **reflaxe:** align package entrypoint HXML files with Reflaxe-generated targets by applying package-scoped `nullSafety("reflaxe.elixir")` before bootstrap/init macros.
8-
* **reflaxe:** enforce the source-tree `.cross.hx` convention so the only checked-in `src/**/*.cross.hx` file remains the documented early `haxe.Exception` override.
9+
* **reflaxe:** enforce that checked-in source trees contain no `.cross.hx` package artifacts; upstream-colliding overrides must be authored under `std/elixir/_std` and flattened by Reflaxe at release time.
910
* **reflaxe:** move BEAM `sys.*` stdlib replacements into `std/elixir/_std/sys` so Reflaxe packages them as `.cross.hx` files instead of shadowing host/eval `sys.*` during package CLI runs.
1011
* **ci:** strengthen the haxelib package smoke to assert the installed artifact keeps Reflaxe-flattened `src/**/*.cross.hx` overrides and does not publish source-only `_std` layout roots.
12+
* **ci:** audit every checked-in scoped `reflaxe.elixir.hxml` so nested example/PhoenixHx development cannot silently omit the target `_std` root and fall back to upstream modules.
13+
* **examples:** align the Phoenix chat app-local scoped library entry with the full Reflaxe source-checkout classpath contract and refresh its generated test helper output.
1114
* **ci:** validate the installed package CLI entrypoint so `main: "Run"` and `src/Run.hx` stay aligned in release artifacts.
1215
* **reflaxe:** audit vendored framework patches against upstream Reflaxe plus the Rust/OCaml converted targets, documenting which local fixes remain required, which are upstream candidates, and which drift needs a separate sync task.
1316
* **reflaxe:** remove debug-only vendored framework drift while preserving required local Reflaxe patches.
14-
* **docs:** clarify the remaining early `src/haxe/**` overrides, including why `src/haxe/Exception.cross.hx` intentionally remains the lone source-tree `.cross.hx` file.
17+
* **docs:** document the source-checkout contract: use the scoped `haxe_libraries/reflaxe.elixir.hxml` (or explicit `_std` classpaths), and build/install the Reflaxe package artifact instead of pointing bare `haxelib dev` at the unbuilt checkout.
1518
* **docs:** update stdlib parity task templates to use the current `_std` / target-owned `std/**` / early `src/haxe/**` ownership model.
1619

1720
## [0.14.20](https://github.com/fullofcaffeine/reflaxe.elixir/compare/v0.14.19...v0.14.20) (2026-07-09)

0 commit comments

Comments
 (0)