# Tasks: complete-installer ## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Error codes - [ ] 1.1 Extend `src/error-codes.ts` `defineCodes("INSTALLER", [...])` tuple with every code listed in `design.md` §"Error codes" (existing nine, seven upgrade codes from the superseded change, eighteen new codes). - [ ] 1.2 Update `src/error-codes.md` to enumerate every code with one-line semantic description. - [ ] 1.3 Rewrite `src/error-codes.spec-conformance.test.ts` to assert every code value is present, frozen, and `INSTALLER.`-prefixed (`MODIFIED: registry contains every complete-installer code`). ## 2. State + lockfile + journal (`src/state/`) - [ ] 2.1 `src/state/state.types.ts` — `InstallerState`, `InstalledPlugin`, `FileHash`, named option / report types. - [ ] 2.2 `src/state/state.schemas.ts` — Zod schemas validating the on-disk shape. - [ ] 2.3 `src/state/state-file.ts` — `loadState`, `writeState` (atomic write → fsync → rename), `updatePlugin`, `removePlugin`. Throws `INSTALLER.STATE_INVALID` on schema failure. - [ ] 2.4 `src/state/state-file.spec-conformance.test.ts` covering atomic write and load-validation paths. - [ ] 2.5 `src/state/hash-tree.ts` — `hashTree(fs, dir)` via BLAKE3 (`@suaveplan/crypto-hash`). - [ ] 2.6 `src/state/journal.ts` — append-only newline-JSON journal with `beginTxn`, `stage`, `commit`, `abort`, `replay`. Throws `INSTALLER.JOURNAL_REPLAY_FAILED` on malformed lines. - [ ] 2.7 `src/state/journal.spec-conformance.test.ts`. - [ ] 2.8 `src/state/lockfile.ts` — `loadLockfile`, `writeLockfile` (deterministic sorted keys, integrity digest). Throws `INSTALLER.LOCKFILE_INVALID` / `INSTALLER.LOCKFILE_WRITE_FAILED`. - [ ] 2.9 `src/state/lockfile.spec-conformance.test.ts` (byte-identical round-trip). - [ ] 2.10 Sibling `.md` for every new file. ## 3. Registry sources (`src/registry/`) - [ ] 3.1 `src/registry/registry.types.ts` — `RegistrySource` interface, `ResolvedPlugin`, `SearchHit`, `SearchOptions`. - [ ] 3.2 `src/registry/registry.schemas.ts` — Zod boundary schemas. - [ ] 3.3 `src/registry/verdaccio/verdaccio.ts` — default source, reuses `discoverPlugins`; adds `search` + version listing over HTTP. - [ ] 3.4 `src/registry/oci/oci.ts` — OCI tarball pull, `OCI_TOKEN`. - [ ] 3.5 `src/registry/git/git.ts` — `git clone --depth 1`. - [ ] 3.6 `src/registry/local-tarball/local-tarball.ts` — tar-extract. - [ ] 3.7 `src/registry/index.ts` — explicit named re-exports. - [ ] 3.8 `*.spec-conformance.test.ts` per source (4 files). - [ ] 3.9 `src/testing/fixtures/registry/verdaccio-container.ts` — testcontainers Verdaccio fixture + fixture plugin catalogue. - [ ] 3.10 Sibling `.md` for every new file. ## 4. Plugin host extensions (`src/host/hooks/`, `src/host/upgrade/`) - [ ] 4.1 `src/host/hooks/hooks.ts` — invoke `preInstall`/`postInstall`/ `preUpgrade`/`postUpgrade`/`preUninstall`/`postUninstall` with OTel spans + rollback-on-throw. - [ ] 4.2 `src/host/hooks/hooks.spec-conformance.test.ts`. - [ ] 4.3 Extend `InstallerPlugin` interface in `src/types/installer.types.ts` with `capabilities`, `dependsOn`, and the six new hook fields. - [ ] 4.4 `src/host/upgrade/upgrade.ts` — full pipeline per spec. - [ ] 4.5 `src/host/upgrade/preflight.ts` — lockfile + dirty-tree gates. - [ ] 4.6 `src/host/upgrade/diff.ts` + `materialise` helpers. - [ ] 4.7 `src/host/upgrade/migrations.ts` + `migrations.types.ts` — `MigrationContext`, `MigrationTable`, `loadMigrationTable`, `selectMigrations` (BFS), `runMigrations` (transactional). - [ ] 4.8 Upgrade `*.spec-conformance.test.ts` files (`upgrade`, `preflight`, `dirty-tree`, `apply-diff`, `migrations`). - [ ] 4.9 Sibling `.md` for every new file. ## 5. Installer class + commands (`src/installer/`) - [ ] 5.1 `src/installer/installer.ts` — `Installer` class wrapping `Host`, exposing every documented method. ≤300 lines: factor each command into its own file. - [ ] 5.2 `src/installer/install.ts` — `install` orchestrator: resolve registry → discover plugin → resolve deps → host run → write state → write lockfile. - [ ] 5.3 `src/installer/reinstall.ts` — force-reapply at recorded version. Throws `REINSTALL_NOT_INSTALLED`. - [ ] 5.4 `src/installer/uninstall.ts` — gate dirty-tree, run hooks, delete recorded files transactionally, drop state + lockfile entry. Throws `UNINSTALL_NOT_INSTALLED`, `UNINSTALL_DIRTY_TREE`. - [ ] 5.5 `src/installer/list.ts` — enumerate with drift status. - [ ] 5.6 `src/installer/info.ts` — manifest + state + transitive dependency graph. Throws `INFO_NOT_INSTALLED`. - [ ] 5.7 `src/installer/pin.ts` — set `pinned: true, resolved`. - [ ] 5.8 `src/installer/unpin.ts` — clear `pinned` flag. - [ ] 5.9 `src/installer/freeze.ts` — deterministic lockfile snapshot. - [ ] 5.10 `src/installer/update.ts` — `--all` bulk upgrade with partial-failure aggregation. Throws `UPDATE_PARTIAL_FAILURE`. - [ ] 5.11 `src/installer/search.ts` — delegate to active registry. Throws `REGISTRY_UNREACHABLE`. - [ ] 5.12 `src/installer/doctor.ts` — every diagnostic check in parallel; `--fix` for journal rollback only. - [ ] 5.13 `src/installer/dependency-graph.ts` — Tarjan cycle detect + topological sort. Throws `DEPENDENCY_CYCLE`, `DEPENDENCY_UNSATISFIED`. - [ ] 5.14 Conformance tests: - [ ] 5.14.1 `src/installer/installer.spec-conformance.test.ts` (install, reinstall, uninstall, list, info, pin/unpin, freeze, update, search, dependency-cycle, OTel span, event-bus). - [ ] 5.14.2 `src/installer/doctor.spec-conformance.test.ts`. - [ ] 5.15 OTel span instrumentation on every public method: `installer.` with documented attributes + error recording. - [ ] 5.16 Typed event-bus emission on every state-mutating method. - [ ] 5.17 `src/installer/index.ts` — explicit named re-exports. - [ ] 5.18 Sibling `.md` for every new file. ## 6. CLI bin (`src/bin/`) - [ ] 6.1 Extend `src/bin/suaveplan-install.ts` to register every verb: `install`, `reinstall`, `upgrade`, `uninstall`, `list`, `info`, `doctor`, `pin`, `unpin`, `freeze`, `update`, `search`. Keep `add` as an alias of `install`. - [ ] 6.2 Parse every documented global flag (`--dry-run`, `--force`, `--no-interactive`, `--answers `, `--cwd `, `--registry `, `--json`) and verb-specific flags from design.md. - [ ] 6.3 `--json` output path: emit the report object verbatim. - [ ] 6.4 `src/bin/suaveplan-install.spec-conformance.test.ts` asserting every verb forwards every flag (recording `Installer` stub). - [ ] 6.5 Update `src/bin/suaveplan-install.md`. ## 7. Type / schema additions (`src/types/`, `src/schemas/`) - [ ] 7.1 Extend `src/types/installer.types.ts` with `InstallerOptions`, `InstallReport`, `UpgradeReport`, `UninstallReport`, `InstalledPluginInfo`, `PluginInfoReport`, `DoctorReport`, `DoctorFinding`, `LockfileReport`, `UpdateReport`, `SearchHit`, `SearchOptions`, lifecycle hook signatures, dependency types. - [ ] 7.2 Extend `src/schemas/` with Zod validators for every new report / option type. - [ ] 7.3 No inline shapes anywhere (AGENTS.md §11). ## 8. Subpath exports + barrels - [ ] 8.1 `package.json` `exports` map gains one subpath per new feature module: `./installer/installer`, `./installer/install`, `./installer/reinstall`, `./installer/uninstall`, `./installer/list`, `./installer/info`, `./installer/pin`, `./installer/unpin`, `./installer/freeze`, `./installer/update`, `./installer/search`, `./installer/doctor`, `./installer/dependency-graph`, `./state/state-file`, `./state/journal`, `./state/lockfile`, `./state/hash-tree`, `./registry`, `./registry/verdaccio`, `./registry/oci`, `./registry/git`, `./registry/local-tarball`, `./host/upgrade`, `./host/hooks`, `./migrations`. - [ ] 8.2 Every `/index.ts` uses explicit named re-exports (AGENTS.md §6a — no `export *`). - [ ] 8.3 Package-root `src/index.ts` re-exports the `Installer` class plus every named report type for the top-level surface. ## 9. Testing fixtures (`src/testing/fixtures/`) - [ ] 9.1 `src/testing/fixtures/plugins/base-plugin.ts` — simple plugin no dependencies, exercises the install / uninstall path. - [ ] 9.2 `src/testing/fixtures/plugins/dependent-plugin.ts` — depends on `base-plugin`, exercises topological resolution. - [ ] 9.3 `src/testing/fixtures/plugins/cyclic-a-plugin.ts` + `cyclic-b-plugin.ts` — exercise `DEPENDENCY_CYCLE`. - [ ] 9.4 `src/testing/fixtures/plugins/upgrade-fixture-plugin.ts` — `1.0.0` and `2.0.0` variants with one migration script. - [ ] 9.5 `src/testing/fixtures/plugins/hooks-fixture-plugin.ts` — every lifecycle hook implemented for hook-order tests. ## 10. Docs - [ ] 10.1 Every new implementation `.ts` has a sibling `.md` meeting AGENTS.md §4 (≥200 words, Purpose / Features / Basic / Advanced / API Reference / Implementation Notes, both examples compile). - [ ] 10.2 Update root `packages/tooling/installer/README.md` to enumerate every verb, link to per-module docs in the **Modules** section, and show a quickstart for `install`, `upgrade`, `uninstall`, `doctor`, `search`. - [ ] 10.3 No `TODO`, `FIXME`, `@deprecated`, marketing language, or stub-doc placeholders anywhere (AGENTS.md §2b). ## 11. Dependent sweep + impact - [ ] 11.1 Add empty `upgrade.ts` `MigrationTable` export to `@suaveplan/install-agent-skills` and wire it through the manifest so the migration-loader path runs even with zero migrations. - [ ] 11.2 Add optional `preInstall` and `postUninstall` hooks to `@suaveplan/install-agent-skills` so hooks-fixture path is exercised by a real consumer. - [ ] 11.3 Extend `install-agent-skills` conformance harness with `upgradePlugin`, `uninstallPlugin`, `reinstallPlugin` helpers mirroring `runPlugin`. - [ ] 11.4 `bunx turbo test --filter=...@suaveplan/installer` green. ## 12. Pre-archive gates (AGENTS.md §13) - [ ] 12.1 `bunx turbo lint typecheck test --filter=@suaveplan/installer` green. - [ ] 12.2 `bunx turbo test:coverage --filter=@suaveplan/installer` 100% istanbul on every new module. - [ ] 12.3 `bun run check` (biome) green. - [ ] 12.4 Banned-pattern scan (`@deprecated|TODO|FIXME|ts-ignore| ts-expect-error|.skip|.only`) zero output in new files. - [ ] 12.5 Test-runner-import scan (`from "vitest"` / `from "bun:test"`) zero output in new files (AGENTS.md §7). - [ ] 12.6 Barrel-shape scan (no `export *` in feature `index.ts` files) zero output (AGENTS.md §6a). - [ ] 12.7 Missing `.md` scan zero output. - [ ] 12.8 Subpath export count matches feature-module count. - [ ] 12.9 Bare-version scan zero output (`catalog:` / `workspace:^`). - [ ] 12.10 File-size scan: every `*.ts` ≤ 300 lines, every `*.test.ts` ≤ 500 lines. - [ ] 12.11 `bunx turbo build --filter=@suaveplan/installer` green. ## 13. Root-doc refresh + markdownlint (AGENTS.md §13b) - [ ] 13.1 `bun scripts/folder-reorg/generate-manifest.ts` to refresh `MANIFEST.md`. - [ ] 13.2 `bun scripts/generate-missing.ts` to refresh `MISSING.yml`. - [ ] 13.3 Update `STATUS.md` installer row (already Completed; refresh surface description). - [ ] 13.4 Update `SUMMARY.md` installer paragraph to enumerate every verb + library surface. - [ ] 13.5 `bunx markdownlint-cli2 --fix` against touched markdown, resolve any unfixable violations by hand. ## 14. Archive (AGENTS.md §14) - [ ] 14.1 Fold `specs/installer/spec.md` delta into `openspec/specs/installer/spec.md` (modified `INSTALLER-09` replaces the existing one verbatim; every ADDED requirement appends). - [ ] 14.2 Delete the superseded folder `openspec/changes/_superseded-narrow-deferrals-2026-05-17/add-installer-upgrade/` since its content is now subsumed. - [ ] 14.3 Move `openspec/changes/complete-installer/` → `openspec/archive/-complete-installer/`. - [ ] 14.4 `openspec validate complete-installer --strict` green prior to archive.