124 lines
9.3 KiB
Markdown
124 lines
9.3 KiB
Markdown
# Tasks: installer-port
|
|
|
|
## 1. Scaffold — `@suaveplan/installer`
|
|
|
|
- [x] 1.1 Create `packages/platform/installer/` with `package.json` (`@suaveplan/installer@0.0.0`), `tsconfig.json` extending `@suaveplan/typescript-config/library.json`, `vitest.config.ts` via `createTestConfig()`, root `README.md`.
|
|
- [x] 1.2 Workspace deps: `@suaveplan/cli`, `@suaveplan/templates`, `@suaveplan/validation`, `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/events`, `@suaveplan/logger`, `@opentelemetry/api`, `zod`. All `workspace:^` for internal, `catalog:` for external.
|
|
- [x] 1.3 Subpath exports: `.`, `./types`, `./errors`, `./host`, `./fs`, `./manifest`, `./testing`.
|
|
- [x] 1.4 `bin` field: `{ "suaveplan-install": "./dist/bin/suaveplan-install.js" }`.
|
|
|
|
## 2. Types and contract
|
|
|
|
- [x] 2.1 `src/types/installer.types.ts` — `InstallerContext`, `InstallerPlugin<TAnswers, THandle>`, `InstallerFs`, `InstallerCli`, `DetectResult`, `PromptSchema<T>`, `JsonMerge`, `TextEdit`.
|
|
- [x] 2.2 `src/types/file-op.types.ts` — `FileOp` discriminated union (`write` | `patch-json` | `patch-text` | `mkdir` | `delete` | `rename`) with per-variant `conflict?: ConflictPolicy`.
|
|
- [x] 2.3 `src/error-codes.ts` — `defineCodes("INSTALLER", [...])` with codes from proposal §5. Sibling `InstallerError` extends `SuaveplanError<InstallerErrorCode>`.
|
|
- [x] 2.4 `src/schemas/` — Zod boundary schemas for `PluginManifest`, `FileOp`, CLI flags. Marker `// schema: boundary-only`.
|
|
|
|
## 3. Virtual filesystem (`./fs`)
|
|
|
|
- [x] 3.1 `src/fs/installer-fs.ts` — `InstallerFs` interface (`exists`, `readFile`, `readJson`, `stat`, `listDir`, `pathOf`).
|
|
- [x] 3.2 `src/fs/disk-fs.ts` — concrete disk-backed implementation with abort propagation.
|
|
- [x] 3.3 `src/fs/memory-fs.ts` — in-memory implementation (used by `./testing`).
|
|
|
|
## 4. Host pipeline (`./host`)
|
|
|
|
- [x] 4.1 `src/host/host.ts` — `Host` class orchestrating `detect → prompts → plan → apply → postInstall`. Each stage wrapped in OTel span `installer.<stage>` with `plugin.id`, `plugin.version`, `dry_run` attributes.
|
|
- [x] 4.2 `src/host/detect.ts` — runs `plugin.detect?`, normalises result, emits `installer.detect` event.
|
|
- [x] 4.3 `src/host/prompts.ts` — Zod-validates answers; `--answers <file>` bypass; `--no-interactive` rejects ambiguous prompts. Failure → `INSTALLER.PROMPT_VALIDATION_FAILED`.
|
|
- [x] 4.4 `src/host/plan.ts` — invokes `plugin.plan(answers, ctx)`, validates returned `FileOp[]` against schema, returns plan record.
|
|
- [x] 4.5 `src/host/apply/apply.ts` — staged-tmp + atomic rename per file, transaction journal, rollback on failure. `--dry-run` prints plan and exits before this stage.
|
|
- [x] 4.6 `src/host/apply/conflict.ts` — resolves `error | overwrite | skip-if-exists | merge | prompt` per `FileOp`. `--force` collapses to `overwrite`.
|
|
- [x] 4.7 `src/host/apply/json-merge.ts` — implements `JsonMerge` (deep-merge with array-replace semantics matching `@suaveplan/config`).
|
|
- [x] 4.8 `src/host/apply/text-patch.ts` — applies `TextEdit[]` (anchor + insert/replace/delete), preserves trailing-newline policy.
|
|
- [x] 4.9 `src/host/post-install.ts` — runs `plugin.postInstall?(handle, ctx)` with abort propagation.
|
|
|
|
## 5. Plugin manifest (`./manifest`)
|
|
|
|
- [x] 5.1 `src/manifest/manifest.ts` — `PluginManifestSchema` (Zod), `loadManifest(packagePath)`, `validateManifest(raw)`. Failure → `INSTALLER.PLUGIN_INVALID_MANIFEST`.
|
|
- [x] 5.2 `src/manifest/discover.ts` — resolves `@suaveplan/install-*` and `@<scope>/suaveplan-install-*` from consumer `node_modules`. `INSTALLER.PLUGIN_NOT_FOUND` when missing.
|
|
|
|
## 6. CLI bin
|
|
|
|
- [x] 6.1 `src/bin/suaveplan-install.ts` — `cli("suaveplan-install", "0.1.0")` wiring `add <plugin>`, `list`, `--dry-run`, `--force`, `--no-interactive`, `--only`, `--exclude`, `--answers <file>`.
|
|
- [x] 6.2 `add <plugin>` command — discovers + loads plugin, builds `InstallerContext`, runs `Host`.
|
|
- [x] 6.3 `list` command — enumerates installed plugins from manifest discovery.
|
|
|
|
## 7. Testing harness (`./testing`)
|
|
|
|
- [x] 7.1 `src/testing/run-plugin.ts` — `runPlugin(plugin, { answers, fs?, cli? })` returns `{ ops, applied, fs }` for assertion. Zero real disk I/O.
|
|
- [x] 7.2 `src/testing/script-cli.ts` — non-TTY `InstallerCli` that returns scripted answers and records prompts asked.
|
|
- [x] 7.3 `src/testing/installer-fs.test-helpers.ts` — `createMemoryFs(seed?)`, `assertWrote(fs, path, predicate)`.
|
|
|
|
## 8. Spec — `@suaveplan/installer`
|
|
|
|
- [x] 8.1 `openspec/changes/installer-port/specs/installer/spec.md` with `INSTALLER-01`…`INSTALLER-09`, each carrying `**Verified by:**`.
|
|
|
|
## 9. Conformance tests — `@suaveplan/installer`
|
|
|
|
- [x] 9.1 `src/host/host.spec-conformance.test.ts` — `INSTALLER-01` (lifecycle order), `INSTALLER-02` (idempotent re-run), `INSTALLER-03` (abort propagation).
|
|
- [x] 9.2 `src/host/apply/apply.spec-conformance.test.ts` — `INSTALLER-04` (transactional apply + rollback), `INSTALLER-05` (conflict policy).
|
|
- [x] 9.3 `src/host/prompts.spec-conformance.test.ts` — `INSTALLER-06` (Zod validation, non-interactive bypass).
|
|
- [x] 9.4 `src/manifest/manifest.spec-conformance.test.ts` — `INSTALLER-07` (manifest schema), `INSTALLER-08` (plugin discovery).
|
|
- [x] 9.5 `src/error-codes.spec-conformance.test.ts` — `INSTALLER-09` (frozen registry, namespaced codes).
|
|
|
|
## 10. Scaffold — `@suaveplan/install-agent-skills`
|
|
|
|
- [x] 10.1 Create `packages/platform/install-agent-skills/` with `package.json` (`@suaveplan/install-agent-skills@0.0.0`), `tsconfig.json`, `vitest.config.ts`, `README.md`.
|
|
- [x] 10.2 Workspace deps: `@suaveplan/installer`, `@suaveplan/error`, `@suaveplan/types`, `zod`. All `workspace:^`.
|
|
- [x] 10.3 Subpath exports: `.`, `./manifest`.
|
|
|
|
## 11. Skills bundle assembly
|
|
|
|
- [x] 11.1 `scripts/build-skills-bundle.ts` — copies every `SKILL.md` + asset directory into `packages/platform/install-agent-skills/assets/skills/<name>/`.
|
|
- [x] 11.2 `assets/skills/manifest.json` — generated `{ skills: [{ id, version, dir, files }] }`. Zod-validated at build time.
|
|
- [x] 11.3 Pre-publish hook: `bun run build:bundle` runs the assembler before `bunx turbo build`.
|
|
|
|
## 12. Plugin implementation
|
|
|
|
- [x] 12.1 `src/plugin.ts` — exports default `agentSkillsPlugin: InstallerPlugin<AgentSkillsAnswers, AgentSkillsHandle>`.
|
|
- [x] 12.2 `src/detect/detect.ts` — checks for `<targetDir>/skills/` and reports already-present skills.
|
|
- [x] 12.3 `src/prompts/prompts.ts` — Zod schema: `targetDir` (default `.suaveplan/skills`), `only?: string[]`, `exclude?: string[]`, `overwrite?: boolean`.
|
|
- [x] 12.4 `src/plan/plan.ts` — reads bundled manifest, applies `--only` / `--exclude` filter, emits `mkdir` + `write` ops + `patch-json` for skill index.
|
|
- [x] 12.5 `src/apply/apply.ts` — thin pass-through; transaction lives in the host.
|
|
- [x] 12.6 `src/post-install/post-install.ts` — prints `installed N skills to <dir>` plus next-steps.
|
|
- [x] 12.7 `src/manifest-loader.ts` — runtime loader for the bundled `assets/skills/manifest.json`. Failure → `INSTALL_SKILLS.MANIFEST_INVALID`.
|
|
- [x] 12.8 `src/error-codes.ts` — `defineCodes("INSTALL_SKILLS", [...])`.
|
|
|
|
## 13. Spec — `@suaveplan/install-agent-skills`
|
|
|
|
- [x] 13.1 `openspec/changes/installer-port/specs/install-agent-skills/spec.md` with `INSTALL_SKILLS-01`…`INSTALL_SKILLS-05`, each with `**Verified by:**`.
|
|
|
|
## 14. Conformance tests — `@suaveplan/install-agent-skills`
|
|
|
|
- [x] 14.1 `src/plan/plan.spec-conformance.test.ts` — `INSTALL_SKILLS-01` (default = all skills), `INSTALL_SKILLS-02` (`--only` / `--exclude` filter), `INSTALL_SKILLS-03` (skill-index patch shape).
|
|
- [x] 14.2 `src/manifest-loader.spec-conformance.test.ts` — `INSTALL_SKILLS-04` (manifest validation).
|
|
- [x] 14.3 `src/plugin.e2e.spec-conformance.test.ts` — `INSTALL_SKILLS-05` (end-to-end via `runPlugin` against memory fs writes full skill set, zero conflicts on fresh target).
|
|
|
|
## 15. Docs (sibling `.md` per implementation `.ts`)
|
|
|
|
- [x] 15.1 `@suaveplan/installer` — `.md` for every non-test/non-types/non-barrel `.ts` per `openspec/AGENTS.md` §4. Basic + Advanced examples mandatory.
|
|
- [x] 15.2 `@suaveplan/install-agent-skills` — same.
|
|
- [x] 15.3 Root `README.md` for both packages with quickstart.
|
|
|
|
## 16. Quality gates
|
|
|
|
- [x] 16.1 `bunx turbo lint typecheck test --filter=@suaveplan/installer` green.
|
|
- [x] 16.2 `bunx turbo lint typecheck test --filter=@suaveplan/install-agent-skills` green.
|
|
- [x] 16.3 `bunx turbo test:coverage --filter=@suaveplan/installer` 100 % istanbul on touched modules.
|
|
- [x] 16.4 `bunx turbo test:coverage --filter=@suaveplan/install-agent-skills` 100 % istanbul on touched modules.
|
|
- [x] 16.5 No banned patterns in `packages/platform/installer/src/` or `packages/platform/install-agent-skills/src/` per `openspec/AGENTS.md` §2.
|
|
- [x] 16.6 No `biome-ignore` in either `src/` per `openspec/AGENTS.md` §2a.
|
|
- [x] 16.7 File-size check: every `src/*.ts` ≤ 300 lines, every `*.test.ts` ≤ 500 lines.
|
|
- [x] 16.8 Sibling `.md` audit per `openspec/AGENTS.md` §4 returns zero gaps.
|
|
|
|
## 17. Manifest + listing refresh
|
|
|
|
- [x] 17.1 Add `installer` and `install-agent-skills` entries to `CLAUDE.md` under `## Packages`.
|
|
- [x] 17.2 `bun scripts/folder-reorg/generate-manifest.ts` to refresh `MANIFEST.md`.
|
|
|
|
## 18. Archive
|
|
|
|
- [x] 18.1 Fold `specs/installer/spec.md` delta into `openspec/specs/installer/spec.md`.
|
|
- [x] 18.2 Fold `specs/install-agent-skills/spec.md` delta into `openspec/specs/install-agent-skills/spec.md`.
|
|
- [x] 18.3 Move `openspec/changes/installer-port/` to `openspec/archive/2026-04-28-installer-port/`.
|