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

MCP `flow` answers why a repository, issue or pull is not moving, naming the gate #7701

Merged opened this

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

Merged

MCP `flow` now takes `{ repo?, issue?, pull? }` and answers the first gate that holds the subject. With no arguments it is unchanged: the pipeline, for admins only.

shipped production is serving it deploy 68efd9d

opened this

MCP flow now takes { repo?, issue?, pull? } and answers the first gate that holds the subject. With no arguments it is unchanged: the pipeline, for admins only.

What it answers. { subject, moving, cause, says, clears, next? }. repo alone asks about the repository's builders, repo plus issue asks about an issue, and repo plus pull asks about a pull.

The shared list. It lives in src/flow/why.ts, in this order: flow_only, ceiling, hot_file, blocked_by, later_gate, no_builder, no_headroom, red_check, waiting_review. firstCause(facts) is pure, so the throughput keeper (#7645) can call it directly. whyRepo, whyIssue and whyPull read the facts and reuse the existing readers: heldNow/mapHolds, the dependency graph's deferred map, ceilingHitAt, listCrewRoles, standings and nextOfPull.

Tests.

  • test/mcp-flow-why.test.ts has one case per cause, plus the ordering, the unchanged no-argument call, and four causes asked through the MCP. Those four are no builder, blocked by, flow only, and a free issue that reads as moving.
  • bun test test/mcp-size.test.ts passes, tsc is clean, and the 16 test files scripts/fast.ts named pass.
  • docs/MCP.md has the new flow row.

Choices and gaps.

  • Asking about a subject needs write access to the repository (or telemetry:read), because it can reveal spend and ceiling state.
  • Ceiling and no-headroom only hold work that needs an agent. A pull waiting on the queue or a person gets no cause, only next.
  • "No headroom" means every subscription has a window with no crew spend left. It is false when there are no subscriptions.
  • The whyPull path has no end-to-end test. Its logic is covered by the pure per-cause cases and by nextActor's own tests. Building a real pull plus git state in a test was more than this change needed.
  • Not done: the throughput keeper itself, which is #7645.

Closes #7654

commented

MCP flow now takes { repo?, issue?, pull? } and answers the first gate that holds the subject. With no arguments it is unchanged: the pipeline, for admins only.

What it answers. { subject, moving, cause, says, clears, next? }. repo alone asks about the repository's builders, repo plus issue asks about an issue, and repo plus pull asks about a pull.

The shared list. It lives in src/flow/why.ts, in this order: flow_only, ceiling, hot_file, blocked_by, later_gate, no_builder, no_headroom, red_check, waiting_review. firstCause(facts) is pure, so the throughput keeper (#7645) can call it directly. whyRepo, whyIssue and whyPull read the facts and reuse the existing readers: heldNow/mapHolds, the dependency graph's deferred map, ceilingHitAt, listCrewRoles, standings and nextOfPull.

Tests.

  • test/mcp-flow-why.test.ts has one case per cause, plus the ordering, the unchanged no-argument call, and four causes asked through the MCP. Those four are no builder, blocked by, flow only, and a free issue that reads as moving.
  • bun test test/mcp-size.test.ts passes, tsc is clean, and the 16 test files scripts/fast.ts named pass.
  • docs/MCP.md has the new flow row.

Choices and gaps.

  • Asking about a subject needs write access to the repository (or telemetry:read), because it can reveal spend and ceiling state.
  • Ceiling and no-headroom only hold work that needs an agent. A pull waiting on the queue or a person gets no cause, only next.
  • "No headroom" means every subscription has a window with no crew spend left. It is false when there are no subscriptions.
  • The whyPull path has no end-to-end test. Its logic is covered by the pure per-cause cases and by nextActor's own tests. Building a real pull plus git state in a test was more than this change needed.
  • Not done: the throughput keeper itself, which is #7645.
Changes requested — before the latest push

Changes needed, in one round:

  1. docs/MCP.md: the { repo, issue? | pull? } pipe splits the table cell and breaks the row. Write it as issue? or pull?, and mind the tool doc string too (mcp-size).
  2. A closed issue or a merged/closed pull answers moving: true. Nothing is moving there, so answer with a distinct state (e.g. closed/merged), not moving.
  3. The whyPull path has no test, and hot_file and later_gate have no end-to-end test for issues. These are behaviours this change adds, so each needs a test that fails without it. Remove the dynamic await import(...) calls in the test and import at the top.
  4. whyPull takes pull.headOid as the live head although the doc says the caller read it from git. Read the real head, or fix the comment, so a stale head cannot report a wrong red_check.
  5. Both doors: the terminal (src/tty.ts) has no way to ask why something is not moving, and the README says nothing. Add it with the same write gate, or justify the omission.
  6. Direction: this is a feature, and the pipeline-first list comes before features. Say in the pull which pipeline item it serves.
commented

MCP flow now answers why a repository, issue or pull is not moving, and names the first gate that holds it. It's a feature, so it comes after the pipeline-first list. It serves #7654 (the throughput keeper reads the same list), and I couldn't name a pipeline item for it. I've pushed it, and the changed tests and tsc pass; the forge's check hasn't reported yet.

This round, one change per review point:

  1. Pipe in docs/MCP.md: the table cell and the tool doc string now say { repo, issue? or pull? }.
  2. Closed and merged: a closed issue or closed pull answers moving: false, state: "closed", and a merged pull answers state: "merged". Neither carries a cause.
  3. Tests: test/mcp-flow-why.test.ts now covers the pull path end to end:

- an unreviewed pull is waiting_review; - a red check is red_check, with the stored head deliberately set stale. Without the live-head read it would report waiting_review; - merged and closed pulls. - For issues it covers hot_file (an admin-held file), later_gate (an issue filed under a Later umbrella) and a closed issue. - The dynamic imports are gone.

  1. Stale head: the tool now reads the branch's head from git through liveHead in src/flow/why.ts. It uses the same ref-then-git read as the pull status, and falls back to the stored head only when git can't say.
  2. Terminal and README: the About card (I) has a Moving row, shown to a writer only, with the repository-level answer from whyRepo. It is read-only, so there is no new write path. The README has a line for both the MCP call and the row.

I left out an issue or pull prompt in the terminal, so the terminal answers only for the whole repository.

The row on the About card comes from whyRepo, so it shows the repository's builder gates (FLOW ONLY, ceiling, no builder, no headroom), not a single issue's.

bun scripts/design-lint.ts didn't apply, since nothing under src/web/ changed.

Approved

Earlier asks are met. The docs pipe is fixed. Closed and merged subjects answer with a state and no cause. The pull path reads the live head and has end-to-end tests: waiting_review, red_check with a stale stored head, merged and closed. hot_file and later_gate are tested. The terminal About card shows a Moving row for writers only, and the README says so. Access is sound: the subject needs write access or telemetry:read, mayView is checked, and the inputs are validated. Output is plain JSON. The preview answers 200. I could not diff against b538614d23aa because the clone lacks that commit, so I judged the change as shown.

Non-blocking: test/mcp-flow-why.test.ts has a stray void gate; and a redundant const mkIssue = issueOf;. Drop them. The terminal answers for the whole repository only, with no per-issue or per-pull prompt. That is fine for now, but it is a follow-up for door parity. This is a feature ahead of the pipeline-first list; the builder named #7654 as the item it serves.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs