spectoflow 0.20.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,13 +20,39 @@ An **agent-agnostic** spec-driven development framework with a **real-time local
20
20
  You speak in plain language; the framework classifies your intent and runs the right workflow. No
21
21
  ceremonial command to start.
22
22
 
23
- **Works with whichever coding agent you have** Claude Code, Codex, Cursor, Gemini CLI, OpenCode,
24
- Kiro CLI, Antigravity, and Kimi CLI are auto-detected at `init`. The dashboard's topbar always shows
25
- the **active agent**, front and center, with a switcher: pick another and it's verified as genuinely
26
- installed before activating (a red **"No agent found"** if none is) — it never silently activates
27
- something that isn't there. (Kimi CLI doesn't yet ship a non-interactive run mode, so spectoflow can
28
- set it as active but won't try to spawn it the agent pickers that launch a run grey it out rather
29
- than hide it.)
23
+ **Works with whichever coding agent you have.** `init` auto-detects what's installed; the dashboard's
24
+ topbar always shows the **active agent**, front and center, with a switcher pick another and it's
25
+ verified as genuinely installed before activating (a red **"No agent found"** if none is), never
26
+ silently activating something that isn't there.
27
+
28
+ > Note the terminology: "agent" is overloaded here on purpose, matching how the ecosystem uses the
29
+ > word. The table below is about **coding-agent CLIs** — the tool you already run in your terminal
30
+ > (Claude Code, Copilot CLI, …). spectoflow's own **team personas** (developer, qa-engineer, …) are a
31
+ > different, unrelated use of "agent" — see [Agents vs skills](#agents-vs-skills) further down.
32
+
33
+ | Coding agent | Headless run | Docs |
34
+ |---|---|---|
35
+ | Claude Code | ✓ | [code.claude.com/docs/en/cli-reference](https://code.claude.com/docs/en/cli-reference) |
36
+ | Codex | ✓ | [developers.openai.com/codex/cli/reference](https://developers.openai.com/codex/cli/reference) |
37
+ | Cursor CLI | ✓ | [cursor.com/docs/cli/overview](https://cursor.com/docs/cli/overview) |
38
+ | Gemini CLI | ✓ | [github.com/google-gemini/gemini-cli](https://github.com/google-gemini/gemini-cli) |
39
+ | OpenCode | ✓ | [opencode.ai/docs/cli](https://opencode.ai/docs/cli/) |
40
+ | Kiro CLI | ✓ | [kiro.dev/docs/cli/headless](https://kiro.dev/docs/cli/headless/) |
41
+ | Antigravity | ✓ | [antigravity.google/docs/cli/headless](https://antigravity.google/docs/cli/headless/) |
42
+ | GitHub Copilot CLI | ✓ | [docs.github.com/copilot/…/about-copilot-cli](https://docs.github.com/copilot/concepts/agents/about-copilot-cli) |
43
+ | Amazon Q Developer CLI | ✓ | [docs.aws.amazon.com/amazonq/…/command-line-chat](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-chat.html) |
44
+ | Factory Droid CLI | ✓ | [docs.factory.ai/droid-exec/overview](https://docs.factory.ai/droid-exec/overview) |
45
+ | Auggie CLI (Augment Code) | ✓ | [docs.augmentcode.com/cli/overview](https://docs.augmentcode.com/cli/overview) |
46
+ | Goose CLI (Block) | ✓ | [block.github.io/goose](https://block.github.io/goose/) |
47
+ | Kimi CLI | detectable, manual only | [github.com/MoonshotAI/kimi-cli](https://github.com/MoonshotAI/kimi-cli) |
48
+
49
+ "Headless run" means spectoflow can actually spawn it non-interactively (`Run`/`Orchestrate`/
50
+ `Summarize` work). Kimi CLI has no confirmed one-shot mode as of this writing — spectoflow still
51
+ detects it and lets you set it as the active agent, it just won't try to spawn it (the pickers that
52
+ launch a run grey it out rather than hide it); drive it yourself in its own terminal meanwhile. The
53
+ same live table, with your own install status, is in the dashboard's **Documentation** tab. Missing
54
+ one you use? `config.json → runners` still takes any custom command by hand — see
55
+ [`templates/README.md`](templates/README.md) — or open an issue.
30
56
 
31
57
  ## Install
32
58
 
@@ -141,16 +167,19 @@ spectoflow dashboard # → http://localhost:4319 (or --port=
141
167
  `spectoflow dashboard` is the simple way — it prints the URL and won't double-start (it detects a
142
168
  dashboard already running on the port). `spectoflow status` tells you whether one is up. Running the
143
169
  `server.js` directly still works for a manual/embedded setup. Zero dependencies, updates live via SSE +
144
- file watching. Eight tabs behind a dense icon-tab header (brand logo · subtitle · a slim
145
- global-progress meter · a sync dot · a **Run** quick-action · a **settings** gear): **Board** (the
146
- control-room Overview — KPI cards, a status donut, a **scope-vs-delivered area curve**, a
170
+ file watching. Ten tabs behind a dense icon-tab header (brand logo · subtitle · **active agent** ·
171
+ autonomy mode · language · a slim global-progress meter · a sync dot · a **Run** quick-action): **Board**
172
+ (the control-room Overview — compact KPI cards, a status donut, a **scope-vs-delivered area curve**, a
147
173
  workflow-at-a-glance strip, per-phase progress bars, filter chips + search — plus the phase board),
148
- **Requests** (tasks awaiting you `to_validate`/`to_analyze`), **Attention** (points the agent raised
149
- via a `::spectoflow attention msg=…` sentinel or that you noted edit/resolve/delete, or **validate →
150
- task**), **Backlog** (a flat sortable/filterable, paginated table of every task, defaulting to open
151
- work), **Workflow** (the pipeline as step cards — click one to enable/disable it, which edits
152
- `workflow.md`), **Agents & Skills** (enriched cards that open a full-body markdown drawer), **Chat** (a
153
- full-height group-chat panel), and **Info** (a project-at-a-glance summary). URLs are real routes
174
+ **Chat** (a full-height group-chat panel with **Summarize**/**Clear**), **Requests** (tasks awaiting
175
+ you `to_validate`/`to_analyze`), **Attention** (points the agent raised via a `::spectoflow attention
176
+ msg=…` sentinel or that you noted — edit/resolve/delete, or **validate task**), **Backlog** (a flat
177
+ sortable/filterable, paginated table of every task, defaulting to open work), **Workflow** (the
178
+ pipeline as step cards click one to enable/disable it, which edits `workflow.md`), **Agents &
179
+ Skills** (enriched cards that open a full-body markdown drawer), **Info** (a project-at-a-glance
180
+ summary), **Documentation** (the supported-agents table above, live with your own install status and
181
+ links, plus the CLI command reference), and **Personalize** (autonomy mode, language, design, the
182
+ active agent, and **Extend spectoflow** — described under *Customize* below). URLs are real routes
154
183
  (`/board`, `/backlog/T-012`, …). Charts are zero-dep, hand-rolled SVG in `dashboard/public/charts.js`
155
184
  (donut/area/bars/ring, animated, `prefers-reduced-motion`-aware), and every aggregate is computed
156
185
  client-side.
@@ -175,7 +204,8 @@ read-only endpoint, `GET /api/agentfile?path=` (scoped to `.spectoflow/agents/**
175
204
  `.spectoflow/skills/**`, path-traversal-safe) — the framework's only other server surface is
176
205
  unchanged.
177
206
 
178
- **Customize.** Settings → **Customize** lets you extend the project's own spectoflow install: add a
207
+ **Customize.** Personalize → **Extend spectoflow** lets you extend the project's own spectoflow
208
+ install: add a
179
209
  dashboard, a skill, or an agent by describing what you want (or hit **Auto** to have the agent survey
180
210
  the project and propose candidates), and it clarifies first if the ask is ambiguous. Dashboards are
181
211
  never raw HTML — they're a small **declarative block spec** (`markdown`, `kpi-row`, `chart-bars`,
package/bin/spectoflow.js CHANGED
@@ -474,10 +474,12 @@ ${c.dim('Docs:')} https://github.com/georgesmomo/spectoflow`);
474
474
  const HELP = {
475
475
  init: `${c.bold('spectoflow init')} ${c.dim('[dir] [--agent=a,b]')}\n
476
476
  Scaffold spectoflow into <dir> (default: current directory).
477
- Auto-detects installed agents (${c.dim('claude, codex, cursor, gemini')}) and writes their entry
478
- shims; override with ${c.g('--agent=claude,codex')}. Also wires ${c.bold('Playwright MCP')} into the
479
- project's ${c.dim('.mcp.json')} (idempotent never touches an existing entry).
480
- ${c.dim('An existing CLAUDE.md is preserved as CLAUDE.md.tomerge for you to merge on first run.')}`,
477
+ Auto-detects installed agents (${c.dim('claude, codex, cursor, gemini, opencode, kiro, antigravity,')}
478
+ ${c.dim('copilot, amazon-q, droid, auggie, goose, kimi')}) and writes their entry shims; override
479
+ with ${c.g('--agent=claude,codex')}. Also wires ${c.bold('Playwright MCP')} into the project's
480
+ ${c.dim('.mcp.json')} (idempotent never touches an existing entry).
481
+ ${c.dim('An existing CLAUDE.md is preserved as CLAUDE.md.tomerge for you to merge on first run.')}
482
+ ${c.dim('Full list with docs links: the dashboard\'s Documentation tab, or the README.')}`,
481
483
  update: `${c.bold('spectoflow update')} ${c.dim('[--dry-run] [--force|-f]')}\n
482
484
  Refresh framework-owned files (engine, dashboard, default agents & skills, AGENTS.md, policy…)
483
485
  to this CLI's version, ${c.bold('preserving your work')}: config.json, workflow.md, specs/, plans/
package/lib/adapters.js CHANGED
@@ -68,6 +68,10 @@ Argument: \`$ARGUMENTS\`
68
68
 
69
69
  // Priority order = which agent becomes the default when several are detected.
70
70
  //
71
+ // `docsUrl` points at that agent's own official CLI docs — cited from the research pass that set
72
+ // `runner`/`headless`, never guessed; it's surfaced verbatim in the dashboard's Documentation tab so
73
+ // "which agent is this and where do I read about it" has a real answer, not just an id.
74
+ //
71
75
  // `headless: false` marks an agent spectoflow can DETECT and let you set as active, but never spawn
72
76
  // itself — no confirmed non-interactive one-shot mode (prompt as trailing arg → stdout → exit) as of
73
77
  // this research pass, so `runner` is null on purpose (a fabricated command would just fail silently
@@ -75,6 +79,16 @@ Argument: \`$ARGUMENTS\`
75
79
  // for it, rather than hiding it — you can drive it yourself in its own terminal meanwhile, and
76
80
  // `config.json → runners` is still yours to hand-wire a command into if one ships later.
77
81
  //
82
+ // A runner string with more than one flag deliberately puts the trailing prompt right after whichever
83
+ // flag takes a value (e.g. `copilot -s --allow-all-tools -p`, not `copilot -p --allow-all-tools`) —
84
+ // runner.js spawns `[...parts.slice(1), prompt]`, appending the prompt as the LAST token, so a
85
+ // value-taking flag must be the last one in the string or the prompt lands on the wrong flag.
86
+ //
87
+ // Researched against both github.com/Fission-AI/OpenSpec/blob/main/docs/supported-tools.md and
88
+ // github.github.io/spec-kit/reference/integrations.html (broad agent-compatibility lists) — those
89
+ // pages document IDE/slash-command integration, not headless CLI support, so every entry below was
90
+ // independently verified against that tool's own primary docs regardless of appearing there.
91
+ //
78
92
  // Left out of KNOWN_AGENTS entirely (not even headless:false) — researched, not re-added on a whim:
79
93
  // DeepSeek Harness (deepseek-ai/deepseek-harness). It has no single installable binary to detect —
80
94
  // it's invoked as `npx @deepseek-ai/dsh <subcommand>`, is explicitly a local WEB-APP framework (not a
@@ -85,63 +99,127 @@ Argument: \`$ARGUMENTS\`
85
99
  const REGISTRY = [
86
100
  {
87
101
  id: 'claude',
102
+ label: 'Claude Code',
88
103
  entries: [
89
104
  { path: 'CLAUDE.md', content: CLAUDE_MD },
90
105
  { path: '.claude/commands/spectoflow.md', content: SLASH_CMD },
91
106
  ],
92
107
  runner: 'claude -p --permission-mode acceptEdits',
93
108
  headless: true,
109
+ docsUrl: 'https://code.claude.com/docs/en/cli-reference',
94
110
  detect: { bin: 'claude', dirs: ['.claude'] },
95
111
  },
96
112
  {
97
113
  id: 'codex',
114
+ label: 'Codex',
98
115
  entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }],
99
116
  runner: 'codex exec',
100
117
  headless: true,
118
+ docsUrl: 'https://developers.openai.com/codex/cli/reference',
101
119
  detect: { bin: 'codex', dirs: ['.codex'] },
102
120
  },
103
121
  {
104
122
  id: 'cursor',
123
+ label: 'Cursor',
105
124
  entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }],
106
125
  runner: 'cursor-agent -p',
107
126
  headless: true,
127
+ docsUrl: 'https://cursor.com/docs/cli/overview',
108
128
  detect: { bin: 'cursor-agent', dirs: ['.cursor'] },
109
129
  },
110
130
  {
111
131
  id: 'gemini',
132
+ label: 'Gemini CLI',
112
133
  entries: [{ path: 'GEMINI.md', content: GEMINI_MD }],
113
134
  runner: 'gemini -p',
114
135
  headless: true,
136
+ docsUrl: 'https://github.com/google-gemini/gemini-cli',
115
137
  detect: { bin: 'gemini', dirs: ['.gemini'] },
116
138
  },
117
139
  {
118
140
  id: 'opencode',
141
+ label: 'OpenCode',
119
142
  entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }],
120
143
  runner: 'opencode run --quiet',
121
144
  headless: true,
145
+ docsUrl: 'https://opencode.ai/docs/cli/',
122
146
  detect: { bin: 'opencode', dirs: ['.opencode'] },
123
147
  },
124
148
  {
125
149
  id: 'kiro',
150
+ label: 'Kiro CLI',
126
151
  entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }],
127
152
  runner: 'kiro-cli chat --no-interactive --trust-all-tools',
128
153
  headless: true,
154
+ docsUrl: 'https://kiro.dev/docs/cli/headless/',
129
155
  detect: { bin: 'kiro-cli', dirs: ['.kiro'] },
130
156
  },
131
157
  {
132
158
  id: 'antigravity',
159
+ label: 'Antigravity',
133
160
  entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }],
134
161
  runner: 'agy -p',
135
162
  headless: true,
136
- detect: { bin: 'agy' },
163
+ docsUrl: 'https://antigravity.google/docs/cli/headless/',
164
+ detect: { bin: 'agy', dirs: [] },
137
165
  },
138
166
  {
139
167
  id: 'kimi',
168
+ label: 'Kimi CLI',
140
169
  entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }],
141
170
  runner: null, // no confirmed non-interactive one-shot mode — see the note above REGISTRY
142
171
  headless: false,
172
+ docsUrl: 'https://github.com/MoonshotAI/kimi-cli',
143
173
  detect: { bin: 'kimi', dirs: [] },
144
174
  },
175
+ {
176
+ id: 'copilot',
177
+ label: 'GitHub Copilot CLI',
178
+ entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }], // also reads CLAUDE.md/GEMINI.md and its own .github/copilot-instructions.md natively
179
+ runner: 'copilot -s --allow-all-tools -p',
180
+ headless: true,
181
+ docsUrl: 'https://docs.github.com/copilot/concepts/agents/about-copilot-cli',
182
+ // No detect.dirs on purpose: `.github/` is common on any project with GitHub Actions, whether or
183
+ // not Copilot CLI is set up — using it as a signal would falsely mark Copilot "installed" on
184
+ // countless unrelated projects. PATH detection (the bin) only.
185
+ detect: { bin: 'copilot', dirs: [] },
186
+ },
187
+ {
188
+ id: 'amazon-q',
189
+ label: 'Amazon Q Developer CLI',
190
+ entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }], // NOT confirmed native — Q wires memory via `.amazonq/rules/**/*.md` referenced in its own agent config; this pointer is a harmless, forward-compatible default in the meantime
191
+ runner: 'q chat --no-interactive --trust-all-tools',
192
+ headless: true,
193
+ docsUrl: 'https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-chat.html',
194
+ detect: { bin: 'q', dirs: ['.amazonq'] },
195
+ },
196
+ {
197
+ id: 'droid',
198
+ label: 'Factory Droid CLI',
199
+ entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }],
200
+ runner: 'droid exec',
201
+ headless: true,
202
+ docsUrl: 'https://docs.factory.ai/droid-exec/overview',
203
+ detect: { bin: 'droid', dirs: ['.factory'] },
204
+ },
205
+ {
206
+ id: 'auggie',
207
+ label: 'Auggie CLI',
208
+ entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }],
209
+ runner: 'auggie --quiet --print',
210
+ headless: true,
211
+ docsUrl: 'https://docs.augmentcode.com/cli/overview',
212
+ detect: { bin: 'auggie', dirs: ['.augment'] },
213
+ },
214
+ {
215
+ id: 'goose',
216
+ label: 'Goose CLI',
217
+ entries: [{ path: 'AGENTS.md', content: ROOT_AGENTS_MD }], // memory-file convention not confirmed AGENTS.md-native — same harmless-default treatment as amazon-q
218
+ runner: 'goose run -t',
219
+ headless: true,
220
+ docsUrl: 'https://block.github.io/goose/',
221
+ detect: { bin: 'goose', dirs: ['.goose'] },
222
+ },
145
223
  ];
146
224
 
147
225
  const byId = (id) => REGISTRY.find((a) => a.id === id);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spectoflow",
3
- "version": "0.20.1",
3
+ "version": "0.21.0",
4
4
  "description": "Agent-agnostic spec-driven development framework + real-time local control plane. Markdown artifacts, intent router, workflow-by-scope.",
5
5
  "keywords": [
6
6
  "spec-driven-development",
@@ -28,6 +28,8 @@ sit at the project root and just point back here.
28
28
  ```
29
29
  - **See what you got:** `spectoflow list` (agents, skills & workflow at a glance), or `spectoflow
30
30
  agents` / `spectoflow skills` / `spectoflow workflow`. Append `-h` to any command for its help.
31
+ (These "agents" are spectoflow's own team personas below, not the coding-agent CLI you're typing
32
+ into — see the dashboard's **Documentation** tab for which coding-agent CLIs spectoflow can drive.)
31
33
  - **Change how it runs** in the dashboard's **Personalize** tab (the **active agent**, always shown
32
34
  in the topbar too — switching is verified against what's actually installed before it activates —
33
35
  plus autonomy mode, output language, and the dashboard **design**), or by editing `config.json`.
@@ -151,7 +151,7 @@ function render(){
151
151
  if(meter) meter.title=`${t('kpi.globalProgress')}: ${s.pct}% (${s.done}/${s.total} ${t('kpi.tasksLabel')})`;
152
152
  renderOverview(); renderBoard(); renderBacklog(); renderWorkflow(); renderTeam();
153
153
  renderChatLog($('#chatLog')); renderChatLog($('#chatTabLog'));
154
- renderSidebar(); renderRequests(); renderAttention(); renderInfo(); renderSettings();
154
+ renderSidebar(); renderRequests(); renderAttention(); renderInfo(); renderDocs(); renderSettings();
155
155
  renderCustomDashboards(); // adds/removes nav tabs + panels before applyActiveTab() below reads them
156
156
  applyActiveTab(); // re-apply the current tab so an SSE-driven re-render never resets to Board
157
157
  applyI18nStatic(); // re-translate the static markup (nav, headers, placeholders…) for this tick's language
@@ -264,7 +264,7 @@ function renderOverview(){
264
264
 
265
265
  // KPI row
266
266
  const kpis=el('div','kpi-row');
267
- kpis.append(kpiCard(t('kpi.globalProgress'), ring(s.pct,72), `${s.done}/${s.total} ${t('kpi.tasksLabel')}`, cssv('--s-done')));
267
+ kpis.append(kpiCard(t('kpi.globalProgress'), ring(s.pct,52), `${s.done}/${s.total} ${t('kpi.tasksLabel')}`, cssv('--s-done')));
268
268
  kpis.append(kpiCard(t('status.in_progress'), numBlock(s.byStatus.in_progress||0,'var(--s-in_progress)'), t('kpi.tasksLabel'), cssv('--s-in_progress')));
269
269
  kpis.append(kpiCard(t('status.to_validate'), numBlock(s.byStatus.to_validate||0,'var(--s-to_validate)'), t('kpi.awaitingReview'), cssv('--s-to_validate')));
270
270
  const r=s.running||{};
@@ -967,7 +967,7 @@ async function czSubmit(kind,description,agent){
967
967
  // A custom dashboard (Customize page) gets its own tab id "custom:<id>" and its own URL shape
968
968
  // /custom/<id> — kept out of ROUTES (a fixed list) since the set of custom ids is dynamic; recognized
969
969
  // by a dedicated branch in tabFromPath()/navigateTab() instead.
970
- const ROUTES=['board','requests','attention','backlog','workflow','team','chat','info','settings'];
970
+ const ROUTES=['board','requests','attention','backlog','workflow','team','chat','info','docs','settings'];
971
971
  function tabFromPath(){
972
972
  const s=location.pathname.split('/').filter(Boolean);
973
973
  if(s[0]==='custom'&&s[1]) return 'custom:'+decodeURIComponent(s[1]);
@@ -1046,7 +1046,11 @@ function mdLite(raw){
1046
1046
  // 2) escape HTML — everything below builds markup only from this escaped text
1047
1047
  text=escHtml(text);
1048
1048
  // 3) convert a small markdown subset to HTML
1049
- const inline=s=> s.replace(/`([^`]+)`/g,'<code>$1</code>').replace(/\*\*([^*]+)\*\*/g,'<strong>$1</strong>');
1049
+ const inline=s=> s
1050
+ .replace(/`([^`]+)`/g,'<code>$1</code>')
1051
+ .replace(/\*\*([^*]+)\*\*/g,'<strong>$1</strong>')
1052
+ .replace(/\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g,'<a href="$2" target="_blank" rel="noopener">$1</a>') // [text](url)
1053
+ .replace(/(^|[^"'>])(https?:\/\/[^\s<]+)/g,'$1<a href="$2" target="_blank" rel="noopener">$2</a>'); // bare https://… URLs, skipping ones already inside an href/text we just built
1050
1054
  const lines=text.split('\n');
1051
1055
  let html='', inCode=false, codeBuf=[], listBuf=[], paraBuf=[];
1052
1056
  const flushPara=()=>{ if(paraBuf.length){ html+='<p>'+paraBuf.join(' ')+'</p>'; paraBuf=[]; } };
@@ -1165,6 +1169,73 @@ function renderInfo(){
1165
1169
  box.append(infoSection(t('info.workflowLabel'),'workflow',wfList));
1166
1170
  }
1167
1171
 
1172
+ // ---- Documentation tab: which coding agents spectoflow can drive (with links to each one's own
1173
+ // docs, sourced from the same registry the topbar switcher reads) + the CLI command reference.
1174
+ // Never build this table from anything but P.knownAgents/P.installedAgents — that data comes from a
1175
+ // real PATH/config-dir test on the server, never a guess spectoflow hasn't verified. ----
1176
+ function linkEl(text,url){ const a=document.createElement('a'); a.href=url; a.target='_blank'; a.rel='noopener'; a.textContent=text; return a; }
1177
+ function docsAgentsTable(){
1178
+ const known=P.knownAgents||[], installed=P.installedAgents||[];
1179
+ const wrap=el('div','table-scroll'); const tbl=el('table','backlog-table');
1180
+ const thead=el('thead'); const htr=el('tr');
1181
+ [t('docs.colAgent'),t('docs.colStatus'),t('docs.colDocs')].forEach(c=>htr.append(el('th',null,c)));
1182
+ thead.append(htr); tbl.append(thead);
1183
+ const tbody=el('tbody');
1184
+ known.forEach(a=>{
1185
+ const tr=el('tr');
1186
+ tr.append(el('td',null,a.label));
1187
+ const statusTd=el('td');
1188
+ const isInstalled=installed.includes(a.id);
1189
+ const chip=el('span','chip s-'+(isInstalled?'done':'todo'), isInstalled?t('docs.installed'):t('docs.notInstalled'));
1190
+ statusTd.append(chip);
1191
+ if(!a.headless){ statusTd.append(document.createTextNode(' ')); statusTd.append(el('span','docs-manual-badge',t('docs.manualOnly'))); }
1192
+ tr.append(statusTd);
1193
+ const docsTd=el('td');
1194
+ if(a.docsUrl) docsTd.append(linkEl(t('docs.officialDocs'),a.docsUrl));
1195
+ tr.append(docsTd);
1196
+ tbody.append(tr);
1197
+ });
1198
+ tbl.append(tbody); wrap.append(tbl);
1199
+ return wrap;
1200
+ }
1201
+ function docsCommandsTable(){
1202
+ const rows=[
1203
+ ['spectoflow init [dir] [--agent=a,b]', t('docs.cmd.init')],
1204
+ ['spectoflow update [--dry-run] [--force|-f]', t('docs.cmd.update')],
1205
+ ['spectoflow status', t('docs.cmd.status')],
1206
+ ['spectoflow dashboard [--port=NNNN]', t('docs.cmd.dashboard')],
1207
+ ['spectoflow dashboard status|stop|restart', t('docs.cmd.dashboardSub')],
1208
+ ['spectoflow dashboard create "…" | --auto', t('docs.cmd.dashboardCreate')],
1209
+ ['spectoflow skill create "…" | --auto', t('docs.cmd.skillCreate')],
1210
+ ['spectoflow agent create "…" | --auto', t('docs.cmd.agentCreate')],
1211
+ ['spectoflow list', t('docs.cmd.list')],
1212
+ ['spectoflow agents · skills · workflow', t('docs.cmd.explore')],
1213
+ ];
1214
+ const wrap=el('div','table-scroll'); const tbl=el('table','backlog-table');
1215
+ const thead=el('thead'); const htr=el('tr');
1216
+ [t('docs.colCommand'),t('docs.colWhatItDoes')].forEach(c=>htr.append(el('th',null,c)));
1217
+ thead.append(htr); tbl.append(thead);
1218
+ const tbody=el('tbody');
1219
+ rows.forEach(([cmd,desc])=>{
1220
+ const tr=el('tr');
1221
+ const cmdTd=el('td'); const code=el('code',null,cmd); cmdTd.append(code); tr.append(cmdTd);
1222
+ tr.append(el('td',null,desc));
1223
+ tbody.append(tr);
1224
+ });
1225
+ tbl.append(tbody); wrap.append(tbl);
1226
+ return wrap;
1227
+ }
1228
+ function renderDocs(){
1229
+ const box=$('#docsBody'); if(!box) return;
1230
+ box.innerHTML='';
1231
+ box.append(infoSection(t('docs.agentsTitle'),'agents',docsAgentsTable()));
1232
+ box.append(infoSection(t('docs.commandsTitle'),'run',docsCommandsTable()));
1233
+ const note=el('p','docs-note');
1234
+ note.append(document.createTextNode(t('docs.moreNote')+' '));
1235
+ note.append(linkEl('github.com/georgesmomo/spectoflow','https://github.com/georgesmomo/spectoflow'));
1236
+ box.append(note);
1237
+ }
1238
+
1168
1239
  function openDrawer(id,keep){
1169
1240
  // named `task`, not `t` — `t` is the global translation function (see i18n.js) and this whole
1170
1241
  // function calls it repeatedly below; shadowing it with a task variable would break every call.
@@ -20,7 +20,7 @@
20
20
  const I18N = {
21
21
  en: {
22
22
  'nav.board':'Board','nav.requests':'Requests','nav.attention':'Attention','nav.backlog':'Backlog',
23
- 'nav.workflow':'Workflow','nav.team':'Agents & Skills','nav.chat':'Chat','nav.info':'Info','nav.settings':'Personalize',
23
+ 'nav.workflow':'Workflow','nav.team':'Agents & Skills','nav.chat':'Chat','nav.info':'Info','nav.docs':'Documentation','nav.settings':'Personalize',
24
24
  'status.todo':'To do','status.in_progress':'In progress','status.to_validate':'To validate',
25
25
  'status.to_analyze':'To analyze','status.done':'Done','status.blocked':'Blocked',
26
26
  'filter.all':'All','filter.open':'Open','filter.resolved':'Resolved',
@@ -114,10 +114,25 @@ en: {
114
114
  'customize.add.dashboard':'Add dashboard','customize.add.skill':'Add skill','customize.add.agent':'Add agent',
115
115
  'customize.empty.dashboard':'No custom dashboards yet.','customize.empty.skill':'No custom skills yet.','customize.empty.agent':'No custom agents yet.',
116
116
  'customize.describePh':'Describe what you want…','customize.auto':'Auto','customize.generate':'Generate','customize.blocksSub':'block(s)',
117
+ 'docs.title':'Documentation','docs.sub':'Which coding agents spectoflow can drive, and the commands that drive them.',
118
+ 'docs.agentsTitle':'Supported agents','docs.commandsTitle':'Commands',
119
+ 'docs.colAgent':'Agent','docs.colStatus':'Status','docs.colDocs':'Docs','docs.colCommand':'Command','docs.colWhatItDoes':'What it does',
120
+ 'docs.installed':'Installed','docs.notInstalled':'Not installed','docs.manualOnly':'Manual only','docs.officialDocs':'Official docs ↗',
121
+ 'docs.moreNote':'Full reference, source and license on GitHub:',
122
+ 'docs.cmd.init':'Scaffold a project (auto-detects agents; wires Playwright MCP).',
123
+ 'docs.cmd.update':'Refresh framework files to this kit version, preserving your work.',
124
+ 'docs.cmd.status':'Progress + whether the dashboard is running.',
125
+ 'docs.cmd.dashboard':'Start the control plane in the background.',
126
+ 'docs.cmd.dashboardSub':'Check, stop, or restart the running dashboard.',
127
+ 'docs.cmd.dashboardCreate':'Generate a custom dashboard from the terminal.',
128
+ 'docs.cmd.skillCreate':'Generate a project-specific skill from the terminal.',
129
+ 'docs.cmd.agentCreate':'Generate a project-specific agent persona from the terminal.',
130
+ 'docs.cmd.list':'Agents, skills and the workflow at a glance.',
131
+ 'docs.cmd.explore':'List the team personas, the procedures, or the pipeline steps.',
117
132
  },
118
133
  fr: {
119
134
  'nav.board':'Tableau','nav.requests':'Demandes','nav.attention':'Attention','nav.backlog':'Backlog',
120
- 'nav.workflow':'Workflow','nav.team':'Agents et compétences','nav.chat':'Chat','nav.info':'Infos','nav.settings':'Personnalisation',
135
+ 'nav.workflow':'Workflow','nav.team':'Agents et compétences','nav.chat':'Chat','nav.info':'Infos','nav.docs':'Documentation','nav.settings':'Personnalisation',
121
136
  'status.todo':'À faire','status.in_progress':'En cours','status.to_validate':'À valider',
122
137
  'status.to_analyze':'À analyser','status.done':'Terminé','status.blocked':'Bloqué',
123
138
  'filter.all':'Tous','filter.open':'Ouverts','filter.resolved':'Résolus',
@@ -211,10 +226,25 @@ fr: {
211
226
  'customize.add.dashboard':'Ajouter un dashboard','customize.add.skill':'Ajouter une compétence','customize.add.agent':'Ajouter un agent',
212
227
  'customize.empty.dashboard':'Aucun dashboard personnalisé pour l’instant.','customize.empty.skill':'Aucune compétence personnalisée pour l’instant.','customize.empty.agent':'Aucun agent personnalisé pour l’instant.',
213
228
  'customize.describePh':'Décrivez ce que vous voulez…','customize.auto':'Auto','customize.generate':'Générer','customize.blocksSub':'bloc(s)',
229
+ 'docs.title':'Documentation','docs.sub':'Les agents de code que spectoflow peut piloter, et les commandes qui les pilotent.',
230
+ 'docs.agentsTitle':'Agents pris en charge','docs.commandsTitle':'Commandes',
231
+ 'docs.colAgent':'Agent','docs.colStatus':'Statut','docs.colDocs':'Docs','docs.colCommand':'Commande','docs.colWhatItDoes':'Ce que ça fait',
232
+ 'docs.installed':'Installé','docs.notInstalled':'Non installé','docs.manualOnly':'Manuel uniquement','docs.officialDocs':'Doc officielle ↗',
233
+ 'docs.moreNote':'Référence complète, source et licence sur GitHub :',
234
+ 'docs.cmd.init':'Initialise un projet (détecte les agents automatiquement ; câble Playwright MCP).',
235
+ 'docs.cmd.update':'Met à jour les fichiers du framework vers cette version, en préservant vos modifications.',
236
+ 'docs.cmd.status':'Progression + si le dashboard tourne.',
237
+ 'docs.cmd.dashboard':'Démarre le plan de contrôle en arrière-plan.',
238
+ 'docs.cmd.dashboardSub':'Vérifie, arrête ou redémarre le dashboard en cours.',
239
+ 'docs.cmd.dashboardCreate':'Génère un dashboard personnalisé depuis le terminal.',
240
+ 'docs.cmd.skillCreate':'Génère une compétence propre au projet depuis le terminal.',
241
+ 'docs.cmd.agentCreate':'Génère un agent (persona) propre au projet depuis le terminal.',
242
+ 'docs.cmd.list':'Agents, compétences et workflow en un coup d’œil.',
243
+ 'docs.cmd.explore':'Liste les personas de l’équipe, les procédures ou les étapes du pipeline.',
214
244
  },
215
245
  es: {
216
246
  'nav.board':'Tablero','nav.requests':'Solicitudes','nav.attention':'Atención','nav.backlog':'Backlog',
217
- 'nav.workflow':'Workflow','nav.team':'Agentes y habilidades','nav.chat':'Chat','nav.info':'Info','nav.settings':'Personalizar',
247
+ 'nav.workflow':'Workflow','nav.team':'Agentes y habilidades','nav.chat':'Chat','nav.info':'Info','nav.docs':'Documentación','nav.settings':'Personalizar',
218
248
  'status.todo':'Por hacer','status.in_progress':'En curso','status.to_validate':'Por validar',
219
249
  'status.to_analyze':'Por analizar','status.done':'Hecho','status.blocked':'Bloqueado',
220
250
  'filter.all':'Todos','filter.open':'Abiertos','filter.resolved':'Resueltos',
@@ -308,10 +338,25 @@ es: {
308
338
  'customize.add.dashboard':'Añadir dashboard','customize.add.skill':'Añadir habilidad','customize.add.agent':'Añadir agente',
309
339
  'customize.empty.dashboard':'Aún no hay dashboards personalizados.','customize.empty.skill':'Aún no hay habilidades personalizadas.','customize.empty.agent':'Aún no hay agentes personalizados.',
310
340
  'customize.describePh':'Describe lo que quieres…','customize.auto':'Auto','customize.generate':'Generar','customize.blocksSub':'bloque(s)',
341
+ 'docs.title':'Documentación','docs.sub':'Qué agentes de código puede pilotar spectoflow, y los comandos que los pilotan.',
342
+ 'docs.agentsTitle':'Agentes compatibles','docs.commandsTitle':'Comandos',
343
+ 'docs.colAgent':'Agente','docs.colStatus':'Estado','docs.colDocs':'Docs','docs.colCommand':'Comando','docs.colWhatItDoes':'Qué hace',
344
+ 'docs.installed':'Instalado','docs.notInstalled':'No instalado','docs.manualOnly':'Solo manual','docs.officialDocs':'Docs oficial ↗',
345
+ 'docs.moreNote':'Referencia completa, código fuente y licencia en GitHub:',
346
+ 'docs.cmd.init':'Crea un proyecto (detecta agentes automáticamente; conecta Playwright MCP).',
347
+ 'docs.cmd.update':'Actualiza los archivos del framework a esta versión, preservando tu trabajo.',
348
+ 'docs.cmd.status':'Progreso + si el dashboard está en ejecución.',
349
+ 'docs.cmd.dashboard':'Inicia el panel de control en segundo plano.',
350
+ 'docs.cmd.dashboardSub':'Consulta, detiene o reinicia el dashboard en ejecución.',
351
+ 'docs.cmd.dashboardCreate':'Genera un dashboard personalizado desde la terminal.',
352
+ 'docs.cmd.skillCreate':'Genera una habilidad propia del proyecto desde la terminal.',
353
+ 'docs.cmd.agentCreate':'Genera un agente (persona) propio del proyecto desde la terminal.',
354
+ 'docs.cmd.list':'Agentes, habilidades y workflow de un vistazo.',
355
+ 'docs.cmd.explore':'Lista los personas del equipo, los procedimientos o los pasos del pipeline.',
311
356
  },
312
357
  de: {
313
358
  'nav.board':'Board','nav.requests':'Anfragen','nav.attention':'Hinweise','nav.backlog':'Backlog',
314
- 'nav.workflow':'Workflow','nav.team':'Agenten & Skills','nav.chat':'Chat','nav.info':'Info','nav.settings':'Personalisieren',
359
+ 'nav.workflow':'Workflow','nav.team':'Agenten & Skills','nav.chat':'Chat','nav.info':'Info','nav.docs':'Dokumentation','nav.settings':'Personalisieren',
315
360
  'status.todo':'Offen','status.in_progress':'In Arbeit','status.to_validate':'Zu prüfen',
316
361
  'status.to_analyze':'Zu analysieren','status.done':'Erledigt','status.blocked':'Blockiert',
317
362
  'filter.all':'Alle','filter.open':'Offen','filter.resolved':'Erledigt',
@@ -405,10 +450,25 @@ de: {
405
450
  'customize.add.dashboard':'Dashboard hinzufügen','customize.add.skill':'Skill hinzufügen','customize.add.agent':'Agent hinzufügen',
406
451
  'customize.empty.dashboard':'Noch keine eigenen Dashboards.','customize.empty.skill':'Noch keine eigenen Skills.','customize.empty.agent':'Noch keine eigenen Agenten.',
407
452
  'customize.describePh':'Beschreiben Sie, was Sie wollen…','customize.auto':'Auto','customize.generate':'Generieren','customize.blocksSub':'Block/Blöcke',
453
+ 'docs.title':'Dokumentation','docs.sub':'Welche Coding-Agenten spectoflow steuern kann, und die Befehle dafür.',
454
+ 'docs.agentsTitle':'Unterstützte Agenten','docs.commandsTitle':'Befehle',
455
+ 'docs.colAgent':'Agent','docs.colStatus':'Status','docs.colDocs':'Docs','docs.colCommand':'Befehl','docs.colWhatItDoes':'Was er macht',
456
+ 'docs.installed':'Installiert','docs.notInstalled':'Nicht installiert','docs.manualOnly':'Nur manuell','docs.officialDocs':'Offizielle Docs ↗',
457
+ 'docs.moreNote':'Vollständige Referenz, Quellcode und Lizenz auf GitHub:',
458
+ 'docs.cmd.init':'Projekt aufsetzen (erkennt Agenten automatisch; verdrahtet Playwright MCP).',
459
+ 'docs.cmd.update':'Framework-Dateien auf diese Version aktualisieren, eigene Änderungen bleiben erhalten.',
460
+ 'docs.cmd.status':'Fortschritt + ob das Dashboard läuft.',
461
+ 'docs.cmd.dashboard':'Startet die Kontrollzentrale im Hintergrund.',
462
+ 'docs.cmd.dashboardSub':'Prüft, stoppt oder startet das laufende Dashboard neu.',
463
+ 'docs.cmd.dashboardCreate':'Erzeugt ein individuelles Dashboard über das Terminal.',
464
+ 'docs.cmd.skillCreate':'Erzeugt einen projektspezifischen Skill über das Terminal.',
465
+ 'docs.cmd.agentCreate':'Erzeugt eine projektspezifische Agenten-Persona über das Terminal.',
466
+ 'docs.cmd.list':'Agenten, Skills und Workflow auf einen Blick.',
467
+ 'docs.cmd.explore':'Listet die Team-Personas, die Verfahren oder die Pipeline-Schritte.',
408
468
  },
409
469
  pt: {
410
470
  'nav.board':'Painel','nav.requests':'Pedidos','nav.attention':'Atenção','nav.backlog':'Backlog',
411
- 'nav.workflow':'Workflow','nav.team':'Agentes e habilidades','nav.chat':'Chat','nav.info':'Info','nav.settings':'Personalizar',
471
+ 'nav.workflow':'Workflow','nav.team':'Agentes e habilidades','nav.chat':'Chat','nav.info':'Info','nav.docs':'Documentação','nav.settings':'Personalizar',
412
472
  'status.todo':'A fazer','status.in_progress':'Em curso','status.to_validate':'Por validar',
413
473
  'status.to_analyze':'Por analisar','status.done':'Concluído','status.blocked':'Bloqueado',
414
474
  'filter.all':'Todos','filter.open':'Abertos','filter.resolved':'Resolvidos',
@@ -502,10 +562,25 @@ pt: {
502
562
  'customize.add.dashboard':'Adicionar dashboard','customize.add.skill':'Adicionar habilidade','customize.add.agent':'Adicionar agente',
503
563
  'customize.empty.dashboard':'Ainda sem dashboards personalizados.','customize.empty.skill':'Ainda sem habilidades personalizadas.','customize.empty.agent':'Ainda sem agentes personalizados.',
504
564
  'customize.describePh':'Descreva o que quer…','customize.auto':'Auto','customize.generate':'Gerar','customize.blocksSub':'bloco(s)',
565
+ 'docs.title':'Documentação','docs.sub':'Quais agentes de código o spectoflow consegue conduzir, e os comandos que os conduzem.',
566
+ 'docs.agentsTitle':'Agentes suportados','docs.commandsTitle':'Comandos',
567
+ 'docs.colAgent':'Agente','docs.colStatus':'Estado','docs.colDocs':'Docs','docs.colCommand':'Comando','docs.colWhatItDoes':'O que faz',
568
+ 'docs.installed':'Instalado','docs.notInstalled':'Não instalado','docs.manualOnly':'Só manual','docs.officialDocs':'Docs oficial ↗',
569
+ 'docs.moreNote':'Referência completa, código-fonte e licença no GitHub:',
570
+ 'docs.cmd.init':'Cria um projeto (deteta agentes automaticamente; liga o Playwright MCP).',
571
+ 'docs.cmd.update':'Atualiza os ficheiros do framework para esta versão, preservando o seu trabalho.',
572
+ 'docs.cmd.status':'Progresso + se o dashboard está em execução.',
573
+ 'docs.cmd.dashboard':'Inicia o painel de controlo em segundo plano.',
574
+ 'docs.cmd.dashboardSub':'Verifica, para ou reinicia o dashboard em execução.',
575
+ 'docs.cmd.dashboardCreate':'Gera um dashboard personalizado a partir do terminal.',
576
+ 'docs.cmd.skillCreate':'Gera uma competência própria do projeto a partir do terminal.',
577
+ 'docs.cmd.agentCreate':'Gera um agente (persona) próprio do projeto a partir do terminal.',
578
+ 'docs.cmd.list':'Agentes, competências e workflow de relance.',
579
+ 'docs.cmd.explore':'Lista os personas da equipa, os procedimentos ou os passos do pipeline.',
505
580
  },
506
581
  it: {
507
582
  'nav.board':'Bacheca','nav.requests':'Richieste','nav.attention':'Attenzione','nav.backlog':'Backlog',
508
- 'nav.workflow':'Workflow','nav.team':'Agenti e competenze','nav.chat':'Chat','nav.info':'Info','nav.settings':'Personalizza',
583
+ 'nav.workflow':'Workflow','nav.team':'Agenti e competenze','nav.chat':'Chat','nav.info':'Info','nav.docs':'Documentazione','nav.settings':'Personalizza',
509
584
  'status.todo':'Da fare','status.in_progress':'In corso','status.to_validate':'Da convalidare',
510
585
  'status.to_analyze':'Da analizzare','status.done':'Fatto','status.blocked':'Bloccato',
511
586
  'filter.all':'Tutti','filter.open':'Aperti','filter.resolved':'Risolti',
@@ -599,6 +674,21 @@ it: {
599
674
  'customize.add.dashboard':'Aggiungi dashboard','customize.add.skill':'Aggiungi skill','customize.add.agent':'Aggiungi agente',
600
675
  'customize.empty.dashboard':'Ancora nessuna dashboard personalizzata.','customize.empty.skill':'Ancora nessuna skill personalizzata.','customize.empty.agent':'Ancora nessun agente personalizzato.',
601
676
  'customize.describePh':'Descrivi cosa vuoi…','customize.auto':'Auto','customize.generate':'Genera','customize.blocksSub':'blocco/i',
677
+ 'docs.title':'Documentazione','docs.sub':'Quali agenti di codice spectoflow può guidare, e i comandi che li guidano.',
678
+ 'docs.agentsTitle':'Agenti supportati','docs.commandsTitle':'Comandi',
679
+ 'docs.colAgent':'Agente','docs.colStatus':'Stato','docs.colDocs':'Docs','docs.colCommand':'Comando','docs.colWhatItDoes':'Cosa fa',
680
+ 'docs.installed':'Installato','docs.notInstalled':'Non installato','docs.manualOnly':'Solo manuale','docs.officialDocs':'Docs ufficiale ↗',
681
+ 'docs.moreNote':'Riferimento completo, codice sorgente e licenza su GitHub:',
682
+ 'docs.cmd.init':'Crea un progetto (rileva gli agenti automaticamente; collega Playwright MCP).',
683
+ 'docs.cmd.update':'Aggiorna i file del framework a questa versione, preservando il tuo lavoro.',
684
+ 'docs.cmd.status':'Avanzamento + se il dashboard è in esecuzione.',
685
+ 'docs.cmd.dashboard':'Avvia il pannello di controllo in background.',
686
+ 'docs.cmd.dashboardSub':'Controlla, ferma o riavvia il dashboard in esecuzione.',
687
+ 'docs.cmd.dashboardCreate':'Genera una dashboard personalizzata dal terminale.',
688
+ 'docs.cmd.skillCreate':'Genera una skill specifica del progetto dal terminale.',
689
+ 'docs.cmd.agentCreate':'Genera un agente (persona) specifico del progetto dal terminale.',
690
+ 'docs.cmd.list':'Agenti, skill e workflow a colpo d’occhio.',
691
+ 'docs.cmd.explore':'Elenca le persona del team, le procedure o i passaggi della pipeline.',
602
692
  },
603
693
  };
604
694
 
@@ -25,6 +25,8 @@
25
25
  attention: wrap('<line x1="4.5" y1="2.4" x2="4.5" y2="15.6"/><path d="M4.5 3.4h8.2l-1.7 2.6 1.7 2.6H4.5z"/>'),
26
26
  // gear — settings (proper cog with teeth)
27
27
  settings: wrap('<circle cx="9" cy="9" r="2.4"/><path d="M9 1.6v2.2M9 14.2v2.2M16.4 9h-2.2M3.8 9H1.6M14.2 3.8l-1.55 1.55M5.35 12.65 3.8 14.2M14.2 14.2l-1.55-1.55M5.35 5.35 3.8 3.8"/>'),
28
+ // open book — documentation
29
+ docs: wrap('<path d="M9 5.4C7.4 4.2 5.2 3.7 2.8 4v9c2.4-.3 4.6.2 6.2 1.4 1.6-1.2 3.8-1.7 6.2-1.4V4c-2.4-.3-4.6.2-6.2 1.4z"/><line x1="9" y1="5.4" x2="9" y2="14.4"/>'),
28
30
  // crescent moon — theme toggle
29
31
  theme: wrap('<path d="M14.6 10.8A5.6 5.6 0 0 1 7.2 3.4 5.7 5.7 0 1 0 14.6 10.8z"/>'),
30
32
  };
@@ -57,6 +57,7 @@
57
57
  <button class="tab" data-tab="workflow" data-i18n-title="nav.workflow" title="Workflow"><span class="tab-ico" data-icon="workflow"></span><span class="tab-label" data-i18n="nav.workflow">Workflow</span></button>
58
58
  <button class="tab" data-tab="team" data-i18n-title="nav.team" title="Agents &amp; Skills"><span class="tab-ico" data-icon="agents"></span><span class="tab-label" data-i18n="nav.team">Agents &amp; Skills</span></button>
59
59
  <button class="tab" data-tab="info" data-i18n-title="nav.info" title="Info"><span class="tab-ico" data-icon="info"></span><span class="tab-label" data-i18n="nav.info">Info</span></button>
60
+ <button class="tab" data-tab="docs" data-i18n-title="nav.docs" title="Documentation"><span class="tab-ico" data-icon="docs"></span><span class="tab-label" data-i18n="nav.docs">Documentation</span></button>
60
61
  <button class="tab" data-tab="settings" data-i18n-title="nav.settings" title="Personalize"><span class="tab-ico" data-icon="settings"></span><span class="tab-label" data-i18n="nav.settings">Personalize</span></button>
61
62
  </nav>
62
63
  <div class="top-right">
@@ -233,6 +234,15 @@
233
234
  </div>
234
235
  </section>
235
236
 
237
+ <!-- DOCUMENTATION (agent compatibility + CLI command reference — filled by renderDocs() in app.js) -->
238
+ <section class="panel" data-panel="docs">
239
+ <div class="info-wrap">
240
+ <h2 class="panel-title" data-i18n="docs.title">Documentation</h2>
241
+ <p class="panel-sub" data-i18n="docs.sub">Which coding agents spectoflow can drive, and the commands that drive them.</p>
242
+ <div class="info-grid docs-grid" id="docsBody"></div>
243
+ </div>
244
+ </section>
245
+
236
246
  <!-- SETTINGS (change autonomy mode + output language → config.json) -->
237
247
  <section class="panel" data-panel="settings">
238
248
  <div class="settings-wrap">
@@ -97,17 +97,17 @@ body { background:var(--bg); color:var(--ink); font-family:var(--sans); font-siz
97
97
 
98
98
  /* overview: KPI cards + status donut + workflow strip + phase bars */
99
99
  .overview { padding:22px 24px 6px; display:flex; flex-direction:column; gap:14px; }
100
- .kpi-row { display:grid; grid-template-columns:repeat(4,1fr); gap:12px; }
101
- .kpi { background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); padding:14px 16px; display:flex; flex-direction:column; gap:8px; transition:box-shadow .15s; }
100
+ .kpi-row { display:grid; grid-template-columns:repeat(4,1fr); gap:9px; }
101
+ .kpi { background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); padding:10px 13px; display:flex; flex-direction:column; gap:4px; transition:box-shadow .15s; }
102
102
  .kpi:hover { box-shadow:var(--shadow); }
103
- .kpi-label { font-size:11px; text-transform:uppercase; letter-spacing:.08em; color:var(--faint); font-weight:700; }
103
+ .kpi-label { font-size:10px; text-transform:uppercase; letter-spacing:.07em; color:var(--faint); font-weight:700; }
104
104
  .kpi-body { display:flex; align-items:center; }
105
- .kpi-num { font-family:var(--mono); font-size:30px; font-weight:700; line-height:1; color:var(--ink); }
106
- .kpi-num.is-text { font-size:17px; text-transform:capitalize; }
107
- .kpi-sub { font-size:11.5px; color:var(--muted); }
105
+ .kpi-num { font-family:var(--mono); font-size:23px; font-weight:700; line-height:1; color:var(--ink); }
106
+ .kpi-num.is-text { font-size:14px; text-transform:capitalize; }
107
+ .kpi-sub { font-size:10.5px; color:var(--muted); }
108
108
 
109
109
  .ring-wrap { position:relative; display:inline-flex; align-items:center; justify-content:center; }
110
- .ring-wrap .ring-label { position:absolute; font-family:var(--mono); font-size:13px; font-weight:700; color:var(--ink); }
110
+ .ring-wrap .ring-label { position:absolute; font-family:var(--mono); font-size:10.5px; font-weight:700; color:var(--ink); }
111
111
  .ring-svg circle { transition:stroke-dashoffset .5s ease; }
112
112
 
113
113
  .ocard { background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); padding:16px 18px; }
@@ -556,6 +556,14 @@ body.booting .ring-svg circle:last-of-type { transform-origin:center; animation:
556
556
  .settings-select:focus { outline:2px solid var(--signal); outline-offset:1px; }
557
557
  .settings-field-hint { font-size:12px; }
558
558
  .settings-field-hint.is-empty { color:var(--s-blocked); }
559
+ .docs-grid { grid-template-columns:1fr; } /* the built-in tables are wide — full width beats 2-up */
560
+ .docs-grid .backlog-table a { color:var(--signal); text-decoration:none; }
561
+ .docs-grid .backlog-table a:hover { text-decoration:underline; }
562
+ .docs-grid .backlog-table code { font-family:var(--mono); font-size:12px; }
563
+ .docs-manual-badge { font-size:10px; text-transform:uppercase; letter-spacing:.05em; color:var(--muted); border:1px solid var(--line); border-radius:999px; padding:2px 7px; }
564
+ .docs-note { margin:14px 2px 0; font-size:12.5px; color:var(--muted); }
565
+ .docs-note a { color:var(--signal); text-decoration:none; }
566
+ .docs-note a:hover { text-decoration:underline; }
559
567
  .settings-saved { align-self:flex-start; font-size:12px; color:var(--s-done); font-family:var(--mono); }
560
568
  .settings-saved[hidden] { display:none; }
561
569
  .settings-readonly { background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); overflow:hidden; }
@@ -35,7 +35,7 @@ function project(){
35
35
  // Known vs. actually-installed agents — the topbar switcher needs both: the full list to offer,
36
36
  // and which ones are real (bin on PATH, or the project already has that agent's config dir) so it
37
37
  // can refuse to activate one that isn't there.
38
- p.knownAgents = agentsRegistry.KNOWN_AGENTS.map((a) => ({ id: a.id, label: a.label, headless: a.headless }));
38
+ p.knownAgents = agentsRegistry.KNOWN_AGENTS.map((a) => ({ id: a.id, label: a.label, headless: a.headless, docsUrl: a.docsUrl }));
39
39
  p.installedAgents = agentsRegistry.installedAgents(ROOT);
40
40
  return p;
41
41
  }
@@ -11,17 +11,25 @@ const path = require('path');
11
11
 
12
12
  // headless:false = detectable and selectable as the active agent, but spectoflow never spawns it
13
13
  // itself (no confirmed non-interactive one-shot mode) — Run/Orchestrate/Summarize stay disabled for
14
- // it client-side; runner/summarize.js also refuse server-side (defense in depth). See the longer
15
- // rationale above lib/adapters.js's REGISTRY, the richer install-time twin of this list.
14
+ // it client-side; runner/summarize.js also refuse server-side (defense in depth). `docsUrl` is that
15
+ // agent's own official CLI docs, surfaced verbatim in the dashboard's Documentation tab. See the
16
+ // longer rationale above lib/adapters.js's REGISTRY, the richer install-time twin of this list —
17
+ // including why DeepSeek Harness isn't here at all, and why some runner strings order their flags
18
+ // the way they do (the trailing prompt must land right after whichever flag takes a value).
16
19
  const KNOWN_AGENTS = [
17
- { id: 'claude', label: 'Claude Code', bin: 'claude', dirs: ['.claude'], runner: 'claude -p --permission-mode acceptEdits', headless: true },
18
- { id: 'codex', label: 'Codex', bin: 'codex', dirs: ['.codex'], runner: 'codex exec', headless: true },
19
- { id: 'cursor', label: 'Cursor', bin: 'cursor-agent', dirs: ['.cursor'], runner: 'cursor-agent -p', headless: true },
20
- { id: 'gemini', label: 'Gemini CLI', bin: 'gemini', dirs: ['.gemini'], runner: 'gemini -p', headless: true },
21
- { id: 'opencode', label: 'OpenCode', bin: 'opencode', dirs: ['.opencode'], runner: 'opencode run --quiet', headless: true },
22
- { id: 'kiro', label: 'Kiro CLI', bin: 'kiro-cli', dirs: ['.kiro'], runner: 'kiro-cli chat --no-interactive --trust-all-tools', headless: true },
23
- { id: 'antigravity', label: 'Antigravity', bin: 'agy', dirs: [], runner: 'agy -p', headless: true },
24
- { id: 'kimi', label: 'Kimi CLI', bin: 'kimi', dirs: [], runner: null, headless: false },
20
+ { id: 'claude', label: 'Claude Code', bin: 'claude', dirs: ['.claude'], runner: 'claude -p --permission-mode acceptEdits', headless: true, docsUrl: 'https://code.claude.com/docs/en/cli-reference' },
21
+ { id: 'codex', label: 'Codex', bin: 'codex', dirs: ['.codex'], runner: 'codex exec', headless: true, docsUrl: 'https://developers.openai.com/codex/cli/reference' },
22
+ { id: 'cursor', label: 'Cursor', bin: 'cursor-agent', dirs: ['.cursor'], runner: 'cursor-agent -p', headless: true, docsUrl: 'https://cursor.com/docs/cli/overview' },
23
+ { id: 'gemini', label: 'Gemini CLI', bin: 'gemini', dirs: ['.gemini'], runner: 'gemini -p', headless: true, docsUrl: 'https://github.com/google-gemini/gemini-cli' },
24
+ { id: 'opencode', label: 'OpenCode', bin: 'opencode', dirs: ['.opencode'], runner: 'opencode run --quiet', headless: true, docsUrl: 'https://opencode.ai/docs/cli/' },
25
+ { id: 'kiro', label: 'Kiro CLI', bin: 'kiro-cli', dirs: ['.kiro'], runner: 'kiro-cli chat --no-interactive --trust-all-tools', headless: true, docsUrl: 'https://kiro.dev/docs/cli/headless/' },
26
+ { id: 'antigravity', label: 'Antigravity', bin: 'agy', dirs: [], runner: 'agy -p', headless: true, docsUrl: 'https://antigravity.google/docs/cli/headless/' },
27
+ { id: 'kimi', label: 'Kimi CLI', bin: 'kimi', dirs: [], runner: null, headless: false, docsUrl: 'https://github.com/MoonshotAI/kimi-cli' },
28
+ { id: 'copilot', label: 'GitHub Copilot CLI', bin: 'copilot', dirs: [], runner: 'copilot -s --allow-all-tools -p', headless: true, docsUrl: 'https://docs.github.com/copilot/concepts/agents/about-copilot-cli' },
29
+ { id: 'amazon-q', label: 'Amazon Q Developer CLI', bin: 'q', dirs: ['.amazonq'], runner: 'q chat --no-interactive --trust-all-tools', headless: true, docsUrl: 'https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-chat.html' },
30
+ { id: 'droid', label: 'Factory Droid CLI', bin: 'droid', dirs: ['.factory'], runner: 'droid exec', headless: true, docsUrl: 'https://docs.factory.ai/droid-exec/overview' },
31
+ { id: 'auggie', label: 'Auggie CLI', bin: 'auggie', dirs: ['.augment'], runner: 'auggie --quiet --print', headless: true, docsUrl: 'https://docs.augmentcode.com/cli/overview' },
32
+ { id: 'goose', label: 'Goose CLI', bin: 'goose', dirs: ['.goose'], runner: 'goose run -t', headless: true, docsUrl: 'https://block.github.io/goose/' },
25
33
  ];
26
34
 
27
35
  // Is `bin` an executable resolvable on PATH? On win32, an extension from PATHEXT is required, so we