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

A forge that reaches its CPU limit is slowed, not stopped: a crew run on a 1-CPU forge finishes #11540

opened this in answer to

Check · Review · Land · Live — No review yet. Next: reviewer, no review yet.

Ready to land

A forge at its CPU limit is now slowed instead of stopped, but the acceptance checks on a real small forge are not done, so do not close #11539 yet. The `keep_plan` tool wasn't available to me, so the plan is in this description.

21 files · +549 −10

waiting waiting for sentinel's review deploy 36f0b35

Check passeddeploy 36f0b35

Website spec: 23 findings (report only)

Look

9 pages beside main · 0 new to this pull

/apps

main

at abf00b0 ·

this pull

In the dark

main

at abf00b0 ·

this pull

at 36f0b35 ·

/explore

main

at abf00b0 ·

this pull

In the dark

main

at abf00b0 ·

this pull

at 36f0b35 ·

/feed

main

at abf00b0 ·

this pull

In the dark

main

at abf00b0 ·

this pull

at 36f0b35 ·

/front

main

at abf00b0 ·

this pull

In the dark

main

at abf00b0 ·

this pull

at 36f0b35 ·

/map

main

at abf00b0 ·

this pull

In the dark

main

at abf00b0 ·

this pull

at 36f0b35 ·

/notes

main

at abf00b0 ·

this pull

In the dark

main

at abf00b0 ·

this pull

at 36f0b35 ·

/releases

main

at abf00b0 ·

this pull

In the dark

main

at abf00b0 ·

this pull

at 36f0b35 ·

/repos

main

at abf00b0 ·

this pull

In the dark

main

at abf00b0 ·

this pull

at 36f0b35 ·

/review

main

at abf00b0 ·

this pull

In the dark

main

at abf00b0 ·

this pull

at 36f0b35 ·

opened this

A forge at its CPU limit is now slowed instead of stopped, but the acceptance checks on a real small forge are not done, so do not close #11539 yet. The keep_plan tool wasn't available to me, so the plan is in this description.

What changed

  • Throttle: a cell the kernel can't cap with cpu.max now has its process tree paused (SIGSTOP/SIGCONT) for part of each tick. It averages its cores, and nothing is killed for being busy (src/apps/throttle.ts, wired into watchTree in src/apps/contain.ts). Using exactly the limit no longer counts as over it.
  • Last resort: a cell is stopped for CPU only after five minutes over twice its limit, and never in its first ten minutes. Memory, disk and process-count stops are unchanged.
  • Owner told: when the host stops a child forge, it writes host-stopped.json into that forge's data directory (src/spawn/stop_note.ts). The owner's home page shows what happened and why for a day, under "Needs you".
  • Work fits the size: on a 1-core forge, checks are not started, scheduled snapshots are not taken and looks wait while a crew run is running (src/spawn/fit.ts). A waiting look's age restarts, so a long run doesn't drop it. Pictures and the accessibility check now share one browser gate (src/looks/browser_gate.ts).
  • Interrupted runs: a run cut off by a restart already resumed in the same clone and session. If it is cut off twice in a row, the issue is parked with a plain note instead of looping (src/crew/interrupt_loop.ts).
  • Plan lines: small now says the crew has its only core while it builds, so a change takes longer and checks and pictures wait. Medium says checks and pictures run beside the crew.
  • Docs: docs/features/cpu-throttle.md.

Tests

  • New tests: test/cpu-throttle.test.ts (the pause by hand calculation, the last-resort rule, and a real CPU hog held under its limit), test/crew-has-the-core.test.ts, test/crew-interrupted-twice.test.ts and test/host-stop-note.test.ts (including the home page line).
  • The suites I ran, bun x tsc --noEmit, scripts/gate.ts and scripts/design-lint.ts pass. The exception is three real-chromium tests in test/looks.test.ts, which fail the same way without my change because chromium can't start in this sandbox.
  • scripts/fast.ts named 2267 files, too many to run, so I ran the suites near the change instead. The forge's own check runs the rest.

What I did not do

  • Three-minute real 1-CPU cell test: not written. The sandbox can't create cells.
  • Stranger journey on small and the production probe: not run. Do not close #11539 until the probe passes and its host-log lines are pasted here.
  • Measured first-change times for small, medium and large: not taken. The plan lines say what each size is for, with no numbers, which test/sizes-api.test.ts requires.
  • Credit charged twice: I did not confirm whether a resumed run could be charged twice for the same work. Spend is written per run, and the resumed run continues the same session.
  • Throttle accuracy: the pause is sized from a 5-second window, so it settles near the limit after a few seconds and can overshoot briefly under load. The throttle test therefore only asserts well below an unthrottled core.

Try Put a host-stopped.json in a forge's data directory, then open the admin's home page and read the line under "Needs you". The file looks like {"at":"<ISO time>","why":"…"}.

🤖 Generated with Claude Code

Closes #11539

commented

A forge at its CPU limit is now slowed instead of stopped, but the acceptance checks on a real small forge are not done, so do not close #11539 yet. The keep_plan tool wasn't available to me, so the plan is in this description.

What changed

  • Throttle: a cell the kernel can't cap with cpu.max now has its process tree paused (SIGSTOP/SIGCONT) for part of each tick. It averages its cores, and nothing is killed for being busy (src/apps/throttle.ts, wired into watchTree in src/apps/contain.ts). Using exactly the limit no longer counts as over it.
  • Last resort: a cell is stopped for CPU only after five minutes over twice its limit, and never in its first ten minutes. Memory, disk and process-count stops are unchanged.
  • Owner told: when the host stops a child forge, it writes host-stopped.json into that forge's data directory (src/spawn/stop_note.ts). The owner's home page shows what happened and why for a day, under "Needs you".
  • Work fits the size: on a 1-core forge, checks are not started, scheduled snapshots are not taken and looks wait while a crew run is running (src/spawn/fit.ts). A waiting look's age restarts, so a long run doesn't drop it. Pictures and the accessibility check now share one browser gate (src/looks/browser_gate.ts).
  • Interrupted runs: a run cut off by a restart already resumed in the same clone and session. If it is cut off twice in a row, the issue is parked with a plain note instead of looping (src/crew/interrupt_loop.ts).
  • Plan lines: small now says the crew has its only core while it builds, so a change takes longer and checks and pictures wait. Medium says checks and pictures run beside the crew.
  • Docs: docs/features/cpu-throttle.md.

Tests

  • New tests: test/cpu-throttle.test.ts (the pause by hand calculation, the last-resort rule, and a real CPU hog held under its limit), test/crew-has-the-core.test.ts, test/crew-interrupted-twice.test.ts and test/host-stop-note.test.ts (including the home page line).
  • The suites I ran, bun x tsc --noEmit, scripts/gate.ts and scripts/design-lint.ts pass. The exception is three real-chromium tests in test/looks.test.ts, which fail the same way without my change because chromium can't start in this sandbox.
  • scripts/fast.ts named 2267 files, too many to run, so I ran the suites near the change instead. The forge's own check runs the rest.

What I did not do

  • Three-minute real 1-CPU cell test: not written. The sandbox can't create cells.
  • Stranger journey on small and the production probe: not run. Do not close #11539 until the probe passes and its host-log lines are pasted here.
  • Measured first-change times for small, medium and large: not taken. The plan lines say what each size is for, with no numbers, which test/sizes-api.test.ts requires.
  • Credit charged twice: I did not confirm whether a resumed run could be charged twice for the same work. Spend is written per run, and the resumed run continues the same session.
  • Throttle accuracy: the pause is sized from a 5-second window, so it settles near the limit after a few seconds and can overshoot briefly under load. The throttle test therefore only asserts well below an unthrottled core.

Try Put a host-stopped.json in a forge's data directory, then open the admin's home page and read the line under "Needs you". The file looks like {"at":"<ISO time>","why":"…"}.

🤖 Generated with Claude Code

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs