dev-board
Dev Board
Generate a visual project dashboard and stakeholder summary from .dev/ PRD files.
Agents
This skill uses a specialized agent for PRD parsing:
- board-generator (magenta) — Parses all feature PRDs and returns structured progress data
Agent definition is in agents/ within this skill's directory.
Step 0: Discover Project Root
Run the discovery script:
bash "$DISCOVER" root
Where $DISCOVER is the absolute path to scripts/discover.sh within this skill's directory.
Path safety — shell state does not persist between tool calls, so you must provide full script paths on each call:
- Use
$HOMEinstead of the literal home directory (e.g.,bash "$HOME/code/…/discover.sh", notbash "/Users/name/…/discover.sh"). This prevents username hallucination. - Copy values from tool output. When reusing a value returned by a previous command (like
$PROJECT_ROOT), copy it verbatim from that command's output. Never retype a path from memory. - Verify on first call: if a script call fails with "No such file", the path is wrong — STOP and re-derive from the skill-loading context.
- Never ignore a non-zero exit. If any script in this skill fails, stop and report the error before continuing.
Store the output as $PROJECT_ROOT. If the command fails, inform the user and stop.
Step 1: Discover Features
Run the discovery script to find features:
bash "$DISCOVER" features "$PROJECT_ROOT"
- If the script exits non-zero (no
.dev/directory): inform the user "No.dev/directory found. Use/dev-planto start a new feature." - If output is empty: inform the user "No features found in
.dev/. Use/dev-planto start a new feature." - Otherwise: store the list of feature folder paths for the next step.
Step 2: Parse Feature Data
Launch the board-generator agent with the list of feature paths.
Provide a prompt like:
"Scan these feature folders and return structured progress data for each:
- $PROJECT_ROOT/.dev/feature-a
- $PROJECT_ROOT/.dev/feature-b
For each folder, extract: Status, Created/Updated dates, Last Checkpoint, Summary, Phase progress (phases and steps), Sub-PRD progress, and Next Action."
Use subagent_type=dev-workflow:board-generator and model=haiku.
After the agent returns, validate the JSON before proceeding:
- Parse the agent's response as JSON. If it's wrapped in code fences, strip them first.
- Verify the result is an array where each object has the required fields:
name(string),status(string),progress(object withphasesComplete,phasesTotal,stepsComplete,stepsTotal),phases(array),subPrds(array). - Verify field naming is camelCase (not snake_case) and status values are lowercase (
"active","complete","stale","no-prd"). - If validation fails, inform the user and stop — do not inject malformed data into the HTML template.
Then present a summary of the parsed data to the user:
## Parsed Feature Data
**Features found**: [N]
| Feature | Status | Progress | Next Action |
|---------|--------|----------|-------------|
| [name] | [status] | [X/Y phases, A/B steps] | [summary] |
Step 3: Generate HTML Board
Build $PROJECT_ROOT/.dev/board.html from the agent's output and the HTML template.
3a. Derive metadata
- Project name: Run
basename $(git rev-parse --show-toplevel 2>/dev/null || pwd). - Timestamp: Use the current date/time in ISO 8601 format (e.g.,
2026-03-02T14:30:00Z).
3b. Build the BOARD_DATA object
The agent returns a JSON array of feature objects. Wrap it into the full data contract:
{
"projectName": "<from 3a>",
"generatedAt": "<from 3a>",
"summary": { "total": N, "active": N, "complete": N, "stale": N, "noPrd": N },
"features": <agent JSON array>
}
Compute summary by counting feature statuses across the array:
total: array lengthactive: features withstatus === "active"complete: features withstatus === "complete"stale: features withstatus === "stale"noPrd: features withstatus === "no-prd"
3c. Inject into template and write
- Read
references/board-template.htmlwithin this skill's directory. - Serialize the JSON object (no indentation needed, compact is fine).
- Replace the
<!-- BOARD_DATA -->comment in the template with:<script>const BOARD_DATA = <JSON>;</script> - Write the result to
$PROJECT_ROOT/.dev/board.html.
Step 4: Generate Stakeholder Markdown
Generate a platform-neutral markdown summary from the agent's structured data. The output must be pure GitHub-flavored markdown — no HTML tags, no raw emoji, text labels only.
4a. Group features by status
From the agent's JSON array, partition features into four groups:
- active:
status === "active" - complete:
status === "complete" - stale:
status === "stale" - noPrd:
status === "no-prd"
4b. Build the markdown
Construct the markdown string following this structure. Omit any section entirely if its group is empty.
Header:
# {projectName} - Status Update
**Date**: {generatedAt as YYYY-MM-DD}
**Features**: {total} total | {active count} active | {complete count} complete[ | {stale count} needs attention]
Only include the "needs attention" count if stale > 0.
Active Features section (if any active features):
For each active feature, render:
## Active Features
### {feature.name}
{feature.summary}
**Progress**: {phasesComplete}/{phasesTotal} phases ({stepsComplete}/{stepsTotal} steps)
**Last Activity**: {lastCheckpoint, or lastUpdated if lastCheckpoint is null}
**Next**: {nextAction, or "No next action defined" if null}
| Phase | Status | Progress |
|-------|--------|----------|
| {number}. {title} | {status label} | {stepsDone}/{stepsTotal} |
Phase status labels: "complete" → "Done", "in-progress" → "In Progress", "not-started" → "Not Started".
If a feature has no phases, show the progress line but skip the phase table.
Place a --- separator between multiple active features (not after the last one).
Completed Features section (if any complete features):
---
## Completed Features
| Feature | Completed |
|---------|-----------|
| {name} | {lastUpdated} |
Needs Attention section (if any stale features):
---
## Needs Attention
| Feature | Last Activity | Progress |
|---------|---------------|----------|
| {name} | {lastCheckpoint or lastUpdated} | {stepsComplete}/{stepsTotal} steps |
Other section (if any no-prd features):
---
## Other
| Feature | Note |
|---------|------|
| {name} | No PRD found |
4c. Write output
Write the constructed markdown to $PROJECT_ROOT/.dev/board-stakeholder.md.
Step 5: Report
Tell the user what was generated:
Generated:
- `.dev/board.html` — Open in a browser to view the project dashboard
- `.dev/board-stakeholder.md` — Copy-paste into GitHub, Confluence, Slack, etc.
[N] features scanned: [X] active, [Y] complete, [Z] stale
Privacy Rules
NEVER include in output or saved files:
- Absolute paths containing usernames (e.g.,
/Users/username/...) - Secrets, API keys, tokens, or credentials
- Personal information
ALWAYS use instead:
- Relative paths from project root (e.g.,
.dev/feature-name/) - Feature names without full paths