Skip to content

Commit fbe7c98

Browse files
hyperpolymathclaude
andcommitted
feat(affinescript): Stage 8 — auto-verify ownership on compile + bridge generators
Wire Tw_verify.verify_from_module into the compilation pipeline: - compile (WASM 1.0 path): post-codegen ownership check, violations printed to stderr as warnings; compilation still succeeds (defence-in-depth) - tea-bridge: ownership verified before binary is written; prints OK/violations - router-bridge: same Both bridge modules pass clean: TEA bridge fn_update uses LocalGet 0 once; router fn_push uses LocalGet 0 in the then-branch only (branch-max=1 → OK). Add 2 E2E tests: - E2E TEA Bridge[6]: ownership verify: clean - E2E TEA Router[8]: ownership verify: clean 159/159 tests passing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ec64ca6 commit fbe7c98

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

bin/main.ml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,12 @@ let eval_file face json path =
343343
public/assets/wasm/ directory, and load via AffineTEA.load(). *)
344344
let tea_bridge_cmd_fn output =
345345
let m = Affinescript.Tea_bridge.generate () in
346+
(* Stage 8: auto-verify ownership constraints before writing. *)
347+
(match Affinescript.Tw_verify.verify_from_module m with
348+
| Ok () ->
349+
Format.printf "typed-wasm ownership verification: OK@."
350+
| Error errs ->
351+
Affinescript.Tw_verify.pp_report Format.std_formatter errs);
346352
Affinescript.Wasm_encode.write_module_to_file output m;
347353
Format.printf "TEA bridge written to %s@." output;
348354
Format.printf " affinescript_init() — initialise TitleModel@.";
@@ -365,6 +371,12 @@ let tea_bridge_cmd_fn output =
365371
public/assets/wasm/ directory, and load via AffineTEARouter.load(). *)
366372
let router_bridge_cmd_fn output =
367373
let m = Affinescript.Tea_router.generate () in
374+
(* Stage 8: auto-verify ownership constraints before writing. *)
375+
(match Affinescript.Tw_verify.verify_from_module m with
376+
| Ok () ->
377+
Format.printf "typed-wasm ownership verification: OK@."
378+
| Error errs ->
379+
Affinescript.Tw_verify.pp_report Format.std_formatter errs);
368380
Affinescript.Wasm_encode.write_module_to_file output m;
369381
Format.printf "Router bridge written to %s@." output;
370382
Format.printf " affinescript_router_init() — initialise RouterModel@.";
@@ -515,6 +527,12 @@ let compile_file face json wasm_gc path output =
515527
(Affinescript.Codegen.show_codegen_error e);
516528
`Error (false, "Code generation error")
517529
| Ok wasm_module ->
530+
(* Stage 8: auto-verify typed-wasm ownership constraints.
531+
Printed as informational; does not block compilation. *)
532+
(match Affinescript.Tw_verify.verify_from_module wasm_module with
533+
| Ok () -> ()
534+
| Error errs ->
535+
Affinescript.Tw_verify.pp_report Format.err_formatter errs);
518536
Affinescript.Wasm_encode.write_module_to_file output wasm_module;
519537
Format.printf "Compiled %s -> %s (WASM)@." path output;
520538
`Ok ())

test/test_e2e.ml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,13 +1290,26 @@ let test_bridge_tea_layout_section () =
12901290
let version_byte = Char.code (Bytes.get payload 0) in
12911291
Alcotest.(check int) "layout version byte = 1" 1 version_byte
12921292

1293+
(** Stage 8: TEA bridge module passes typed-wasm Level 7/10 verification.
1294+
[fn_update] uses [LocalGet 0] (msg) exactly once — branch-max semantics
1295+
ensure the if/else in fn_push does not cause false positives here. *)
1296+
let test_bridge_ownership_verify () =
1297+
let m = Tea_bridge.generate () in
1298+
match Tw_verify.verify_from_module m with
1299+
| Ok () -> () (* expected *)
1300+
| Error errs ->
1301+
let msg = String.concat "; " (List.map (fun e ->
1302+
Format.asprintf "%a" Tw_verify.pp_error e) errs) in
1303+
Alcotest.fail (Printf.sprintf "TEA bridge failed ownership verification: %s" msg)
1304+
12931305
let tea_bridge_tests = [
12941306
Alcotest.test_case "structure (7 funcs, 1 mem, 8 exports)" `Quick test_bridge_structure;
12951307
Alcotest.test_case "export names all present" `Quick test_bridge_export_names;
12961308
Alcotest.test_case "two custom sections" `Quick test_bridge_custom_sections;
12971309
Alcotest.test_case "Wasm binary magic + version" `Quick test_bridge_wasm_magic;
12981310
Alcotest.test_case "update msg param is Linear" `Quick test_bridge_update_msg_linear;
12991311
Alcotest.test_case "tea_layout section present + versioned" `Quick test_bridge_tea_layout_section;
1312+
Alcotest.test_case "ownership verify: clean" `Quick test_bridge_ownership_verify;
13001313
]
13011314

13021315
(* ============================================================================
@@ -1436,6 +1449,18 @@ let test_router_tea_layout_section () =
14361449
let version_byte = Char.code (Bytes.get payload 0) in
14371450
Alcotest.(check int) "layout version byte = 1" 1 version_byte
14381451

1452+
(** Stage 8: Router bridge module passes typed-wasm Level 7/10 verification.
1453+
Branch-max semantics: fn_push uses [LocalGet 0] in the then-branch only
1454+
(else = stack full, silent drop). max(1, 0) = 1 → OK. *)
1455+
let test_router_ownership_verify () =
1456+
let m = Tea_router.generate () in
1457+
match Tw_verify.verify_from_module m with
1458+
| Ok () -> () (* expected *)
1459+
| Error errs ->
1460+
let msg = String.concat "; " (List.map (fun e ->
1461+
Format.asprintf "%a" Tw_verify.pp_error e) errs) in
1462+
Alcotest.fail (Printf.sprintf "Router bridge failed ownership verification: %s" msg)
1463+
14391464
let tea_router_tests = [
14401465
Alcotest.test_case "structure (11 funcs, 1 mem, 12 exports)" `Quick test_router_structure;
14411466
Alcotest.test_case "export names all present" `Quick test_router_export_names;
@@ -1445,6 +1470,7 @@ let tea_router_tests = [
14451470
Alcotest.test_case "present_popup param is Linear" `Quick test_router_present_popup_param_linear;
14461471
Alcotest.test_case "resize w+h params are both Linear" `Quick test_router_resize_params_linear;
14471472
Alcotest.test_case "tea_layout section present + versioned" `Quick test_router_tea_layout_section;
1473+
Alcotest.test_case "ownership verify: clean" `Quick test_router_ownership_verify;
14481474
]
14491475

14501476
(* ============================================================================

0 commit comments

Comments
 (0)