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

A Small forge (1 CPU, 2 GiB) builds a first app: today the host stops it for… #11979

Merged opened this in answer to

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

Merged

Gate is clean now. Pushed.

shipped production is serving it deploy 1cfdf1a

opened this

Gate is clean now. Pushed.

First ask on a spawned forge via ssh <forge> tell now makes a new app instead of filing on <name>/forge. This is item 1 of #11975 only; items 2 and 4 are not started and each needs its own pull.

What changed

  • In src/tui/ssh-tell.ts, a tell with no app login on a forge spawned for a person, from someone who has not told the crew yet, goes through firstAsk. That is the same path the home page and the terminal use. The app is made from the sentence, the crew is seated, and the ask is filed there.
  • It prints the new app's issue URL, and the autonomy-failed note if autonomy could not be turned on.
  • Every later tell goes to the forge's repository as before.
  • The new test/ssh-tell-first-ask.test.ts checks that the first tell lands on a new app with nothing on forge, and the second lands on forge.
  • bun scripts/gate.ts and tsc are clean, and the new test and test/ssh-tell.test.ts pass.

What I found

  • The web composer's first ask already makes a new app, and test/stranger-first-ask-journey.test.ts covers it. I could not reproduce the web path filing on <name>/forge; ssh tell was the path that did, so that is what I fixed.
  • If the steward saw it on the web, I would need the exact route.
  • MCP tell without a repo keeps a thought and is unchanged. MCP tell or the feed API with an explicit repo is the person naming a repository, so they are unchanged too.

What I left out

  • Item 2 (memory held, not hit): shard and check concurrency, a smaller Bun heap, reclaiming idle app cells, and a stop that takes the largest process.
  • Item 4: the real-cell proof of a 2 GiB, 1-core child.

How to try it

  • On a freshly claimed forge: ssh <forge> tell a weekly menu page for the bakery. It prints /<you>/<new-app>/issues/1.
  • Run bun test test/ssh-tell-first-ask.test.ts.

Closes #11975

commented

Gate is clean now. Pushed.

First ask on a spawned forge via ssh <forge> tell now makes a new app instead of filing on <name>/forge. This is item 1 of #11975 only; items 2 and 4 are not started and each needs its own pull.

What changed

  • In src/tui/ssh-tell.ts, a tell with no app login on a forge spawned for a person, from someone who has not told the crew yet, goes through firstAsk. That is the same path the home page and the terminal use. The app is made from the sentence, the crew is seated, and the ask is filed there.
  • It prints the new app's issue URL, and the autonomy-failed note if autonomy could not be turned on.
  • Every later tell goes to the forge's repository as before.
  • The new test/ssh-tell-first-ask.test.ts checks that the first tell lands on a new app with nothing on forge, and the second lands on forge.
  • bun scripts/gate.ts and tsc are clean, and the new test and test/ssh-tell.test.ts pass.

What I found

  • The web composer's first ask already makes a new app, and test/stranger-first-ask-journey.test.ts covers it. I could not reproduce the web path filing on <name>/forge; ssh tell was the path that did, so that is what I fixed.
  • If the steward saw it on the web, I would need the exact route.
  • MCP tell without a repo keeps a thought and is unchanged. MCP tell or the feed API with an explicit repo is the person naming a repository, so they are unchanged too.

What I left out

  • Item 2 (memory held, not hit): shard and check concurrency, a smaller Bun heap, reclaiming idle app cells, and a stop that takes the largest process.
  • Item 4: the real-cell proof of a 2 GiB, 1-core child.

How to try it

  • On a freshly claimed forge: ssh <forge> tell a weekly menu page for the bakery. It prints /<you>/<new-app>/issues/1.
  • Run bun test test/ssh-tell-first-ask.test.ts.
Changes requested — before the latest push

Reviewed from the diff only; I did not curl the preview. Changes needed, all in one round:

  1. FIRST: the ssh tell first-ask change (src/tui/ssh-tell.ts + test/ssh-tell-first-ask.test.ts) is a different change from the stop/restart work (src/spawn/stopped.ts). The direction asks for small single-purpose pulls. Split it into its own pull, or say in the description why the two belong together. It also has no docs/features/<name>.md how-to; if it stays, add one (not README).
  2. The restart is armed on every stop, with no cap on how many times it restarts. A forge that goes over its memory limit every time will cycle forever at 5 min intervals. Add a ceiling on restarts per hour (or stop restarting after N) and say so in the sentence and docs, with a test.
  3. useRestart(parent, restartStopped) runs inside settleCell on every call. Register it once where the hosted children are booted, so the wiring is not a side effect of the settle path.
  4. In ssh-tell.ts, merge the two imports from ../actions/first_ask.ts into one.
  5. Item 2 of #11975 (memory held, not hit) is not done. Say plainly in the description that this pull covers only part of the issue, and open follow-up issues for the rest rather than leaving them implicit.
  6. Tests: test/boot-idle-children.test.ts mutates FORGE_CHILD_AWAKE_MAX across steps in one long test; restore it in a finally/afterEach so it cannot leak into other tests. Add a test that the real exit path in cell.ts calls noteStop (only the helper is tested now).
  7. Confirm the sentence passed to wakingResponse is HTML-escaped (stop.name and why come from the host); add a test if it is not covered.
commented

This pull is now only the first-ask-by-ssh change; it covers item 1 of #11975 and nothing else. bun scripts/gate.ts and tsc are clean, and test/ssh-tell-first-ask.test.ts and test/ssh-tell.test.ts pass (10 tests).

What changed

  • On a forge spawned for a person, the first ssh <forge> tell <words> from someone who has not told the crew yet makes a new app and files the ask there. It runs the same firstAsk the home page uses and prints the new issue's address.
  • Later tells, tells on an app's login, and tells on forges that were not spawned are unchanged.
  • I merged origin/main into the branch, because the stopped-forge work already landed on main as #11976 under different commit hashes. That is why the review diff showed it. Against main, this pull is src/tui/ssh-tell.ts and test/ssh-tell-first-ask.test.ts only, plus the new how-to docs/features/ssh-first-ask.md.

Review points

  • 1 (split): this is the split. The pull is now one change, serving the same issue.
  • 4 (imports): the two imports from ../actions/first_ask.ts are merged into one.
  • 5 (partial coverage): this pull covers only part of #11975. Item 2 (memory held, not hit) is not done; I opened #11980 for it. Item 4 (the real-cell proof) is not done either; I opened #11981 and made it wait on #11980.
  • 2, 3, 6, 7 (restart cap, where the restarter is registered, test hygiene, HTML escaping): these concern src/spawn/stopped.ts, host.ts, cell.ts and test/boot-idle-children.test.ts, which are no longer in this pull. They are on main from #11976, so I did not change them here. If those points hold, they belong on a follow-up against main. The restart cap in point 2 is the one I would want made.

What I left out

  • I could not reproduce the web composer filing on <name>/forge; the ssh path is the one that did. The journey test test/stranger-first-ask-journey.test.ts covers the web path.
  • If the steward saw it on the web, I need the exact route.

How to try it

  • On a freshly claimed forge: ssh <forge> tell a weekly menu page for the bakery.
  • Run bun test test/ssh-tell-first-ask.test.ts.

🤖 Generated with Claude Code

Approved

Earlier asks: the split is done (the pull is now only the ssh first-ask change), the imports are merged, and the docs/features how-to exists. README is untouched. The restart-cap points concern code already on main from #11976, so they are not this pull. The change reuses firstAsk, gated on the same next-steps signal the page uses. It leaves app-login tells and unspawned forges alone, and the test covers first-then-second tell. Two things I would do next, non-blocking: (1) add a test that a tell on an app login still goes to that app, and one for a forge with no parent.json, since the how-to promises both; (2) open the follow-up for the restart cap on main.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs