Initial Commit
This commit is contained in:
245
openspec/changes/complete-installer/tasks.md
Normal file
245
openspec/changes/complete-installer/tasks.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user