Skip to content

feat(run): bounded per-worker escalation in ak run (ADR-0019) - #90

Merged
pacphi merged 1 commit into
pacphi:mainfrom
robertelee78:feat/run-escalation
Jul 30, 2026
Merged

feat(run): bounded per-worker escalation in ak run (ADR-0019)#90
pacphi merged 1 commit into
pacphi:mainfrom
robertelee78:feat/run-escalation

Conversation

@robertelee78

Copy link
Copy Markdown
Contributor

Summary

The #76 closure punch list requires ordered, bounded cross-host escalation in the canonical ak run path — tested with an OpenCode-qualified route — and explicitly says keeping escalation only in deprecated ak dual does not satisfy the issue. This lands it, with the migration decision recorded as ADR-0019.

Design (ADR-0019) — bounded per-worker ladder attempts, opt-in via --escalate:

  • The resolved route's escalate array travels with each worker at materializeRunPlan; self-equal rungs are dropped (legacy L4 rule) and unroutable rungs fail materialization exactly like an unroutable primary route.
  • A cleanly-failed worker (failed/timed_out) advances one rung per attempt in ladder order, bounded by the ladder's length; --timeout applies per attempt.
  • Never advanced: blocked/cancelled (dependency state, not a worker failure), permission_required (a consent boundary — escalating around it would violate the supervised-host contract the opencode abort implements), orphaned (uncertain state → double-run risk).
  • The final result carries attempts[] (host/model/status/category/duration/reason) only when more than one attempt ran — a single attempt is indistinguishable from escalation off, and a fabricated trail would be a lie. Final host/model = the rung that executed (observed truth); attempts is schema-validated like every other result field; success-after-escalation unblocks dependents; a rung with no adapter records cli_unavailable and continues.
  • ak dual keeps its legacy whole-pipeline semantics untouched until GA blocker: remove all deprecated commands, compatibility code, and legacy documentation #83 removes the wrapper; the deliberate semantic difference is named in UPGRADING.md.

Verification

  • 13 new tests: engine ordering/bound/exclusions/trail/schema-validation (incl. an OpenCode-qualified route through injected adapters), plan materialization + unroutable-rung rejection, CLI flag flow, --dry-run ladder display.
  • pnpm run check exit 0 (1080 kit + cjs), pnpm run test:surface exit 0 (25).
  • Live OpenCode-qualified proof (sandboxed repo, real claude + opencode CLIs, implementation:opencode with a bogus provider/model):
    coder: opencode:failed(worker_error) -> claude:succeeded(success)
    
    The opencode attempt fails with the serve's 400, advances to the claude rung, which succeeds and writes the mutation (hello.mjs, typed). Dependents unblocked; permission/consent surfaces untouched.

Refs #76 (punch-list item 1), #83 (the wrapper removal that consumes this migration).

The pacphi#76 closure punch list requires ordered, bounded cross-host escalation
in the canonical ak run path, tested with an OpenCode-qualified route —
the legacy whole-pipeline retry in deprecated ak dual does not satisfy it.

Design (ADR-0019):
- The resolved route's escalate array travels with each worker at
  materializeRunPlan; self-equal rungs are dropped (legacy L4 rule) and
  unroutable rungs fail materialization exactly like an unroutable primary.
- On --escalate, a cleanly-failed worker (failed/timed_out) advances ONE
  rung per attempt in ladder order, bounded by the ladder's length, with
  per-attempt timeout. Never advanced: blocked/cancelled (dependency
  state), permission_required (a consent boundary — escalating around it
  would violate the supervised-host contract), orphaned (uncertain state).
- The final result carries attempts[] (host/model/status/category/
  duration/reason per attempt) ONLY when more than one attempt ran — no
  fabricated trail; the final host/model are the rung that executed;
  attempts is schema-validated like every other result field. A
  succeeded-after-escalation unblocks dependents normally. A rung with no
  adapter records cli_unavailable and continues to the next.
- ak dual keeps its legacy semantics untouched until pacphi#83 removes the
  wrapper; the semantic difference is named in UPGRADING.md.

Tests: 13 new (engine ordering/boundaries/trail/schema, plan
materialization + rejection, CLI flag flow + --dry-run ladder display).
pnpm run check exit 0 (1080 kit + cjs), pnpm run test:surface exit 0 (25).

Live proof (OpenCode-qualified route, sandboxed repo + real CLIs):
implementation:opencode with a bogus provider/model → the opencode attempt
fails with the serve's 400 (worker_error), advances to the claude rung,
which succeeds and writes the mutation — trail recorded verbatim:
  coder: opencode:failed(worker_error) -> claude:succeeded(success)
Dependents unblocked; permission/consent surfaces untouched.
@pacphi
pacphi merged commit 7168865 into pacphi:main Jul 30, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants