Phase 1 / Etch / Entity-scoped events and entity-bound async rules#43
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes milestone M1.0.14 — Entity-scoped events and entity-bound async rules. Brief:
briefs/M1.0.14-entity-scoped-events.md(Status: CLOSED).Five review gates (E1→E5), each GO'd on the pushed diff. Round-trips recorded: one FROZEN-scope amendment at E2 (
5589078— entity-boundasync ruleexecution absorbed); one E3 STOP (ruling renumber to the brief's order); two E4 STOP fixes (string use-after-free stabilization —.string_run, then borrowed.string_persistent).Closing notes (from the brief)
entity_eventrealized asglobal_event+ predicates over the SAME per-tickEventStoreand the M1.0.11/12 wake/task substrate — no parallel mechanism. The single shared designated-field policy (AstArena.resolveEventEntityTarget) let the type-checker (diagnose) and the interpreter (capture) agree with zero interp→types dependency. Reusing the synchronous selection walk in collect mode (a threaded nullable buffer) gave entity-bound task spawning identical selection order +whensemantics for free (ruling 4). Byte-identical wake ticks preserved — every pre-existing M1.0.11/12/13 async + timer test passes UNMODIFIED.async ruleexecution was absorbed at the E2 STOP round-trip (FROZEN amendment,5589078) — an end-to-end Etchentity_eventawaiter is inexpressible without an entity-scoped awaiter, and no parameterless body expression yields anEntity. Ruling numbering follows the BRIEF (1 = re-arm, 2 = when-gates-spawn) vs spec §9.2's inverted 1/2 (E3 STOP renumber — comment/test-name only, no logic change).@on_eventobserver reading a computed (.string_run) or borrowed-resource (.string_persistent) event field dangled before this milestone; the deep-copy at both escape boundaries (emit → per-tick store-owned; filter capture → husk buffer, gated bystringNeedsOwning) fixes it and enforces capture-once for string filters. The matched event is NOT consumed (multi-awaiter + observer coexistence — E5 tests 1–2). A post-close drift audit (10 adversarial verifiers over CLAUDE.md + brief vs code) confirmed 8/10 claims verbatim and surfaced one stalerunAsyncRuleheader comment (fixed here,docs(etch)— behavior already correct) plus one wording imprecision in log entry :160 (corrected); the other flagged item (E4 fixes not in Recorded deviations) is by-design — that section is scoped to FROZEN-SECTION changes, and the E4 fixes are bug fixes journalled in the Execution log.global_eventpath; no entity index added). Test count 975 → 995 passing (+20 tests across E1–E5); full suite 995/1012 pass, 0 failed, 17 pre-existing skips, 255/255 build steps;zig fmt --check+zig build lintgreen; pre-push gate (debug + ReleaseSafe, ×2) green.future/Future<T>is the sole remaining fail-loudawaittarget (the last await gap). Event matching is a linear per-tick scan — an entity-keyed event index is deferred to the Phase-2 typed bus. Cancel-on-despawn deferred (Phase 2+): a task whose entity despawns mid-suspension fails loud on the next dead-handle access (ruling 3). Impliciteventbinding / payload delivery at resume not implemented (unit is normative, §9.4). Non-equality filter predicates, emit-side targeting, anddt/non-entity rule-parameter injection are out of grammar/scope for EBNF v0.6.Validation checklist (Étape 4)
E0908/E0909+ shared designated-field helper; E3 entity-bound async rules + four rulings; E4entity_event/filter runtime + capture-once + string stabilization; E5 integration) — gate-by-gate GO on the pushed diffsfuturestill fail-loud; equality-only filters; unit at resume — no impliciteventbinding; no entity index; no cancel-on-despawn; nodt/non-entity param injection; emit-side targeting untouched)debugandReleaseSafe(995/1012 pass, 0 failed, 17 pre-existing skips)DialogueStart, suspends onawait entity_event(e, DialogueComplete), resumes on its OWNDialogueComplete(a decoy entity's DC coexists without waking it), emitsQuestStarted, observed via an@on_eventsink)zig build,zig build test(debug + ReleaseSafe),zig fmt --check,zig build lintgreendocs(claude-md): update for M1.0.14)runAsyncRuleheader comment fixed (docs(etch)), one log-entry :160 wording imprecision corrected; the Recorded-deviations flag is by-design (FROZEN-SECTION scope)Status: CLOSED,Closed: 2026-07-05docs(brief): close M1.0.14For Guy: merge (squash-and-merge, one commit on
main) and the tagv0.10.14-entity-scoped-eventsare yours — CC performs neither. The squash message + tag annotation content come from Claude.ai at closure (per protocol), as does anyetch-reference-part1.md§9.2/§9.4/§9.12 KB re-upload. One deviation to confirm: the CLAUDE.md patch's item 4 said "append after the M1.0.12 scope-boundary entry," but an M1.0.13 open-decisions entry already exists after M1.0.12 — I placed the new M1.0.14 entry after M1.0.13 (chronological end of list) to avoid an out-of-order list. Move it up one slot if you intended it literally between M1.0.12 and M1.0.13.🤖 Generated with Claude Code