Files
suaveplan/openspec/specs/install-agent-skills/spec.md
2026-05-27 23:29:53 +01:00

3.2 KiB

Install-Agent-Skills — Spec

Requirements

INSTALL_SKILLS-01 — Default plan installs every bundled skill

When no --only or --exclude filter is supplied, agentSkillsPlugin.plan(answers, ctx) MUST emit FileOp[] covering every entry in the bundled assets/skills/manifest.json. The plan MUST contain exactly one mkdir op per skill directory, one write op per file enumerated under that skill's files array, and exactly one patch-json op targeting the project skill index (creating it when absent). The default targetDir MUST be .suaveplan/skills relative to ctx.cwd.

Verified by: src/plan/plan.spec-conformance.test.ts (INSTALL_SKILLS-01).

INSTALL_SKILLS-02 — --only and --exclude filters

When answers.only is a non-empty array, the plan MUST contain ops only for skills whose id appears in only. When answers.exclude is a non-empty array, the plan MUST omit ops for skills whose id appears in exclude. When both are supplied, only is applied first and exclude second. An only or exclude entry not present in the bundled manifest MUST surface as InstallSkillsError(INSTALL_SKILLS.UNKNOWN_SKILL) carrying the unknown id.

Verified by: src/plan/plan.spec-conformance.test.ts (INSTALL_SKILLS-02).

INSTALL_SKILLS-03 — Skill-index patch shape

The patch-json op targeting the project skill index MUST use JsonMerge to upsert an entry of shape { id: string, version: string, dir: string, source: "@suaveplan/install-agent-skills", installedAt: string } for each installed skill, where installedAt is an ISO 8601 UTC timestamp captured at plan time. The merge MUST replace any prior entry with the same id (idempotent re-install). The index file path MUST default to <targetDir>/index.json and MUST be created with conflict policy merge.

Verified by: src/plan/plan.spec-conformance.test.ts (INSTALL_SKILLS-03).

INSTALL_SKILLS-04 — Bundled manifest validation

loadBundledManifest() MUST Zod-validate assets/skills/manifest.json at runtime. Required schema: { skills: Array<{ id: string, version: string (semver), dir: string, files: string[] }> }. Validation failures MUST surface as InstallSkillsError(INSTALL_SKILLS.MANIFEST_INVALID, { cause }). The loader MUST NOT cache across invocations of runPlugin in the testing harness so that test fixtures can swap in alternate manifests.

Verified by: src/manifest-loader.spec-conformance.test.ts (INSTALL_SKILLS-04).

INSTALL_SKILLS-05 — End-to-end install on fresh target

runPlugin(agentSkillsPlugin, { answers: { targetDir: "/x" } }) against an empty MemoryFs MUST result in: every skill directory created under /x, every skill file written with the expected bytes, the skill index file written at /x/index.json with one entry per installed skill, zero conflicts reported, and a postInstall summary recording the installed count. The same harness invocation re-run against the resulting fs MUST be idempotent under default conflict policy merge for the index and skip-if-exists for already-present files (no INSTALLER.APPLY_CONFLICT raised).

Verified by: src/plugin.e2e.spec-conformance.test.ts (INSTALL_SKILLS-05).