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.
238 lines
9.4 KiB
Markdown
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> ''
|
|
|
|
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> ''
|
|
|
|
# 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> ''
|
|
|
|
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.
|
|
|