Skip to content

Subagents ask their orchestrator; fix t3_request_user_input; usage-weighted model choice #12

Closed

Description

@tannerpolley

Goal

Subagents ask their orchestrator instead of the owner, the fork's question tool works, Codex and Claude ask questions the same way, and orchestrators spread subagents across Claude and Codex by weekly usage left.

Decisions (owner, 2026-10-12)

  • Subagent questions go to the orchestrator first. This covers every question a delegated subagent asks: Claude's AskUserQuestion, Codex's request_user_input and T3's t3_request_user_input. The owner sees no icon, popup or notification for them. The orchestrator answers, or asks the owner in its own thread and relays the answer. It works up a chain of orchestrators.
  • Subagent approvals go to the orchestrator too. The orchestrator can approve or deny its own subagents' permission requests, or pass them up. Don't ask mode still auto-approves when on.
  • Model choice is ranked by weekly usage left. Within each model role, the choice whose provider has the most weekly room relative to the time left in its week goes first, and the numbers are shown (for example "Codex 62% left, Claude 18%"). The orchestrator can still override.

Bug: t3_request_user_input always fails

It fails with parent_not_active, "The calling provider no longer owns an active thread run". ThreadManagementService.requestUserInput compares the MCP credential id (scope.thread.providerSessionId, a bare UUID from McpSessionRegistry.issue) with the active provider thread's providerSessionId (provider-session:provider-instance:…:thread:…:<uuid>). Those never match. The integration test from eb5c406 sets the scope's id to the real provider session id, which hides the bug. Fix the check at its root and test it with a real issued credential.

Plan (after the upstream merge in #11 lands, so this adds no conflicts)

  • Fix t3_request_user_input.
  • Routing. User-input and approval requests from an app-owned delegated child are marked as owned by the parent. They are hidden from the owner's question card, sidebar badge and notifications, and from upstream's "Subagent needs input" banner (ed4ea10). The parent is woken with the question.
  • Answering.
    • t3_pending_request_respond lets a parent answer or approve requests from its own descendants only (a lineage check).
    • Record respondedBy: "orchestrator" and show it on the child's answer.
    • The parent escalates by asking with its own question tool.
  • Children's instructions and the parent wake text describe the flow. Remove the "ancestor send denied → ask the user" guidance.
  • Codex. T3 turns on features.default_mode_request_user_input itself, so Codex's options card works in Default mode without the owner's personal config.
  • Usage.
    • orchestrator_capabilities and the model-role instructions carry each provider's weekly window: percent left, when it resets, and pace.
    • Order each role's choices by pace-adjusted headroom.
    • Replace "the first choice is the default" with wording about equal alternatives.
  • Review, then a build.

Existing lead ownership repair (owner, 2026-10-12)

  • When standalone Issues Start has neither an origin thread nor a registered orchestrator, show a picker to choose an existing lead or explicitly create the first orchestrator. The owner selected this behavior through the question panel; no automatic replacement lead.

  • General Issues page/side-panel Start agent uses the existing repository orchestrator and creates the issue worker beneath it, preserving issue-tree nesting; it must not silently create a replacement lead. Regression covers this entry point.

  • Cancel/release stopped roots' unclaimed issue requests through durable commands, retaining request and cancellation audit history.

  • Restore an explicitly selected existing lead as registered repository root without creating a replacement, changing live children's parentage, losing claims, or interrupting workers. Guard stale revisions and claim races.

  • Allow the stopped unwanted root to be archived after its stale request is cancelled; keep guards for real active work.

  • Regression: paused/stopped root + unclaimed request blocks archive; cancellation and restoration preserve the original lead and direct child, and allow archiving the unwanted root.

  • After reviewed code is installed through owner-approved deployment gates, recover ePC-SAFT: root 9354899b-b105-431d-8207-dd5739bbbcdb, preserve its direct feat: Allow Maximize terminal panel pingdotgg/t3code#449 child, cancel request 71dec6bf-d8b8-4577-b180-63350c9ce79c, archive unwanted root thread:delegated-task:issue-root%3Agithub.com%3A1364883813. No projection-row patches or packaged-runtime edits.

Activity

  1. tannerpolley commented on Oct 12, 2026

    @tannerpolley
    OwnerAuthor

    The existing-lead ownership repair is integrated into sync/upstream-v2 (local, not pushed). Commits:

    • 66f0222159: the repair, ported onto the upstream merge.
    • 0868968fba: Opus fixes for the four round-1 findings from Astra (compacted rebuild, lock-order deadlock, stuck rejection receipt, logic moved to the fork-owned IssueWorkRecovery.ts).
    • a99eeaf01c: refuse a missing restore target before locking. This was Astra's round-2 finding; Astra verified the fix with a probe.

    All 105 tests in ThreadLaunchService.test.ts pass. Each new regression test fails without its fix. The server type-check with tsc-rs passes.

    Known limit, accepted by the reviewer: retrying in the same Start panel after a rejected adoption replays the rejection until a selection changes or the component remounts.

    Still open: review of the questions/model-choice build (56e9449b75), which merges cleanly on top. Then a build, the owner's install approval, and the ePC-SAFT recovery steps.

  2. tannerpolley commented on Oct 13, 2026

    @tannerpolley
    OwnerAuthor

    Design recovery for routed-request visibility (2026-10-12)

    Recurring failure. Requests routed to the orchestrator kept getting stranded, hidden from the owner with no parent to act on them, and each review found a new case:

    • Round 1: a restart.
    • Round 2: a wake held or cancelled while the server kept running.
    • Round 3: a cancelled started wake with restart continuation turned off, and a parent interrupted after a blocking delegate_task wait had returned the question.

    Cause. Hidden state was stored (routedTo) and cleared by catching wake-run lifecycle events (releaseStrandedDelegatedRequest, the wake-reachability rule, a run-update listener, a restart hook). Every lifecycle path that was missed left a stranded request.

    Recovery: replace the release machinery with a derived rule.

    • Stored: routedTo, the parent thread id, recorded when the request is created. It is set only for app-owned delegated children with a live parent.
    • Derived: a routed request is hidden from the owner only while the parent is active. That means running, or holding queued or pending work, and not archived or deleted.
    • When it shows: as soon as the parent is idle, stopped, interrupted, failed, archived or gone, the request is visible on every owner surface.
    • One owner for the rule: a single shared helper used by the server and the clients (sidebar attention, child-input banner, question popup, notifications).
    • Removed: the stranded-release events, the wake-reachability rule, the run-update listener and the restart hook.
    • Kept:
      • the parent wake with full details;
      • respondedBy: "orchestrator";
      • the descendant-only approval check;
      • the Codex permission prompt, the expired-window ranking fix and the drain-race fix from rounds 1–2.

    The behavior the owner chose stays the same: the orchestrator answers first, and the owner sees anything it doesn't act on.

    Falsifying checks. A routed request becomes owner-visible, without any restart or extra event, in each of these cases:

    • the parent is stopped or interrupted, including during a blocking wait;
    • the parent ends its turn without answering;
    • the parent is archived;
    • a restart happens with continuation turned off.

    While the parent is running or has the wake queued, the request stays hidden.

  3. tannerpolley commented on Oct 13, 2026

    @tannerpolley
    OwnerAuthor

    Review of the derived-visibility redesign (7b94b4f7bb), GPT-6 Astra. All earlier stranding cases pass under the derived rule. Six new findings:

    Fixing now (task issue12-derived-visibility-fix-r1):

    • 1 (P1): a checkpoint failure leaves the parent run stuck waiting. This is a run-lifecycle bug.
    • 3: the brief window before the parent wake commits.
    • 4: the relay misses run.created.
    • 5: the relay re-alerts after stop → resume → stop.
    • 6: the first owner-visible child request gets no web notification.
    • Performance: parent invalidation scans every past subagent. Restrict it to pending routed requests.

    Known limit (mobile is out of scope): the mobile thread list drops every subagent, so on mobile an owner-visible request whose parent is archived can't be reached from the list.

  4. tannerpolley commented on Oct 13, 2026

    @tannerpolley
    OwnerAuthor

    Second review of the derived-visibility fixes (bec10bb66e), GPT-6 Astra.

    Resolved:

    • the exhausted checkpoint (upstream shares this bug);
    • run.created invalidation;
    • the first-notification baseline;
    • the indexed lookup. Migration 007 took 0.02 s on a copy of the real database.

    Still open: the durable wake intake added for the brief-flash finding isn't covered by the Stop and queue-hold rules:

    Hosted-relay suppression changes: only take effect on upstream's hosted relay, so they're out of scope for this fork.

    Owner decision (2026-10-12, question tool; answered by Don't ask mode, which picked the recommended option): short delay, simpler.

    • Remove the durable intake.
    • Routed questions raise owner alerts (popup, toast, desktop notification) only after about 3 s of continuous owner visibility. The sidebar badge stays immediate, and a sub-second flicker is accepted.
    • The child-question wake respects a held parent queue.
    • Drop the hosted-relay changes.

    Known limits:

    • With an unchanged upstream hosted relay, remote alerts may repeat after a card is withdrawn.
    • Mobile is out of scope.

    Task: issue12-settle-delay-simplify-r1.

  5. tannerpolley commented on Oct 13, 2026

    @tannerpolley
    OwnerAuthor

    Integrated into sync/upstream-v2 at 509f1bac81 (local only, not pushed).

    Settle-delay simplification 43daaabecc (GPT-6.1 Sol), verified by GPT-6 Astra:

    • The original Stop and held-queue probes now pass.
    • Findings 1, 4 and 6, the stranding cases D1, D2, restart, archive and nested chain, and the timer cleanup all hold.

    Astra's last two findings:

    1. Fixed in 509f1bac81: cancelling a stopped parent's queued entry hid the Stop. The wake guard now uses latestExecutedRun. The regression test fails with the old line and passes with the fix; the delivery suite passes 35/35 and the server tsc-rs passes.
    2. Not fixed, deliberately: outbox rows left over from bec10bb66e's intake could block a database that ran that commit. No real database ever did: bec10bb66e was never built or installed, the builders ran no dev servers, and the owner's database never ran it. A cleanup migration would guard against a state that can't occur, so it's left out.

    Known limits:

    • Repeat alerts from the unchanged upstream hosted relay.
    • Mobile is out of scope.
    • Nothing has been checked in a real client yet.

    Next: build v2.11 and stage it to install on next open (owner's choice through Don't ask mode). After install, check in the app: a subagent asks, its orchestrator answers; and Codex asks a question in Default mode.

  6. tannerpolley commented on Oct 13, 2026

    @tannerpolley
    OwnerAuthor

    Done. Merged and pushed in main (1613234e03), and included in v2.11, which installs on next open.

    To check in a real client after install:

    • a subagent asks and its orchestrator answers, with no owner popup unless the orchestrator is idle or stopped for more than 3 s;
    • Codex shows its option question card in Default mode;
    • t3_request_user_input opens the question panel.

    ePC-SAFT recovery is waiting on the owner's OK after install: cancel request 71dec6bf…, restore lead 9354899b…, and archive the unwanted root. Known limits: repeat alerts from the hosted relay, and mobile is out of scope.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions