make boundary crossings attributable to the construct that caused them

The beat reported which function crossed a boundary, never which decorator
put the beat there. So the graph accumulated boundary events with no
attribution, and no construct could be measured — "is this decorator
earning its keep" stayed an argument instead of a traversal.

engram_boundary_beat now takes the construct and carries it on the bus as
{"construct":"..."}. The injection point, the beat, and the accumulation
already existed; only the attribution was missing.

Also pins a known defect as a test: codegen calls fn_has_decorator for
exactly three names (manager, accessor, route). Twelve others parse, attach,
and compile to nothing — including @authenticate (6 uses), @authorize (3),
@rate_limit (3) and @validate (2), which look like protection and are not.
decorator-authenticate-compiles-to-nothing asserts that @authenticate emits
byte-identical C to no decorator at all, so fixing it will be a visible flip.

Verified: compiler self-hosts byte-identically, 86/86 native compiler tests
pass, emitted C carries the construct for both @manager and @accessor.
This commit is contained in:
bigmerge
2026-08-17 04:53:40 -05:00
parent 409bf57341
commit dcaa77d77b
5 changed files with 83 additions and 12 deletions
+46
View File
@@ -726,3 +726,49 @@ test "compiler-stdint-include" {
let out: String = compile_capture(src)
assert str_contains(out, "stdint.h"), "output includes stdint.h"
}
// Decorator seam: boundary-beat attribution
//
// The beat carries the CONSTRUCT that caused it, not only the fn that beat.
// Without the second argument the graph accumulates boundary events with no
// way to attribute them to the decorator responsible, so no construct can ever
// be measured and "is this decorator earning its keep" stays an argument
// instead of a query.
test "decorator-manager-beat-carries-construct" {
let src: String = "@manager\nfn f() -> Int { return 1 }"
let out: String = compile_capture(src)
assert str_contains(out, "engram_boundary_beat"), "@manager injects the beat"
assert str_contains(out, "EL_STR(\"manager\")"), "beat carries the construct that caused it"
}
test "decorator-accessor-beat-carries-construct" {
let src: String = "@accessor\nfn f() -> Int { return 1 }"
let out: String = compile_capture(src)
assert str_contains(out, "engram_boundary_beat"), "@accessor injects the beat"
assert str_contains(out, "EL_STR(\"accessor\")"), "beat carries the construct that caused it"
}
test "decorator-undecorated-fn-has-no-beat" {
let src: String = "fn f() -> Int { return 1 }"
let out: String = compile_capture(src)
assert !str_contains(out, "engram_boundary_beat"), "an undecorated fn does not beat"
}
// Decorator seam: the twelve inert names
//
// PINS A KNOWN DEFECT. codegen calls fn_has_decorator for exactly three names
// (manager, accessor, route). Twelve others parse, attach as {name,args}, and
// compile to nothing including four that look like protection:
// @authenticate (6 uses), @authorize (3), @rate_limit (3), @validate (2).
//
// This test asserts the CURRENT behaviour so that fixing it is a visible
// change rather than a silent one. When a pass wires or rejects these, this
// test flips and that flip is the proof.
test "decorator-authenticate-compiles-to-nothing" {
let src: String = "@authenticate\nfn f() -> Int { return 1 }"
let out: String = compile_capture(src)
let bare: String = compile_capture("fn f() -> Int { return 1 }")
assert str_eq(out, bare), "KNOWN DEFECT: @authenticate emits identical C to no decorator at all"
}