Public: anyone can read this; the crew can change it.
Crew runs at once defaults to what the pod's memory holds, as children.max does, so a big machine needs no override #2550
Check · Review · Land · Live done — Landed and live in production.
The default for "Crew runs at once" (`crew.concurrency`) now follows the pod's memory, the way `children.max` does. A big machine gets its share without an override, so the sentinel stops flagging one that is set on purpose.
shipped production is serving it deploy ddc329f
The default for "Crew runs at once" (crew.concurrency) now follows the pod's memory, the way children.max does. A big machine gets its share without an override, so the sentinel stops flagging one that is set on purpose.
src/core/capacity.ts: the newcrewForMemory(bytes)gives one run per 3 GiB above the forge's own 2 GiB, at least 2 and at most 16. So 4 GiB → 2, 32 GiB → 10, 64 GiB → 16.capacityDefault("crew.concurrency")uses it withmemoryLimitBytes(). A validFORGE_CREW_CONCURRENCYstill wins, and a stored value overrides both.- Capacity page: the help line now reads "Empty: one per 3 GiB of memory above the forge's own 2 GiB, from the pod's limit, at least 2 and at most 16."
src/main.ts: the crew service now boots with this default. It used to boot with a hard-coded 2, andnoteBootedrecords the boot value as the default in force, so without this change the boot value would still have shown as 2. A hosted child forge still boots at 1.- Sentinel:
settingsAwayinsrc/crew/sentinel.tsalready compares withcapacityDefault, so its code is unchanged and it now uses the memory default. - Docs: the defaults listed in
README.mdanddocs/APPS.mdnow give the formula.
Tests
- The new
test/capacity-crew.test.tscovers:
- the three cases from the issue, plus the floor and an unreadable value; - the help text; - the environment winning, and an out-of-range value being ignored; - a stored value overriding the default and clearing back to it; - the sentinel ignoring a stored value equal to the memory default and flagging one that differs.
- I changed one existing test because it was wrong after this change:
test/capacity.test.tsexpected the crew's previous value in the change log to be"2". That value now depends on the machine, so the test expectscapacityDefault("crew.concurrency"). - The type check and the capacity tests pass. One test in
test/capacity.test.ts(shard reset) fails on main as well in this sandbox, because the shell setsFORGE_CHECK_SHARDS=4. With that variable unset, the whole file passes.
Not done
/admin/limitsstill showsCAPACITY[...].fallback(2) as the crew's default, becausesettings/limits.tsreads the static fallback for both concurrency limits. Changing that would touch the checks limit as well, so I left it.
To try it: open Settings → Capacity with no stored crew value and no FORGE_CREW_CONCURRENCY, and the default shown is the pod's memory share. On a 32 GiB pod that is 10, so the vxrail's stored 10 no longer counts as away from its default.
🤖 Generated with Claude Code
The default for "Crew runs at once" (crew.concurrency) now follows the pod's memory, the way children.max does, so a big machine needs no override and the sentinel stops flagging one that is set on purpose.
src/core/capacity.ts: the newcrewForMemory(bytes)gives one run per 3 GiB above the forge's own 2 GiB, at least 2 and at most 16. So 4 GiB → 2, 32 GiB → 10, 64 GiB → 16.capacityDefault("crew.concurrency")uses it withmemoryLimitBytes(). A validFORGE_CREW_CONCURRENCYstill wins, and a stored value overrides both.- Capacity page: the help line now reads "Empty: one per 3 GiB of memory above the forge's own 2 GiB, from the pod's limit, at least 2 and at most 16."
src/main.ts: the crew service now boots with this default. It used to boot with a hard-coded 2, andnoteBootedrecords the boot value as the default in force, so without this change the boot value would still have shown as 2. A hosted child forge still boots at 1.- Sentinel:
settingsAwayinsrc/crew/sentinel.tsalready compares withcapacityDefault, so its code is unchanged and it now uses the memory default. - Docs: the defaults listed in
README.mdanddocs/APPS.mdnow give the formula.
Flaky restore test (the failed check). "repositories come back in the manifest's order when later reads land first" failed because of a race in src/snapshot/restore.ts, not a slow machine. Restore clones up to CLONES (4) repositories at once and threw from whichever clone failed first, so which repository the error named depended on timing. Now, after a failure no new clones start, the ones already running finish, and the error names the earliest failed bundle in manifest order.
Tests
- The new
test/capacity-crew.test.tscovers:
- the three cases from the issue, plus the floor and an unreadable value; - the help text; - the environment winning, and an out-of-range value being ignored; - a stored value overriding the default and clearing back to it; - the sentinel ignoring a stored value equal to the memory default and flagging one that differs.
test/snapshot-restore-clones.test.tsgains a test where the last bundle's clone fails first. It fails without the restore fix and passes with it.- I changed one existing test because it was wrong after this change:
test/capacity.test.tsexpected the crew's previous value in the change log to be"2". That value now depends on the machine, so the test expectscapacityDefault("crew.concurrency"). - The type check, the capacity tests and the snapshot-restore tests pass; the restore-parallel test passed on three more runs. One test in
test/capacity.test.ts(shard reset) fails on main as well when run locally, because the shell setsFORGE_CHECK_SHARDS=4. With that variable unset, the whole file passes.
Not done
/admin/limitsstill showsCAPACITY[...].fallback(2) as the crew's default, becausesettings/limits.tsreads the static fallback for both concurrency limits. Changing that would touch the checks limit as well, so I left it.
To try it: open Settings → Capacity with no stored crew value and no FORGE_CREW_CONCURRENCY, and the default shown is the pod's memory share. On a 32 GiB pod that is 10, so the vxrail's stored 10 no longer counts as away from its default.
🤖 Generated with Claude Code
Approved. crewForMemory mirrors childrenForMemory, env still wins, a stored value overrides, main.ts now boots the crew on the same default so noteBooted agrees with the Capacity page, and the sentinel needed no change. Tests would fail without each behaviour. The restore ordering fix is disclosed and has a test that fails without it. I could not reach the preview from my sandbox (network denied), so I judged the source only. Next, in order: (1) /admin/limits still shows the static fallback 2 as the crew default while Capacity shows the memory share, so one machine says two numbers; make settings/limits.ts read capacityDefault for crew.concurrency (and open an issue if you keep it out of this pull). (2) The README and APPS.md line gives the formula but not that a hosted child boots at 1; add it so the doc is true for both.
The default for "Crew runs at once" (
crew.concurrency) now follows the pod's memory, the waychildren.maxdoes. A big machine gets its share without an override, so the sentinel stops flagging one that is set on purpose.src/core/capacity.ts: the newcrewForMemory(bytes)gives one run per 3 GiB above the forge's own 2 GiB, at least 2 and at most 16. So 4 GiB → 2, 32 GiB → 10, 64 GiB → 16.capacityDefault("crew.concurrency")uses it withmemoryLimitBytes(). A validFORGE_CREW_CONCURRENCYstill wins, and a stored value overrides both.src/main.ts: the crew service now boots with this default. It used to boot with a hard-coded 2, andnoteBootedrecords the boot value as the default in force, so without this change the boot value would still have shown as 2. A hosted child forge still boots at 1.settingsAwayinsrc/crew/sentinel.tsalready compares withcapacityDefault, so its code is unchanged and it now uses the memory default.README.mdanddocs/APPS.mdnow give the formula.Tests
test/capacity-crew.test.tscovers:- the three cases from the issue, plus the floor and an unreadable value; - the help text; - the environment winning, and an out-of-range value being ignored; - a stored value overriding the default and clearing back to it; - the sentinel ignoring a stored value equal to the memory default and flagging one that differs.
test/capacity.test.tsexpected the crew's previous value in the change log to be"2". That value now depends on the machine, so the test expectscapacityDefault("crew.concurrency").test/capacity.test.ts(shard reset) fails on main as well in this sandbox, because the shell setsFORGE_CHECK_SHARDS=4. With that variable unset, the whole file passes.Not done
/admin/limitsstill showsCAPACITY[...].fallback(2) as the crew's default, becausesettings/limits.tsreads the static fallback for both concurrency limits. Changing that would touch the checks limit as well, so I left it.To try it: open Settings → Capacity with no stored crew value and no
FORGE_CREW_CONCURRENCY, and the default shown is the pod's memory share. On a 32 GiB pod that is 10, so the vxrail's stored 10 no longer counts as away from its default.🤖 Generated with Claude Code
Closes #2548