# Internal: Workspace ## Purpose Explain the helpers that construct local session and run paths, coordinate single-writer access, and confine cleanup. The authoritative physical layout and retention workflow belong in [Operations](../operations.md#local-state-layout). ## Path Ownership `internal/artifacts` owns canonical session, run, spool, cache, and previous-cache path construction. `SessionPathsFor` provides the session-scoped path model, and layout creation goes through `EnsureLayoutFor`. Callers should consume those helpers instead of rebuilding relative paths. `internal/pathsafe` validates relative destinations. `internal/fileops` opens explicit cleanup roots and removes only normalized proper descendants through the resulting root handle. `internal/fileops` owns the ordinary workspace mode contract. On POSIX, `WorkspaceDirectoryMode` is setgid `02775` and `WorkspaceFileMode` is `0664`. `EnsureWorkspaceDirectory` reapplies the directory mode after creation so a restrictive umask cannot remove group access, while retaining existing ownership and group. Credential paths are outside this contract; the platform-specific operational requirements are in [Operations](../operations.md#workspace-permissions). ## Run-Local Stage Layout `internal/stage/run_local.go` maps stage outputs and diagnostics into an invocation-scoped layout. Successful outputs are validated and atomically materialized into canonical session paths before stage success. Managed previous-session cache paths remain session-durable and are never redirected into run-local output space. Extraction uses run-local receipt, stderr, and output-root helpers, then validates and renames the external bundle to the unique immutable Notarius bundle path supplied by `internal/artifacts`. Exact physical paths belong in [Operations](../operations.md#extraction-workflow). ## Locking `artifacts.LocalStore` enforces the single-writer session lock via an operating-system lock held on `.lock` (`ErrLockConflict` on contention). The file retains owner metadata after release or process death; its existence is not evidence that a lock is active. Command and restore flows wait for this lock only while their context remains active, and report a release failure. The runner assigns every invocation a run-workspace identity but creates the physical directory only before an executing stage that requires it. Fully reused invocations and cleanup-only invocations therefore do not accumulate empty run directories. ## Cleanup Semantics The canonical cleanup stage: - runs after notify only when selected by the invocation range; - requires a succeeded publish record with `uploaded=true`, the published run ID, remote commit key, and current commit-pointer key; - consumes the resolved cleanup policy described in [Configuration](../config.md); - refuses unsafe deletes (root delete, traversal, and out-of-root targets); - treats missing targets as successful, idempotent deletion; and - uses its ordinary failed/succeeded manifest stage record for retry. A later full run can skip reusable upstream stages and retry cleanup without republishing. Manual cleanup uses the same root-confined deletion mechanism. Invocation syntax and exact deletion scope belong in [CLI](../cli.md#clean) and [Operations](../operations.md#cleanup). ## Invariants - campaign-aware session root is mandatory. - manifest-driven stage state is durable across runs. - cleanup guardrails prevent destructive root/out-of-scope deletion. - restore installation is confined to validated relative paths beneath the selected session root. - ordinary workspace paths retain group-writable directory and file modes across nested creation, replacement, and Notarius promotion. ## Implementation And Tests - Path model and local store: `internal/artifacts/paths.go`, `internal/artifacts/local.go` - Run-local materialization: `internal/stage/run_local.go` - Immutable bundle installation: `internal/stage/extract.go` - Workspace modes: `internal/fileops/modes.go` - Cleanup confinement: `internal/fileops/cleanup.go`, `internal/stage/cleanup.go`, `internal/stage/cleanup_plan.go`, and `internal/app/cleanup_targets.go` - Tests: `internal/artifacts/paths_model_test.go`, `internal/artifacts/local_test.go`, `internal/stage/run_local_test.go`, `internal/fileops/modes_posix_test.go`, `internal/fileops/cleanup_test.go`, `internal/app/cleanup_targets_test.go`, `internal/stage/cleanup_test.go`, and `internal/app/cleanup_orchestration_test.go`