From cogni-consult
Generate an interactive HTML dashboard showing a cogni-consult engagement's status — action fields, deliverables, design-thinking stage, and persona-review progress. Use whenever the user mentions dashboard, engagement dashboard, engagement status, "show me the engagement", "visualize the engagement", WBS view, status overview, or wants to see the engagement in a browser — even if they don't say "dashboard".
How this skill is triggered — by the user, by Claude, or both
Slash command
/cogni-consult:consult-dashboardThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate a self-contained HTML dashboard that visualizes a consulting engagement's
Generate a self-contained HTML dashboard that visualizes a consulting engagement's
status — the action-field work breakdown, every deliverable's state and
design-thinking stage, acting-persona review progress, knowledge-base linkage, and
the recommended next action. The dashboard opens in the browser and is the visual
sibling of the text WBS table that consult-resume and consult-action-fields
render inline.
Engagement status lives in consult-project.json plus one field.json per action
field, where each deliverable carries its own state, dt_stage, and
persona_review. The text WBS table is good for a quick check; this dashboard is for
visual exploration — scanning field-by-field progress, spotting which deliverables are
stuck mid-loop, and seeing persona-review coverage at a glance.
Deliverable state is the single source of truth (it lives only in field.json);
field and engagement completion are derived at read time, never stored. The
generator is read-only — it never modifies any engagement file.
Discover engagements with scripts/discover-projects.sh (the registry wrapper), or scan
for consult-project.json files under cogni-consult/ paths. If multiple engagements
exist, ask the user which one to open. Store the resolved engagement directory path.
First, check whether <engagement-dir>/output/design-variables.json already exists from
a previous dashboard run. If it does, ask the user: "A dashboard theme is already
configured. Reuse it, or pick a new one?" Default to reuse — most re-runs just want fresh
data with the same look.
cogni-workspace:pick-theme
skill to let the user select a theme. The skill returns theme_path, theme_name, and
theme_slug.Additional skip conditions (auto-select without prompting): the caller already
provided a theme_path, or only one theme exists in the workspace.
Read the selected theme.md and produce a design-variables JSON file at
<engagement-dir>/output/design-variables.json, following the schema at
$CLAUDE_PLUGIN_ROOT/skills/consult-dashboard/schemas/design-variables.schema.json. See
the example at
$CLAUDE_PLUGIN_ROOT/skills/consult-dashboard/examples/design-variables-cogni-work.json.
This is the same design-variables contract the rest of the ecosystem uses, so the consult
dashboard inherits the same look as the portfolio dashboard. What the LLM adds beyond a
raw token extraction: derive surface2 (~4% darker than surface), accent_muted /
accent_dark variants from accent, a Google Fonts @import URL, dark-theme shadow
opacity, and WCAG-AA contrast between text and surfaces.
Required fields: theme_name, colors (13 keys), status (4 keys), fonts (3 keys).
Optional with defaults: google_fonts_import (empty), radius ("12px"), shadows.
python3 $CLAUDE_PLUGIN_ROOT/skills/consult-dashboard/scripts/generate-dashboard.py "<engagement-dir>" --design-variables "<engagement-dir>/output/design-variables.json"
The script reads consult-project.json and every action-fields/<slug>/field.json (the
same read model as engagement-status.sh), counts research syntheses under scope/research/
and action-fields/<slug>/research/, loads the design-variables JSON, writes a self-contained
HTML file at <engagement-dir>/output/dashboard.html, and prints
{"success": true, "data": {"path": ..., "theme": ..., "completion_pct": ...}, "error": ""}.
After the dashboard is written, resolve any {{asm:}} assumption placeholders it
carries so the status view shows registered values instead of raw markers. Run a
read-only dry-run resolve (omit --in-place) and write the returned resolved
text back to dashboard.html yourself — this rewrites only the generated output,
never the assumption registry:
# 1. Dry-run resolve → JSON on stdout (omit --in-place; assumptions.json stays untouched).
# 2. Extract data.resolved_text and overwrite dashboard.html with it — but only when
# placeholders were actually found, so a marker-free dashboard is a clean no-op.
python3 $CLAUDE_PLUGIN_ROOT/scripts/resolve-assumptions.py "<engagement-dir>" resolve "<engagement-dir>/output/dashboard.html" \
| python3 -c 'import json,sys; e=json.load(sys.stdin); d=e.get("data") or {}; (open("<engagement-dir>/output/dashboard.html","w",encoding="utf-8").write(d["resolved_text"]) if e.get("success") and d.get("placeholders_found",0)>0 else (None if e.get("success") else sys.stderr.write((e.get("error") or "resolve failed")+chr(10))))'
resolve-assumptions.py — the plugin-level scripts/ resolver, distinct from the
skill-local generate-dashboard.py above — reads assumptions.json and returns
each {{asm:<suffix>}} marker replaced by the registered value (and, where
present, its status and provenance) in data.resolved_text. Take that text and
overwrite dashboard.html with it; when data.placeholders_found is 0 the
dashboard has no markers and no write is needed (a clean no-op). Deliberately
omit --in-place: the in-place mode records a used_by[] reference edge back
into assumptions.json, which would both mutate engagement state (breaking the
read-only contract below) and pollute the register's backlink graph with an
ephemeral, overwrite-on-rerun render artifact. The dry-run keeps assumptions.json
untouched. The resolver is fail-loud on an unknown or malformed placeholder (exit
1, success:false with a data.failed_check discriminator) — surface that as a
warning rather than aborting the dashboard.
Legacy fallback: the script also accepts --theme <path-to-theme.md> (best-effort
markdown parse) for CI/automated runs. Precedence: --design-variables > --theme >
built-in default.
open "<engagement-dir>/output/dashboard.html"
Tell the user the dashboard is open. To refresh after working on deliverables, just rerun the
script (re-running overwrites the previous output/dashboard.html), or let the
consult-dashboard-refresher agent regenerate it at a milestone — see Milestone Dashboard below.
The dashboard is also a checkpoint tool, not just a capstone. Once an engagement has a theme
configured (output/design-variables.json), the engagement skills offer a fresh dashboard at
natural milestones — consult-design-thinking after a deliverable reaches complete (or its
persona review closes), consult-action-fields after the WBS structure changes, and
consult-resume at re-entry. At those checkpoints the skill delegates to the
consult-dashboard-refresher agent (engagement_dir, plugin_root: $CLAUDE_PLUGIN_ROOT), which
runs the read-only generator and opens the HTML without a theme prompt. When no theme is
configured yet, the skills point the consultant back here to set one up first.
The generated HTML is a single self-contained page with these sections:
done/total count; each deliverable row shows its title, a
state badge, a five-step design-thinking indicator (empathize→define→ideate→prototype→test
with the current stage highlighted), and its persona-review status. A deliverable that an
upstream change has invalidated (lineage_status.status: "stale") carries a stale badge
next to its state, and a deliverable with declared dependencies shows a ⤴ depends on
hint listing the upstream deliverables to refresh first. A deliverable that has been published
via consult-publish shows a 📤 publish sub-row — one chip per published format naming
the format, the brief path, and the publish date, with a → render in Claude Design pointer
(hand the brief to Claude Design to render). An unpublished deliverable shows no sub-row.
A deliverable that carries any of the optional scheduling fields (start_date, due_date,
duration, owner, milestone) in its field.json shows a 🗓 schedule sub-row — an
owner chip, a start→due range chip, and a duration chip, preceded by a ◆ milestone marker
when the deliverable is a milestone. These fields are authored for the project-plan / schedule
read model (consult-project-plan, deliverable-graph.py schedule); a deliverable with none of
them set shows no schedule sub-row — the surface degrades silently, the same graceful pattern as
the publish sub-row. Read-only throughout: the dashboard never writes these fields.consult-publish, or (when all are published) hand
the briefs to Claude Design to render.A Warnings card appears only when a field.json is unreadable (surfaced, never conflated
with "pending").
consult-project.json, field.json, and assumptions.json without ever modifying them. The only file it writes is its own generated output/dashboard.html (rendered by generate-dashboard.py, then rewritten in place with resolved assumption values via the dry-run resolve above — the resolver reads assumptions.json read-only and records no used_by[] edge).output/dashboard.html.language field, which is
the deliverable axis (it controls the dashboard document's <html lang> and the language
badge, not how you address the user). Technical terms, skill names, and CLI commands remain in
English. See $CLAUDE_PLUGIN_ROOT/references/interaction-language.md.Guides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.
npx claudepluginhub cogni-work/insight-wave --plugin cogni-consult