15 KiB
spec, created, status
| spec | created | status |
|---|---|---|
| docs/specs/tasks/autopilot-mode.md | 2026-08-08 | implemented |
Implementation Plan: Task Autopilot Mode
Overview
Persist autopilot as an immutable task-creation choice, derive a matching prompt and task-mode MCP tool inventory, and add a durable non-blocking parent-question lifecycle. Surface the identity and waiting state through shared desktop/mobile task components, then cover the complete create → ask → answer → resume path with backend, frontend, restart, and Playwright tests.
Issue: #2425
MCP profile decision: ADR-2026-08-08-mcp-tool-profiles
Design constraints
autopilotdefaults to false, never implicitly inherits, and cannot be edited after creation.- The persisted task is the source of truth. Prompts, tool discovery, APIs, boot payloads, and UI projection must not derive the value independently.
- Autopilot replaces the blocking operator-question capability with a structured, immediate-return parent-question capability.
- Question capabilities are mutually exclusive: normal tasks get the user-question tool, autopilot children get the parent-question tool, and autopilot roots get no question tool.
- Questions route to the current direct parent. A parent may relay upward through a separate question; top-level autopilot agents proceed without asking the user.
- A pending question gates workflow completion and normal queue draining until a correlated parent answer, explicit superseding input, or terminal transition.
- Existing non-autopilot clarification and peer-message behavior must remain unchanged.
- The first release rejects incompatible non-task/Office/passthrough runtime modes rather than silently providing partial autopilot semantics.
- MCP discovery uses a backend-owned profile registry. A base surface selects the task, Office, configuration, or external tool groups. Typed capability groups add or remove context-specific tools without copying a complete mode branch.
Backend
Persist and publish the task property
Likely files:
apps/backend/internal/task/models/models.goapps/backend/internal/task/dto/dto.goapps/backend/internal/task/dto/requests.goapps/backend/internal/task/repository/sqlite/base_schema.goapps/backend/internal/task/repository/sqlite/base_migrations.goapps/backend/internal/task/repository/sqlite/task.goapps/backend/internal/task/handlers/task_http_handlers.goapps/backend/internal/mcp/server/server.goapps/backend/internal/mcp/handlers/handlers.go
Add a non-null autopilot_enabled task column with a false default, carry it
through scan/insert/update/read DTO paths, and accept autopilot in HTTP and MCP
creation requests. Keep it out of mutation DTOs. Validate the resolved agent
profile/runtime mode before committing an autopilot task. Extend server schemas,
argument validation, handler forwarding, and API contract tests together so MCP
discovery and execution cannot drift.
Derive the runtime prompt and tools
Likely files:
apps/backend/config/prompts/kandev-context.mdapps/backend/internal/sysprompt/sysprompt.goapps/backend/internal/sysprompt/sysprompt_test.goapps/backend/internal/orchestrator/task_operations.goapps/backend/internal/orchestrator/event_handlers_workflow.goapps/backend/internal/task/handlers/message_handlers.goapps/backend/internal/agent/runtime/agentctl/control.goapps/backend/internal/agent/runtime/lifecycle/container.goapps/backend/internal/agent/runtime/lifecycle/executor_docker.goapps/backend/internal/agent/runtime/lifecycle/executor_standalone.goapps/backend/internal/agent/runtime/lifecycle/manager_launch.goapps/backend/internal/agentctl/server/config/config.goapps/backend/internal/agentctl/server/instance/instance.goapps/backend/internal/agentctl/server/instance/manager.goapps/backend/internal/agentctl/server/api/server.goapps/backend/internal/mcp/server/server.goapps/backend/internal/mcp/server/tool_profiles.goapps/backend/internal/mcp/server/tool_profiles_test.go
Carry the resolved profile context in explicit launch/runtime configuration to agentctl. Build the autopilot prompt section at prompt-construction time, including autonomy, last-action, direct-parent, and top-level behavior. Replace the current mode/boolean registration branch with a declarative profile registry:
kanban-taskkeeps the current Kanban task, plan, review, workspace, and diagnostics groups;office-taskkeeps the slimmer Office/skill/CLI surface and no Kanban task creation tools;configurationkeeps configuration groups;externalkeeps configuration plus task creation and no live-session tools;- additive groups handle
user-question,parent-question,task-title, and provider automation.
Question groups remain mutually exclusive: parent question for an autopilot child,
no question group for an autopilot root, and user question for a normal task. Use
one typed profile context instead of independent enable/disable booleans or an
agent-supplied arbitrary allowlist. Keep SetMcpMode and SetMcpProviders as
compatibility paths while adding the backend-owned profile update path. Tests must
cover first launch, resume/restart, reparenting, live list replacement, and every
executor transport used by task sessions.
Add the parent-question lifecycle
Likely files:
apps/backend/internal/mcp/server/server.goapps/backend/internal/mcp/server/handlers.goapps/backend/internal/mcp/handlers/handlers.goapps/backend/internal/task/models/models.goapps/backend/internal/task/repository/sqlite/message.goapps/backend/internal/task/statussummary/model.goapps/backend/internal/task/statussummary/projector.goapps/backend/internal/task/statussummary/rebuild.goapps/backend/internal/task/handlers/message_handlers.goapps/backend/internal/orchestrator/event_handlers_clarification.goapps/backend/internal/orchestrator/clarification_guard.goapps/backend/internal/clarification/types.goapps/backend/internal/clarification/store.goapps/backend/internal/clarification/canceller.go
Register and validate the structured ask-parent tool. Persist a hidden typed message
with correlation and lifecycle metadata before sending an attributed peer prompt to
the resolved parent. Extend message_task_kandev with
reply_to_question_id; authorize the recorded parent and atomically resolve and
resume the child. Use the per-session serialization boundary for answer,
superseding prompt, terminal transition, workflow completion, and queue-drain races.
Project a pending parent question to the existing clarification pending-action category while suppressing the operator clarification overlay. Extend status-summary rebuild and restart recovery. Test duplicate asks/replies, unavailable or reparented parents, full queues, crash boundaries, stale answers, and the rule that no second child turn or parent prompt is created.
Frontend
Likely files:
apps/web/lib/types/http.tsapps/web/lib/api/domains/kanban-api.tsapps/web/lib/kanban/map-task.tsapps/web/components/task-create-dialog-types.tsapps/web/components/task-create-dialog-state.tsapps/web/components/task-create-dialog-form-body.tsxapps/web/components/task-create-dialog-prop-builders.tsapps/web/components/task-create-dialog-submit.tsxapps/web/components/task/new-subtask-dialog.tsxapps/web/components/task/new-subtask-form-state.tsapps/web/components/task/new-subtask-form-parts.tsxapps/web/components/task/use-subtask-submit.tsapps/web/components/task/task-session-sidebar-item.tsapps/web/components/task/task-switcher-types.tsapps/web/components/task/task-item.tsxapps/web/components/task/chat/chat-input-area.tsxapps/web/src/locales/en/task.jsonapps/web/src/locales/pt-pt/task.jsonapps/web/src/locales/pseudo/task.jsonapps/web/src/locales/zh-cn/task.json
Add autopilot to the shared task type and mapping. Keep top-level task creation
UI free of an Autopilot control for now; expose an off-by-default compact switch
only in the subtask creation dialog and include it in the creation request. Give
the switch a localized hover/focus help control. In the shared chat status row,
render a yellow localized badge for autopilot tasks. In the shared task item, keep
the existing primary status icon (including the question indicator) and add a
secondary autopilot icon with localized hover/focus tooltip and accessible name.
All new copy goes through t(). The pseudo-locale and i18n checks must cover the
chip, subtask switch label/help, and tooltip. Existing tasks whose payload omits the
field map to false during rolling compatibility.
Mobile design contract
- Desktop outcome: creation dialog switch, status-row chip, and sidebar identity icon; a pending parent question uses the current primary question icon.
- Mobile entry point: the existing responsive task creation dialog and the task switcher sheet; no new route or desktop-only hover action.
- Nearest exemplars:
task-create-dialog-form-body.tsxandnew-subtask-form-parts.tsxfor create-only fields, and the existing sharedtask-item.tsxstatus/question rendering used by the mobile task switcher. - Presentation: keep the switch inline because it is one reversible creation choice; do not add a nested drawer. The informational sidebar icon has no action, so touch users receive its accessible/visible identity without a tooltip-only dependency.
- Hierarchy and scrolling: the primary task-state icon keeps precedence; autopilot is a secondary identity mark. The composer chip participates in the existing wrapping status row, and neither the dialog nor switcher introduces a horizontal scroll container.
- Touch target: the switch row remains at least 44 px high and the whole labeled row toggles the control. Disabled/incompatible profiles explain why before submit.
- Shared state: desktop and mobile read the same mapped task boolean and pending action; no viewport-specific autopilot store exists.
Tests
- Repository/model tests cover migration defaults, round trips, and immutability.
- HTTP and MCP tests cover omitted/false/true creation, nested task creation, incompatible profiles, the exact short autopilot description, and schema/handler synchronization.
- System-prompt and MCP inventory tests prove normal and autopilot sessions expose the correct mutually exclusive question capability on launch and resume, including no question tool for an autopilot root.
- Profile registry tests prove the Kanban, Office, configuration, and external
surfaces, additive title/provider groups, atomic replacement, and one
tools/list_changednotification per effective profile change. - Parent-question service/orchestrator tests cover direct-parent routing, turn-end gating, answer correlation, idempotency, races, stale/superseded state, and restart reconstruction.
- Frontend tests cover request serialization, DTO mapping, create-only switch visibility, badge styling/copy, both sidebar icons, tooltip/focus semantics, and missing-field compatibility.
E2E
Add a deterministic mock-agent scenario that creates an autopilot child, invokes the parent-question tool, ends its turn, receives a correlated parent answer, and resumes once. A desktop Playwright spec verifies creation and the full lifecycle. A mobile spec verifies the creation control, chat chip, autopilot identity icon, pending question icon, answer clearing, and no horizontal overflow. Include a backend restart while pending if the existing fixture can restart without weakening isolation; otherwise keep restart proof in Go integration tests.
Public documentation
Update:
docs/public/automation-and-mcp.mddocs/public/agent-communication.mddocs/public/coordination.md
Document the creation parameter, immutable first-release semantics, profile surfaces, context-specific capability groups, ask-parent payload, correlated reply, direct-parent ownership, top-level behavior, and visible waiting state. Examples must not imply that an autopilot child can call the operator clarification tool or that an Office task can create Kanban tasks through MCP.
Waves
Wave 1:
Wave 2:
Wave 3:
Wave 4:
Verification
Targeted backend:
(cd apps/backend && go test ./internal/task/... ./internal/mcp/server/... ./internal/mcp/handlers/... ./internal/sysprompt/... ./internal/orchestrator/... ./internal/clarification/...)
Targeted frontend:
(cd apps && pnpm install --frozen-lockfile)
(cd apps && pnpm --filter @kandev/web test -- --run components/task-create-dialog-defaults.test.ts components/task-create-dialog-form-body.test.tsx components/task/new-subtask-form-parts.test.tsx components/task/new-subtask-form-state.test.ts components/task/use-subtask-submit.test.ts components/task/task-item.test.tsx components/task/chat/chat-input-area.test.tsx lib/kanban/map-task.test.ts)
(cd apps/web && pnpm run typecheck)
(cd apps/web && pnpm run lint)
(cd apps/web && pnpm run i18n:check)
(cd apps/web && pnpm run i18n:ratchet)
E2E:
cd apps/web && pnpm e2e:run --project chromium tests/task/autopilot-mode.spec.ts
cd apps/web && pnpm e2e:run --project mobile-chrome tests/task/mobile-autopilot-mode.spec.ts
Public docs:
node --test scripts/validate-public-docs.test.mjs
node scripts/validate-public-docs.mjs
Verification results
Implemented. Verification passed: 2,263 Go tests across 9 focused packages; 156 focused web tests; web typecheck and lint; i18n checks/ratchet; public docs validation (58 tests, 41 pages); and desktop/mobile Playwright autopilot scenarios. The fixup adds profile-capability selection tests, parent-question ownership and claim/restore coverage, omitted-field preservation tests, and the autopilot hook fallback test.
Risks
- Tool discovery and prompt composition travel through several launch transports; missing one executor path would create a split contract after resume.
- Parent questions compose with clarification cancellation, queue admission, and workflow turn completion. The pending gate must share existing per-session serialization rather than introducing a parallel lock.
- Durable delivery and answer idempotency need stable identities; retrying after a crash must never generate a second parent request or child answer turn.
- Reparenting while a question is pending must fail closed. The implementation must either keep the recorded parent authoritative for that question or mark it stale before accepting a new parent; it must never silently accept both.