Skip to content

feat(workhub): add typed action gate - #3818

Open
ARE404 wants to merge 5 commits into
apache:mainfrom
ARE404:feat/workhub-action-gate
Open

feat(workhub): add typed action gate#3818
ARE404 wants to merge 5 commits into
apache:mainfrom
ARE404:feat/workhub-action-gate

Conversation

@ARE404

@ARE404 ARE404 commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Slice 4 from #3492 on top of the merged Slice 3 coordination-session work:

  • adds closed typed contracts for answer_here, delegate_existing, create_new, and clarify;
  • exposes a bounded Runtime-owned candidate set with opaque candidate references;
  • introduces a deterministic Runtime Host Action Gate for fresh target validation and execution admission;
  • makes create_new the only WorkHub disposition that can create an ordinary Session;
  • delegates create, submit, and exact-Turn Stop through existing Runtime Host Session authorities;
  • routes the production Desktop WorkHub path through the Action Gate while retaining R2.4 only as an explicit regression-test harness.

Safety and authority boundaries

  • Strategy output cannot name arbitrary Session IDs, workspaces, tools, or permission modes.
  • Candidate discovery is scoped to the current Runtime Host and excludes archived, Coordination, side-conversation, and child Sessions.
  • The Gate refreshes candidates before admission and rejects stale or invented references, waiting targets, self-routing, invalid creation context, and conflicting action replays.
  • New ordinary Session identity is derived inside Runtime Host from the action identity; Desktop supplies only trusted workspace context.
  • Stop is limited to the exact non-steered root Turn previously admitted by the same Gate.
  • Successful actions are idempotently replayable; rejected admissions release the action identity so an actionable precondition can be fixed and retried.
  • Tool calls and permission elevation remain owned by the target ordinary Session. The closed WorkHub action protocol provides no field that can widen either ceiling.

Explicit replacement confirmation design

This PR deliberately does not add a model-provided confirmed flag. Such a flag would let strategy output authorize its own interruption.

For the only Slice 4 action that interrupts existing work—replace, which may Stop a WorkHub-owned Turn—the Runtime Host Gate examines the exact original user message. Admission requires both:

  1. an explicit rejection or Stop of the previous route; and
  2. an explicit direction to use, switch, move, or delegate to a replacement.

Chinese and English correction forms are handled deterministically. A strategy-generated replace attached to neutral text such as “Continue the target work” is rejected with confirmation_required, before Stop or submit. Ambiguous routing still returns clarify; ordinary create/delegate does not add a second confirmation prompt, and any later filesystem/tool/external effect remains subject to the target Session's existing permission flow.

This chooses explicit user intent in the original message as confirmation, rather than adding a modal confirmation to every correction. It keeps the common correction flow conversational while preventing a model or routing strategy from independently authorizing Stop.

Verification

  • Slice 4 focused Runtime Host/Desktop tests: 94 passed
  • Runtime Host Action Gate focused suite: 6 passed
  • Desktop full suite: 1533 passed
  • lint, format check, ASF headers, typecheck, production build, and affected knip workspaces passed
  • Runtime Host full run reached 1222 passing tests; its one unrelated lifecycle cleanup failure passed when rerun in isolation
  • A local all-workspace run also exposed two pre-existing environment/timing failures outside this diff: macOS /private/var vs /var temp-path identity in MCP and an Eval relay-cleanup timeout

Closes the Slice 4 implementation items in #3492. The persistent delegation linkage and execution-feedback contract remain Slice 5.

AI assistance: Codex helped implement and verify this change. The commit includes the required Generated-by: Codex trailer.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Update on b65c5c2313:

CODE NO-GO — 4×P2

  • P2-1 correction without explicit intent fails confirmation_required before Stop.
  • P2-2 dropping replace when source outside bounded set silently forks while reporting corrected.
  • P2-3 concurrent replacements lack source lock → fan-out to different targets after Stop.
  • P2-4 record 48 KiB vs retry probe 32 KiB → retry after success hits commit_outcome_unknown.

Fix: make correction carry explicit stop text or relax gate; keep replace mandatory or fail; add source lease across actions; align byte limits. Hosted test: SUCCESS does not waive these.

简体中文四处权限/一致性阻塞。

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Update on 48666a0ceb:

CODE NO-GO — 3×P2

  • P2 candidate path does not write admitted.targetTurnId to local map → natural-language correction cannot send replacement (fail-closed at 814). E2E workhub-reconstruction fails (32879372758).
  • P2 Stop-then-submit with swallowed replay leaves source stopped and target unconfirmed → retry gets stop_not_owned.
  • P2 48 KiB user + 8 KiB assistant JSON record can exceed 72 KiB retry lookup after escaping → retry becomes commit_outcome_unknown.
简体中文存在路径阻塞与重放问题。

Preserve Runtime-admitted root receipts for natural-language corrections and avoid deleting newer ownership after a concurrent Stop.\n\nGenerated-by: Codex

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Update on f2785c5dc0:

CODE NO-GO — 2×P2 plus required check red

  • P2 Stop-then-submit with swallowed replay leaves source stopped and target unconfirmed → retry stop_not_owned.
  • P2 JSON record escaped bytes exceed 72 KiB retry lookup → retry commit_outcome_unknown.

Note: natural-language correction P2 from prior head is now closed (gated receipt saved). Hosted test: FAILURE on format check (new test ternary).

简体中文仍有两处阻塞,另需格式化修复。

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Update on 05d3d26e20:

CODE NO-GO — 2×P2 (carry-over, formatting fix only)

  • P2 Stop-then-submit without replay on target failure → retry stop_not_owned.
  • P2 JSON escaped record may exceed 72 KiB retry lookup → commit_outcome_unknown.

Formatting failure from prior head fixed; logic unchanged. Hosted test: QUEUED — not green.

简体中文仍有两处阻塞。

Resume the exact target submission after a replacement Stop and budget summary replay reads for worst-case JSON escaping.\n\nGenerated-by: Codex

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Update on 92d0947890:

[P2] #replacementRecoveries can exhaust to Host-wide outage

Capacity 256 is only released on Stop failure or target success. After Stop succeeds, permanent target rejections (e.g. session_busy) keep the recovery forever with no TTL/reaper — 256 failures exhaust replacements Host-wide as host_not_ready until restart.

Fix: give recoveries reconciled lifecycle / TTL for permanent failures.

Checks on 92d0947890d2aeec9a6363f17b68ff0850deb5b0 are test: SUCCESS — code is NO-GO.

简体中文异常恢复容量会耗尽。

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