9.7 KiB
spec, created, status
| spec | created | status |
|---|---|---|
| docs/specs/system-page/requirements/storage-maintenance.md | 2026-08-08 | complete |
Implementation Plan: Registered Kandev temporary-artifact cleanup
Overview
Add a manual-only temporary_artifacts resource to the existing Storage page. The backend first
gets a durable registry and marker contract for exact Kandev service-created temporary roots, then
adds analysis/quarantine/API composition, followed by the responsive resource action and desktop /
mobile coverage. The implementation must preserve the inherited shared-temp boundary: anonymous
/tmp folders, caches, preview/CI roots, and other-installation data are never swept.
The architectural boundary is recorded in ADR-2026-08-08-owned-temp-artifact-cleanup, which supplements ADR 0045.
Backend
Ownership registry and producer lifecycle
- Add a
storage_temp_artifactstable and replay-safe migration inapps/backend/internal/system/storage/store_migrations.go, with exact path, allowlisted kind, artifact ID, marker token, lifecycle state, owner PID/lease timestamps, and metadata. - Add
apps/backend/internal/system/storage/tempartifacts/with registry operations that create top-level directories below the effective service temp root, write an owner-only marker atomically, persist the record, heartbeat active leases, close normal lifecycles, and reconcile records after restart. All path checks useLstat/canonical containment and fail closed on symlinks or uncertainty. - Migrate backend-owned long-lived roots in
apps/backend/internal/improvekandev/bundle.goandapps/backend/internal/agent/hostutility/manager.goto the registry. Remove the independent name/age sweep fromapps/backend/internal/backendapp/helpers.go; unregistered legacy roots stay host-policy data.
Storage provider and API composition
- Implement analysis and explicit cleanup in
tempartifacts/provider.go: report total, active, stale-candidate, skipped, and unavailable bytes/counts; only closed or abandoned records older than 24 hours qualify; same-filesystem rename moves a qualifying root to the existing quarantine. - Extend storage summary/capability types and
storage_quarantine_entries.resource_typefortemporary_artifact. Reuse quarantine retention, restore, and permanent deletion; do not add astorage_maintenancesetting in this release. - Reuse
ExplicitCleanupProvidersotemporary_artifactsis no-op for scheduled and unscoped full runs but performs cleanup forresources: ["temporary_artifacts"]. Extend provider composition inapps/backend/internal/backendapp/storage_maintenance.goand keep overview totals non-overlapping. - Accept the stable resource name through the existing
POST /api/v1/system/storage/runcontract; return provider counts/bytes and skipped warnings through the existing run result and preserve the current activity gate and busy/force behavior.
Frontend
Storage analysis and action
- Extend
apps/web/lib/types/system.tswith the temporary-artifact summary, capability, quarantine resource type, and provider result shapes. No new policy field is added. - Update
apps/web/components/settings/system/storage/storage-totals.tsso measured temporary artifact bytes participate once in the non-overlapping total, with a partial result when that provider is unavailable. - Add a localized Kandev temporary artifacts resource row to
apps/web/components/settings/system/storage/storage-overview-card.tsx. Show measured bytes, stale eligible bytes/count, active protection, skipped warnings, and an explicit Clean stale artifacts action only when cleanup is available. - Thread
runNow(["temporary_artifacts"])through the existing Storage controller and add a normal reversible confirmation instorage-confirmation-dialogs.tsx; do not introduce a second page or a scheduled toggle. Keep busy feedback andRun anywayon the existing gate. - Add the new copy to
en,pseudo,pt-pt, andzh-cnsystem.jsoncatalogs. All paths remain i18n-guarded and filesystem values are interpolated rather than translated.
Mobile contract
- Keep the existing one-column Storage accordion and action composition. The temporary-artifact row must wrap long paths/warnings, retain a 44px-or-larger action target, and remain usable with no horizontal document overflow at the mobile project viewport.
Tests
- Registry persistence and marker safety: create/close/heartbeat/reconcile registered artifacts,
reject unregistered prefixes, missing or mismatched markers, symlink replacement, path escape, and
cross-install/legacy records. Files:
apps/backend/internal/system/storage/tempartifacts/*_test.go,apps/backend/internal/system/storage/store_test.go,apps/backend/internal/improvekandev/bundle_test.go, and host-utility lifecycle tests. How: table-driven filesystem tests undert.TempDir()plus SQLite migration/restart tests. - Provider behavior: analysis is read-only, active/recent roots are protected, stale roots move
atomically to quarantine, cross-device/error/symlink cases remain untouched, and unscoped/scheduled
runs do not invoke destructive temp cleanup. Files:
apps/backend/internal/system/storage/tempartifacts/provider_test.go,apps/backend/internal/system/storage/operations_test.go, andapps/backend/internal/system/storage/runner_test.go. How: fake clocks, fake leases, fake rename/filesystem adapters, and provider result assertions. - API and composition: the overview exposes the new summary,
temporary_artifactsis accepted only as a valid explicit resource, quarantine rows round-trip the new resource type, and handler errors preserve400/409semantics. Files:apps/backend/internal/system/storage/handler_test.go,storage_routes_test.go, andapps/backend/internal/backendapp/storage_test.go. How: handler-to-service-to-store tests with real SQLite and a fake provider, plus composition wiring coverage. - Frontend rendering/action: the row shows active versus stale state, the confirmation sends the
exact resource selection, success/error/busy feedback remains localized, and existing Go-cache /
global actions remain unchanged. Files:
apps/web/components/settings/system/storage/storage-overview-card.test.tsx,storage-confirmation-dialogs.test.tsx,storage-totals.test.ts,apps/web/hooks/domains/system/use-storage-maintenance.test.tsx, andapps/web/lib/api/domains/system-api.test.ts. How: Vitest and Testing Library interaction tests with mocked overview/run responses.
E2E Tests
- Scenario: a current-install registered stale artifact and an unregistered
kandev-*folder are present, WHEN Storage analysis runs, THEN only the registered artifact appears in the temporary-artifact row and the unregistered folder is not counted or changed. File:apps/web/e2e/tests/system/storage-maintenance.spec.tsusing the existing Storage API route fixture pattern plus an explicit-run assertion. - Scenario: the user selects Clean stale artifacts, WHEN confirmation completes,
THEN the request contains
{ resources: ["temporary_artifacts"] }, the cleanup job completes, and the result is visible in Quarantine while a global Run now leaves the artifact untouched. File:apps/web/e2e/tests/system/storage-maintenance.spec.ts. - Scenario: the same row and confirmation are opened from the mobile settings sheet, WHEN
the user taps the action, THEN the action is reachable at a 44px target and the document has no
horizontal overflow. File:
apps/web/e2e/tests/system/mobile-storage-maintenance.spec.ts.
Focused UI commands use the managed production-build runner:
cd apps/web && pnpm e2e:run tests/system/storage-maintenance.spec.ts
cd apps/web && pnpm e2e:run tests/system/mobile-storage-maintenance.spec.ts -- --project=mobile-chrome
Verification Results
- Backend storage, Improve Kandev, host-utility, and backend-app tests passed:
go test ./internal/system/storage/... ./internal/improvekandev/... ./internal/agent/hostutility/... ./internal/backendapp/... -count=1. - Focused frontend tests passed: 71 tests across six files; web typecheck and lint passed.
pnpm run i18n:checkandpnpm run i18n:ratchetpassed. The check reported only the repository's existing 209 advisory pt-pt/zh-cn parity issues and one existing orphan.- Desktop Storage Playwright: 7 passed, including the registered-artifact row, scoped cleanup, quarantine/job feedback, cache isolation, busy override, progressive loading, and settings persistence scenarios.
- Mobile Storage Playwright: 5 passed, including the scoped action, touch target, and document overflow assertions.
- Public documentation validation passed: 58 tests and 41 published pages.
git diff --checkpassed.
Implementation Waves And Parallel Candidates
Wave 1 (sequential backend foundation):
Wave 2 (backend provider/API after Task 01):
Wave 3 (frontend after Task 02; shared frontend files make this sequential):
Wave 4 (desktop/mobile E2E after Task 03):
Wave 5 (docs after behavior is implemented):