docs: plan, UAT, and execution prompt for plugin tarball publish + categories
This commit is contained in:
parent
2a76b30c51
commit
e9bef5b065
@ -0,0 +1,305 @@
|
|||||||
|
# UAT — Plugin publish (tarball) + categories
|
||||||
|
|
||||||
|
Date: 2026-06-03
|
||||||
|
|
||||||
|
> **THIS CHECKLIST IS A HARD GATE.** Implementation is NOT complete until
|
||||||
|
> every item below has been executed and observed to pass. Build-green and
|
||||||
|
> tests-green are necessary but NOT sufficient. The work is unfinished if
|
||||||
|
> any UAT item is skipped, glossed over, or marked done without the exact
|
||||||
|
> observation recorded.
|
||||||
|
>
|
||||||
|
> Do not edit this file to soften any item. If an item turns out to be
|
||||||
|
> ambiguous or impossible, STOP and ask the user to amend it. Do not
|
||||||
|
> rationalise around it.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
Execute each item against a freshly-rebuilt orchestrator (`podman compose
|
||||||
|
build orchestrator-backend && podman compose up -d orchestrator-backend`)
|
||||||
|
and a freshly-reinstalled CLI (`go install ./cmd/ninja` from `~/src/core`).
|
||||||
|
For each item, capture the actual output/observation next to the
|
||||||
|
expectation. Mark a checkbox ONLY after observing the success criterion
|
||||||
|
with your own eyes.
|
||||||
|
|
||||||
|
The DB connection used in items below is whatever the local orchestrator
|
||||||
|
uses; commands assume access via `podman exec blockninja-db psql -U orchestrator orchestrator`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Group A — `ninja plugin init`
|
||||||
|
|
||||||
|
### A1. Init writes plugin.mod with all fields and auto-commits it
|
||||||
|
|
||||||
|
- [ ] Setup:
|
||||||
|
```bash
|
||||||
|
rm -rf /tmp/uat-a1 && mkdir /tmp/uat-a1 && cd /tmp/uat-a1
|
||||||
|
git init -q && git commit --allow-empty -qm "initial"
|
||||||
|
```
|
||||||
|
- [ ] Run: `ninja plugin init --host https://my.localdev.blockninjacms.com --scope @themes --name uat-a1` (answer: kind=plugin, categories=1,2)
|
||||||
|
- [ ] Observe `cat plugin.mod` includes:
|
||||||
|
- `name = "uat-a1"`
|
||||||
|
- `scope = "@themes"`
|
||||||
|
- `version = "0.1.0"`
|
||||||
|
- `kind = "plugin"`
|
||||||
|
- `categories = ["analytics", "seo"]`
|
||||||
|
- [ ] Observe `git log --oneline` shows a commit whose subject is `Add plugin.mod` at HEAD.
|
||||||
|
- [ ] Observe `git remote -v` outputs nothing (no `ninja` remote).
|
||||||
|
- [ ] Observe `grep -A1 '\[remote' .git/config` finds NO `ninja` block.
|
||||||
|
|
||||||
|
### A2. Init for a theme writes kind=theme and skips category prompt
|
||||||
|
|
||||||
|
- [ ] Setup:
|
||||||
|
```bash
|
||||||
|
rm -rf /tmp/uat-a2 && mkdir /tmp/uat-a2 && cd /tmp/uat-a2
|
||||||
|
git init -q && git commit --allow-empty -qm "initial"
|
||||||
|
```
|
||||||
|
- [ ] Run init for `@themes/uat-a2`, answer kind=theme. The category prompt MUST NOT appear.
|
||||||
|
- [ ] Observe `plugin.mod` contains `kind = "theme"` and NO `categories =` line.
|
||||||
|
|
||||||
|
### A3. Init when not in a git repo prints a warning, still registers
|
||||||
|
|
||||||
|
- [ ] Setup:
|
||||||
|
```bash
|
||||||
|
rm -rf /tmp/uat-a3 && mkdir /tmp/uat-a3 && cd /tmp/uat-a3
|
||||||
|
```
|
||||||
|
- [ ] Run init for `@themes/uat-a3`. STDOUT/STDERR contains a warning mentioning `git init` before publish.
|
||||||
|
- [ ] `plugin.mod` exists on disk.
|
||||||
|
- [ ] No `.git` directory was created.
|
||||||
|
- [ ] Database row exists: `psql -c "SELECT 1 FROM registry_plugins WHERE name='uat-a3';"` returns 1.
|
||||||
|
|
||||||
|
### A4. Init twice with same name returns AlreadyExists, leaves repo unchanged
|
||||||
|
|
||||||
|
- [ ] In a freshly-init'd repo with no plugin.mod, run init twice with the same scope+name.
|
||||||
|
- [ ] Second invocation errors with a message mentioning the plugin already exists.
|
||||||
|
- [ ] `git log` shows exactly ONE `Add plugin.mod` commit (not two).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Group B — `ninja plugin publish`
|
||||||
|
|
||||||
|
### B1. Publish posts a tar.zst, no git tag, no git push
|
||||||
|
|
||||||
|
- [ ] Setup from a working init'd repo (e.g. uat-a1 above).
|
||||||
|
- [ ] Pre-record:
|
||||||
|
```bash
|
||||||
|
git tag --list # capture before
|
||||||
|
git rev-parse HEAD # capture HEAD before
|
||||||
|
```
|
||||||
|
- [ ] Run `ninja plugin publish --host https://my.localdev.blockninjacms.com`.
|
||||||
|
- [ ] STDOUT contains `Published @themes/uat-a1@0.1.0 (NNN bytes)`.
|
||||||
|
- [ ] After publish, `git tag --list` output is byte-identical to before. (NO `v0.1.0` tag was created.)
|
||||||
|
- [ ] `git rev-parse HEAD` is unchanged.
|
||||||
|
- [ ] `git remote -v` is still empty.
|
||||||
|
- [ ] DB row exists with the new version:
|
||||||
|
```sql
|
||||||
|
SELECT v.version, v.source_archive_key, v.source_archive_size, v.source_archive_sha256
|
||||||
|
FROM registry_versions v
|
||||||
|
JOIN registry_plugins p ON p.id = v.plugin_id
|
||||||
|
WHERE p.name = 'uat-a1';
|
||||||
|
```
|
||||||
|
Observe: `source_archive_key` ends with `/source.tar.zst`. `source_archive_size > 0`.
|
||||||
|
|
||||||
|
### B2. The stored archive matches the posted bytes (sha256)
|
||||||
|
|
||||||
|
- [ ] On disk (or via the signed URL), retrieve the stored archive bytes.
|
||||||
|
- [ ] Compute `sha256sum <archive>`. Compare against `source_archive_sha256` from the DB.
|
||||||
|
- [ ] Hashes match exactly.
|
||||||
|
|
||||||
|
### B3. The archive contains only tracked files and excludes gitignored
|
||||||
|
|
||||||
|
- [ ] Setup:
|
||||||
|
```bash
|
||||||
|
rm -rf /tmp/uat-b3 && mkdir /tmp/uat-b3 && cd /tmp/uat-b3
|
||||||
|
git init -q
|
||||||
|
echo "secret" > ignored.log
|
||||||
|
echo "ignored.log" > .gitignore
|
||||||
|
git add .gitignore && git commit -qm "ignore"
|
||||||
|
```
|
||||||
|
- [ ] Run init + publish for `@themes/uat-b3`.
|
||||||
|
- [ ] Extract the stored archive (download via signed URL → `zstd -d | tar -xv`).
|
||||||
|
- [ ] Observe `plugin.mod`, `.gitignore` present; `ignored.log` absent.
|
||||||
|
|
||||||
|
### B4. Working tree dirty check fires; `--allow-dirty` bypasses
|
||||||
|
|
||||||
|
- [ ] In a published repo, touch a file: `echo x >> README.md`.
|
||||||
|
- [ ] Run `ninja plugin publish ...` — must error with text including `working tree dirty`.
|
||||||
|
- [ ] Bump patch, then `ninja plugin publish --allow-dirty ...` — must succeed.
|
||||||
|
|
||||||
|
### B5. Tracked-yet-gitignored files trigger a warning
|
||||||
|
|
||||||
|
- [ ] Setup:
|
||||||
|
```bash
|
||||||
|
rm -rf /tmp/uat-b5 && mkdir /tmp/uat-b5 && cd /tmp/uat-b5
|
||||||
|
git init -q
|
||||||
|
echo "data" > dist.log
|
||||||
|
git add dist.log && git commit -qm "tracked"
|
||||||
|
echo "dist.log" > .gitignore
|
||||||
|
git add .gitignore && git commit -qm "ignore"
|
||||||
|
```
|
||||||
|
- [ ] Init + publish for `@themes/uat-b5`.
|
||||||
|
- [ ] STDERR includes a warning that `dist.log` is tracked and will still be shipped, plus the hint `git rm --cached`.
|
||||||
|
|
||||||
|
### B6. Duplicate version rejected
|
||||||
|
|
||||||
|
- [ ] In a successfully-published repo, immediately re-run publish without bumping.
|
||||||
|
- [ ] Error includes `version already published`.
|
||||||
|
|
||||||
|
### B7. Version mismatch between plugin.mod and request rejected
|
||||||
|
|
||||||
|
- [ ] Edit `plugin.mod` to a different version than the one expected by the bump sequence (manually write `version = "9.9.9"` without committing).
|
||||||
|
- [ ] Run publish — must succeed locally but the orchestrator may accept or reject; if rejected the error mentions version mismatch. Either way, no DB row at version `9.9.9` should exist unless it succeeded — record what happened.
|
||||||
|
- [ ] Reset:
|
||||||
|
```bash
|
||||||
|
git checkout plugin.mod
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Group C — Categories + kind validation
|
||||||
|
|
||||||
|
### C1. ListCategories returns the seeded set
|
||||||
|
|
||||||
|
- [ ] Run:
|
||||||
|
```bash
|
||||||
|
curl -sS -X POST \
|
||||||
|
https://my.localdev.blockninjacms.com/orchestrator.v1.PluginRegistryService/ListCategories \
|
||||||
|
-H 'Content-Type: application/json' -d '{}'
|
||||||
|
```
|
||||||
|
- [ ] Response includes ALL of: `analytics`, `seo`, `social`, `commerce`, `forms`, `import-export`, `media`, `developer`.
|
||||||
|
|
||||||
|
### C2. CreatePlugin rejects unknown category
|
||||||
|
|
||||||
|
- [ ] Setup a fresh repo and start init manually entering a bogus category number — NOT possible via the CLI menu. Instead, hit the RPC directly:
|
||||||
|
```bash
|
||||||
|
TOKEN=$(jq -r '.hosts["https://my.localdev.blockninjacms.com"].token' ~/.config/ninja/creds.json)
|
||||||
|
curl -sS -X POST \
|
||||||
|
https://my.localdev.blockninjacms.com/orchestrator.v1.PluginRegistryService/CreatePlugin \
|
||||||
|
-H "Authorization: Bearer $TOKEN" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{"scopeSlug":"themes","name":"uat-c2","kind":"plugin","categories":["bogus"]}'
|
||||||
|
```
|
||||||
|
- [ ] Response is a Connect error with code `invalid_argument` and message mentioning unknown category.
|
||||||
|
|
||||||
|
### C3. CreatePlugin rejects theme with categories
|
||||||
|
|
||||||
|
- [ ] Same setup as C2 but kind=theme with categories=["analytics"]:
|
||||||
|
```bash
|
||||||
|
curl -sS -X POST \
|
||||||
|
https://my.localdev.blockninjacms.com/orchestrator.v1.PluginRegistryService/CreatePlugin \
|
||||||
|
-H "Authorization: Bearer $TOKEN" \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{"scopeSlug":"themes","name":"uat-c3","kind":"theme","categories":["analytics"]}'
|
||||||
|
```
|
||||||
|
- [ ] Response is invalid_argument with message including "themes do not carry categories".
|
||||||
|
|
||||||
|
### C4. CreatePlugin rejects unknown kind
|
||||||
|
|
||||||
|
- [ ] POST with `kind: "module"` (or anything other than plugin/theme).
|
||||||
|
- [ ] Response is invalid_argument.
|
||||||
|
|
||||||
|
### C5. PublishVersion rejects plugin.mod kind mismatch
|
||||||
|
|
||||||
|
- [ ] In a published-once `plugin`-kind repo, hand-edit `plugin.mod` to `kind = "theme"`, commit, bump, publish.
|
||||||
|
- [ ] Publish errors with text including `kind does not match registered`.
|
||||||
|
|
||||||
|
### C6. PublishVersion rejects plugin.mod categories mismatch
|
||||||
|
|
||||||
|
- [ ] In a published-once `plugin`-kind repo, add a category to `plugin.mod` that wasn't in the original `CreatePlugin`, commit, bump, publish.
|
||||||
|
- [ ] Publish errors with text including `categories do not match registered`.
|
||||||
|
|
||||||
|
### C7. ListPlugins filters by kind
|
||||||
|
|
||||||
|
- [ ] Setup: at least one `plugin` and one `theme` in the registry (any from earlier UAT items).
|
||||||
|
- [ ] Hit ListPlugins with `kind=plugin`:
|
||||||
|
```bash
|
||||||
|
curl -sS -X POST \
|
||||||
|
https://my.localdev.blockninjacms.com/orchestrator.v1.PluginRegistryService/ListPlugins \
|
||||||
|
-H "Authorization: Bearer $TOKEN" \
|
||||||
|
-H 'Content-Type: application/json' -d '{"kind":"plugin"}'
|
||||||
|
```
|
||||||
|
Response contains only kind=plugin rows.
|
||||||
|
- [ ] Same with `{"kind":"theme"}`. Response contains only kind=theme rows.
|
||||||
|
- [ ] With `{}` (no filter). Response contains both.
|
||||||
|
|
||||||
|
### C8. ListPlugins filters by category
|
||||||
|
|
||||||
|
- [ ] Setup a plugin with categories=["analytics"].
|
||||||
|
- [ ] Hit ListPlugins with `{"categories":["analytics"]}`. The plugin appears.
|
||||||
|
- [ ] Hit with `{"categories":["forms"]}`. The plugin does NOT appear.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Group D — Deletion of git infrastructure
|
||||||
|
|
||||||
|
### D1. `/git/*` HTTP route is gone
|
||||||
|
|
||||||
|
- [ ] Run:
|
||||||
|
```bash
|
||||||
|
curl -sS -o /dev/null -w "%{http_code}\n" \
|
||||||
|
https://my.localdev.blockninjacms.com/git/themes/lcars.git/info/refs?service=git-upload-pack
|
||||||
|
```
|
||||||
|
- [ ] HTTP code is `404` (not 200, not 403). The route does not exist.
|
||||||
|
|
||||||
|
### D2. `registry/git/` package is fully removed
|
||||||
|
|
||||||
|
- [ ] Run:
|
||||||
|
```bash
|
||||||
|
ls ~/src/orchestrator/backend/internal/registry/ 2>&1
|
||||||
|
```
|
||||||
|
- [ ] Output does NOT include a `git` directory.
|
||||||
|
- [ ] `grep -r "internal/registry/git" ~/src/orchestrator/backend/ 2>/dev/null | grep -v "^Binary"` returns nothing.
|
||||||
|
|
||||||
|
### D3. `RegistryGitPath` config is gone
|
||||||
|
|
||||||
|
- [ ] Run `grep -n "RegistryGitPath\|REGISTRY_GIT_PATH" ~/src/orchestrator/backend/internal/config/config.go`.
|
||||||
|
- [ ] Output is empty.
|
||||||
|
|
||||||
|
### D4. `registry_versions.git_commit` / `git_tag` columns are gone
|
||||||
|
|
||||||
|
- [ ] Run:
|
||||||
|
```bash
|
||||||
|
podman exec blockninja-db psql -U orchestrator orchestrator -c "\d registry_versions"
|
||||||
|
```
|
||||||
|
- [ ] Output shows NO column named `git_commit` and NO column named `git_tag`.
|
||||||
|
|
||||||
|
### D5. `Plugin.git_remote_url` is not in the proto
|
||||||
|
|
||||||
|
- [ ] Run `grep -n "git_remote_url\|GitRemoteUrl" ~/src/orchestrator/proto/orchestrator/v1/plugin_registry.proto ~/src/core/proto/orchestrator/v1/plugin_registry.proto`.
|
||||||
|
- [ ] No matches.
|
||||||
|
|
||||||
|
### D6. The CLI no longer references the `ninja` git remote
|
||||||
|
|
||||||
|
- [ ] Run `grep -nE 'remote\s+(add|remove)\s+"?ninja' ~/src/core/cmd/ninja/cmd/plugin.go`.
|
||||||
|
- [ ] No matches.
|
||||||
|
- [ ] Run `grep -nE '"git",\s*"push",\s*"ninja"' ~/src/core/cmd/ninja/cmd/plugin.go`.
|
||||||
|
- [ ] No matches.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Group E — Smoke install path
|
||||||
|
|
||||||
|
### E1. ResolveInstall returns the new .tar.zst URL
|
||||||
|
|
||||||
|
- [ ] For any published plugin/version (e.g. uat-a1@0.1.0), call ResolveInstall:
|
||||||
|
```bash
|
||||||
|
curl -sS -X POST \
|
||||||
|
https://my.localdev.blockninjacms.com/orchestrator.v1.PluginRegistryService/ResolveInstall \
|
||||||
|
-H 'Content-Type: application/json' \
|
||||||
|
-d '{"scopeSlug":"themes","pluginName":"uat-a1","versionOrChannel":"0.1.0"}'
|
||||||
|
```
|
||||||
|
- [ ] Response contains `archiveUrl` whose path ends with `/source.tar.zst` and includes `sig=` and `exp=` query params.
|
||||||
|
|
||||||
|
### E2. The signed URL actually downloads
|
||||||
|
|
||||||
|
- [ ] `curl -sS -o /tmp/uat-e2.tar.zst "<archiveUrl from E1>"`
|
||||||
|
- [ ] `file /tmp/uat-e2.tar.zst` reports a Zstandard compressed file.
|
||||||
|
- [ ] `sha256sum /tmp/uat-e2.tar.zst` matches the `archiveSha256` from the ResolveInstall response.
|
||||||
|
- [ ] `zstd -dc /tmp/uat-e2.tar.zst | tar -tf - | head` shows `plugin.mod` and the expected files.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Sign-off
|
||||||
|
|
||||||
|
- [ ] Every box above is ticked, with at-the-time-of-execution observation logged inline.
|
||||||
|
- [ ] Any unticked box → work is NOT complete. Return to the plan.
|
||||||
|
- [ ] Final test reports any deviations from expected behaviour even when the box can be ticked.
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
# Execution prompt — Plugin publish (tarball) + categories
|
||||||
|
|
||||||
|
Copy the body below verbatim into a new Claude Code session at the repo
|
||||||
|
root (`~/src/core`) when you want execution to start. The prompt is
|
||||||
|
self-contained: anyone reading it should be able to drive the work end
|
||||||
|
to end without further context.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Begin prompt
|
||||||
|
|
||||||
|
You are the inline execution agent for the "Plugin publish (tarball) +
|
||||||
|
categories" change. You are doing the work; you are not advising. Follow
|
||||||
|
the process below in order. Do not skip steps. Do not improvise.
|
||||||
|
|
||||||
|
### 1. Required reading (in this order)
|
||||||
|
|
||||||
|
Read these three files fully before touching any code. Treat each as
|
||||||
|
authoritative for its purpose. They live in `~/src/core`:
|
||||||
|
|
||||||
|
1. **Spec / design** — `docs/superpowers/specs/2026-06-03-plugin-publish-and-categories-design.md`. Defines *what* and *why*. Do not change this without the user's explicit OK.
|
||||||
|
2. **Plan** — `docs/superpowers/plans/2026-06-03-plugin-publish-and-categories.md`. Defines the ordered, bite-sized tasks with full code blocks. Do not change this without the user's explicit OK either. Each task ends with a commit.
|
||||||
|
3. **UAT checklist** — `docs/superpowers/audits/2026-06-03-plugin-publish-and-categories-uat.md`. The hard gate. The work is NOT done until every UAT item has been observed to pass with your own eyes. The UAT may not be softened, skipped, or interpreted away. If any item turns out to be ambiguous or impossible, STOP and ask the user.
|
||||||
|
|
||||||
|
Also be aware: work spans TWO git repos.
|
||||||
|
- `~/src/core` — Go module `git.dev.alexdunmow.com/block/core`. Holds the ninja CLI (`cmd/ninja/`), the SDK (`plugin/`), and a mirrored copy of the orchestrator proto under `proto/` + `internal/api/`.
|
||||||
|
- `~/src/orchestrator` — Go module at `backend/`. Holds the orchestrator service, schema, migrations, and proto source of truth.
|
||||||
|
|
||||||
|
CLAUDE.md in each repo applies. Read `~/src/core/CLAUDE.md` if you have not (key rule: no `replace` directives in any `go.mod`).
|
||||||
|
|
||||||
|
### 2. Process
|
||||||
|
|
||||||
|
Invoke the `superpowers:executing-plans` skill and follow its discipline.
|
||||||
|
Within that:
|
||||||
|
|
||||||
|
- Work tasks in the order written in the plan (Task 1 → Task 20 + Task 11.5). Do not reorder. The order encodes dependency.
|
||||||
|
- After completing each task, commit per the commit step in the task. Do not batch multiple tasks into one commit. Do not amend the user's previous commits.
|
||||||
|
- After each task's commit, run an internal checkpoint: did the build pass? did the tests added in this task pass? did this task actually do what the plan said? If anything is off, fix it before moving on.
|
||||||
|
- Stop and report at any of these points:
|
||||||
|
- Task instructions are unclear or contradicted by current code.
|
||||||
|
- A task's code block doesn't compile after applying it verbatim AND the fix isn't obvious from the build error.
|
||||||
|
- `make sqlc` produces field names that differ from what later tasks reference (this is plausible; sqlc field naming sometimes surprises).
|
||||||
|
- You need to install tooling that isn't already on the system (e.g. `buf`, `goose`, `sqlc`).
|
||||||
|
- Do NOT edit the plan or design to fit reality. If reality has diverged, surface that to the user and ask how to resolve.
|
||||||
|
|
||||||
|
### 3. When to dispatch subagents
|
||||||
|
|
||||||
|
The plan is mostly sequential. Most tasks should be executed inline by
|
||||||
|
you. Dispatch a `general-purpose` subagent ONLY for the tasks listed
|
||||||
|
below. These are isolated, pure-function, well-bounded units whose work
|
||||||
|
benefits from a clean context. Hand the subagent the full task body
|
||||||
|
including all code blocks; tell it the working directory; tell it the
|
||||||
|
exact files to create or modify; tell it not to commit (you commit after
|
||||||
|
reviewing the changes).
|
||||||
|
|
||||||
|
Subagent-suitable tasks:
|
||||||
|
|
||||||
|
- **Task 3** — `[core] BuildSourceArchive`. Pure helper in a new package. Self-contained TDD.
|
||||||
|
- **Task 4** — `[orch] OpenAndValidate`. Pure helper, TDD, no external state.
|
||||||
|
- **Task 5** — `[orch] Drop git fields migration + sqlc regen`. Mechanical schema + regen. Pure file manipulation.
|
||||||
|
- **Task 14** — `[orch] kind + categories migration + sqlc regen`. Same shape as Task 5.
|
||||||
|
|
||||||
|
All other tasks (proto changes, handler rewrites, wiring, CLI changes,
|
||||||
|
delete-the-git-package) you do yourself in the main context. Reasons:
|
||||||
|
they cross many files, depend on context from earlier tasks, and require
|
||||||
|
running and reading the orchestrator/CLI in your hands.
|
||||||
|
|
||||||
|
Smoke tests (Tasks 12, 20) and UAT execution: do these yourself in the
|
||||||
|
main context. Subagents cannot easily run interactive flows or report
|
||||||
|
back observations of running services.
|
||||||
|
|
||||||
|
### 4. UAT gate (HARD)
|
||||||
|
|
||||||
|
After Task 20 (and Task 11.5) are committed and pushed-ready in both
|
||||||
|
repos, execute the UAT checklist
|
||||||
|
(`docs/superpowers/audits/2026-06-03-plugin-publish-and-categories-uat.md`)
|
||||||
|
top to bottom. For each box:
|
||||||
|
|
||||||
|
- Run the command(s) the item specifies, against the actual orchestrator
|
||||||
|
(you may need to `podman compose build orchestrator-backend &&
|
||||||
|
podman compose up -d orchestrator-backend` first) and the actual
|
||||||
|
installed CLI (`cd ~/src/core && go install ./cmd/ninja`).
|
||||||
|
- Observe the result with your own eyes.
|
||||||
|
- Tick the box ONLY if the observation matches the expectation.
|
||||||
|
- If it doesn't match: do not tick. Return to the plan, identify which
|
||||||
|
task is implicated, and either fix it (new commit) or report back.
|
||||||
|
|
||||||
|
You may not declare the work complete with any UAT box unticked. You
|
||||||
|
may not pre-tick boxes "based on the test suite passing". UAT is the
|
||||||
|
gate; tests are not.
|
||||||
|
|
||||||
|
If an UAT item is ambiguous, ask the user before guessing.
|
||||||
|
|
||||||
|
### 5. Tone
|
||||||
|
|
||||||
|
Short status updates between tasks. State what's next in one line. State
|
||||||
|
problems concretely with the command and output that demonstrated the
|
||||||
|
problem. No speculation, no apologies. When asking the user, present
|
||||||
|
specific options.
|
||||||
|
|
||||||
|
### 6. Done
|
||||||
|
|
||||||
|
When all UAT items are ticked, summarise in one message:
|
||||||
|
- Total commits made across both repos.
|
||||||
|
- Any deviations from the plan (with task numbers and one-line justification).
|
||||||
|
- Status of each UAT group (A–E) — all pass.
|
||||||
|
- Suggested next step (likely: announce the change in the team channel, or move on to a follow-up like an admin UI for category management — both out of scope here).
|
||||||
|
|
||||||
|
## End prompt
|
||||||
2350
docs/superpowers/plans/2026-06-03-plugin-publish-and-categories.md
Normal file
2350
docs/superpowers/plans/2026-06-03-plugin-publish-and-categories.md
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user