pm-board · git:20260729.4a3a4d0 · 2026-07-29 · sha256 eb713831f32a6ce4

pm-board git:20260729.4a3a4d0A

Immutable. This exact content is served forever at /api/v1/blob/eb713831f32a6ce4.

---
name: pm-board
description: "Open the great-pm board — a native, zero-dependency project board (hybrid stage×status Kanban + artifact panels + verdict metrics) served from the great-pm plugin itself. Self-contained, no npm packages."
---

## Codex host binding

- Treat references to Claude slash workflows as the equivalently named Codex skill.
- Before delegating to any specialist, read the `great-pm-runtime` skill and the selected packaged role file.
- Treat "invoke", "assign", "delegate", "spawn", and source Agent-tool instructions as a required Codex `spawn_agent` call with that role and a bounded assignment.
- Store every returned agent identifier. Never call a wait tool until a spawn has returned an identifier, and wait only on identifiers returned by successful spawns.
- If `spawn_agent` is unavailable or a spawn fails, report BLOCKED; do not impersonate the specialist or wait on an empty agent set.
- Resolve bundled paths from the installed GreatPM plugin root.
- Ignore Claude-only model aliases, colors, turn limits, and tool allowlists.
- Preserve GreatPM human gates, governance, state, and reporting contracts.


You are the great-pm `$pm-board` command. Open the native great-pm board.

## Operating procedure

1. Resolve the plugin root and register the current project so the board's
   switcher can find it:
   ```bash
   ROOT="${PLUGIN_ROOT}"
   REG="$HOME/.great-pm/projects.json"
   mkdir -p "$HOME/.great-pm"
   CWD="$(pwd)"
   # project name: title from .great-pm/PROJECT.md, else folder name
   NAME="$(grep -m1 '^# ' .great-pm/PROJECT.md 2>/dev/null | sed 's/^# *//' | head -c 40)"
   [ -z "$NAME" ] && NAME="$(basename "$CWD")"
   TS="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
   python3 - "$REG" "$CWD" "$NAME" "$TS" <<'PY'
   import json,sys,os
   reg,path,name,ts=sys.argv[1:5]
   try: d=json.load(open(reg))
   except Exception: d={"projects":[]}
   ps=[p for p in d.get("projects",[]) if os.path.abspath(p.get("path",""))!=os.path.abspath(path)]
   ps.insert(0,{"path":path,"name":name,"lastSeen":ts})
   json.dump({"projects":ps},open(reg,"w"),indent=2)
   print("registered:",name)
   PY
   ```

2. If the board is already serving on port 3142, just open it; otherwise start it
   (detached) from the plugin and open the browser:
   ```bash
   if [ "$(curl -sS -o /dev/null -w '%{http_code}' --max-time 3 http://localhost:3142/ 2>/dev/null)" = "200" ]; then
     open http://localhost:3142 2>/dev/null || xdg-open http://localhost:3142 2>/dev/null
     echo "opened existing board"
   else
     nohup node "$ROOT/board/server.mjs" --port 3142 > "$HOME/.great-pm/board.log" 2>&1 &
     disown
     sleep 2
     open http://localhost:3142 2>/dev/null || xdg-open http://localhost:3142 2>/dev/null
     echo "started board → http://localhost:3142"
   fi
   ```

3. Tell the user what they're looking at:
   - **Rows** = the 6 great-pm stages (Discover → Measure) + an **Unstaged / Ops**
     lane; **columns** = Backlog / In Progress / Done.
   - **Drag a card** across columns to change its status, or across rows to set its
     stage. **+ New issue** creates a beads task. All changes write straight to `bd`.
   - Right panel = pending gates, drafts, latest verdicts, brain.md. Top strip =
     verdict-derived metrics (cost is not instrumented yet).
   - Use the sidebar **Project** switcher to jump between any great-pm projects
     you've opened the board from.

## Notes

The board is fully self-contained in the plugin (`board/server.mjs` +
`board/public/`). It reads the same beads store + `.great-pm/` state the agents
write, and only mutates beads in direct response to your drag/click — never
autonomously.

## Reporting

- **DONE**: `DONE: great-pm board open at http://localhost:3142.`
- **BLOCKED**: when the board cannot start (node unavailable, port 3142 held by a
  non-board process). Include `tried` + `failed_because` + `need`.