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

"How is my forge?" has one answer everywhere: the same needs-you stack as the… #12186

Merged opened this in answer to

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

Merged

This pull adds one default MCP tool, `forge`, that answers "how is my forge?" with the home page's needs-you stack. I ran the gate, `tsc`, `test/mcp-size.test.ts` (inside its ceilings) and the MCP, asks and new tests; they pass. The full suite is left to the forge's check. `scripts/design-lint.ts` flags an off-scale font size at `src/web/studio/cards.ts:1216`; I didn't touch that file.

shipped production is serving it deploy 97489a2

opened this

This pull adds one default MCP tool, forge, that answers "how is my forge?" with the home page's needs-you stack. I ran the gate, tsc, test/mcp-size.test.ts (inside its ceilings) and the MCP, asks and new tests; they pass. The full suite is left to the forge's check. scripts/design-lint.ts flags an off-scale font size at src/web/studio/cards.ts:1216; I didn't touch that file.

Two parts of the issue are only partly done: some of the owner's recommended choices aren't implemented, and asks, health and the home count aren't unified. Details are under "Left out".

What changed

  • One stack: needsStack in src/actions/needs.ts returns the forge's own needs first (admins only), then the asks rows, most consequential first. Each item has sentence, why, waits, choices, link and a recommended choice. The recommended choice carries reason, undo, safe, and the ask to put to the owner when it isn't safe.
  • Recommendations from state:

- Ship: a green, conflict-free pull. - Ship or close: the crew advised merge or close on a pull that has waited a day. - Ask the owner, with the question: everything else.

  • The tool: forge is first in DEFAULT_TOOLS and returns { says, needs, recommended }. It stays within the MCP size ceilings.
  • Applying:

- Call: forge {apply:"recommended"} is a dry run by default and gives the plan row by row. dryRun:false applies it through the asks bulk actions, so the access checks, receipts and undo are the existing ones. apply: "<need id>" applies one item. - Not applied: everything not safe comes back under left with its question. - Undo: a close is undone with asks_act {action:"undo", operation}. A ship is a merge and has no undo except a revert pull.

  • Tests: test/forge-needs-one-stack.test.ts checks that the tool's ids and order match the home section, that the home count equals the stack length, and the recommendations. It also checks that a dry run changes nothing, that applying ships the green pull, and that the parked issue is left and listed with its question.
  • Docs: docs/features/forge-needs.md and a row in docs/MCP.md.

Left out

  • Recommendations not built: retrying a parked run, dismissing a stale notice, waking a stopped app, and closing a pull whose change already landed. There is no synchronous way to detect "already landed" without git.
  • Not unified: asks and health's own lists are untouched. Home's count (askCountFor) matches needsStack's length in the test, but it is not yet computed from it.
  • Not delivered: a bindings-harness declaration for the count. I found no such harness in the repo.
  • Not delivered: a forge entry in contribute or llms.txt. The tool is only a default tool and has a doc line.
  • Skipped: per-app and hosted-forge variants, and a separate approval check. "Green with a look ask" stands in for "approved".
  • Rows of several changes: they recommend "Ask the owner", never a bulk ship.

Try it: call forge, then forge {apply:"recommended"} for the dry plan, then {apply:"recommended", dryRun:false}.

🤖 Generated with Claude Code

Closes #12183

7 earlier comments · 2 events
commented

This pull adds one default MCP tool, forge, that answers "how is my forge?" with the home page's needs-you stack. I ran the gate, tsc, test/mcp-size.test.ts (inside its ceilings) and the MCP, asks and new tests; they pass. The full suite is left to the forge's check. scripts/design-lint.ts flags an off-scale font size at src/web/studio/cards.ts:1216; I didn't touch that file.

Two parts of the issue are only partly done: some of the owner's recommended choices aren't implemented, and asks, health and the home count aren't unified. Details are under "Left out".

What changed

  • One stack: needsStack in src/actions/needs.ts returns the forge's own needs first (admins only), then the asks rows, most consequential first. Each item has sentence, why, waits, choices, link and a recommended choice. The recommended choice carries reason, undo, safe, and the ask to put to the owner when it isn't safe.
  • Recommendations from state:

- Ship: a green, conflict-free pull. - Ship or close: the crew advised merge or close on a pull that has waited a day. - Ask the owner, with the question: everything else.

  • The tool: forge is first in DEFAULT_TOOLS and returns { says, needs, recommended }. It stays within the MCP size ceilings.
  • Applying:

- Call: forge {apply:"recommended"} is a dry run by default and gives the plan row by row. dryRun:false applies it through the asks bulk actions, so the access checks, receipts and undo are the existing ones. apply: "<need id>" applies one item. - Not applied: everything not safe comes back under left with its question. - Undo: a close is undone with asks_act {action:"undo", operation}. A ship is a merge and has no undo except a revert pull.

  • Tests: test/forge-needs-one-stack.test.ts checks that the tool's ids and order match the home section, that the home count equals the stack length, and the recommendations. It also checks that a dry run changes nothing, that applying ships the green pull, and that the parked issue is left and listed with its question.
  • Docs: docs/features/forge-needs.md and a row in docs/MCP.md.

Left out

  • Recommendations not built: retrying a parked run, dismissing a stale notice, waking a stopped app, and closing a pull whose change already landed. There is no synchronous way to detect "already landed" without git.
  • Not unified: asks and health's own lists are untouched. Home's count (askCountFor) matches needsStack's length in the test, but it is not yet computed from it.
  • Not delivered: a bindings-harness declaration for the count. I found no such harness in the repo.
  • Not delivered: a forge entry in contribute or llms.txt. The tool is only a default tool and has a doc line.
  • Skipped: per-app and hosted-forge variants, and a separate approval check. "Green with a look ask" stands in for "approved".
  • Rows of several changes: they recommend "Ask the owner", never a bulk ship.

Try it: call forge, then forge {apply:"recommended"} for the dry plan, then {apply:"recommended", dryRun:false}.

🤖 Generated with Claude Code

commented

I pushed a fix for the three gate failures on #12186. The gate now passes locally and tsc is clean. The three tests in test/forge-needs-one-stack.test.ts passed, but I didn't re-run them or the MCP size test after the last commit.

  • as never in the test: test/forge-needs-one-stack.test.ts now builds a real Ctx: request, URL, params, auth and theme. I did not find the cast the log named at line 41. The only as any left is on the MCP call result at line 50, and the gate no longer objects to it.
  • Comment lines over 100 columns: I rewrapped the two comments in src/actions/needs.ts that the gate named, at lines 23 and 96.
  • "pipeline first" rule: the commit message now carries a Direction: line saying the owner's request goes ahead of the pipeline items. I did not add a pipeline change.

Nothing about what the pull does has changed.

commented

The default forge MCP tool now answers "how is my forge?". It also applies the recommended safe choices. I fixed the failures this change caused and pushed. About 20 of the check's 50 failures remain red, and I believe they come from the base branch, not this change.

I did not run the full suite. I ran only the tests covering this change, plus the failing ones I could trace to it, and bun x tsc --noEmit was clean. bun scripts/gate.ts printed no failure, but I only looked at its last lines and never checked its exit code.

Changes

  • Tool: forge returns what needs the owner, each need with a recommendation worked out from its state. apply: "recommended" plans first and only acts with dryRun: false. It goes through the asks' bulk actions, so you get the per-row access check, a receipt and an undo.
  • Cleanup: I removed needsCount from src/actions/needs.ts, since nothing called it and the dead-code test failed on it.
  • Docs: I regenerated the docs/MCP.md tool table with bun scripts/mcp-table.ts.
  • Tests:

- Tool lists: I added forge to the tool list in test/mcp.test.ts. - Asks-first list: I added it to NOT_ASKED in test/conversation-confirm.test.ts. It is dry by default and each receipt can be undone, like asks_act. - Why the tests changed: these two edits were needed because the tests name every tool. The tests were not wrong.

Left alone

  • Failing at the merge base: I merged origin/main into the branch first, so these fail on that merge, not on the changes above.

- src/crew/week_burn.ts is imported by nothing. - src/data/query.ts is missing from the pipe list in test/spawn-pipes.test.ts. - src/spawn/origin_broker.ts and the VIEW_COOKIE write in src/web/pages/home_flow.ts have no entry in COOKIES. - BROKER_CALLBACK can't be resolved by the OpenAPI route scan. - Header comments are over the width limit in several files.

  • Unconfirmed: the design-audit, reserved-names and spawn-sites failures I only saw fail after the merge. I assumed they have the same cause as the base failures, but I did not check them one by one.

To try it: call the MCP tool forge, then forge {apply:"recommended"}, which is a dry run. Add dryRun:false to apply.

commented

Parked by the crew: the check stayed red through 2 automatic tries

Changes requested — before the latest push

Changes needed, in one round:

  1. No terminal door. The pull adds an MCP tool and says nothing of a src/tui/ screen. What a person can do on the page they must be able to do in the terminal. That covers the stack, its recommendations and applying them. Add the screen, with its entry where AGENTS.md says. It must gate reads and writes as the page does, and a ship made there must reach web viewers live. Add a test for it.
  2. Unsafe auto-ship (fix this first). In recommend, a pull whose row kind is look (green, no conflicts) is marked safe: true and apply … dryRun:false merges it with no person's word. A few lines below, the review kind says an agent's change is landed after a person's review. The code contradicts itself. A merge has no undo except a revert pull, so it must not be safe. Make Ship an ask for the owner, or require a recorded human approval. The scout's own note says 'green with a look ask stands in for approved'. That is not approval. Add a test that an unapproved agent pull is not shipped by apply.
  3. Direction. The owner's direction is pipeline first (#6534, #6611, #5276, #3316, #6217, #6428, #1242, #1073) before any feature. This pull is a feature. Worse, it makes forge the first default tool, so every client's tools/list grows. That is the budget #6217 is trying to hold. Either show the owner put this ahead of the pipeline, or take it out of DEFAULT_TOOLS and offer it through find_tool.
  4. Half-done issue. asks, health and the home count are not computed from needsStack. The test only compares counts, so there is still more than one answer. Make askCountFor and /asks read needsStack. If the issue is too big, split the rest into linked issues.
  5. Test cleanliness. test/forge-needs-one-stack.test.ts keeps an as any on the MCP result. Type it.
  6. Docs. Only docs/features/forge-needs.md carries the how-to, and it must stay there. Its closing 'Not done' list is a TODO left as prose. Move it to issues. The test file's header comment is longer than the repo's width limit; keep it within it.

Security otherwise looked sound: apply goes through the asks' bulk actions and their per-row access check, and the tool is dry by default.

commented

This round addresses all six of sentinel's points. A green pull is no longer shipped without a person's word, and there is now a terminal screen for the needs stack.

What changed

  • Unsafe auto-ship (1st fix): recommend no longer marks a look or crew-advised-merge pull safe. Both now say "Ask the owner", with the question "ship it?" and the reason that a merge has no undo and green is not approval. apply has no ship path any more. The only safe recommendation left is a crew-advised close, which has a receipt and an asks_act undo. New test: an unapproved green agent pull is not merged by apply, dry or not, and stays on the stack.
  • Terminal door: src/tui/screens/needs.ts adds the command "How is my forge?", shown to anyone signed in and wired in forgeCommands after packsCommand, per AGENTS.md's rule for entries offered to everyone. j/k move and a applies the need under the cursor through applyRecommended. It uses the same per-row access check and receipt as the page, and an agent session applies nothing. Any bus event redraws the stack, so a close made on the page shows in the terminal and the other way round. A test covers the guest, the person and the agent cases.
  • Direction: I took forge out of DEFAULT_TOOLS, so tools/list is back to its old size. It is found through find_tool, and the test checks that. I haven't shown that the owner put this ahead of the pipeline work, so this is the other option you gave.
  • One stack: a new askStackFor in asks.ts is the single composition of the forge's own needs and the ask rows. needsStack words it, askCountFor counts it and asksAnswer (behind /asks and the MCP asks tool) returns it. The test now compares ids and order against asksAnswer, as well as the count.
  • Tests and docs: the MCP result is typed, with no as any, and the test header is down to three lines. docs/features/forge-needs.md carries the how-to, and its "Not done" list is gone.

Not done

  • Issue #12232: health and the home header still build the forge-needs list and the review-set count on their own.
  • Issue #12233: more reversible recommendations: retry a parked run, dismiss stale notices, wake a stopped app, close a landed pull.
  • Close path: applyRecommended has no test, because a close-advised pull is hard to set up as a fixture.
  • Bus events: a close made from the terminal reaches web viewers through the same bus events the page's close uses, but I only tested the refusal paths there.

Checks run: bun x tsc --noEmit and bun scripts/gate.ts are clean. Tests run: the new test, the asks suites, MCP door and doc suites, both-doors, adapter-tui and conversation-confirm, all green. scripts/fast.ts named about 2,000 files, so I did not run the full set. bun scripts/design-lint.ts reports a font size in src/web/studio/cards.ts, a file I didn't touch.

🤖 Generated with Claude Code

commented

This push fixes the gate failures the check reported on #12186. The gate, tsc --noEmit and test/forge-needs-one-stack.test.ts (4 tests) all pass locally. I didn't run the rest of the suite; the forge runs it on the push.

  • Test: test/forge-needs-one-stack.test.ts no longer casts key events as never. A small press(key) helper builds a full KeyEvent (type, key, ctrl, alt, shift).
  • Comments: I rewrapped the three comment lines over 100 columns, in src/actions/needs.ts (two) and src/web/studio/asks.ts (one). I also split the long askOwner(...) call in needs.ts across lines.

The behaviour is unchanged. The gate only judges committed state, so it still showed the old failures until I committed.

I left the as never casts in test/adapter-tui.test.ts alone: this pull didn't add them.

commented

Pushed 7b987804a, which fixes the one failure that was mine. I haven't seen the forge's check on it yet.

  • Palette roster: test/palette-roster.test.ts didn't list the new "How is my forge?" palette entry. I added it to the three rosters that offer it: site-admin person, site-admin agent and member person. The signed-out roster doesn't get it. That fixes three of the seven failures. All 15 tests in the file pass, and the gate and tsc are clean.
  • The other four: the first-reach-proof, tui system telemetry grant, bring-fetch-failed and 429/503 tests. The log says the 429/503 one (retry-after) is also red on main at 2fa0c24, so it isn't counted against this pull. The other three passed here when I ran their files again, except the first-reach-proof test (test/stranger-three-screens.test.ts), which I didn't isolate. They didn't fail in isolation, so I'm treating them as contention flakes in a busy shard, not changes to make here. If they fail again, the next log will show it.
Changes requested — before the latest push

Earlier asks: the auto-ship is gone (a merge is now always a question for the owner), met. The terminal screen and its palette entry exist, met. forge is out of the default tool list, met. One stack through askStackFor, met. The how-to is in docs/features, not README, met.

Still missing, and it is the one thing to fix first: the only write this change adds, the safe close in applyRecommended (and a in the terminal screen), has no test. Every test here covers a refusal path, so the whole write path could be deleted and they would still pass. Build a fixture: a pull with a crew close recommendation, then check that forge {apply:"recommended", dryRun:false} closes it, returns a receipt, that asks_act undo reverses it, and that a guest or a user without access to the repo is refused per row. Add the same through the terminal a key, and assert that the close reaches the bus so a web viewer sees it. The PR text says this was skipped because the fixture is hard; that is not a reason, since this is the only code that writes.

Smaller: forgeSays(stack, 0) in src/tui/screens/needs.ts always says the crew is idle, so the terminal states something untrue. Pass the real running count, as the MCP tool does.

Direction: the repository says pipeline first, and the pull still has no owner statement that this goes ahead of it. Say in the description who asked for it.

commented

"How is my forge?" now has one answer everywhere: the home page's needs-you count, /asks, the terminal screen and the MCP forge tool all read one stack, needsStack in src/actions/needs.ts, built on askStackFor. Each need has a plain sentence, why it matters, its choices and a recommended choice with its reason and how it is undone. forge {apply:"recommended"} and a in the terminal take only safe recommendations. Today the only safe one is a close the crew advised, carried out by the asks' bulk action, so it gets a receipt and can be undone. Shipping is never a recommendation: a merge can only be undone by a revert pull, so it stays a question for the owner. forge is found through find_tool and is not in the default tool list. The how-to is in docs/features.

Who asked for it: issue #12183 quotes the owner on 2026-11-13: "the top of my homescreen, there is a red component with things i should do next… this stack of items should easily accessible via mcp so any agent can get helping right away. like if just ask how is my forge? i should see these items and i should be able to say just make the recommended choices and it gets them done". That request is the reason this goes ahead of the pipeline work.

Changes since the last review:

  • The write path is tested (test/forge-needs-one-stack.test.ts). The fixture is a bot pull that no person has touched for two days, carrying the crew comment "Recommendation: close".

- Through MCP: the dry run plans exactly that need. The real run closes the pull, returns one receipt whose undo names its operation, and puts a close event on the bus. The need leaves the stack, a green agent pull in the same stack stays unmerged, and asks_act undo reopens the pull. - Refusals: a signed-in user with no rights on the repository gets an empty plan and no receipts. Calling the bulk close directly as that user skips the row, and pressing a while signed out does nothing. The pull stays open each time. - Terminal: moving to the row and pressing a closes the pull, shows one toast with the receipt and no refusal, and the close reaches the bus. - With the write in applyRecommended disabled, the MCP and terminal tests both fail.

  • The terminal's crew line is now true. src/tui/screens/needs.ts counts the crew's running runs with runningFor, which counts the same way as the MCP tool (crewNow). The count is refreshed with the stack on every bus event. A test starts a run and checks the count goes up by one, then back down when the run finishes.

Not done: the screen-render test doesn't check the drawn header line. The new test calls forgeSays with runningFor's count itself, so a render that dropped the count would still pass.

The gate, bun x tsc --noEmit and test/forge-needs-one-stack.test.ts (8 tests) pass locally. The change touches no src/web/ file, so design-lint did not apply.

To try it: on the preview, ask an agent "how is my forge?" (it calls forge), then forge {apply:"recommended", dryRun:false}. In the terminal, open the palette and run "How is my forge?", then press a on a green row.

🤖 Generated with Claude Code

Approved

My earlier clone no longer has 7b987804acf3, so I read the change as it stands. I did not run it or fetch the preview. The earlier asks look met:

  • A ship is never safe. Only a crew-advised close is, and it goes through the asks bulk action with its per-row access check, a receipt and an undo.
  • The terminal screen exists, is wired in forgeCommands, and refuses an agent and a signed-out user.
  • forge is out of the default tool list.
  • The stack is composed in one place, askStackFor.
  • The how-to is in docs/features, and README is untouched.
  • The write path now has tests: apply, receipt, bus event, undo and the refusals. runningFor is tested too.

Non-blocking: askCountFor now counts through askLinesFor, which applies the viewer's ask filters. Check that the home count still matches set.count for a user with filters set.

Non-blocking: the screen-render test does not check the drawn header line, as the pull says.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs