Files
kandev/docs/plans/detached-workspace-continuity/plan.md
T
Clément Fiere 01b0dedd6c fix: harden task archive lifecycle recovery (#3651)
Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
2026-09-14 16:34:25 +01:00

7.0 KiB

created, status, requirements, system_design, legacy_specs
created status requirements system_design legacy_specs
2026-09-04 completed
REQ-TASKS-DETACHED-WORKSPACE-CONTINUITY-001
REQ-TASKS-DETACHED-WORKSPACE-CONTINUITY-002
../../specs/tasks/system-design/detached-workspace-continuity.md
../../specs/tasks/requirements/subtask-detachment.md

Implementation Plan: Detached Workspace Continuity

Overview

Make detachment transfer shared-workspace stewardship atomically, route every child creation surface through the same workspace attachment step, and prevent stale cleanup from acting after an ownership generation changes. The work is one sequential backend package because the schema, repository transaction, service flow, and regression tests share one ownership contract.

Scope

In scope

  • Persist ownership generations for workspace groups and task environments.
  • Atomically detach a task and transfer group and environment stewardship.
  • Fence task-resource and workspace-group cleanup by owner and generation.
  • Move child workspace attachment into the canonical task creation sequence.
  • Cover SQLite, PostgreSQL, concurrency, restart recovery, and all creation entry points named by the requirements.

Out of scope

  • Copying a shared workspace during detachment.
  • Frontend interaction changes or new user-facing copy.
  • Changing workflow placement, descendant relationships, blockers, or active session lifecycle during detachment.
  • Broad task cleanup refactoring beyond ownership and generation checks.

Technical approach

Persistence and models

  • Add OwnershipGeneration to Office WorkspaceGroup and task TaskEnvironment models.
  • Add replayable ownership_generation migrations and fresh-schema columns in the task and Office SQLite/PostgreSQL repositories.
  • Extend environment and group queries, inserts, updates, and cleanup snapshots to preserve the generation.

Atomic ownership operations

  • archivecascade.Store.DetachTask owns the single transaction over workspace, barriers, task/revision, effects/claims, environment/repository, group/member, marker, and outbox rows. Its command carries actor plus expected parent/group/ environment generations; SQLite code is private dialect helpers only.
  • The transaction discovers and revalidates all affected operation/barrier scopes, locks barrier 4 -> task 5 -> revision 6 -> effects/claims 7-10 -> environment/repository 11 -> group/member 12 -> cleanup/markers 13-14 -> outbox 16, with tiers 2,3,15,17 intentionally empty, and commits once.
  • Mode/owner preconditions transfer stewardship only for inherited parent-owned materialization; shared-group and new-workspace children preserve ownership.
  • Replace unguarded environment owner transfers with expected-owner and expected-generation compare-and-swap operations used by direct delete, cascade archive/delete, rollback, and detachment.
  • Add generation-aware workspace-group cleanup claim and completion methods so stale cleanup cannot change status or remove resources.
  • Add workspace-policy inputs and an injected attachment coordinator to the task service create sequence.
  • Resolve and attach policy through a typed CreationPlan step before task.created publication and before Created returns. Use handle-bound Abort only when its closed predicate holds; otherwise persist pending recovery for Runtime reconciliation.
  • Remove handler-owned REST and MCP attachment calls and cover WebSocket, plugin, workflow/internal child, REST, and MCP creation through the service boundary.

Cleanup and recovery

  • Compare live environment owner and generation with the cleanup snapshot before task environment and worktree teardown.

  • Treat superseded snapshots and retries as safe no-ops while preserving error reporting for genuinely failed current-generation cleanup.

  • Prove that restart processing cannot revive an old generation's authority.

  • apps/backend/internal/task/archivecascade/detached_workspace_continuity_test.go: SQLite transaction, idempotency, mode/owner branching, rollback, publication, cleanup-barrier, concurrent detach, and stale-generation cases.

  • apps/backend/internal/task/archivecascade/detached_workspace_continuity_postgres_test.go: shared-DB crash rollback/replay, detach-vs-cleanup, sibling detach, and every adjacent lock-inversion case using KANDEV_TEST_POSTGRES_DSN.

  • apps/backend/internal/office/repository/sqlite/workspace_group_generation_test.go: group generation claims, membership role uniqueness, stale status writes, and SQLite/PostgreSQL schema replay.

  • apps/backend/internal/task/service/service_detachment_test.go and a focused cleanup test file: aggregate delegation, detached child continuity after parent archive/delete, stale durable-job recovery, and unchanged physical workspace binding.

  • Handler, MCP, plugin adapter, and CreateChildTask tests: every creation route reaches the service-owned workspace attachment coordinator; failed attachment uses only eligible Abort or durable recovery and never direct deletion.

E2E tests

Skipped. The existing detach UI and API response do not change. Repository and service integration tests exercise the workspace lifecycle guarantee below the UI.

Work orders

Verification results

Completed on 2026-09-04.

  • Atomic detach, stewardship transfer, role updates, and ownership generations are covered by service and repository regressions.
  • Current-owner cleanup barriers, guarded owner-generation transfers, stale environment cleanup, and generation-fenced workspace cleanup are covered.
  • The task service owns workspace attachment through a typed CreationPlan step before publication or return; failure uses predicate-proven handle-bound Abort or durable Runtime recovery and never direct rollback deletion.
  • Focused repository tests passed: 27 tests across task and Office persistence.
  • Focused service tests passed: 19 tests.
  • Creation entry-point tests passed: 15 tests across HTTP, MCP, plugins, and backend composition.
  • Final combined ownership and creation regressions passed: 76 tests across seven packages.
  • Race-enabled ownership tests passed: 37 tests across three packages.
  • Backend lint passed with zero issues.
  • Specification linter tests passed: 30 tests; all specification files passed.
  • PostgreSQL integration tests were not run because no isolated KANDEV_TEST_POSTGRES_DSN was configured.
  • The full backend suite reported 9,907 passes, 16 skips, and seven unrelated config-discovery failures caused by the VM's existing /root/.kandev/config.yaml overriding those tests' temporary home fixtures.

Risks

  • Task and Office repositories initialize tables in a defined order; both fresh and replayed schemas must converge before cross-table detachment queries run.
  • Cleanup invokes external filesystem or provider operations, so its database claim must prevent ownership transfer for the complete destructive window.
  • External-ID deduplication must not attach a retry's workspace policy to an existing task.