From 5b8c3fd2027538a7f5a46afb92852e7df9e10999 Mon Sep 17 00:00:00 2001 From: stack72 Date: Mon, 13 Apr 2026 20:43:06 +0100 Subject: [PATCH] feat: add swamp-extension-publish skill with state-machine checklist (#92) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create a dedicated publishing skill that enforces prerequisites as gates before allowing an extension push. The state machine walks through repo initialization, authentication, manifest validation, collective ownership, version bumping, formatting, and dry-run — each step must pass before the next begins. The final push requires explicit user approval. Moves publishing.md from swamp-extension-model to the new skill and updates all four extension creation skills plus the report skill to cross-reference it. Registers the new skill in BUNDLED_SKILLS so it ships with repo init and repo upgrade. Co-authored-by: Sean Escriva Co-Authored-By: Claude Opus 4.6 (1M context) --- .../skills/swamp-extension-datastore/SKILL.md | 16 +- .../skills/swamp-extension-driver/SKILL.md | 16 +- .claude/skills/swamp-extension-model/SKILL.md | 44 +-- .../evals/trigger_evals.json | 24 +- .../skills/swamp-extension-publish/SKILL.md | 273 ++++++++++++++++++ .../evals/trigger_evals.json | 73 +++++ .../references/publishing.md | 24 +- .claude/skills/swamp-extension-vault/SKILL.md | 16 +- .claude/skills/swamp-report/SKILL.md | 5 +- src/infrastructure/assets/skill_assets.ts | 8 +- 10 files changed, 410 insertions(+), 89 deletions(-) create mode 100644 .claude/skills/swamp-extension-publish/SKILL.md create mode 100644 .claude/skills/swamp-extension-publish/evals/trigger_evals.json rename .claude/skills/{swamp-extension-model => swamp-extension-publish}/references/publishing.md (93%) diff --git a/.claude/skills/swamp-extension-datastore/SKILL.md b/.claude/skills/swamp-extension-datastore/SKILL.md index 4e495cf5..9e7a5468 100644 --- a/.claude/skills/swamp-extension-datastore/SKILL.md +++ b/.claude/skills/swamp-extension-datastore/SKILL.md @@ -202,18 +202,10 @@ Present findings to the user before proceeding. ## Publishing -Publishing is the same for all extension types. Before pushing: - -1. **Get next version**: - `swamp extension version --manifest manifest.yaml --json` -2. **Bump version** in `manifest.yaml` — use the `nextVersion` from above -3. **Format & lint**: `swamp extension fmt manifest.yaml` -4. **Dry-run**: `swamp extension push manifest.yaml --dry-run --json` -5. **Push**: `swamp extension push manifest.yaml --yes --json` - -For the full manifest schema, CalVer versioning, safety rules, and -troubleshooting, see the -[publishing guide](../swamp-extension-model/references/publishing.md). +Use the `swamp-extension-publish` skill to publish extensions to the registry. +It provides a state-machine checklist that enforces all prerequisites +(repository initialization, authentication, manifest validation, collective +verification) before allowing a push. ## When to Use Other Skills diff --git a/.claude/skills/swamp-extension-driver/SKILL.md b/.claude/skills/swamp-extension-driver/SKILL.md index 2ca319f2..b11ffb96 100644 --- a/.claude/skills/swamp-extension-driver/SKILL.md +++ b/.claude/skills/swamp-extension-driver/SKILL.md @@ -233,18 +233,10 @@ findings to the user before proceeding. ## Publishing -Publishing is the same for all extension types. Before pushing: - -1. **Get next version**: - `swamp extension version --manifest manifest.yaml --json` -2. **Bump version** in `manifest.yaml` — use the `nextVersion` from above -3. **Format & lint**: `swamp extension fmt manifest.yaml` -4. **Dry-run**: `swamp extension push manifest.yaml --dry-run --json` -5. **Push**: `swamp extension push manifest.yaml --yes --json` - -For the full manifest schema, CalVer versioning, safety rules, and -troubleshooting, see the -[publishing guide](../swamp-extension-model/references/publishing.md). +Use the `swamp-extension-publish` skill to publish extensions to the registry. +It provides a state-machine checklist that enforces all prerequisites +(repository initialization, authentication, manifest validation, collective +verification) before allowing a push. ## References diff --git a/.claude/skills/swamp-extension-model/SKILL.md b/.claude/skills/swamp-extension-model/SKILL.md index ba2acdb4..848a56a8 100644 --- a/.claude/skills/swamp-extension-model/SKILL.md +++ b/.claude/skills/swamp-extension-model/SKILL.md @@ -138,7 +138,7 @@ export const model = { Use `swamp extension version @myorg/my-model --json` to get the correct next version. See -[references/publishing.md](references/publishing.md#determining-the-next-version) +[publishing reference](../swamp-extension-publish/references/publishing.md#determining-the-next-version) for details. ## Version Upgrades @@ -445,37 +445,10 @@ before proceeding to testing. ## Publishing Extensions -Extensions are published to the swamp registry via a `manifest.yaml` and the -`swamp extension push` command. Extensions can contain models, workflows, -vaults, drivers, datastores, and reports. - -**Minimal manifest:** - -```yaml -manifestVersion: 1 -name: "@myorg/my-model" -version: "2026.02.26.1" -models: - - my_model.ts -``` - -**Push commands:** - -```bash -swamp extension push manifest.yaml --json # Push to registry -swamp extension push manifest.yaml --dry-run --json # Validate without pushing -swamp extension push manifest.yaml -y --json # Skip confirmation prompts -``` - -The manifest `name` collective must match your authenticated username. Content -paths are relative to their respective directories (`extensions/models/`, -`extensions/vaults/`, `extensions/drivers/`, `extensions/datastores/`). Local -imports are auto-resolved. **All manifest paths must be relative and -downward-only — paths containing `..` components or starting with `/` are -rejected during push to prevent broken archives.** - -For the full manifest schema, safety rules, CalVer versioning, and -troubleshooting, see [references/publishing.md](references/publishing.md). +Use the `swamp-extension-publish` skill to publish extensions to the registry. +It provides a state-machine checklist that enforces all prerequisites +(repository initialization, authentication, manifest validation, collective +verification) before allowing a push. ## Key Rules @@ -489,7 +462,8 @@ troubleshooting, see [references/publishing.md](references/publishing.md). 7. **Version upgrades**: When bumping `version`, always add an `upgrades` entry For import styles, helper scripts, collective naming rules, and version details, -see [references/publishing.md](references/publishing.md). +see the +[publishing reference](../swamp-extension-publish/references/publishing.md). ## Verify @@ -523,8 +497,8 @@ swamp model type describe @myorg/my-model --json # Check schema complete model examples (CRUD lifecycle, data chaining, extensions, etc.) - **Scenarios**: See [references/scenarios.md](references/scenarios.md) for end-to-end scenarios (custom API, cloud CRUD, factory models) -- **Publishing**: See [references/publishing.md](references/publishing.md) for - manifest schema, push workflow, safety rules, and CalVer versioning +- **Publishing**: Use the `swamp-extension-publish` skill for the full + publishing workflow, manifest schema, safety rules, and CalVer versioning - **Smoke Testing**: See [references/smoke_testing.md](references/smoke_testing.md) for the pre-push smoke-test protocol, CRUD lifecycle testing, and common failure patterns diff --git a/.claude/skills/swamp-extension-model/evals/trigger_evals.json b/.claude/skills/swamp-extension-model/evals/trigger_evals.json index 847da31d..43ded5f3 100644 --- a/.claude/skills/swamp-extension-model/evals/trigger_evals.json +++ b/.claude/skills/swamp-extension-model/evals/trigger_evals.json @@ -93,36 +93,36 @@ { "query": "Make a manifest.yaml so I can push my extension", "should_trigger": true, - "note": "manifest.yaml and push extension are triggers" + "note": "manifest creation is shared between this skill and swamp-extension-publish" }, { "query": "Publish my model to the registry", - "should_trigger": true, - "note": "publish extension and publish to registry are triggers" + "should_trigger": false, + "note": "Publishing → swamp-extension-publish" }, { "query": "Help me push this extension to swamp-club", - "should_trigger": true, - "note": "push extension is a trigger" + "should_trigger": false, + "note": "Pushing extensions → swamp-extension-publish" }, { "query": "I need to write a manifest for my model", "should_trigger": true, - "note": "write manifest and manifest are triggers" + "note": "manifest creation is part of model authoring" }, { "query": "Prepare my extension for publishing", - "should_trigger": true, - "note": "prepare for publishing is a trigger" + "should_trigger": false, + "note": "Publishing workflow → swamp-extension-publish" }, { "query": "How do I swamp extension push my model?", - "should_trigger": true, - "note": "extension push is a trigger" + "should_trigger": false, + "note": "Extension push → swamp-extension-publish" }, { "query": "I want to release a new version of my extension", - "should_trigger": true, - "note": "release extension and bump version are triggers" + "should_trigger": false, + "note": "Releasing extensions → swamp-extension-publish" } ] diff --git a/.claude/skills/swamp-extension-publish/SKILL.md b/.claude/skills/swamp-extension-publish/SKILL.md new file mode 100644 index 00000000..f581a21a --- /dev/null +++ b/.claude/skills/swamp-extension-publish/SKILL.md @@ -0,0 +1,273 @@ +--- +name: swamp-extension-publish +description: Publish swamp extensions to the registry with an enforced state-machine checklist that verifies repo initialization, authentication, manifest validation, collective ownership, version bumping, formatting, and dry-run before allowing a push. Use when publishing, pushing, or releasing extensions. Triggers on "publish extension", "push extension", "extension push", "publish to registry", "swamp extension push", "release extension", "prepare for publishing", "extension-publish". +--- + +# Swamp Extension Publish + +Publish extensions (models, workflows, vaults, drivers, datastores, reports) to +the swamp registry. This skill is a **state machine** — each state gates the +next. You MUST NOT advance to the next state until the current state's +**Verify** step passes. The final push is blocked until every prior state has +passed. + +## State Machine + +``` +start → repo_verified → auth_verified → manifest_validated + → versioned → formatted → dry_run_passed → pushed +``` + +**Core rule:** If any Verify fails, execute the On Failure action. Never skip a +state. Never reorder states. The user cannot push until all gates have passed. + +## Before Starting + +Present the full checklist to the user so they know what to expect: + +> **Publishing checklist — 8 steps must pass before push:** +> +> 1. **Repository** — verify `.swamp.yaml` exists (swamp repo initialized) +> 2. **Authentication** — verify logged in to swamp registry +> 3. **Manifest** — validate `manifest.yaml` structure and file references +> 4. **Collective** — verify manifest name matches authenticated user +> 5. **Version** — get next CalVer version and bump manifest +> 6. **Formatting** — run `swamp extension fmt` and verify clean +> 7. **Dry run** — validate push without uploading +> 8. **Push** — publish to registry (requires your explicit approval) +> +> Starting now. I'll report progress at each step. + +Then begin with State 1. + +## State 1: repo_verified + +Confirm the extension directory is an initialized swamp repository. + +**Gate:** The user has a directory containing extension code and a +`manifest.yaml`. + +**Action:** + +```bash +ls .swamp.yaml +``` + +**Verify:** The file exists and is valid YAML. If you are in a subdirectory, +check parent directories up to the filesystem root. + +**On Failure:** The directory is not a swamp repository. Run: + +```bash +swamp repo init --json +``` + +Then re-verify. If `swamp repo init` fails, check that swamp is installed and up +to date (`swamp update`). + +## State 2: auth_verified + +Confirm the user is authenticated with the swamp registry. + +**Gate:** State 1 passed (`.swamp.yaml` exists). + +**Action:** + +```bash +swamp auth whoami --json +``` + +**Verify:** The output contains a `username` field and `authenticated: true`. + +**On Failure:** The user is not logged in. Run: + +```bash +swamp auth login +``` + +Then re-verify. If login fails, check network connectivity and credentials. + +## State 3: manifest_validated + +Confirm `manifest.yaml` exists and is structurally valid. + +**Gate:** State 2 passed (authenticated). + +**Action:** Read `manifest.yaml` and validate: + +1. `manifestVersion: 1` is present +2. `name` is present and matches `@collective/name` format +3. At least one content array (`models`, `workflows`, `vaults`, `drivers`, + `datastores`, or `reports`) has entries +4. All referenced files exist at their expected paths (models in + `extensions/models/`, workflows in `workflows/`, etc.) + +**Verify:** All 4 checks pass. + +**On Failure:** Report which checks failed. Common fixes: + +- Missing `manifestVersion` → add `manifestVersion: 1` +- Invalid name → use `@collective/extension-name` format +- No content arrays → add at least one of `models`, `workflows`, etc. +- Missing files → create the files or fix the paths + +See [references/publishing.md](references/publishing.md) for the full manifest +schema and field reference. + +## State 4: collective_verified + +Confirm the manifest collective matches the authenticated user. + +**Gate:** State 3 passed (manifest is valid). + +**Action:** Extract the collective from the manifest `name` field (the part +between `@` and `/`). Compare it against the `username` from +`swamp auth whoami --json`. + +**Verify:** The collective matches the authenticated username, or the user has +confirmed they have permission to publish under this collective. + +**On Failure:** Collective mismatch. Report: + +> Manifest collective `@` does not match your authenticated username +> ``. Either: +> +> 1. Update the manifest `name` to use `@/...` +> 2. Confirm you have publishing rights to `@` + +Do not proceed until the user resolves this. + +## State 5: versioned + +Get the next version and bump the manifest. + +**Gate:** State 4 passed (collective verified). + +**Action:** + +```bash +swamp extension version --manifest manifest.yaml --json +``` + +**Verify:** The command succeeds and returns a `nextVersion` field. Update +`manifest.yaml` with this version. If the model source file also contains a +`version` field, update it to match. + +**On Failure:** + +- If the extension has never been published, `currentPublished` will be `null` — + this is normal. Use `nextVersion` as-is. +- If the command fails, check that the manifest `name` is valid and the registry + is reachable. + +See [references/publishing.md](references/publishing.md#calver-versioning) for +CalVer format details. + +## State 6: formatted + +Format and lint all extension files. + +**Gate:** State 5 passed (version bumped). + +**Action:** + +```bash +swamp extension fmt manifest.yaml --json +``` + +**Verify:** The command exits successfully (exit code 0). Run the check mode to +confirm: + +```bash +swamp extension fmt manifest.yaml --check --json +``` + +**On Failure:** If `--check` reports issues after formatting, there are +unfixable lint errors. Read the error output, fix the issues manually, then +re-run `swamp extension fmt manifest.yaml`. + +See [references/publishing.md](references/publishing.md#extension-formatting) +for details on what fmt checks. + +## State 7: dry_run_passed + +Validate the extension can be pushed without actually uploading. + +**Gate:** State 6 passed (formatting clean). + +**Action:** + +```bash +swamp extension push manifest.yaml --dry-run --json +``` + +**Verify:** The command exits successfully. Review the output for any warnings +(subprocess spawning, long lines, base64 blobs) and confirm with the user if +warnings are present. + +**On Failure:** Read the error output. Common issues: + +- `eval()` or `new Function()` → remove dynamic code execution +- Symlinks → replace with regular files +- File too large → reduce file size below 1 MB +- Too many files → reduce to under 150 files +- Bundle compilation failed → fix TypeScript errors + +See [references/publishing.md](references/publishing.md#safety-rules) for the +full list of safety rules. + +## State 8: pushed + +Publish the extension to the registry. + +**CRITICAL: Do NOT run the push command automatically.** Always stop and ask the +user for explicit confirmation. Present the summary and wait. + +**Gate:** ALL prior states (1–7) have passed. Present this summary and STOP: + +> All pre-publish checks passed: +> +> - Repository: initialized +> - Auth: verified as `` +> - Manifest: valid +> - Collective: `@` matches auth +> - Version: `YYYY.MM.DD.MICRO` +> - Formatting: clean +> - Dry run: passed +> +> Ready to push `@collective/extension-name` version `YYYY.MM.DD.MICRO` to the +> registry. **Shall I proceed?** + +**Action:** Only after the user explicitly says yes, approved, go, or proceed: + +```bash +swamp extension push manifest.yaml --yes --json +``` + +**Verify:** The command exits successfully and reports the published version. + +**On Failure:** If the push fails: + +- Version already exists → bump the MICRO component and retry +- Network error → check connectivity and retry +- Auth error → re-run `swamp auth login` (go back to State 2) + +## References + +- **Publishing Details**: See + [references/publishing.md](references/publishing.md) for manifest schema, + field reference, CalVer versioning, safety rules, and common errors +- **Extension Creation**: Use the `swamp-extension-model`, + `swamp-extension-vault`, `swamp-extension-datastore`, or + `swamp-extension-driver` skills to create extension code before publishing + +## When to Use Other Skills + +| Need | Use Skill | +| ------------------------------- | --------------------------- | +| Create custom models | `swamp-extension-model` | +| Create custom vaults | `swamp-extension-vault` | +| Create custom datastores | `swamp-extension-datastore` | +| Create custom execution drivers | `swamp-extension-driver` | +| Repository setup and management | `swamp-repo` | +| Create reports | `swamp-report` | diff --git a/.claude/skills/swamp-extension-publish/evals/trigger_evals.json b/.claude/skills/swamp-extension-publish/evals/trigger_evals.json new file mode 100644 index 00000000..48b6ff4f --- /dev/null +++ b/.claude/skills/swamp-extension-publish/evals/trigger_evals.json @@ -0,0 +1,73 @@ +[ + { + "query": "Publish my extension to the registry", + "should_trigger": true + }, + { + "query": "Push my extension to swamp-club", + "should_trigger": true + }, + { + "query": "How do I swamp extension push my model?", + "should_trigger": true + }, + { + "query": "Prepare my extension for publishing", + "should_trigger": true + }, + { + "query": "I want to release a new version of my extension", + "should_trigger": true + }, + { + "query": "Run the publishing checklist for my extension", + "should_trigger": true + }, + { + "query": "I need to push my vault extension to the registry", + "should_trigger": true + }, + { + "query": "Help me publish my datastore extension", + "should_trigger": true + }, + { + "query": "Make a manifest.yaml so I can push my extension", + "should_trigger": true, + "note": "manifest creation for publishing triggers both this skill and swamp-extension-model" + }, + { + "query": "swamp extension push manifest.yaml", + "should_trigger": true + }, + { + "query": "How do I create a custom model using TypeScript and Zod?", + "should_trigger": false, + "note": "Creating models → swamp-extension-model" + }, + { + "query": "List all the data stored from running my models", + "should_trigger": false, + "note": "Viewing model data → swamp-data" + }, + { + "query": "Run my custom model with this input data", + "should_trigger": false, + "note": "Running models → swamp-model" + }, + { + "query": "Initialize a new swamp repository", + "should_trigger": false, + "note": "Repository setup → swamp-repo" + }, + { + "query": "Create a custom vault for AWS Secrets Manager", + "should_trigger": false, + "note": "Creating vaults → swamp-extension-vault" + }, + { + "query": "How do I smoke test my extension model before pushing?", + "should_trigger": false, + "note": "Smoke testing → swamp-extension-model" + } +] diff --git a/.claude/skills/swamp-extension-model/references/publishing.md b/.claude/skills/swamp-extension-publish/references/publishing.md similarity index 93% rename from .claude/skills/swamp-extension-model/references/publishing.md rename to .claude/skills/swamp-extension-publish/references/publishing.md index 71e424c7..9ecfccf8 100644 --- a/.claude/skills/swamp-extension-model/references/publishing.md +++ b/.claude/skills/swamp-extension-publish/references/publishing.md @@ -3,6 +3,22 @@ Publish extension models, workflows, vaults, drivers, and datastores to the swamp registry so others can install and use them. +## Repository Prerequisite + +The extension directory **must be an initialized swamp repository** before +`swamp extension fmt` or `swamp extension push` will work. Both commands require +a `.swamp.yaml` marker file (created by `swamp repo init`). + +If you see `Not a swamp repository` errors, run: + +```bash +swamp repo init --json +``` + +This creates `.swamp.yaml` and the standard directory structure. For monorepos +with multiple extensions, each subdirectory that needs to publish independently +must have its own `swamp repo init`. + ## Manifest Schema (v1) Create a `manifest.yaml` in your repository root (or any directory): @@ -153,6 +169,8 @@ reports: ## Pre-Push Checklist +0. **Verify swamp repository**: Confirm `.swamp.yaml` exists — run + `swamp repo init --json` if missing 1. **Get next version**: `swamp extension version --manifest manifest.yaml --json` 2. **Bump version** in `manifest.yaml` — use `nextVersion` from the output above @@ -162,8 +180,9 @@ reports: ## Push Workflow -> **Before you push:** Your extension must pass -> `swamp extension fmt --check`. The push command enforces this +> **Before you push:** Your extension directory must be an initialized swamp +> repository (`.swamp.yaml` must exist). Your extension must also pass +> `swamp extension fmt --check`. The push command enforces formatting > automatically — if your code has formatting or lint issues, the push will be > rejected. Run `swamp extension fmt ` to auto-fix before pushing. @@ -317,6 +336,7 @@ swamp extension version --manifest manifest.yaml --json | Error | Fix | | ------------------------------- | ----------------------------------------------------------------------- | +| "Not a swamp repository" | Run `swamp repo init --json` in the extension directory | | "Not authenticated" | Run `swamp auth login` first | | "collective does not match" | Manifest `name` must use `@your-username/...` | | "CalVer format" error | Use `YYYY.MM.DD.MICRO` (e.g., `2026.02.26.1`) | diff --git a/.claude/skills/swamp-extension-vault/SKILL.md b/.claude/skills/swamp-extension-vault/SKILL.md index b1ca8eb9..9c950fd2 100644 --- a/.claude/skills/swamp-extension-vault/SKILL.md +++ b/.claude/skills/swamp-extension-vault/SKILL.md @@ -214,18 +214,10 @@ findings to the user before proceeding. ## Publishing -Publishing is the same for all extension types. Before pushing: - -1. **Get next version**: - `swamp extension version --manifest manifest.yaml --json` -2. **Bump version** in `manifest.yaml` — use the `nextVersion` from above -3. **Format & lint**: `swamp extension fmt manifest.yaml` -4. **Dry-run**: `swamp extension push manifest.yaml --dry-run --json` -5. **Push**: `swamp extension push manifest.yaml --yes --json` - -For the full manifest schema, CalVer versioning, safety rules, and -troubleshooting, see the -[publishing guide](../swamp-extension-model/references/publishing.md). +Use the `swamp-extension-publish` skill to publish extensions to the registry. +It provides a state-machine checklist that enforces all prerequisites +(repository initialization, authentication, manifest validation, collective +verification) before allowing a push. ## When to Use Other Skills diff --git a/.claude/skills/swamp-report/SKILL.md b/.claude/skills/swamp-report/SKILL.md index 31ac9ee5..ceef9a0d 100644 --- a/.claude/skills/swamp-report/SKILL.md +++ b/.claude/skills/swamp-report/SKILL.md @@ -273,8 +273,9 @@ reports: - compliance_report.ts ``` -For the full publishing workflow, CalVer versioning, and safety rules, see the -[publishing guide](../swamp-extension-model/references/publishing.md). +For the full publishing workflow, use the `swamp-extension-publish` skill. It +provides a state-machine checklist that enforces all prerequisites before +allowing a push. ## CLI Flags diff --git a/src/infrastructure/assets/skill_assets.ts b/src/infrastructure/assets/skill_assets.ts index 44e51b0b..b38d89d3 100644 --- a/src/infrastructure/assets/skill_assets.ts +++ b/src/infrastructure/assets/skill_assets.ts @@ -147,8 +147,12 @@ const BUNDLED_SKILLS: SkillInfo[] = [ name: "swamp-extension-model", }, { - relativePath: "swamp-extension-model/references/publishing.md", - name: "swamp-extension-model", + relativePath: "swamp-extension-publish/SKILL.md", + name: "swamp-extension-publish", + }, + { + relativePath: "swamp-extension-publish/references/publishing.md", + name: "swamp-extension-publish", }, { relativePath: "swamp-extension-model/references/checks.md",