feat(TASK-035): wire turn/session/compression seams + top-level agent bracket
Turn bracket (repl::TurnBracket): turn.started on entry and exactly one of
turn.{completed,interrupted,failed} on exit, with the interrupted-vs-failed
discrimination (abort_signal.aborted_ctrlc()) in one place. Wired at the
three outer boundaries: ask(), start_directive, and shell_execute — never at
the per-LLM-round before/after_chat_completion seams.
Session seams: session.started fires for newly created sessions only
(use_session's new_from_ctx paths; resume fires nothing), session.ended in
exit_session while the session is still attached, session.compressed on the
success path of both compress_session call sites (auto-compression and the
.compress command).
Session-held role hooks: Session snapshots the role's HooksMap on set_role,
clears it on clear_role/sync_agent, and re-reads it from the role file on
load; resolved_hooks gains a session leg so role hooks keep firing when the
role lives in the session (fresh set_role and resumed sessions alike).
Top-level agent bracket: agent.started/completed/failed once per agent RUN —
headless --agent dispatch and the interactive agent-context lifetime (enter
via .agent or startup; exit via switch-away or REPL teardown), never per
message. COYOTE_AGENT_ID is synthesized as top-<agent-name>-<nonce>.
Exit-path seams call hooks::drain_pending with a 2s bound so exit hooks
finish spawning before process teardown; interactive mid-session events
never drain.
This commit is contained in:
5 files changed
+778
-32
No files matched your search
+12
-4
@@ -97,9 +97,10 @@ impl RequestContext {
|
||||
/// (whitelisted through `global_hooks` when an agent is active), then
|
||||
/// role, then agent. Duplicate names across scopes all fire.
|
||||
///
|
||||
/// Role hooks resolve only while the role is held directly on the context;
|
||||
/// a role held by an active session is not consulted, because sessions do
|
||||
/// not carry hooks. Resolution through sessions is a call-site concern.
|
||||
/// Role hooks resolve from the role held directly on the context or,
|
||||
/// when the active role was moved into (or restored by) a session, from
|
||||
/// the hooks snapshot the session captured via `Session::set_role` /
|
||||
/// `Session::load_from_ctx`.
|
||||
#[allow(dead_code)]
|
||||
pub fn resolved_hooks(&self, event: HookEvent) -> Vec<ResolvedHook> {
|
||||
resolve_hooks(
|
||||
@@ -108,7 +109,14 @@ impl RequestContext {
|
||||
self.agent
|
||||
.as_ref()
|
||||
.map(|agent| (agent.global_hooks(), agent.name())),
|
||||
self.role.as_ref().and_then(|role| role.hooks()),
|
||||
self.role
|
||||
.as_ref()
|
||||
.and_then(|role| role.hooks())
|
||||
.or_else(|| {
|
||||
self.session
|
||||
.as_ref()
|
||||
.and_then(|session| session.role_hooks())
|
||||
}),
|
||||
self.agent
|
||||
.as_ref()
|
||||
.map(|agent| (agent.hooks(), agent.name())),
|
||||
|
||||
Reference in new issue
Block a user