Skip to content

feat(subagent): codify outcome-aware worker escalation policy - #1394

Merged
TheGreatAxios merged 1 commit into
mainfrom
cl-10432-codify-outcome-aware-escalation-policy-for-blocked-worker
Oct 13, 2026
Merged

TheGreatAxios merged 1 commit into
mainfrom
cl-10432-codify-outcome-aware-escalation-policy-for-blocked-worker

Conversation

@bwachman

@bwachman bwachman commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Note on base

This branch is stacked on #1393 (cl-10189-show-required-input-for-primary-session-ask_operator-at-the, tip 8638639), which provides the worker-wait / parked-question machinery this policy integrates with. The diff in this PR is the CL-10432 change only.

Summary

Codify an outcome-aware escalation policy for blocked workers: a closed classification union classifies every ask_director outcome from seven pre-escalation facts, routine questions never park/pending/wake, director_resolvable is parent-only (not operator), operator_decision_required stays distinct from minimum authority, and verification_blocked is a terminal outcome that is never verified, is retained in session state, and has a store-level replace-only-on-explicit-report API (reportVerifiedOutcome, not yet called at runtime, see Deferred). Least-authority is preserved: no permission source change, grant_request_id attaches only the envelope, resolutions deliver text only, and there is no auto-retry.

Verification

After the rebase onto main and the review fixes, CI passes on fd6416e; the results below are from the original verification.

Gate Result Exit
bun test src/subagent/escalation-policy.test.ts src/subagent/ask-director.test.ts src/subagent/session-store.test.ts src/subagent/agent-fleet.test.ts src/subagent/lifecycle-tools.test.ts src/subagent/run-ask-director-grant.test.ts src/permission/worker-grant.test.ts src/permission/worker-grant-flow.test.ts src/subagent/fleet-report.ask-wake.test.ts src/tui/worker-wait.test.ts src/tui/agent-ask-wake.test.ts src/tui/runner/wiring.ask-wake.test.ts 355 pass / 0 fail, typecheck clean, dead-exports 0 violations, no regression 0

Both blockers + all 8 should-fix + 5 nits in CL-10432-review-v2.md resolved (opt-in bypass removed, terminalOutcome visible, wait/list exposure, questionId validation, declines record outcome, per-field renderer bounding, question in wake, message/resolution overlap, routine audit, integration seams, nits). Least-authority boundary preserved.

AC to code and test mapping

  • seven pre-escalation facts + closed classification union: src/subagent/escalation-policy.ts + escalation-policy.test.ts
  • routine no-park enforcement (never parks/pending/wake): src/subagent/ask-director.ts + ask-director.test.ts
  • director_resolvable parent-only, not operator: src/subagent/ask-director.ts + fleet-report.ts + tests
  • operator_decision_required vs minimum authority distinct: src/subagent/escalation-policy.ts + tests
  • verification_blocked terminal outcome (never verified, retained; replace-only store API deferred, see Deferred): src/subagent/session-store.ts + session-store.test.ts (get()/listForStrip())
  • least-authority: no src/permission source change; grant_request_id only attaches envelope; resolutions deliver text only; no auto-retry (worker-grant-flow.test.ts, run-ask-director-grant.test.ts)
  • wake/panel dedup key sessionId+questionId (assessment compared by value), routine absent from wake: fleet-report.ask-wake.test.ts, worker-wait.test.ts, agent-ask-wake.test.ts, wiring.ask-wake.test.ts

Deferred / Notes

  • reportVerifiedOutcome has no production caller: the runtime has no typed "worker verified" signal, so a verification_blocked outcome cannot yet be replaced at runtime. Tracked in CL-10568.
  • Durable on-disk persistence of assessments is a separate concern (this ticket retains typed terminal results in session state through complete/list/wait/resume, not across process restart).

Refs CL-10432

@linear-code

linear-code Bot commented Oct 11, 2026

Copy link
Copy Markdown

CL-10432

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Hey @bwachman

Based on reading the PR -- is it possible to trim out the other elements and just be the relevant commits here? If this relies on other code, suggest using gh stack instead.

@bwachman
bwachman force-pushed the cl-10432-codify-outcome-aware-escalation-policy-for-blocked-worker branch from e7783e7 to c713780 Compare October 11, 2026 16:32
@bwachman
bwachman changed the base branch from main to cl-10200-make-parked-worker-ask_director-questions-visible-and October 11, 2026 16:32
@bwachman
bwachman force-pushed the cl-10432-codify-outcome-aware-escalation-policy-for-blocked-worker branch from c713780 to 9375c76 Compare October 11, 2026 18:39
@bwachman
bwachman force-pushed the cl-10432-codify-outcome-aware-escalation-policy-for-blocked-worker branch from 9375c76 to 5c7743b Compare October 11, 2026 20:50
@bwachman
bwachman changed the base branch from cl-10200-make-parked-worker-ask_director-questions-visible-and to cl-10189-show-required-input-for-primary-session-ask_operator-at-the October 11, 2026 20:50
Comment thread src/subagent/escalation-policy.ts Resolved
return true;
},

reportVerifiedOutcome(id: string, outcome: VerifiedOutcome): boolean {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reportVerifiedOutcome has no production caller (interface + tests only); "replace-only on explicit report" for verification_blocked is an uncalled store API, so a verification-blocked outcome can never be replaced at runtime. Wire it up or mark deferred.
Plain: there's a function for replacing a dead-end outcome, but nothing ever calls it — so a dead-end can never actually be replaced. Wire it or say it's coming later.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marked deferred rather than wired. The interface method now carries a doc comment saying there is no production caller because the runtime has no typed "worker verified" signal (comment), and the design options for that signal are laid out in CL-10568. I left this thread open for you to confirm that is acceptable.

Comment thread src/subagent/escalation-policy.ts Resolved
Comment thread src/subagent/run.ts Resolved
Comment thread src/subagent/ask-director.ts Resolved
Comment thread src/subagent/session-store.ts Resolved
Comment thread src/tui/worker-wait.ts Resolved
Comment thread src/subagent/ask-director.ts Resolved

@TheGreatAxios TheGreatAxios left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Policy codification verified — the classification union is closed, routine never parks, and least-authority is preserved (no permission-source change, envelope-only grant_request_id, text-only resolutions). Nine items — the two that matter: comparableConfidence overrides classification in routing (the policy's teeth), and reportVerifiedOutcome has no production caller (verification_blocked can never be replaced at runtime). Plus: inconsistent safeDefault rendering, dedup-key vs body claim, "six facts" miscount, routine-ask cap bypasses, stale base note, and a stale comment.

@bwachman
bwachman force-pushed the cl-10432-codify-outcome-aware-escalation-policy-for-blocked-worker branch from 5c7743b to fd6416e Compare October 13, 2026 00:50
@bwachman
bwachman force-pushed the cl-10189-show-required-input-for-primary-session-ask_operator-at-the branch from 0481351 to 8638639 Compare October 13, 2026 00:50
@corbits-triage

corbits-triage Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

@bwachman, please address the following:

  • required checks are failing: test (src), eslint, build-and-test, typecheck, prettier, test (3/4), build, test (4/4), static-analysis, test (1/4), test (2/4)

@bwachman

Copy link
Copy Markdown
Contributor Author

On trimming to the relevant commits: this PR is now a single commit (CL-10432 only) stacked on #1393's branch, so its diff shows only its own change. The earlier stack commits are no longer part of this diff.

@TheGreatAxios
TheGreatAxios force-pushed the cl-10189-show-required-input-for-primary-session-ask_operator-at-the branch from 8638639 to b1b64b2 Compare October 13, 2026 01:31
@TheGreatAxios
TheGreatAxios force-pushed the cl-10432-codify-outcome-aware-escalation-policy-for-blocked-worker branch from fd6416e to 2c73ecd Compare October 13, 2026 01:42
@TheGreatAxios
TheGreatAxios changed the base branch from cl-10189-show-required-input-for-primary-session-ask_operator-at-the to main October 13, 2026 01:42
@TheGreatAxios
TheGreatAxios merged commit 46eec6c into main Oct 13, 2026
15 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants