Public: anyone can read this; the crew can change it.
One pipeline model: stage events, throughput, wait and failure reasons, behind the chart, boards, home and MCP #7562
duplicate of #7554
The owner, 2026-10-27 22:50Z: "i am interested in observability into the CI pipe. i want to see it still churning when the subscription is off so i can understand clearly what is getting shipped and what the lag is in real terms."
So the pipeline model must answer, in wall-clock terms and with no model running:
- What shipped: each release, with the pulls in it (title and author), and what's on main but not yet live (count, oldest).
- The lag per pull, from its timestamps:
- opened → approved - approved → landed (queue wait) - landed → live (release lag) - opened → live (end to end) - Reported as p50/p90 per day.
- Churn: checks, gates and landings per hour, and the queue depth. A page reading only the database (no agent calls) on
/pipeline, phone width, live-updating. - When the subscription is out, the page says so ("builders and reviewers paused: subscription limit") and still shows the queue landing and releases going out.
Tests: a fake history of pulls with known timestamps gives the exact p50/p90 for each lag, and the page renders it with no agents configured.
The owner, 22:55Z: "thats also the line between the deterministic autonomy of the forge and the undeterministic generative power of the crew. seeing that clearly is important to me"
The pipeline page draws that line. Every stage is marked either:
- Engine (deterministic, no model): checks, the merge queue, landing, releases and verification.
- Crew (generative, needs the subscription): building, reviewing, rebases and triage.
Each side shows its own throughput, and when the subscription is out, the crew side goes visibly idle while the engine side keeps moving. The same split goes on the boards and in MCP pipeline.
Part of the epic #7553. First child: everything else reads this.
Problem
The forge has two stage lists (
src/flow/pipeline.ts:20, 8 keys;src/flow/stage.ts:13, 6 keys) that give counts now, but no history: no throughput per stage, no wait-time distribution, no failure reasons, and nothing for "released" or "verified live". The bottleneck chart, boards, home and MCP each compute their own view (src/flow/vitals.ts,src/web/pages/flow-panel.ts,src/http/mcp/tools/flow.ts).Build
pipeline_eventtable (item kind and id, stage, entered_at, left_at, outcome, reason code) written where the transitions already happen (run start/finish, review verdict, queue gate result, merge, release cut, verify result). Reasons are a small fixed list (red functional, red budget, red infra, conflicted, held, changes requested, timeout) so they can be grouped.src/pipeline/): per stage, for 1 h / 6 h / 24 h — throughput, WIP, wait p50/p95, failure reasons by count; the bottleneck stage is the one with the longest wait among waiting items (keep today's rule frompipeline.ts:6).GET /api/v1/pipelineand MCP toolpipeline(new files undersrc/http/andsrc/http/mcp/tools/, not inapi.ts).forge/boardssources (src/boards/sources.ts) and the home KPIs read it; delete the duplicate math they carry.run,review,issue,pullfor the last 7 days so charts are not empty on day one.Done when
/api/v1/pipelineand MCPpipelinereturn per-stage throughput, WIP, wait p50/p95 and failure reasons for 1/6/24 h; the bottleneck stage named there is the one the chart and the home bottleneck sentence name (same numbers, one reader).pipelinecan be queried by aforge/boardsJSON board.test/pipeline-model.test.ts(stage mapping; a pull's whole life writes ordered events),test/pipeline-reasons.test.ts(each reason code produced by its cause),test/pipeline-backfill.test.ts(7-day backfill matches live counts),test/pipeline-one-reader.test.ts(chart, home and MCP agree on a seeded db).src/http/api.tsandsrc/web/pages/repo.tsget at most one route-registration line.