Files
firehose/.pi/skills/demo/SKILL.md
T
Willem van den Ende 3eae3afcbb demo skill: look up routing and demo users in the project
Steps 2 and 4 carried copy-paste from another project (lib/hub_web/router.ex,
alias Hub.Accounts, /users/log-in with user[email]). A stale path there sends
the agent to a router that does not exist, and a guessed module alias fails at
run time.

Both are now generic instructions to read the project:

- route map: locate the router by searching for `use Phoenix.Router`, then read
  its scopes, pipelines and live_sessions to see what is public and what needs
  a session
- authentication: only when the route actually needs it; take credentials from
  documented demo accounts or the project's seeds, create a demo user through
  the project's own path (seeds, registration route, or the accounts function
  found by grep - never a guessed alias), and read the login route and form
  selectors off the router and rendered form

The port example keeps its concrete app/endpoint pair, now labelled as an
example with the grep that finds the right names, plus a note to use the
project's toolchain/build wrapper instead of bare `mix`.

make check green.
2026-10-26 21:26:19 +00:00

238 lines
9.4 KiB
Markdown

---
name: demo
description: >-
Generate a living demo document proving a feature works. Uses showboat for
Markdown assembly with captured command output and rodney for Chrome browser
screenshots. Use when the user says "demo this", "show me it works", "create
a demo", or after /build completes.
allowed-tools: Read Write Glob Grep Bash
---
# Demo Skill
Role: worker. This command generates a standalone Markdown demo document that
proves a feature works, using showboat for document assembly and rodney for
browser automation.
You have been invoked with the /demo command.
Parse Arguments
Arguments: $ARGUMENTS
Positional: <feature-name> (required) - short name or description of the feature to demo
--scenario <description>: Explicit demo scenario describing what to show. If omitted, infer from the plan and recent commits.
--plan <path>: Path to the plan file. If omitted, search plans/ for the most recently modified .md file with status implemented or approved.
Steps
1. Check tool availability
Verify showboat and rodney are installed:
showboat --help 2>/dev/null && echo "showboat: ok" || echo "showboat: missing"
rodney --help 2>/dev/null && echo "rodney: ok" || echo "rodney: missing"
If either tool is missing, tell the user:
One or more demo tools are missing. Install them with:
go install github.com/simonw/showboat@latest
go install github.com/simonw/rodney@latest
Do not proceed until both tools are confirmed available.
2. Gather feature context
Build an understanding of what to demo from these sources (in priority order):
Explicit scenario (--scenario): If provided, use as primary guide.
Plan file: Read the plan's Goal, Acceptance Criteria, and completed Steps.
Recent commits: Run git log --oneline -15 and git diff main...HEAD --stat to identify changed files and commit messages.
Route map: Find the router yourself - do not assume a path. Search the project for its router (`grep -rn "use Phoenix.Router" lib/`; conventionally lib/<app>_web/router.ex), then read the scopes, pipelines and live_sessions to learn which routes the feature touches, which are public, and which require a logged-in user.
From these sources, produce a demo outline:
Narrative: 2-3 sentence description of what the feature does
Backend evidence: mix commands, test output, or database queries to run
UI pages: which routes to visit and what to look for
Interactions: any clicks, form fills, or navigation sequences to perform
If no plan exists and commits are ambiguous, ask the user for a brief description of what to demo.
3. Resolve the dev port, then check the server
Never assume a port. Read it from the project config, from the repo root:
DEMO_PORT=$(cd app && mix run --no-start -e \
'IO.puts(Application.get_env(:firehose, FirehoseWeb.Endpoint)[:http][:port])')
DEMO_BASE_URL="http://localhost:${DEMO_PORT}"
curl -s -o /dev/null -w "%{http_code}" "$DEMO_BASE_URL/"
Adapt that command to the project: find the app/endpoint pair in `config/*.exs`
(`grep -rn "Endpoint," config/`) and use the same names. If the config reads the
port from the environment, the value above already reflects it. Do not resolve
the port with `<Endpoint>.config(:http)`: with `--no-start` the endpoint's ETS
table does not exist and it raises.
If the project pins a toolchain or wraps builds, use its wrapper for every
command below (`mise exec -- mix ...`, asdf shims, or its `make` targets - check
AGENTS.md/README first). Bare `mix` is not a safe assumption.
If the server is not reachable:
The Phoenix dev server is not running. Start it now?
mkdir -p .tmp && (cd app && PORT=$DEMO_PORT mix phx.server \
> ../.tmp/phx-demo.log 2>&1 &)
Then poll `$DEMO_BASE_URL` for up to 10 seconds. If it still fails, read
`.tmp/phx-demo.log`: an error about an unresolvable JS module means the
project's JS packages are not installed - run its assets install step (in this
repository `make -C app assets`, which root `make deps` also runs). Only when
the server really cannot come up, proceed with backend-only evidence (skip all
browser screenshots) and note the limitation in the demo document.
Use `$DEMO_BASE_URL` for every URL below - there is no default port to fall
back on.
4. Handle authentication (only if the route needs it)
Decide this from the project, not from this file. If every page you need is
public, skip this step. A route needs a session when the router found in step 2
puts it inside a `pipe_through` that requires a logged-in user, or inside a
`live_session` guarded that way.
When you do need a session, read each part from the project instead of assuming
it:
- Credentials: check README, AGENTS.md, docs and the project's seeds
(`priv/repo/seeds.exs`, a `mix demo`-style task). Use documented demo
credentials if they exist - never invent them.
- Demo user: if nothing is documented, create one through the project's own
path, in this order: run its seeds; use its registration route; call the
accounts/context function you find by searching for it (`grep -rn
"get_user_by_email\|register_user\|create_user" lib/`). Copy the exact module,
function and field names from the source; do not guess an alias.
- Login route, form fields and submit button: read them off the router and out of
the rendered form (`rodney html form` or `rodney ax-tree`) rather than
assuming a path or an input name.
Then drive the form with the selectors you just read:
rodney start
rodney open "$DEMO_BASE_URL<login-route>"
rodney wait "<email-input-selector>"
rodney input "<email-input-selector>" "<email>"
rodney input "<password-input-selector>" "<password>"
rodney click "<submit-selector>"
rodney waitidle
Confirm the session took - `rodney url` should have left the login route, and
the page should show the user (name, avatar, menu). If login fails, warn, note it
in the demo document, and proceed with backend-only evidence.
5. Initialize the demo document
Slugify the feature name (lowercase, hyphens, no special chars). Then:
showboat init "demos/demo-$(date +%Y%m%d-%H%M%S)-<slug>.md" "Demo: <Feature Name>"
Store the demo file path for use in all subsequent steps.
6. Narrative introduction
showboat note <demo-file> "## Feature Overview
<2-3 sentence description derived from the plan or commits.>
**Branch**: $(git branch --show-current)
**Commits**: <N> commits ahead of main
**Plan**: <plan file path or 'none'>
"
7. Backend evidence
Capture backend proof via showboat exec. Always include relevant tests. Add narrative notes between evidence blocks explaining what each proves.
Test output (always include):
showboat note <demo-file> "## Test Suite"
showboat exec <demo-file> bash "mix test <relevant-test-files> --color"
showboat note <demo-file> "All <N> tests pass, confirming <specific criterion>."
Compilation check:
showboat note <demo-file> "## Compilation Check"
showboat exec <demo-file> bash "mix compile --warnings-as-errors"
Database state (if relevant to the feature):
showboat note <demo-file> "## Database State"
showboat exec <demo-file> bash "mix run -e '<query expression>'"
8. UI screenshots
For each UI page identified in step 2, navigate with rodney, screenshot, and embed via showboat.
Static page capture:
rodney open "$DEMO_BASE_URL/<route>"
rodney waitidle
rodney screenshot demos/screenshots/<feature>-<page-name>.png
showboat note <demo-file> "### <Page Name>
<What this page shows and why it proves the feature works.>"
showboat image <demo-file> '![<What the screenshot demonstrates>](demos/screenshots/<feature>-<page-name>.png)'
Interactive flow (form submissions, navigation):
showboat note <demo-file> "### Interactive Flow: <Flow Name>"
# Before state
rodney screenshot demos/screenshots/<feature>-before.png
showboat image <demo-file> '![Before: <initial state>](demos/screenshots/<feature>-before.png)'
# Perform interaction
rodney click "<selector>"
rodney input "<selector>" "<value>"
rodney click "<submit-selector>"
rodney waitidle
# After state
rodney screenshot demos/screenshots/<feature>-after.png
showboat image <demo-file> '![After: <resulting state>](demos/screenshots/<feature>-after.png)'
9. Acceptance criteria checklist
If a plan file exists, map each acceptance criterion to evidence:
showboat note <demo-file> "## Acceptance Criteria Verification
- [x] <Criterion 1> -- see Test Suite output above
- [x] <Criterion 2> -- see <Page Name> screenshot
- [x] <Criterion 3> -- see Database State output
"
If no plan, summarize what was demonstrated and what it proves.
10. Clean up
rodney stop 2>/dev/null || true
11. Report results
Display:
## Demo Complete
- **Document**: demos/<filename>.md
- **Screenshots**: <N> captured in demos/screenshots/
- **Evidence**: <N> backend commands, <N> UI screenshots
- **Acceptance criteria**: <N>/<M> demonstrated
Error Handling
Tools not installed: Show go install commands. Do not proceed without them.
Dev server not running: Offer to start. If startup fails, produce backend-only demo and note the limitation.
Authentication failure: Proceed with backend-only evidence. Note skipped UI screenshots in the document.
Screenshot failure: Log the error as a note in the demo document, continue with remaining screenshots.
No plan found: Infer from git commits and changed files. Ask the user for a description if commits are ambiguous.
Rodney/Chrome crash: Run rodney stop then rodney start to reset. Retry once. If it fails again, degrade to backend-only.