Feat/turn handle - #164
Merged
Merged
Conversation
- wait types migrate together with the goal state machine (the controller's Wait decision folds out of it); stores/probes/sweeps stay host concerns - explicit migration order: turn handle + evidence first, then goal/wait types with the store traits (so PAL's planned transactional repository is written against them once), then run convergence - the turn handle is not the send-or-queue channel dispatch; a merged operation would need an explicit Queued outcome - RunSpec budgets are owner policy (PAL children run to completion by design); the run/attempt split is what ChildRun still lacks - durable approvals: PAL builds action intents P0 in pal_core first, the upstream generalization is a deliberate second migration
start_turn_if_idle is the typed sibling of try_send_user_message_if_idle (ROADMAP 'Replace event inference with an exact turn handle'): it starts a turn only on an idle session, atomically inside the service actor, and returns a TurnHandle identifying exactly that turn. The handle resolves once with a bounded TurnOutcome — final narration, tool lifecycle records, resource writes, token/tool/wall-time usage, and whether a queued user message was absorbed mid-run — collected by a TurnRecorder teed synchronously into the session's event publisher, so outcomes never depend on a broadcast subscriber keeping up. An aborted agent task resolves the outcome as failed via the recorder's Drop instead of losing it; the token delta is read from the state the run persisted, not from fire-and-forget metadata events. Also: - AgentRuntimeOptions.llm_client_factory: injectable LLM construction per run (scripted providers for tests and fault-injection harnesses) - compaction: a model unknown to models.json (playback, injected factory) disables automatic compaction for the run instead of failing the turn
The generic half of PAL's durable-goal feature moves upstream, per the ROADMAP's 'Now: converge goals' slice: Goal/GoalState/CompletionContract/ Budget/Subgoal, the attempt/evidence ledger with claim+revision atomicity, the deterministic controller fold (apply_evaluation → Continue/Wait/ AwaitInput/Blocked/Done/Failed), typed wait barriers (WaitKind, the armed → satisfied/timed-out/cancelled machine, clock-only predicates), the GoalEvaluator/WaitProbe seams, the bounded LLM evaluator over an injected provider, and goal-turn framing. All 78 deterministic tests moved with it and run without an LLM or frontend. Host-neutral owner binding: SessionKey generalizes to OwnerKey (a plain hierarchical string key; PAL re-exports it as its lane key), the goals/waits owner field deserializes legacy 'lane'-keyed JSON via a serde alias. GoalRepository/WaitRepository traits capture the store surface: the bundled JSON stores (explicit path, no global config) implement them today; PAL's planned transactional repository implements the same traits instead of migrating persistence twice. PAL keeps everything deployment-shaped: lane binding, gateway passes (goal_pass/wait_pass), startup sweeps, durable probes, delivery.
PAL's existing goals.json/waits.json key the owner as 'lane'; the serde alias keeps them readable after the OwnerKey generalization (the initial mechanical rename had rewritten the alias string itself).
The evaluator prompt listed 'a reply from the user must arrive' under the generic waiting verdict while also offering needs_input, without explaining the mechanically different consequences: waiting+human_input parks the goal Waiting and the user's NEXT message on the channel wakes it automatically; needs_input parks it Blocked until someone deliberately resumes it. The prompt now states the consequence on both bullets and gives the choice rule: human_input only for a just-asked concrete question whose next reply is expected to be the answer; needs_input for decisions that must not auto-continue on an arbitrary message.
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.
No description provided.