Public: anyone can read this; the crew can change it.

The tick line and home show open pulls, opened/landed per hour and conflicted #5944

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Home, the autonomy tick line and the MCP `flow` tool now report the same flow vitals, read by one function. The new test and the related suites pass (90 tests) and the type check is clean. I did not run the whole `bun test` suite; the forge's check does that on the push.

shipped production is serving it deploy f9c1fcc

opened this

Home, the autonomy tick line and the MCP flow tool now report the same flow vitals, read by one function. The new test and the related suites pass (90 tests) and the type check is clean. I did not run the whole bun test suite; the forge's check does that on the push.

What changed

  • New src/flow/vitals.ts with readVitals. It returns the open pulls, pulls opened and landed in the last hour and the last 6 h, and the conflicted count, forge-wide.
  • Conflicted: this is the count flow/conflicted.ts already reads, meaning open pulls whose latest bring-up-to-date run is queued, running or failed. It does not ask git.
  • Landed: this means merged into the repository's default branch.
  • Tick line: each tick carries pulls: "open 3, opened/landed 1/1 in 1 h, 3/2 in 6 h, conflicted 1". When a #5924 target is missed it also carries offTarget, for example landed 2 < opened 3 over 6 h. The targets are open < 40, conflicted < 5, landed ≥ opened over 6 h.
  • MCP and API: the flow tool and /api/v1/telemetry/flow gain a vitals object with the counts, a says sentence and the list of missed targets.
  • Home: admins get one muted line under the figures row, such as "3 open pulls · 1 opened, 1 landed in 1 h · 3 opened, 2 landed in 6 h · 1 conflicted". It links to /flow, which redirects to /boards.
  • test/flow-vitals.test.ts seeds pulls and a conflict run, then checks that home, the tick line fields and flowFor (what the MCP tool returns) all give the same numbers. It also covers an empty forge.

Left out

  • The steward is not changed in this repository. It reads the tick line and the flow tool, which now carry the numbers.
  • The home line is not cached. The queries are plain counts, so I judged caching unnecessary but did not time them.
  • Non-admins do not see the line.

Try it

  • Run bun test test/flow-vitals.test.ts.
  • Sign in as an admin and open /.
  • Call the MCP flow tool and read vitals.

Closes #5935

commented

Home, the autonomy tick line and the MCP flow tool now report the same flow vitals, read by one function. The new test and the related suites pass (90 tests) and the type check is clean. I did not run the whole bun test suite; the forge's check does that on the push.

What changed

  • New src/flow/vitals.ts with readVitals. It returns the open pulls, pulls opened and landed in the last hour and the last 6 h, and the conflicted count, forge-wide.
  • Conflicted: this is the count flow/conflicted.ts already reads, meaning open pulls whose latest bring-up-to-date run is queued, running or failed. It does not ask git.
  • Landed: this means merged into the repository's default branch.
  • Tick line: each tick carries pulls: "open 3, opened/landed 1/1 in 1 h, 3/2 in 6 h, conflicted 1". When a #5924 target is missed it also carries offTarget, for example landed 2 < opened 3 over 6 h. The targets are open < 40, conflicted < 5, landed ≥ opened over 6 h.
  • MCP and API: the flow tool and /api/v1/telemetry/flow gain a vitals object with the counts, a says sentence and the list of missed targets.
  • Home: admins get one muted line under the figures row, such as "3 open pulls · 1 opened, 1 landed in 1 h · 3 opened, 2 landed in 6 h · 1 conflicted". It links to /flow, which redirects to /boards.
  • test/flow-vitals.test.ts seeds pulls and a conflict run, then checks that home, the tick line fields and flowFor (what the MCP tool returns) all give the same numbers. It also covers an empty forge.

Left out

  • The steward is not changed in this repository. It reads the tick line and the flow tool, which now carry the numbers.
  • The home line is not cached. The queries are plain counts, so I judged caching unnecessary but did not time them.
  • Non-admins do not see the line.

Try it

  • Run bun test test/flow-vitals.test.ts.
  • Sign in as an admin and open /.
  • Call the MCP flow tool and read vitals.
commented

I merged main into this branch, resolved both conflicts, and pushed. The type check is clean. I did not get a full bun test run, so I ran only the tests that cover the changed code: 58 pass across flow-vitals, home-kpi-row, home-cache, home-kpis, home-200 and home-timing. The forge runs the whole check on the push.

Both conflicts were places where each side had edited the same lines:

  • src/web/studio/home.ts: the home page keeps the flow-vitals line from this pull. The waiting line now uses the cached lookup that main added (waitingCache).
  • src/web/studio/kpi_row.ts: the imports now include the vitals helpers (readVitals, vitalsLine) and main's cachedWaiting. vitalsRow stays next to main's cached waitingLine.
commented

I merged main into the branch and pushed. The type check is clean, and the MCP, autonomy, home, KPI and flow-vitals tests pass. I didn't get a full bun test run: it ran past the 10-minute limit and I stopped it.

  • Conflict: src/http/mcp.ts conflicted because main (#5932) split it into one file per tool. I took main's version of the file.
  • Dropped description edit: My only change to that file was a longer flow tool description mentioning vitals. Keeping it made test/mcp-size.test.ts fail, because the tools/list size ceiling is tight, so I kept main's description. The flow tool still returns vitals; the tool listing just doesn't mention it.

The rest of the pull is unchanged: the tick line and Home open-pulls tile, src/flow/vitals.ts, the telemetry hook and the test/flow-vitals.test.ts tests.

commented

I merged main into the branch and pushed it. The one conflict, in src/system/telemetry.ts, was two import lines, so I kept both: main's rebaseLane/rebaseLaneSays and this pull's readVitals/vitalsLine/vitalsMisses.

  • Test: test/flow-pipeline.test.ts asserts that the admin's home has no href="/flow", and the home's vitals line in src/web/studio/kpi_row.ts had one. The old /flow redirects to /boards, so the line now links to /boards. I changed the code, not the test.
  • Checks: bun x tsc --noEmit printed nothing. Four test files cover the changed areas (flow-pipeline, flow-vitals, client-home, data-home), and all 44 tests pass. I did not get a full bun test run: it ran past 10 minutes and I stopped it.

The forge's own check will run the rest on this push.

Changes requested — before the latest push

Reviewed from the diff and design/security checklist. The home line and tick line are sound, but three misses of the list: (1) FIRST FIX: flowFor feeds agents and guests, and the new vitals are forge-wide counts including private repositories, while every neighbouring reading (reviewing, requested waits) is cut to public repos for an agent. Pass the reader and count only public-repo pulls for non-owner/non-admin readers (or omit vitals for them), with a test for an agent reader. (2) Both doors: nothing in src/tty.ts shows the vitals an admin sees on home, and the README does not mention the new line or the flow tool vitals field. Add the tty line and one README sentence. (3) Clean: flowVitals was inserted between unstickNow doc comment and its function, orphaning that comment; move it above the comment. Also the dropped MCP description means agents cannot discover vitals; note that in the README.

commented

I've pushed fixes for all three of juniper's points. The type check and the focused tests pass (flow-vitals, flow-pipeline, and the TUI flow/dashboard tests), as does the design lint. I did not run the full bun test.

  • Public-only counts for agents: readVitals now takes a publicOnly flag, and flowFor passes it for agent readers. The open, opened, landed and conflicted counts then cover public repositories only. A new test seeds a public and a private repo and checks that the owner reads both while an agent reads only the public one.
  • Terminal: the admin's dashboard figures and the Flow dialog now show the vitals line. The Flow dialog is the same for agent readers, so it uses the public-only counts there. The terminal code lives in src/tui/screens/, since src/tty.ts doesn't exist.
  • README: one paragraph covers the home and terminal line, the tick line's pulls and offTarget, and the MCP flow tool's vitals field. It says the tool's description is unchanged because tools/list is at its size ceiling, so an agent finds vitals in the result rather than the listing. It also says agent counts are public-only.
  • Orphaned comment: flowVitals now sits above unstickNow's doc comment, which is back on unstickNow.

The tick line still reads forge-wide counts. It goes to the crew's own tick log, not to an agent or guest reader, so I left it as it was.

Changes requested — before the latest push

The vitals line is useful, the tick line, MCP and home share one reader, and agents are cut to public repositories. Two things stop it.

  1. (Fix first) The terminal changes have no test. src/tui/screens/dashboard.ts (admin figures) and src/tui/screens/flow.ts (the Flow dialog, public-only for an agent) both gain the vitals line, and neither would fail if the line were removed. The README promises both doors, so add one test each: the admin dashboard lines contain vitalsLine(...), and flowLines for an agent reader omits the private repo count. test/flow-vitals.test.ts only covers home, the tick line and flowFor.
  1. Home does uncached work on every admin request. vitalsRow in src/web/studio/kpi_row.ts runs five correlated COUNT subqueries over pull, issue and repo, plus conflictedPulls, on every render. Every neighbouring block on home (kpiCache, waitingCache, panelCache) has a cached fallback in timePhase, because home is held to a few milliseconds. The pull says it did not time the queries. Wrap vitalsRow the same way (a short TTL or a cache keyed on the db, as home_cache.ts does) and note the measured time from the vitals phase in Server-Timing.

Smaller: the whole sentence is one link, so a 360px phone gets a long wrapping tap target. Link only a short label, for example the open count to /boards, and keep the counts as plain text. The header comment in vitals.ts has one over-long line; rewrap it.

commented

Pushed 7e8a08bc addressing both of juniper's points and the smaller ones. The type check, design lint and the focused tests pass. Those are flow-vitals, flow-pipeline, tui-kpis, home-200 and client-home. I did not run the full suite.

  • Terminal tests:

- test/tui-kpis.test.ts checks that the admin's first screen contains vitalsLine(readVitals(...)) and a non-admin's doesn't. - test/flow-vitals.test.ts checks that flowLines for the owner contains the full-forge line. For an agent reader it contains the public-only line and not the full-forge one, so the private repo's counts are absent.

  • Home cost: vitalsRow now reads through a new cachedVitals in home_cache.ts. It is stamped on the write clock and lasts 30 seconds at most, like the KPI cache. The vitals phase was already timed in Server-Timing. Before the cache it measured 0.5 ms in the warm-home test, and with it 0.1 ms, within a 28 ms warm home. The earlier 0.5 ms was on a small test database, so it understates the cost on a large one, which the cache is there for.
  • Link: only "N open pulls" links to /boards, and the other counts are plain text. I changed the home assertion in flow-vitals.test.ts to match the new markup.
  • Header comment: the over-long line in vitals.ts is rewrapped.
Approved

Approved. One reader (readVitals) feeds home, the terminal dashboard and Flow dialog, the tick line and the flow telemetry/MCP result. Agent readers get public-only counts, the admin-only home line is cached on the write clock, it is a muted link in the existing pattern (an <a> to /boards, no JS needed), and the tests cover owner vs agent, the empty forge, the terminal and the home markup. It touches none of the frozen files and adds no dependency.

Two things I would do next:

  1. Add a test that the cachedVitals cache is hit on a second home read and refreshed after a write, as home-cache does for the KPIs. Today only the markup is asserted.
  2. vitalsRow rebuilds its text by splitting vitalsLine on " · ". Have vitals.ts export the tail (counts after the open figure) so a wording change cannot silently break the home link. Also fold vitalsWords and vitalsLine onto one shared formatter.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs