# Workstream 10 Implementation Plan — Quality, Testability, And Documentation Alignment ## Status Planned implementation for Workstream 10, **Quality, testability, and documentation alignment**, in [`refactoring.md`](refactoring.md). Workstreams 1 through 9 are complete prerequisites. This is the final actionable workstream in the consolidated refactoring roadmap; it closes cross-cutting gaps that were not already completed alongside the behavior-owning workstreams. ## Authoritative Scope And Fixed Decisions Workstream 10 in [`refactoring.md`](refactoring.md) is authoritative. Its supporting first-pass findings are H07, H08, H12, H13, H17, H18, H23, and H25 in [`audit.md`](audit.md). The corresponding contract decisions are C01 through C06 in [`audit-decisions.md`](audit-decisions.md); their full rationale remains in [`contract-audit.md`](contract-audit.md). Read those cited sections rather than re-auditing unrelated hypotheses. Most of Workstream 10's risk coverage and documentation alignment landed with Workstreams 1 through 9. Preserve that completed work. The remaining decisions are: - Do not reopen completed product, compatibility, filesystem, manifest, analyze, configuration, publication, lock, or cleanup decisions. This workstream changes internal testability and test diagnostics without changing CLI, configuration, artifact, manifest, integration, publish, restore, or cleanup behavior. - Remove the seven remaining mutable application function seams: `readSecretsDirectoryEntries`, `loadPipelineConfigFn`, `downloadObjectToTempFn`, `newObjectStoreFromConfigFn`, `discoverRemoteCurrentStateFn`, `buildRestorePlanFn`, and `executeRestorePlanFn`. Compiled regular-expression values, canonical stage relations, and fixed command-name data are not collaborator seams and are not part of this removal. - Use one package-private, value-owned `commandDependencies` set for these collaborators. A normalization function supplies production defaults for nil fields. Each command invocation receives its own value; there is no mutable default singleton, context-carried service locator, dependency-injection framework, or new public interface. Keep runner `invocationDependencies` separate because it owns a different lifecycle. - Preserve exported command entry points and their existing signatures. Production wrappers use normalized defaults. Private dependency-aware entry points let tests supply only the external or phase boundary they control. Thread the dependency value explicitly through application-owned command, configuration-loading, secret-loading, object-store, and restore helpers. - Tests must never replace or restore package-level functions. Use dependency values, real temporary filesystems, `storage.FakeBackend`, and existing controlled subprocess helpers at their durable boundaries. Process environment mutation remains permitted where credential behavior itself is under test, but such tests must remain non-parallel and restore state through `t.Setenv` or the existing focused helper. - Add `github.com/google/go-cmp/cmp` only for the audit's selected large structural comparisons: composed configuration values, analyze plans/state, restore plans/actions, and publish output plans/mappings. Preserve nil versus empty and ordering semantics unless a domain contract explicitly equates them. Use direct comparison or `slices.Equal` for simple comparable values; do not mechanically replace every `reflect.DeepEqual` call. - Apply `slices` or `maps` in production only when code touched by this workstream performs a genuinely shallow clone, membership check, or deterministic key operation with identical nil, empty, and ordering behavior. Do not conduct a repository-wide style rewrite and do not replace domain normalization, deep copies, provenance merges, or topological order. - Retain the focused behavior coverage already established for atomic file visibility, bounded reads and adapter diagnostics, group modes, validated downloads, Notarius rename, destructive confinement, restore symlink conflicts, secret protection, session-only progress, per-artifact analyze checkpoints, planning/execution parity, remote-lock carry-forward, and idempotent cleanup. Delete only dead helpers and reset choreography associated with the removed mutable seams; do not delete a current-contract test merely to reduce test lines. - Update only canonical internal documentation whose implemented dependency or test boundary changes. Because public behavior is unchanged, do not churn CLI, configuration, operations, troubleshooting, integration, examples, or release documentation unless implementation uncovers a factual inaccuracy in its owning document. ## Instructions For Every Stage Before each stage: 1. Read `docs/development.md`, all documents under `docs/policy/`, this plan, Workstream 10 in [`refactoring.md`](refactoring.md), and only its cited audit sections. Read [`../internal/overview.md`](../internal/overview.md) and, for restore changes, [`../internal/command-restore.md`](../internal/command-restore.md). 2. Inspect the affected production code and focused tests. Prefer the codebase knowledge graph for Go definitions and call paths; use text search for mutable assignments, test reset choreography, documentation, fixtures, and final removal checks. 3. Confirm worktree state and preserve unrelated changes. Do not implement release work or any deferred/no-action audit hypothesis. During each stage, keep dependencies package-private and invocation-owned, preserve acyclic package direction, keep default tests deterministic and offline, and retain credential redaction and filesystem safety. Prefer behavior assertions over collaborator choreography. Run `gofmt` on changed Go files, `go mod tidy` when module state changes, and `git diff --check`. Commit only a completed stage with a short plain-English message, and update a canonical internal document in the same stage only when its owned behavior changes. ## Stage 1 — Replace Configuration And Secret-Loading Globals **Status:** Completed ### Goal Establish the command-scoped dependency value and remove global substitution from configuration and API-key loading. ### Required Work 1. Add a package-private `commandDependencies` type in `internal/app` with typed function fields for pipeline loading, temporary object download, secrets-directory reading, object-store construction, remote-current discovery, restore-plan construction, and restore-plan execution. Add a value-returning normalizer that fills nil fields with the current production functions. Do not store a normalized instance in a package variable. 2. Add dependency-aware private variants of the configuration-loading path: `loadCommandConfig`, `loadPipelineCampaignConfig`, and `loadPipelineConfig` should receive or delegate to an explicit dependency value. Preserve local session precedence, remote fallback, source provenance, bounded temporary download behavior, and idempotent temporary-file cleanup. 3. Add a dependency-aware private secret loader used by focused tests and by later command composition. Production callers continue through a wrapper using normalized defaults. Preserve directory/file privacy checks, symlink rejection, bounded reads, existing-environment precedence, redaction, and the ancestor-replacement failure case. 4. Remove `loadPipelineConfigFn`, `downloadObjectToTempFn`, and `readSecretsDirectoryEntries`. Rewrite `config_loader_test.go`, loader-focused cases in `remote_session_test.go`, and `secrets_env_test.go` to pass copied dependency values instead of saving, replacing, and restoring globals. Leave command-routing remote-session cases for the command stage that owns their entry point. Retain tests at the narrowest existing behavior boundary; do not reproduce the loader's internal call sequence with mocks. 5. Keep production command behavior unchanged while this foundation is introduced. It is acceptable for the object-store and restore fields to use their production defaults until Stages 2 through 4 migrate their callers. ### Verification And Exit Criteria Run: ```sh go test ./internal/app -run 'Config|RemoteSession|Secret' go test -race ./internal/app -run 'Config|RemoteSession|Secret' git diff --check ``` The three named mutable globals are absent, remote/local configuration behavior and secret protections remain covered, and tests supply collaborators through local dependency values. ## Stage 2 — Carry Dependencies Through Pipeline Commands **Status:** Completed ### Goal Carry one dependency value through the pipeline-oriented command paths, including remote session fallback, without changing their public API. ### Required Work 1. Add a private dependency-aware execution dispatcher alongside `Execute`. `Execute` retains its signature and uses normalized production dependencies. Extend the existing private pipeline-executor path rather than creating a second command switch or an application framework. 2. Thread `commandDependencies` through `run`, `regenerate-artifacts`, `run-stage`, `analyze`, `publish`, `plan`, and `status` paths and the shared configuration loader they use. Preserve the independent `pipelineExecutor` seam and pass both values explicitly where required. 3. Make remote session fallback initialize its object store through the dependency value and preserve the rule that secrets load before the factory. Public command wrappers continue to use production defaults. 4. Rewrite the assembled pipeline-command tests and only those remote-session tests reached through pipeline commands to call the dependency-aware dispatcher with a fake store. Remove their global object-store replacement/reset choreography. Leave remote-session cases reached through `session` commands for Stage 3. It is acceptable for the factory global itself to remain temporarily for restore and operator callers until Stages 3 and 4 migrate them. 5. Preserve command syntax, exit classification, stdout/stderr behavior, configuration discovery, artifact selection, executor injection, and remote session provenance. Do not move adapter construction into configuration or storage packages. ### Verification And Exit Criteria Run: ```sh go test ./internal/app -run 'Run|Stage|Analyze|Publish|Plan|Status|RemoteSession|Command' go test -race ./internal/app -run 'Run|Stage|Analyze|Publish|Plan|Status|RemoteSession' git diff --check ``` Pipeline commands use invocation-owned dependencies, production defaults still select the real storage constructor, and focused tests remain offline. ## Stage 3 — Carry Dependencies Through Operator Commands **Status:** Completed ### Goal Migrate session and maintenance commands to the same invocation-owned command dependency path before removing the final shared storage seam. ### Required Work 1. Thread `commandDependencies` through the `session` dispatcher, session initialization and validation, artifact listing, lock listing/add/remove, and session-scoped or cache-aware clean helpers. Exported command functions remain production-default wrappers. 2. Update the dependency-aware top-level dispatcher so every operator command reached through `Execute` receives the invocation's value. Keep local-only paths independent of remote construction; do not initialize an object store merely because a dependency value exists. 3. Rewrite `object_store_test.go`, `operator_helpers_test.go`, affected session/clean tests, and remote-session cases reached through the `session` dispatcher to supply a local object-store factory. Keep complete CLI routing tests at the private dispatcher and narrow construction-order tests at `newCommandObjectStore`. Remove original-value capture and reset boilerplate in the migrated tests. 4. Preserve secret-before-factory ordering, local/remote session initialization, validation findings, artifact availability, per-source remote lock behavior, cleanup scope, output, and errors. Continue using `storage.FakeBackend` for remote behavior. 5. Leave only restore callers on the temporary global storage seam. Do not remove it until Stage 4 can update restore and its tests atomically. ### Verification And Exit Criteria Run: ```sh go test ./internal/app -run 'ObjectStore|SessionInit|SessionValidate|Artifacts|Locks|Clean|Operator' go test -race ./internal/app -run 'ObjectStore|SessionInit|SessionValidate|Artifacts|Locks|Clean' git diff --check ``` All non-restore commands use invocation-owned dependencies, their tests mutate no factory global, and remote behavior remains deterministic and offline. ## Stage 4 — Replace Restore Phase Globals With Explicit Dependencies **Status:** Completed ### Goal Make restore sequencing testable per invocation without global phase hooks or a new restore framework. ### Required Work 1. Keep `Restore` as the public production wrapper and add one private dependency-aware restore entry point. Normalize dependencies once at that boundary and use its object-store constructor, remote-current discovery, plan builder, and plan executor throughout the invocation. 2. Remove `newObjectStoreFromConfigFn`, `discoverRemoteCurrentStateFn`, `buildRestorePlanFn`, and `executeRestorePlanFn`. Call the concrete production functions through the normalized dependency value; do not add interfaces around pure phase functions or move restore orchestration out of `internal/app`. 3. Rewrite `restore_test.go`, `restore_execution_test.go`, and `restore_recovery_test.go` to pass local dependencies. Consolidate repeated dependency construction into one small test helper that returns a fresh value and never mutates package state. 4. Preserve the observable restore boundaries: dry-run performs no local installation; non-dry-run planning occurs while holding the session lock; conflicts do not execute; the incomplete marker brackets installation; reports reflect failure or success; manifest installation remains last; and lock release errors remain joined with an earlier failure. 5. Prefer real `buildRestorePlan` and `executeRestorePlan` with `storage.FakeBackend` where the test is about restore results or filesystem state. Stub a phase only when the phase call or its timing is the behavior being tested, such as proving the transition lock is already held. 6. Update `docs/internal/command-restore.md` only if its description of phase composition or test seams is no longer accurate. Do not change the operator restore contract. ### Verification And Exit Criteria Run: ```sh go test ./internal/app -run 'Restore' go test -race -shuffle=on -count=3 ./internal/app -run 'Restore' git diff --check ``` No command has a mutable production function seam, restore transaction ordering and recovery outcomes remain covered, and restore tests can execute independently without save/restore choreography. ## Stage 5 — Improve Selected Large Structural Test Diagnostics **Status:** Completed ### Goal Make failures in the four audit-selected large-value test categories readable without imposing a repository-wide assertion style. ### Required Work 1. Add `github.com/google/go-cmp/cmp` as a direct test dependency and update `go.mod` and `go.sum` with the Go toolchain. Do not add an assertion framework or helper wrapper around `cmp.Diff`. 2. Replace existing whole-value `reflect.DeepEqual` assertions with `cmp.Diff` where a field-level diff is materially useful in these files: - composed/effective configuration comparisons in `internal/config/pipeline_composition_test.go` and `internal/config/pipeline_profiles_test.go`; - complete analyze plans, artifact-state maps, or stage records in `internal/stage/analyze_plan_test.go`, `internal/stage/analyze_reconciliation_test.go`, and `internal/app/analyze_checkpoint_recovery_test.go`; - restore action collections or complete plans in `internal/app/restore_plan_test.go`; and - complete output outcomes, declarations, or mappings in `internal/stage/publish_output_plan_test.go`. 3. Keep direct field assertions that intentionally isolate one invariant. Use `slices.Equal` for simple ordered slices in the touched files where it is clearer; retain `reflect.DeepEqual` when its value is small and the mismatch is already obvious. Do not expand this stage to every test package. 4. Do not use `cmpopts.EquateEmpty`, `cmp.AllowUnexported`, blanket ignore options, or custom comparers merely to force a passing comparison. Compare the same observable values as before and preserve distinctions in nil, empty, order, timestamps, and provenance. 5. Run `go mod tidy` and confirm the dependency is used only by tests. Apply `slices` and `maps` to production touched in Stages 1–4 only where the fixed decisions above permit an identical shallow operation; do not manufacture a production change to demonstrate their use. ### Verification And Exit Criteria Run: ```sh go mod tidy go test ./internal/config ./internal/stage ./internal/app go test -race ./internal/config ./internal/stage ./internal/app git diff --check ``` The selected large comparisons emit useful structural diffs, simple assertions remain simple, module state is tidy, and no broad assertion-style migration has occurred. ## Stage 6 — Verify Coverage, Align Internal Documentation, And Close The Roadmap **Status:** Completed ### Goal Prove that the reduced test and documentation system protects the final refactored architecture, then close Workstream 10 and the consolidated roadmap. ### Required Work 1. Search production and tests for all seven retired function-seam names and for assignments that replace application functions. Remove any remaining dead wrappers, original-value captures, reset helpers, or cleanup callbacks whose sole purpose was global substitution. Do not remove compiled regexes, canonical data tables, or legitimate local function values. 2. Review the existing focused owners—not the entire suite indiscriminately—to confirm retained coverage for: - atomic visibility and bounded reads in `internal/fileops` and storage adapter tests; - POSIX group modes in `internal/fileops/modes_posix_test.go`; - validated storage downloads and Notarius promotion in storage adapter and extract tests; - destructive confinement and restore symlink conflicts in fileops, cleanup, and restore tests; - credential privacy and redaction in secrets, logging, subprocess, and adapter tests; - session-only progress and per-artifact recovery in manifest, stage, and application checkpoint tests; - planning/execution parity in `internal/app/run_control_test.go`; - remote-lock carry-forward in publish planning/execution tests; and - idempotent final cleanup in stage and application cleanup tests. Add a test only if a listed consequential boundary is genuinely absent; consolidate or delete only demonstrably redundant mechanism coverage. 3. Review `docs/policy/architecture.md`, `docs/internal/overview.md`, focused internal component documents, and their test inventories for current accuracy. Remove stale implementation claims and duplicate volatile detail; retain links to the canonical CLI, configuration, operations, integration, and release owners rather than copying those contracts. 4. Confirm no current-behavior document treats a retired compatibility path, run manifest, cleanup obligation, central lock manifest, custom directory promotion, or mutable test hook as supported behavior. Historical roadmap and audit records remain unchanged. 5. Run the complete validation matrix below. Use a fresh temporary directory for the release-asset build and remove it afterward; do not create a release note, tag, or publication. Record native-platform limitations exactly as in `docs/development.md` rather than treating cross-compilation as runtime evidence. 6. Only after every check passes, mark Stages 1–6 in this plan and Workstream 10 in `refactoring.md` **Complete**. Confirm every numbered workstream is then complete. Do not delete the audits, roadmap, or implementation plan and do not prepare or publish a release. ### Verification And Exit Criteria At minimum run: ```sh go mod tidy -diff test -z "$(gofmt -l $(git ls-files '*.go'))" go test -count=1 ./... go test -race -count=1 ./... go test -race -shuffle=on -count=3 ./... go vet ./... go build ./... go test -count=1 ./internal/doccheck go test -count=1 ./internal/config -run '^TestExamplesLoadAndValidate$' git diff --check ``` Also run `scripts/build-release-assets.sh v0.0.0-test ` and delete only that verified temporary directory afterward. The workstream is complete when application collaborators are invocation-scoped, selected large test failures are diagnostic, retained high-risk behavior is credibly covered, canonical documentation describes the implemented reduced contracts, all ten workstreams are complete, and the worktree contains no release artifact. ## Open Questions None. The audits, completed prerequisite workstreams, and fixed decisions above make the remaining quality and documentation work decision-complete.