preset-creator ยท diff

git:20260614.4a7852c to git:20260707.b0f4f4c

135 added, 20 removed. Audit B to B.

---
name: preset-creator
description: Create, review, or update Harness Anything presets. Use when designing preset-manifest JSON, preset script entrypoints, reads/writes scopes, preset profiles, process-action presets, or preset tests for Harness Anything. Enforces declaration-first presets and forbids hardcoding preset-specific behavior in CLI core TypeScript.
---
# Preset Creator
## Core Rule
- Keep presets declaration-first. A preset is a manifest plus optional package-local scripts/templates. Do not add `presetId` or action-specific branches to CLI core code.
+ Keep presets declaration-first. A preset is a `preset-manifest/v2` manifest plus optional package-local scripts and template selections. Template bodies are assets owned by a template catalog, not inline manifest strings. Do not add `presetId` or action-specific branches to CLI core code.
The CLI may provide only generic infrastructure:
- Manifest/schema validation.
- Layer resolution: builtin, user, project.
- Generic script execution.
- Declared `reads`/`writes` permission handling.
- Generic result envelope collection.
Preset behavior belongs in the preset package:
- `preset.json`
- `scripts/*`
- - profile/template selections
+ - `profiles[*].templateSelections`
- declared inputs, reads, and writes
## Workflow
1. Define the preset's job in one sentence.
2. Decide whether it is `template-content` or `process-action`.
- 3. Write or update `preset.json` with explicit `entrypoints`.
- 4. For script entrypoints, declare the narrowest possible `reads` and `writes`.
- 5. Put all preset-specific action logic in `scripts/`, not CLI command dispatch.
- 6. If a script needs to return rich command output, write `artifacts/preset-result.json`.
- 7. Add tests in the correct tier and update `tools/test-tier-manifest.mjs` when adding new test files.
+ 3. Write or update `preset.json` as `preset-manifest/v2`.
+ 4. Put template overlays in `profiles[*].templateSelections`; point each selection at `template://<id>@<version>`.
+ 5. Put template body Markdown in the vertical template assets, then reference it from `template-catalog/v2` with `bodyPath`.
+ 6. For script entrypoints, declare the narrowest possible `reads` and `writes`.
+ 7. Put all preset-specific action logic in `scripts/`, not CLI command dispatch.
+ 8. Run `ha preset validate <manifest>` before publishing the preset.
+ 9. Add tests in the correct tier and update `tools/test-tier-manifest.mjs` when adding new test files.
- ## Manifest Pattern
+ ## Manifest v2 Contract
- Use `reads` for input permissions and `writes` for output permissions:
+ Allowed top-level keys are exactly:
+ - `schema`
+ - `id`
+ - `title`
+ - `vertical`
+ - `version`
+ - `kind`
+ - `extends`
+ - `kernelVersionRange`
+ - `capabilityImports`
+ - `entrypoints`
+ - `profiles`
+ - `defaultProfile`
+
+ Use `schema: "preset-manifest/v2"`. `profiles` must contain at least one profile, and `defaultProfile` must match one declared profile id. `extends` is optional; when present, the parent preset must be available to the validation context. A standalone `ha preset validate <manifest>` run validates only that one manifest, so omit `extends` in minimal examples unless you also validate through a resolved preset set.
+
+ ## Minimal Valid Preset
+
+ This example was validated with `ha preset validate preset.json`.
+
```json
{
"schema": "preset-manifest/v2",
- "id": "example-process",
- "title": "Example Process",
+ "id": "example-note",
+ "title": "Example Note",
"vertical": "software/coding",
"version": "1.0.0",
- "kind": "process-action",
+ "kind": "template-content",
"kernelVersionRange": { "min": "1.0.0", "maxExclusive": "2.0.0" },
- "capabilityImports": [],
+ "capabilityImports": [
+ { "id": "example-note-template", "kind": "template", "version": "1", "required": false }
+ ],
"entrypoints": {
- "plan": {
- "type": "script",
- "command": "scripts/preset-action.mjs",
- "reads": ["{{outputRoot}}/**"],
- "writes": ["{{outputRoot}}/**"],
- "inputs": {}
+ "scaffold": {
+ "type": "template",
+ "writes": ["{{outputRoot}}/notes/example.md"],
+ "templates": {
+ "note": "template://example/note@1"
+ }
}
},
- "profiles": [{ "id": "baseline", "title": "Baseline", "checkerProfile": "standard", "templateSelections": [] }],
+ "profiles": [
+ {
+ "id": "baseline",
+ "title": "Baseline",
+ "checkerProfile": "standard",
+ "templateSelections": [
+ {
+ "slot": "example.note",
+ "templateRef": "template://example/note@1",
+ "materializeAs": "notes/example.md",
+ "localePolicy": { "prefer": "project", "fallback": "en-US" }
+ }
+ ]
+ }
+ ],
"defaultProfile": "baseline"
}
```
+ Validate it:
+
+ ```sh
+ ha preset validate preset.json
+ ```
+
+ ## Asset-Based Templates
+
+ Preset manifests select templates; template catalogs own template metadata; Markdown files own template bodies. Do not put inline `body` content in `template-catalog/v2`; v2 catalogs use `bodyPath` only.
+
+ Preferred package layout:
+
+ ```text
+ assets/software-coding/
+ template-catalog.json
+ templates/
+ example.note/
+ en-US.md
+ zh-CN.md
+ presets/
+ example-note/
+ preset.json
+ ```
+
+ Catalog entry:
+
+ ```json
+ {
+ "id": "example/note",
+ "version": "1",
+ "documentKind": "example-note",
+ "slot": "example.note",
+ "materializeAs": "notes/example.md",
+ "frontmatterSchema": "task-package/v2",
+ "requiredAnchors": ["## Summary"],
+ "fallbackLocale": "en-US",
+ "locales": [
+ {
+ "locale": "en-US",
+ "anchors": ["## Summary"],
+ "bodyPath": "templates/example.note/en-US.md"
+ },
+ {
+ "locale": "zh-CN",
+ "anchors": ["## Summary"],
+ "bodyPath": "templates/example.note/zh-CN.md"
+ }
+ ]
+ }
+ ```
+
+ `templates/example.note/en-US.md` must contain every required anchor:
+
+ ```md
+ ## Summary
+
+ Write the note here.
+ ```
+
## Script Pattern
+ Process-action presets use script entrypoints. Use `reads` for input permissions and `writes` for output permissions:
+
+ ```json
+ {
+ "type": "script",
+ "command": "scripts/preset-action.mjs",
+ "reads": ["{{outputRoot}}/**"],
+ "writes": ["{{outputRoot}}/**"],
+ "inputs": {}
+ }
+ ```
+
Scripts should read `process.env.HARNESS_PRESET_CONTEXT`, use only declared paths, and write outputs under `context.outputRoot`.
If the CLI should surface a domain result, write:
```json
{
"ok": true,
"rows": 1,
"report": { "schema": "example-report/v1" }
}
```
to `artifacts/preset-result.json`.
## Review Checklist
+ - `preset.json` uses `schema: "preset-manifest/v2"`.
+ - Top-level manifest keys match the v2 allowed key list.
+ - `profiles` and `defaultProfile` are declared and consistent.
+ - Any `extends` parent is available to the validation path used.
+ - Template bodies live in `.md` assets referenced by `template-catalog/v2` `bodyPath`.
+ - No catalog or manifest example teaches inline `body`.
+ - `ha preset validate <manifest>` passes for the manifest being published.
- No CLI core branch checks `presetId`, preset title, or action name for behavior.
- No preset script requires permissions not declared in `preset.json`.
- `writes` never grants repo-root write access.
- Any repo-wide read is deliberate and justified by the preset's job.
- Process-action presets are not left as capability-smoke placeholders.
- Tests prove unauthorized script runs fail and authorized runs produce expected artifacts.