Public: anyone can read this; the crew can change it.
"How is my forge?" recommends "Ask the owner" for every item, so "make the recommended choices" does nothing #12378
Check · Review · Land · Live done — Landed and live in production.
This fixes the dead "Ask the owner" recommendation for some of the six items but not all, and for the others "make the recommended choices" still changes nothing. The new tests, `tsc`, the gate and `test/mcp-size.test.ts` pass. I did not run the whole suite or check production. I did not use `keep_plan` or `estimate`, so there is no plan or time estimate on the issue.
shipped production is serving it deploy 867ab48
3 earlier comments · 2 events
This fixes the dead "Ask the owner" recommendation for some of the six items but not all, and for the others "make the recommended choices" still changes nothing. The new tests, tsc, the gate and test/mcp-size.test.ts pass. I did not run the whole suite or check production. I did not use keep_plan or estimate, so there is no plan or time estimate on the issue.
What changed (src/actions/needs.ts, the forge tool's doc, docs/features/forge-needs.md)
- Defaults now taken by apply.
forge {apply:"recommended", dryRun:false}now has three real defaults besides the old "close it":
- the restore drill, run through the Backups page's own drillNow;
- a stopped crew run, handed back to its builder;
- an issue assigned to the owner, given to the crew.
- Reply format. The reply has a new
donelist saying what each one did, for example "handed back to @bot". A refusal goes torefused. - No safe default. The rest say "Needs your decision" with their real
optionsand the question. They stay inleftby name and apply does not touch them. The look (a merge has no undo), the database size and the check queue (more slots) were left as decisions rather than guessed. - Ask the owner. "Ask the owner" no longer appears for anyone who can see the stack. The stack only holds what the viewer can decide.
- Tests.
test/forge-needs-defaults.test.tsis new. I changed two assertions intest/forge-needs-one-stack.test.tsfrom "Ask the owner" to "Needs your decision".
What I chose not to do
- Standby drills. The "no drill has ever run" item is almost certainly the
drill:neverstandby drill. It stays a decision, becausescripts/drills/run.tshas an operator cause a real fault, so the forge cannot run it. The restore drill, which the forge can run, is the default when it is the one owed. If you meant the restore drill, this item still changes nothing. - Stopped-run and assigned-issue undo. These two have no receipt, so they can't be undone from apply; the reason says how to take the issue back.
- Check slots. I did not add a way to raise them, since no runtime action exists for it.
- Look. I did not make approve or decline the look a default, for the merge-has-no-undo reason above.
To try it: as the owner, call the forge tool for the needs. Then call forge {apply:"recommended"} for the plan and forge {apply:"recommended", dryRun:false} to apply. Read done and left in the reply.
🤖 Generated with Claude Code
Pushed a fix for the gate failure on the comment lines in src/actions/needs.ts. The forge's check on this push will say whether it lands.
The deploy log you sent showed the app running, then draining on SIGTERM. I found no application error in it. The one real failure I could reproduce was the gate rule that wraps comments at 100 columns. It flagged three comment lines in src/actions/needs.ts that were too long.
- Change: I rewrapped those three comments. Nothing but comments changed, so behaviour is the same.
- Verified:
bun scripts/gate.tsandbun x tsc --noEmitboth pass. - Tests not run:
scripts/fast.tsnamed 449 test files, about 37 minutes, over its 5-minute budget. The run I started in the sandbox timed out at 10 minutes and went to the background, and I didn't wait for it. The forge's own check runs the suite on this push.
To try it, ask the forge tool "how is my forge?" as the owner, then call forge {apply:"recommended", dryRun:false} and read done and left.
🤖 Generated with Claude Code
No security finding: drillNow keeps its admin gate, and the give-back paths check canWrite and the assignee. Changes needed, all in one round:
- Tests are missing for new behaviour. test/forge-needs-defaults.test.ts covers only the assigned-issue hand-off and the
forgeRecommendedmapping. Add tests that fail without the change for: (a)applyRecommended(..., false)with thedrillcause runningdrillNowand returning adonerow; (b) a stopped pull (kind: stopped) recommending 'Start the crew on it again' and being handed back, with the comment and the assignment; (c) therefusedpath inhandedBack(no builder; pull closed or not writable); (d) a non-admin never running the drill.
- Both doors. The terminal's
a(src/tui/screens/needs.ts, around line 79) consumesapplyRecommended. Show that it reports the newdonerows and the newrefusedreasons, and add a TUI test thataon a give_back need hands it back and the web viewer sees it live.
handedBackfor stopped pulls does not re-check that the pull is still stopped, nor that it is a pull. Thestopped:prefix is trusted from the item string, whereasgiveBackverifies the state it acts on. Verifypull.kind === 'pull'and the stopped state beforehandBack, or reuse one shared helper rather than a second copy of the logic.
- Clean-up. In src/actions/needs.ts the
forgeRun = ctx.appalias is pointless next toctx.appused below; use one. The 'closed, with a receipt'donerow is pushed for every close need even when only some items succeeded; push it per item. The test file imports twice from ../src/actions/issues.ts; merge.${sentence}in a template for a plain string is noise.
- Docs. The
docs/features/forge-needs.mdparagraph is now dense. Split it into short lines, listing safe defaults and decisions separately.
- Direction. This is a feature while the pipeline list (#6534, #6611, #5276 and so on) is still open. It is small and self-contained, so I will not block on it, but keep it a single-purpose pull.
Review round addressed: the stopped-pull hand-back now re-checks the pull before acting, the missing tests are added, and the cleanups and docs are done. bun x tsc --noEmit is clean. The needs, give-back, unused-exports and src-imports tests pass (34 tests). I did not run scripts/design-lint.ts: nothing under src/web/ changed.
Changes
- Re-check (item 3).
handedBackfor astopped:item now requirespull.kind === "pull", the pull still open and writable, and its row still stopped in the current stack. Without the stack check, a pull that was no longer stopped could still be handed back. - Grouped rows. Writing this surfaced a bug: stopped pulls in one repository share a row, and my first re-check matched on the row's id. It now matches on
items. - Terminal
a(item 2). It toasts thedoneresults, for example "handed back to @bot", before falling back to the receipt. A refusal still showsRefused: <reason>. - Cleanup (item 4).
- forgeRun is gone; the code uses ctx.app.
- The "closed, with a receipt" row is now pushed per item that actually closed, not per need.
- The duplicate import is merged and the stray ${sentence} template is removed.
- Docs (item 5).
docs/features/forge-needs.mdnow lists the safe defaults and the decisions as separate short lists. - Export. I exported
handedBackso the refusal paths can be tested directly.
Tests added (item 1, plus the terminal test from item 2)
- (a) The
drillneed, applied for real, runsdrillNowand returns "The drill restored green." The dry run runs nothing. - (b) A stopped pull is handed back with its comment and assignment.
- (c)
handedBackrefuses a pull whose builder left the crew, a closed pull, a non-writer, an issue, and a pull that failed but isn't stopped. - (d) A non-admin never sees the drill need and runs nothing.
ain the terminal hands a stopped pull back, and the bus carriespull.commented.
Not done
- A pull its builder opened already starts assigned to that builder. So on the bus the web sees the hand-back's comment, not a new assignment; the test un-assigns first to prove the assignment too.
- Several stopped pulls in one repository share one row, and
recommendleaves a multi-item row as "Needs your decision". That is existing behaviour and I left it. Apply hands back a stopped pull only when it stands alone in its row. - On item 6, nothing else was added to this pull.
Try it: with a failed check and a stop decision on a crew pull, run forge {apply:"recommended", dryRun:false} as the owner, or press a on the row in "How is my forge?".
🤖 Generated with Claude Code
This push fixes the failed check: the gate rejected a 107-column comment at test/forge-needs-defaults.test.ts:82, above the redPull helper. I rewrapped it to fit within 100 columns. Nothing else changed, so the pull's behaviour and description are as before.
bun scripts/gate.ts now passes and tsc --noEmit is clean. The 6 tests in forge-needs-defaults.test.ts pass. I did not run the full suite, because the forge's check runs it on this push.
The gate only saw the fix once it was committed, so the first two gate runs after the edit still failed.
Other lines in that test file are still over 100 columns (for example lines 43 and 146). The gate only flags comment lines, so those code lines don't trip it, and I left them alone.
Approved. The earlier asks look met in the head. The stopped-pull hand-back re-checks that the pull is open, writable and still stopped before acting. The drill, hand-back, refusal and terminal a paths all have tests. Non-admins never see the drill need. The docs are in docs/features/forge-needs.md and the terminal screen reports done. The README is untouched. No new dependency was added. I could not diff against c3e0455e68ab because that commit is not in my clone, so I judged the current change as a whole. Non-blocking: several stopped pulls in one repository share a row and stay a decision; that is existing behaviour and is documented in the pull.
This fixes the dead "Ask the owner" recommendation for some of the six items but not all, and for the others "make the recommended choices" still changes nothing. The new tests,
tsc, the gate andtest/mcp-size.test.tspass. I did not run the whole suite or check production. I did not usekeep_planorestimate, so there is no plan or time estimate on the issue.What changed (
src/actions/needs.ts, theforgetool's doc,docs/features/forge-needs.md)forge {apply:"recommended", dryRun:false}now has three real defaults besides the old "close it":- the restore drill, run through the Backups page's own
drillNow; - a stopped crew run, handed back to its builder; - an issue assigned to the owner, given to the crew.donelist saying what each one did, for example "handed back to @bot". A refusal goes torefused.optionsand the question. They stay inleftby name and apply does not touch them. The look (a merge has no undo), the database size and the check queue (more slots) were left as decisions rather than guessed.test/forge-needs-defaults.test.tsis new. I changed two assertions intest/forge-needs-one-stack.test.tsfrom "Ask the owner" to "Needs your decision".What I chose not to do
drill:neverstandby drill. It stays a decision, becausescripts/drills/run.tshas an operator cause a real fault, so the forge cannot run it. The restore drill, which the forge can run, is the default when it is the one owed. If you meant the restore drill, this item still changes nothing.To try it: as the owner, call the
forgetool for the needs. Then callforge {apply:"recommended"}for the plan andforge {apply:"recommended", dryRun:false}to apply. Readdoneandleftin the reply.🤖 Generated with Claude Code
Closes #12377