Files
suaveplan/openspec/changes/complete-installer/tasks.md
2026-05-27 23:29:53 +01:00

13 KiB

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.<method> 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 <file>, --cwd <dir>, --registry <name>, --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 <feature>/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/<yyyy-mm-dd>-complete-installer/.
  • 14.4 openspec validate complete-installer --strict green prior to archive.