V3 Issue #241 — Working Plans and Task Lifecycle
Issue-specific plan for #241, based on the reviewed #264 migration branch. #242 will add richer atomic edit, ordering, and dependency operations.
Goal: Keep simple work unplanned, allow optional plans for medium work, and require an explicit, mutable, durable Working Plan before substantial complex work. The model proposes strategy; runtime state owns plan and task identity and validates lifecycle transitions.
Scope boundary: Reuse TaskManager, the existing tasks repository, ToolRegistry, and the new ordered SQLite migrations. Add only the persisted plan identity/state and the typed update_plan entry needed by this contract. Full revision history, atomic multi-operation edits, dependency validation, parallel scheduling, and AgentEngine loop replacement remain later issues. Keep textual TaskList/TaskDone confined to legacy compatibility paths while the native structured path adopts the typed plan contract.
Caller and persistence map
openkyrozen/tasks/engine.pyandtasks/models.py: task identity, receipt correlation, evidence-backed completion, status transitions, recovery, and legacy text adapters.openkyrozen/persistence/database.pyandpersistence/tasks.py: schema version 4 migration and durable plan/task association, extending the migration framework introduced by #264.openkyrozen/agent/initial_response.py,protocol.py,action_rounds.py,prompts.py, andruntime.py: complexity policy and current TaskList/TaskDone protocol; retain simple-task behavior and prevent complex work from reaching substantial execution without a plan.openkyrozen/tools/manifest.pyand workspace binding: expose typedupdate_planthrough the authoritative registry without a global bound executor.- Existing task, interaction, web/TUI, and acceptance tests: preserve stable IDs, scoped recovery, compatibility behavior, and visible plan state.
Task 1 — Add failing plan and lifecycle regressions
- [x] Test simple tasks without plan creation, optional medium plans, and complex-task rejection/recovery before any substantial tool execution.
- [x] Test a persisted Working Plan with stable plan/task IDs, scope isolation, restart recovery, mutable acceptance metadata, and crash-window completion reconciliation.
- [x] Test allowed and rejected status transitions while preserving the evidence requirement for
succeededand current failed/blocked recovery behavior. - [x] Test that typed
update_planuses object arguments and canonical task IDs, while legacy TaskList/TaskDone callers remain explicitly compatible. - [x] Test scoped deletion, terminal-plan identity, failed/blocked cleanup, hidden legacy discovery, receipt-to-task correlation, and structured ID transport.
Task 2 — Persist the minimal Working Plan contract
- [x] Add an ordered SQLite migration for a scoped Working Plan record and task association; preserve current rows and support databases at schema version 3.
- [x] Give each plan a stable ID, scope, complexity, lifecycle status, creation/update timestamps, and its stable task identities.
- [x] Load/recover plans and unfinished tasks without running work or implying completion; reject mismatched scope or malformed plan payloads.
- [x] Keep schema and migration validation centralized in
SQLiteDatabase; do not add placeholders for later revision history.
Task 3 — Enforce plan ownership and typed update behavior
- [x] Add an explicit
WorkingPlan/task lifecycle contract in the task subsystem, with runtime-owned IDs and validated status transitions. - [x] Register a workspace-bound typed
update_planoperation backed by the existing ToolRegistry; model-provided task strategy enters as structured objects, not prose parsing. - [x] Preserve plan/task IDs through typed execution receipts and MCP structured results; correlate declared action/argument contracts with runtime receipts.
- [x] Preserve simple work without mandatory planning, permit medium work without a plan, and require a valid Working Plan for complex work before substantial tool execution.
- [x] Keep TaskList/TaskDone only as legacy adapters; native structured calls update the Working Plan and task state through the typed boundary.
- [x] Keep successful task completion evidence-backed; revise task acceptance explicitly when the plan strategy changes.
Task 4 — Verify and deliver #241
- [x] Run focused task/persistence/runtime tests on Python 3.12 and 3.13, including plan recovery and complexity gates.
- [x] Run full tests,
make check,make lint,make docs-check, Go TUI tests, and offline agent/subagent/TUI acceptance. - [x] Independently review the complete #241 diff, reproduce and fix any actionable findings, and resolve published review threads.
- [ ] Sign and verify the commit, open one PR targeting the #264 branch, attach it, and wait for final-head CI/review. Leave it unmerged.
Risks and acceptance
PASS requires simple and medium work to retain low-friction behavior, complex execution to have a durable plan first, stable IDs and legal lifecycle transitions to survive recovery, and no plan/task status to substitute for verified effect or acceptance evidence. Existing textual callers remain on the compatibility path until native AgentEngine migration. No paid provider calls or new dependency are in scope.