Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .claude/skills/dispatch-oneshot/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,26 @@ Specify the work before feeding it. Two ways in:
do not feed an underspecified task into the pipeline; it is L3-class automation
and will not reliably succeed.

### Input shapes — a task need not be in the issue format

The feeder builds the seed controller's raw intake (the front door) from each
task; inputs do **not** have to be pre-split into the issue format. The seed
content-classifies:

- **A real GitHub issue** (`"issue": <n>` with a `repo`) → pulled and handled as a
GitHub issue.
- **A bare prompt** (`{"prompt": "…"}`) → the seed seeds `title`/`goal` from the
prompt and handles it interactively (optional gaps like acceptance are left open,
and degrade cleanly to unset when run headless — no TTY hang).
- **A structured task** (`title` + `body`) → a non-interactive job request.

The `issue` carried on a oneshot job is a **negative local work-id** used only for
the engineer's clone/branch naming — it is *not* a GitHub issue. The build phase
honours the negative marker: `admin:publish` still deploys and `consolidate_pr`
still opens ONE PR, but the issue-keyed GitHub mutations (`intake_invoice`'s label
state machine, the `Closes #<n>` trailer) are skipped. This replaces the old
fabricated-GitHub-issue hack.

For more than one task, interview each, and confirm the **order** — the feeder runs
them sequentially, each fully through the pipeline before the next.

Expand Down Expand Up @@ -81,8 +101,21 @@ Run the feeder, which processes the tasks sequentially and streams each phase:
python3 app/scripts/oneshot_feed.py <tasks.json> --repo owner/repo # dry-run
python3 app/scripts/oneshot_feed.py <tasks.json> --engine websitewf -v # trace
python3 app/scripts/oneshot_feed.py <tasks.json> --repo owner/repo --live # real model
# demo: create+seed the target repo from a template first, then run live with the
# full phase-by-phase debug trace streamed (audience-visible), tee'd to a log.
python3 app/scripts/oneshot_feed.py <tasks.json> --repo owner/repo --live -v \
--provision owner/repo --template ~/path/to/template |& tee oneshot-demo.log
```

`--provision owner/repo --template DIR` ensures the target repo exists and is
seeded (via `app/scripts/demo/provision-from-template.sh`) **before** the pipeline
clones it, so `engineer:act_clone` has a cloneable, deployable base. `admin:prepare_env`
then sees the repo already exists and leaves it untouched (idempotent).

`-v` sets `DISPATCH_DEBUG=1` and streams the engine's phase-by-phase action trace —
run it this way for a live demo so the audience can watch each controller/action
fire. Run it as a background task (or `tee` to a log) so the trace is scrollable.

Stream the output. For each task report whether the tick completed (`ok=`) and the
deliverables produced; on a failure, surface the detail/error the feeder prints.

Expand Down
9 changes: 9 additions & 0 deletions app/scripts/demo/dogblog-oneshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[
{
"title": "Enhance interactive dog-blog components: like toggle, email validation, a11y labels",
"body": "## Goal\nThe three client-side components (LikeButton, CommentBox, NewsletterSignup) in `moonexpr/dog-blog-demo` already render interactively with basic `useState` — but each has a stub gap to close.\n\n## Research findings\n- Stack: Next.js 14, React 18, TypeScript, Tailwind. No form library, no state management beyond bare `useState`. All three already have `\"use client\"`.\n- LikeButton (`src/components/LikeButton.tsx`): increment-only; should toggle liked/unliked with `aria-pressed`; count is ephemeral per mount (no per-post persistence needed for demo); `postSlug` prop already present.\n- CommentBox (`src/components/CommentBox.tsx`): add-to-list + empty guard already work; needs a visible `<label>` on the text input for accessibility.\n- NewsletterSignup (`src/components/NewsletterSignup.tsx`): success state already shown; current `@`-only validation is too weak — use `type=\"email\"` native validation plus an inline error message for invalid submissions; needs `<label>` on the email input.\n- No test suite — acceptance is manual verification in the dev server.\n\n## Acceptance criteria\n- [ ] LikeButton toggles liked/unliked state; `aria-pressed` reflects current state; rapid repeated clicks do not race (guard with disabled state during optimistic update).\n- [ ] CommentBox has a visible `<label>` (or visually-hidden equivalent) associated with its text input via `htmlFor`/`id`; existing empty-input guard is preserved.\n- [ ] NewsletterSignup email input has a visible `<label>`; invalid/empty email is rejected client-side with an inline error message; valid email shows the existing success state.\n- [ ] All changes are pure client-side (no backend, no DB, no fetch calls); state is ephemeral per page-load — localStorage not required.\n- [ ] No new npm dependencies introduced; use only the existing React `useState` pattern.\n- [ ] `npm run build` passes with no TypeScript errors.\n\n## Scope\nEdit only the three component files:\n- `src/components/LikeButton.tsx`\n- `src/components/CommentBox.tsx`\n- `src/components/NewsletterSignup.tsx`\n\nDo NOT change `src/app/page.tsx` or any other file unless a build error demands it.\n\n## Verification\nRun `npm run dev`, open the app in a browser, and manually verify:\n1. Clicking the like button toggles it; `aria-pressed` reflects state in DevTools.\n2. Submitting a blank comment does nothing; a non-blank comment appends to the list.\n3. Submitting blank/invalid email shows inline error; valid email shows the success state.\n4. `npm run build` exits 0.",
"repo": "moonexpr/dog-blog-demo",
"engine": "websitewf",
"framework": "nextjs"
}
]
Loading
Loading