Feat/v3.9 panel goal UI - #55
Conversation
Wire the two built-but-unexposed V3.9 engines toward user invocation. Before this, runPanel had only the goal-loop grader as a caller and makeGoalLoop/makeGoalLoopWiring had zero production callers. P1 — state foundation: - settings: expertPanelDefault (global default arm-state for the panel) - session-state: panelArmed (per-conversation toggle) + activeGoal pointer (goalId/planDocId/phase/startedAt, phase adds "paused"); accessors + normalizeState backfill P2 — Expert Panel standalone entry: - panel/panelist-runner.ts: extracted the shared panelist logic so the panel and the goal loop convene identically; upgraded to load the real per-lens prompts (panel/*.txt) instead of a generic inline prompt - panel/consult.ts: consultPanel(), standalone convener (default/security policies), decoupled from the goal loop - goal-loop-wiring.ts: refactored to reuse the shared runner P3 — Goal Loop driver: - session/goal-driver.ts: materializePlanDoc (in-memory plan → the graded store doc, idempotent INV-4), startGoal, runToCompletion (background tick loop with cooperative pause/stop + status ports) Tests: session-state slots (9), settings (+2), consult (4), goal-driver (6). All typecheck clean; existing panel/goal-loop suites green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Expose the P1–P3 engines over HTTP so the UI can invoke them.
GoalManager service (session/goal-manager.ts): the resident in-process
supervisor that owns running goals. start() materializes the session
plan, assembles the flag-gated ControllerDeps (makeGoalLoopWiring),
and drives runToCompletion as a BackgroundJob; pause/resume/stop/status
track per-session control state observed live by the driver ports. Each
tick publishes goal.updated and mirrors the session-state pointer.
Registered in app-runtime + the httpapi route service graph.
goal.updated event (session/goal-event.ts): live phase + budget ledger,
flows through the same SSE stream as plan.updated.
Routes (deepagent group): POST /deepagent/panel/consult + /panel/arm;
POST /deepagent/goal/{start,pause,resume,stop} + GET /goal/status. Panel
and goal are independently flag-gated server-side (handler fail-closes
with 400 when disabled). Reachable from the app via client.request by
path — no SDK regen required.
Typecheck clean (core + deepagent-code); 71 panel/goal/app-runtime tests
green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add goal as the third primary agent alongside build/plan — the mode a user selects to define a bounded, objectively-decidable goal and produce the plan the Goal Loop drives. Same working permission ruleset as build (setup reads + plans; autonomous execution runs in goal-worker child sessions). Ships with a goal-mode system prompt that steers toward a decidable finish line, explicit bounds, and a concrete plan. Gated on experimentalGoalLoop: the mode is registered only when the flag is on, so it never appears in the switcher without a backend that can start a goal (the goal.start route independently fail-closes too). RuntimeFlags added to the Agent service + defaultLayer. Tests: goal agent present when flag on, absent when off (build/plan unaffected). Full agent suite green (72). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The SolidJS surface for the two engines.
Data plane:
- panel-goal.api.ts: raw-request client for /deepagent/panel/{consult,arm}
and /goal/{start,pause,resume,stop,status} (by path, no SDK regen).
- goal.updated event → session_goal store (mirrors session_plan): types,
reducer case, server-sync setter/store, bootstrap type.
View plane:
- PanelButton (composer toolbar): per-conversation armed toggle seeded
from the expertPanelDefault setting; OFF→ON convenes a panel on the
current context and shows the verdict, then stays quiet; re-press
re-convenes; a small × disarms.
- PanelVerdictDialog: decision + confidence + evidence + preserved dissent.
- GoalStatusBar (composer dock): live phase + tick/token ledger with
pause/resume/stop; dismiss on terminal phase. Reads session_goal.
- Settings: "Arm expert panel by default" toggle (general).
Gating: the panel button appears only when the `goal` primary agent is
present (client-side proxy for the experimental surface being on); the
goal mode itself auto-appears in the agent switcher. Backend routes
independently fail-close.
Tests: goal.updated reducer routing + panel/goal route contract (all
method/url/body locked). app/deepagent-code/core all typecheck clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Panel (§C) and Goal Loop (§D) are now gated independently in both UIs, driveable from the CLI, and their loose ends closed — replacing the earlier goal-agent proxy. Capabilities (backend): /global/capabilities.features advertises expertPanel + goalLoop from the env-backed RuntimeFlags, so UI availability == route availability. Same source the routes fail-close on. GUI: prompt-input fetches capabilities and shows the panel button iff expertPanel is on (was: proxied on the goal agent's presence). Goal mode self-gates — the `goal` primary agent only registers when goalLoop is on. The two flags are now fully independent in the UI. CLI (TUI): /panel convenes the expert panel on the current conversation and toasts the verdict; /goal <objective> starts the goal loop (the text after the command seeds a plan when the session has none, else the loop drives the existing plan). Each gated on its Flag (added EXPERT_PANEL + GOAL_LOOP to core/flag), hidden when its flag is off. Raw /deepagent routes (no SDK regen). Follow-ups closed: - panelArmed is now null-by-default (= not explicitly toggled). New /deepagent/panel/status resolves the EFFECTIVE armed state (explicit toggle, else the server's expertPanelDefault setting), and the button seeds from it — so the default is server-authoritative, not a client guess. setPanelArmed writes an explicit choice; resolvePanelArmed does the fallback. - GoalManager.start accepts an optional objective and seeds a minimal single-step plan from it when the session has no plan, so /goal <objective> works without a prior plan mode pass. Tests: capabilities advertise the flags; fetchCapabilities + fetchPanelStatus contract; effective-armed resolution; objective-seeded plan is a valid goal carrier. Server harnesses provide RuntimeFlags. All four packages typecheck clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Four settings/composer UX fixes.
1. Share URL i18n: the Sharing section (section title + shareUrl
title/description/placeholder) was English-only, so it showed
untranslated. Added zh + zht translations, and backfilled all 15
non-English locales so the settings-key parity test passes (it was
already red on these keys + the earlier expertPanelDefault keys).
2. Approval control moved to the composer: removed the auto-accept row
from settings and added an ApprovalControl next to the build/plan
agent selector, modeled on Codex's approval selector — a two-option
picker ("Request approval" default, "Auto-approve" when armed) whose
button label reflects the current mode. Directory-scoped, backed by
the existing permission context (isAutoAcceptingDirectory /
toggleAutoAcceptDirectory).
3. Servers tab: the duplicate "Add server" + "Connect to server" buttons
are merged into one "Add server" menu with two items (Add HTTP server
/ Connect to server), matching the single-entry status popover.
4. Import: the run button is now a full-width bar button under the
options (with Cancel beside it while running) instead of a small
right-aligned row control.
Tests: i18n parity green; settings-UX test updated to assert the
approval control moved to the composer. App suite 540 pass, typecheck
clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Hey! Your PR title Please update it to start with one of:
Where See CONTRIBUTING.md for details. |
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
|
Superseded — this work already landed on dev via #46 (Feat/v3.9 panel goal UI), #49 (composer approval), and #52 (user-facing tails). Verified: panel-button.tsx and goal-status-bar.tsx are byte-identical to dev, and dev's panel-goal.api.ts is newer than this branch's (it carries the |
Issue for this PR
Closes #
Type of change
What does this PR do?
Please provide a description of the issue, the changes you made to fix it, and why they work. It is expected that you understand why your changes work and if you do not understand why at least say as much so a maintainer knows how much to value the PR.
If you paste a large clearly AI generated description here your PR may be IGNORED or CLOSED!
How did you verify your code works?
Screenshots / recordings
If this is a UI change, please include a screenshot or recording.
Checklist
If you do not follow this template your PR will be automatically rejected.