# the wrapper was conditional One `Ishikawa → scientific method → Six Sigma` loop. The record below is the commit message as written at the time, before the outcome was known to anyone reading this file. ## Record — `4f7568b` ``` give a construct its after-crossing face, and let constructs compose §6 records 62 persist-after-mutate sites, 10 auth-per-route, and index-after-append that failed at 9 of 9 — every one an obligation at a crossing that decayed into "remember to do this afterwards." An obligation a human must remember is not an obligation, and the 9-of-9 figure is what that costs. @decorator("injects_at_exit", "persist_now") fn durable() {} The body moves into a static helper and the visible fn becomes a wrapper, so EARLY RETURNS pass through the exit injection. Emitting it only before the fall-through return would have silently missed every early return — the exact failure class this seam exists to remove. Fns with no exit construct emit byte-identically to before. Three independent constructs now compose on one fn, none known to the compiler: el_val_t mutate(el_val_t k) { { el_val_t __g = my_auth(EL_STR("mutate"), EL_STR("authenticate")); if (__g) return __g; } engram_boundary_beat(EL_STR("mutate"), EL_STR("manager")); el_val_t __r = __el_body_mutate(k); persist_now(EL_STR("mutate"), EL_STR("durable"), __r); return __r; } Guard, then entry, then body, then exit. §5.2 asked whether `hold` is one construct or two; the implementation answers one construct with two faces, selected by declared kind rather than by two mechanisms. Verified: existing output byte-identical, compiler self-hosts byte-identically, early returns pass through the exit, ordering holds under composition. 98/98 native compiler tests pass. ``` ## Record — `285166c` ``` EXPERIMENT: emit the wrapper unconditionally, so exit binds at runtime too ISHIKAWA: why did exit injection still need compile-time knowledge? Because the body-helper wrapper was only emitted when codegen already knew an exit construct existed. The wrapper being conditional was the cause, not the wrapper being necessary. PREDICTIONS AND RESULTS P1 exit becomes runtime-bindable TRUE returns 14, bound after the build P2 codegen shrinks TRUE 5094 -> 5044 P3 cost 5-15% from a call frame on every fn FALSE 0.37s -> 0.38s, ~3% P4 fixpoint holds TRUE Every fn now gets a body helper and a wrapper. It has to be unconditional: early returns must route through something for an exit construct to observe them, and codegen cannot know which fns will be bound after the binary exists. Removed with the machinery: declare_exit, decorator_exit, cg_exit_target, cg_exit_construct, and the injects_at_exit scanner branch. Two controls failed and were rewritten rather than repaired -- no-exit-construct-emits-no-wrapper asserted the optimisation this removes, so it is now inverted. The integration harness gained a seventh assertion: an exit construct declared after the build replaces the result. 99/99 native, 7/7 integration, fixpoint gen2==gen3. ``` ## Record — `b40754f` ``` land unconditional wrapper: exit crossings resolve at runtime ```