Skip to content

feat(runtime): add bounded foreground ad hoc child route - #4701

Closed
testikun wants to merge 6 commits into
apache:mainfrom
testikun:codex/issue-4538-testikun
Closed

feat(runtime): add bounded foreground ad hoc child route#4701
testikun wants to merge 6 commits into
apache:mainfrom
testikun:codex/issue-4538-testikun

Conversation

@testikun

@testikun testikun commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the bounded foreground ad hoc child-agent slice for #4538:

  • adds a desktop setting for an explicitly enabled temporary child-agent policy, including the maximum profile and model connection/model/thinking-level selection;
  • exposes the synthetic temporary-bounded route through the existing agent_list/agent_spawn catalog path only when enabled and its host-resolved model connection is available;
  • preserves an existing ad hoc policy when ordinary presets are updated;
  • accepts only bounded task-scoped role text, while Runtime/Host continue to select the profile, model, tools, permission, workspace, lifecycle, and nesting authority;
  • rejects model-supplied overreach (model, connection, tools, permission, workspace, lifecycle/nesting, write-back/isolation, and a second profile selector);
  • rejects invalid role data, nested creation, graph/background use, unavailable routes, and over-broad contract requests before child Session creation;
  • rejects child creation from Side Conversations as well as linked child Sessions;
  • preflights the temporary child against the parent Session execution boundary;
  • preserves the existing linked Session/RuntimeInvocation lineage, idempotency, cancellation, recovery, transcript isolation, and artifact paths;
  • extracts shared synthetic-preset construction and adds focused coverage.

Current-head real App verification (2026-09-04)

Built and launched pre-rebase feature tree 58979f3 in a visible local Electron window; current head 7b81677 is the rebased equivalent on apache/main 19ac204ab, opened Settings → Subagents, enabled the temporary-subagent policy, saved it, and verified the persisted Host setting. These are direct screenshots from the running Maka App; they are not mockups or generated images.

1. Current-head disabled state with the new route controls

Temporary subagent policy disabled

2. Current-head enabled state after saving the policy

Temporary subagent policy enabled and saved

Verification

  • rebased the current PR branch onto current apache/main (19ac204ab)
  • full workspace and Desktop production build — passed
  • Desktop typecheck — passed
  • renderer architecture checker — passed (71/71)
  • child-session Runtime test group — passed (16/16)
  • real Electron persistence journey: disabled → enable → save → persisted Host setting — passed
  • Biome check on all 19 changed TypeScript, TSX, and CSS files — passed
  • git diff --check — passed
  • legacy screenshot binaries removed from the source diff; evidence remains in this first PR description

AI use

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex provided material implementation and review assistance, fixed the architecture-budget and RuntimeInvocation convergence regressions, added a real Electron persistence test, ran visible App verification, and prepared the commits.

Closes #4538

@github-actions github-actions Bot added the effort/XL Under 2500 readable lines label Sep 4, 2026
@testikun
testikun force-pushed the codex/issue-4538-testikun branch from 567f777 to 158390d Compare September 4, 2026 02:06
testikun pushed a commit to testikun/maka that referenced this pull request Sep 4, 2026
@testikun
testikun force-pushed the codex/issue-4538-testikun branch from 158390d to 8f12a84 Compare September 4, 2026 07:09
@testikun
testikun force-pushed the codex/issue-4538-testikun branch 2 times, most recently from 0caf646 to 7b81677 Compare September 4, 2026 08:50
@testikun
testikun force-pushed the codex/issue-4538-testikun branch from 7b81677 to 8357a79 Compare September 5, 2026 02:06
@Astro-Han

Copy link
Copy Markdown
Contributor

Thanks for the thorough implementation; the authority placement is careful, and I traced it before deciding. I am closing this one on the problem rather than the code, and I want to be precise about why.

It does not relieve the problem #4538 states. AdHocSubagentPolicy (packages/core/src/subagent-settings.ts:66-72) is field-for-field a SubagentPreset with profile renamed maxProfile and id/name/description hardcoded; syntheticAdHocPreset() converts it straight back. The user still opens Settings and picks profile, connection and model before the route exists, which is exactly the pre-configuration the issue says users should not need. One general-purpose preset gives acceptance 1–7 today with zero code, and agent_spawn's task field already carries task-specific text. The one real delta is that purpose/instructions are spliced into the child's system prompt (session-manager.ts:3095-3106); that moves model-authored text from the user channel into the trusted channel for no capability task lacks, and it is the part I would least want to ship.

And the headline field does not work. hasUnsafeRoleText (subagent-settings.ts:118-120) rejects \u0000-\u001f, which includes \n and \t. The zod layer accepts newlines, so a multi-line instructions passes tool validation and then throws from SessionManager with a message that only mentions length caps. The test that should cover it (session-manager.test.ts:2434-2461) omits subagentId, so it never reaches normalizeAdHocSubagentRole.

Against that, the PR adds a persisted setting, a synthetic catalog route, a model-facing field group, validation in four owner files and 676 production lines, and deletes nothing. #4538 itself has no maintainer response, and your claim said "subject to maintainer alignment on the protocol shape", which is the right instinct: that alignment should come first, and the shape that would earn it is one that removes pre-configuration rather than duplicating a preset. I will leave a note on the issue.

One part is worth landing on its own. The Side Conversation blocking (commit 6ec47d18fd) is a real fix: on main the only thing stopping a Side Conversation from spawning children is a prompt sentence (side-conversation.ts:34), and interactive-run-composer.ts:356 gives it root tools. Please open it as a standalone PR with its own regression through a configured preset, since it changes behavior for existing presets too. Two things to settle in it: it is enforced at two layers (session-manager.ts:3074-3076 and the tool-surface suppression), one should be the owner; and allowParentAgentTools?: boolean read as !== false is a tri-state where a required boolean will do.

Also from this pass, in case any of it is reused: the execution-boundary preflight at session-manager.ts:3078-3092 is gated on the ad-hoc id, but the escalation it blocks is identical for configured presets and nothing checks it on that path, so either it belongs before the if or it should go; the renderer re-sends adHoc on every preset write (subagent-settings-page.tsx:193-200) and can revert a just-saved policy, while the PR's own settings.test.ts:128-131 proves the two merge layers already keep it; pageState fuses route and draft to fit the hook ratchet; maxProfile is not a maximum.

Evidence boundary: static read at 8357a79af5 against c180a2bac3, no build, no tests, no Desktop launched; the newline rejection was checked by evaluating the regex directly.

AI-assisted review: drafted with Maka; I verified the preset field mapping, the newline rejection and the Side Conversation tool routing myself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/XL Under 2500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

proposal(runtime): let the root Agent create a bounded task-specific Sub Agent

2 participants