feat(workflows): pipeline pass rates and skill/plugin usage

Restores the five analytics sections that turned out to be worth keeping
(patterns, model delegation, error propagation, session complexity, compaction
impact) and reworks what the page opens on.

The lane panel no longer mirrors the Workspace's live lane strip. It now
answers the question the strip cannot: how often each pipeline node actually
passes. GET /api/lanes/pipeline-stats aggregates every stage record of every
lane AND every archived feature — a lane's own `stages` only holds its current
feature, so without the archive the history resets each time a lane starts new
work. Evidence-backed passes are counted apart from bare claims, the same line
the pipeline map draws between `done` and `passed-no-evidence`.

Beside it, GET /api/workflows/skill-usage reports which skills and plugins the
sessions actually reach for. Only PreToolUse rows are counted: every call also
emits a PostToolUse, and counting both would double every number. A plugin's
total includes calls to the MCP tools it ships, so one used purely through MCP
does not read as unused.

Still dropped from issue #6: the agent collaboration network and the subagent
effectiveness scorecards.
This commit is contained in:
2026-08-26 10:32:13 +07:00
parent 4a0f99583d
commit 348c645ef3
23 changed files with 3944 additions and 239 deletions
+72
View File
@@ -567,6 +567,78 @@ Converge the clone-root `proof/` directory (if it exists at `<lane.cwd>/proof`)
- **200** — success
- **404** `{ "error": { "code": "ENOLANE", "message": "lane not found" } }` — lane doesn't exist
#### Pipeline pass statistics
```http
GET /api/lanes/pipeline-stats
```
How often each pipeline node was actually passed, aggregated over every lane
**and** every archived feature (an archived feature is a finished run of a
pipeline, so it carries most of the history once a lane starts its next
feature). No parameters; grouped by pipeline template, busiest first.
```json
{
"pipelines": [
{
"id": "default",
"name": "Default feature pipeline",
"runs": 4,
"nodes": [
{ "id": "plan", "label": "plan", "icon": "🧭", "gate": false,
"entered": 4, "passed": 4, "withEvidence": 4, "failed": 0 }
]
}
]
}
```
- **`runs`** — lanes plus archived features recorded against this template.
- **`entered`** — stage records that resolve onto this node (aliases included).
- **`failed`** — records whose `result` is `"fail"`; **`passed`** is the rest,
so `passed + failed === entered`.
- **`withEvidence`** — the subset of passes that carry evidence. Tracked apart
from `passed` because a claim and a proof are not the same fact — the same
distinction the pipeline map draws between `done` and `passed-no-evidence`.
**Status codes:** **200** always (an empty `pipelines` array when no lane has
recorded a stage yet).
### Workflows
#### Skill and plugin usage
```http
GET /api/workflows/skill-usage?status=active|completed
```
Skill invocations counted from `Skill` tool events — `PreToolUse` rows only,
since every call also emits a `PostToolUse` and counting both would double
every number. `status` filters by session lifecycle, same convention as
`GET /api/workflows`; omit it (or pass `all`) for no filter.
```json
{
"skills": [
{ "name": "ccam:ship-feature", "plugin": "ccam", "count": 12, "sessions": 5 },
{ "name": "daily-report", "plugin": null, "count": 3, "sessions": 3 }
],
"plugins": [
{ "name": "ccam", "skills": 1, "skillCalls": 12, "mcpCalls": 4 }
]
}
```
- **`skills`** — top 30 by call count. `plugin` is the `plugin:skill` prefix, or
`null` for a built-in or personal skill.
- **`plugins`** — per-plugin totals: distinct skills used, their calls, and
calls to the MCP tools that plugin ships (`mcp__plugin_<plugin>_<server>__*`),
so a plugin used only through MCP does not report zero.
**Status codes:** **200** always; **500** with `{ "error": { "message" } }` on a
query failure.
### Locks