You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Document the reactor.done vs inference.done distinction
Names the failure mode in the events table, cites the three
defects it caused, and points at the onTurnBoundary /
onReactorShutdown guards. States plainly that this is a naming
convention rather than an enforced constraint: no lint tooling
is configured in this repo to add a restricted-syntax rule, and
a type-level fix would require modifying the vendored
@intx/types / @intx/inference packages, which is off-limits.
Copy file name to clipboardExpand all lines: docs/ARCHITECTURE.md
+26-1Lines changed: 26 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,8 +18,33 @@ This repeats until the director emits `capabilities.done()`.
18
18
19
19
| Event | When it fires |
20
20
|---|---|
21
-
|`inference.done`| The LLM finished one assistant turn. Carries the full turn content. |
21
+
|`inference.done`| The LLM finished one assistant turn. Carries the full turn content. Fires once per turn, every turn — this is the **turn boundary**. |
22
22
|`tool.done`| One tool call completed. Carries the result and the original `callId`. |
23
+
|`reactor.done`| The reactor loop shut down. Fires once, at the end of the run — not between turns. |
24
+
25
+
`inference.done` and `reactor.done` read as near-synonyms at a call site but
26
+
answer different questions: "did a turn end" versus "did the reactor shut
27
+
down." Three shipped defects came from code that needed a turn boundary but
28
+
keyed off `reactor.done` instead: queued messages never dispatched because
29
+
the send-queue drain waited for shutdown; `run.json`'s `turnsUsed` froze for
30
+
an entire session because the mid-run snapshot only re-fired on shutdown;
31
+
and the shell run state didn't return to idle between turns. Documentation
32
+
didn't prevent the second and third instances, so code that needs to ask
33
+
"did a turn end" or "did the reactor shut down" should go through the
34
+
`onTurnBoundary` / `onReactorShutdown` guards in `src/agent/reactor-events.ts`
35
+
rather than comparing `event.type` to a string directly — naming the
36
+
question makes the right thing easier to write than the wrong one.
37
+
38
+
This is a convention, not an enforced constraint: nothing stops a future
39
+
call site from writing `event.type === "reactor.done"` directly instead of
40
+
reaching for the guard. Two enforcement routes were considered and both are
41
+
out of scope here — a lint rule (`no-restricted-syntax` or similar) would
42
+
mean standing up ESLint or Biome from scratch, since neither is configured
43
+
anywhere in this repo, disproportionate for a Low-priority cleanup; and a
44
+
type-level fix branding `event.type` would require modifying `@intx/types`
45
+
or `@intx/inference`, which are vendored and off-limits. Reviewers should
46
+
treat a bare `event.type === "reactor.done"` / `"inference.done"` comparison
47
+
outside `reactor-events.ts` as a signal to ask why the guard wasn't used.
0 commit comments