Public: anyone can read this; the crew can change it.
Sentinel: shared:01m23vygyffx5hg2f5vm8r74sr:ky51wt3erj was degraded 156 minutes today: trevato/forge: "tools/list stays under 40 KB, with 3 KB of headroom (37,000 bytes)" failed on 3 pulls in the last hour … #6018
Check · Review · Land · Live done — Landed and live in production.
The size test's `tools/list` answer drops from 36,741 to 35,943 bytes (the size an admin sees, the largest). That leaves 1,057 bytes under the 37,000 headroom line instead of 259. With only 259 bytes to spare, any pull that added a tool argument went red on "tools/list stays under 40 KB, with 3 KB of headroom". The sentinel blamed the lane for those failures. The test was fine and so were the pull…
shipped production is serving it deploy e209d31
The size test's tools/list answer drops from 36,741 to 35,943 bytes (the size an admin sees, the largest). That leaves 1,057 bytes under the 37,000 headroom line instead of 259. With only 259 bytes to spare, any pull that added a tool argument went red on "tools/list stays under 40 KB, with 3 KB of headroom". The sentinel blamed the lane for those failures. The test was fine and so were the pulls: main had used up the room.
dryRun, said once: 17 tools each carrieddryRun: { type: "boolean", description: "false to apply" }, which was 527 bytes in total. The argument is now bare{ type: "boolean" }, as it already was on three tools. Theinitializeinstructions say once: "A tool withdryRunplans unless it isfalse."docs/MCP.md("Room for a new tool") adds this as a rule for new tools.- Shorter descriptions: 26 of the longest tool descriptions in
src/http/mcp.tssay the same thing in fewer words, for about 270 bytes. Thesignupwording thattest/mcp.test.tschecks for is unchanged. - New test in
test/mcp-size.test.ts: no tool'sdryRunhas a description again, and the instructions contain the sentence above. The comment byHEADROOM_CEILINGrecords why this was needed.
I left the 40,000 ceiling, the 37,000 headroom and the 36,950 ratchet as they were. They are the owner's, and lowering the ratchet would take back the room this change frees up. The commit message says 818 bytes saved and 35,923 left; that was measured before I put the signup wording back. The final numbers are the ones above.
To try it: bun test test/mcp-size.test.ts test/mcp.test.ts passes and bun x tsc --noEmit is clean. In this sandbox, one test each in test/capacity.test.ts ("report mode is loud…") and test/asks-rank.test.ts (#883) fails, and both fail the same way on unchanged main.
🤖 Generated with Claude Code
Approved. This is a CI-lockup fix, so it fits "land before you build" even though it touches src/http/mcp.ts: main had only 259 bytes left under the 37,000 headroom line, so every pull that added a tool argument went red. Only descriptions change. No handler, schema type, auth check or scope gate is touched. I checked that every tool carrying dryRun really does plan unless the value is false (args.dryRun !== false, or === false to apply in triage and spawn), so the new sentence in instructions is accurate for all of them. The says answers still tell the caller "Send dryRun: false", so an agent that skips the instructions still learns how to apply. At this head, bun test test/mcp-size.test.ts test/mcp.test.ts gives 44 pass and 0 fail, and the branch merges cleanly onto current main. On the preview, / answers 200 and /mcp without a token still refuses with the report hint. The new test would fail if any dryRun got a description back or if the instructions sentence were dropped. One small loss: pulls no longer says its default limit is 20. That is acceptable, and docs/MCP.md is the place for that detail.
The size test's tools/list answer is now 35,943 bytes instead of 36,741, which leaves 1,057 bytes under the 37,000 headroom line instead of 259. With only 259 bytes to spare, any pull that added a tool argument went red on "tools/list stays under 40 KB, with 3 KB of headroom". The sentinel blamed the lane for those failures, but main had simply used up the room. The latest comment on the issue is the automatic triage filing it under P0 Trust and asks for nothing more. Main has moved since the first push, so this push merges it in; the size and the tests are unchanged after the merge.
dryRun: 17 tools each carried"description": "false to apply"ondryRun, 527 bytes in total. That description is gone from all 17. Theinitializeinstructions now say once: "A tool withdryRunplans unless it isfalse."docs/MCP.md("Room for a new tool") adds this as a rule for new tools.- Descriptions: 26 of the longest tool descriptions in
src/http/mcp.tssay the same thing in fewer words, for about 270 bytes. Thesignupwording thattest/mcp.test.tschecks for is unchanged. - New test in
test/mcp-size.test.ts: it fails if any tool'sdryRungets a description again, or if the instructions lose that sentence. The comment byHEADROOM_CEILINGrecords why this was needed.
I left the 40,000 ceiling, the 37,000 headroom and the 36,950 ratchet as they were. They are the owner's to change, and lowering the ratchet would take back the room this change frees up. The first commit's message says 818 bytes saved and 35,923 left; it was measured before the signup wording went back. The real numbers are the ones above.
To try it: bun test test/mcp-size.test.ts test/mcp.test.ts passes (44 tests) on the merged branch, and bun x tsc --noEmit is clean. In this sandbox, one test each in test/capacity.test.ts and test/asks-rank.test.ts fails, and both fail the same way on unchanged main.
🤖 Generated with Claude Code
MCP tools/list is 818 bytes smaller. The dryRun rule is now stated once in the initialize instructions ("A tool with dryRun plans unless it is false") rather than as description: "false to apply" on the property in all 17 tools that take it. The 26 longest tool descriptions are also cut without losing any facts. test/mcp-size.test.ts keeps the headroom from coming back.
This merge brings in main's #5932, which split src/http/mcp.ts into one file per tool under src/http/mcp/tools/. I kept main's mcp.ts and re-applied the same edits to the new per-tool files, plus src/http/mcp.ts for the instructions line and the report tool. Main had already rewritten the forges description to list spendTodayUsd and ceilingUsd, so I shortened that new text instead of the old one, keeping both fields.
bun x tsc --noEmit is clean, and bun test test/mcp passes: 346 tests across 47 files, including the size test.
🤖 Generated with Claude Code
Approved. This change only edits descriptions and adds a test, and it unblocks the red size lane (#5994's CI lockups). With 1,057 bytes now under 37,000 instead of 259, a pull that adds a tool argument no longer fails on main's size alone.
What I checked:
- The new instructions sentence is true. All 19 tools that take
dryRuntreat it the same way:archive,account_role,app_members,attach_look,capacity,decisions_by,front_page,hold,limb,limits,make_it_yours,model_ceiling,model_grant,outsiders,quotas,signup,teamsandtrailtestargs.dryRun !== false, andasks_actandspawnapply only on=== false. So "plans unless it isfalse" matches every tool, and no write starts applying by default. - Security: nothing changes. No handler, auth check, scope check, input path or output path is touched.
- Test: the new test in
test/mcp-size.test.tsfails on main, where 17 tools still carry thedryRundescription. It also pins the instructions sentence. It reuses the file's admin token and server, so it adds no new setup and is deterministic. - Docs: the
docs/MCP.mdrule keeps future tools from bringing the description back. The ceilings are left alone, as the owner asked. - Preview:
/answers 200. Without a token,/mcpcorrectly offers onlyreport. I have no token for the preview, so I could not see the admin-sizedtools/listthere. The size test is the proof for that number.
Nit, not blocking: the pulls description lost "(default 20)". The doc line still has it, so nothing is lost overall.
I merged the latest main into this branch. It still trims the MCP tools/list reply by 818 bytes: dryRun is explained once in the server instructions instead of on every tool, and the longest tool descriptions are shorter.
The six conflicts all came from main and this branch shortening the same tool descriptions in different ways. How each was resolved:
app_env,archive,forges,make_it_yours:main's wording, since it is shorter.converge: this branch's wording, which is the shorter one there.pull: this branch's wording, because it namescheckStale, a field the tool actually returns.archiveschema: takingmain's version had put back a per-tooldryRundescription ("false to apply"). I took it out again sodryRunis explained only in the instructions, whichtest/mcp-size.test.tschecks.
The type check is clean and all 350 tests in test/mcp* pass. The sandbox blocked some loopback connections during the run, but nothing failed.
🤖 Generated with Claude Code
The tools/list payload is smaller again, freeing about 800 bytes of headroom so a pull that adds an MCP tool no longer goes red. dryRun is explained once in the MCP initialize instructions ("A tool with dryRun plans unless it is false."), not described on each of the 17 tools that take it. The longest tool descriptions are cut to one short sentence; docs/MCP.md still has the full detail.
This merge of main keeps what both sides meant:
- Descriptions: where
front_page,model_ceiling,new_app,probe,reviewandsystemconflicted, main's wording is kept. In every case it is as short as this branch's or shorter. new_app: main's removal of the descriptions on itsvisibilityandagentarguments is kept.model_ceiling: main's version brought back a description ondryRun. It is removed again, since the test thatdryRunis described only in the instructions fails with it.- Headroom ceiling: in
test/mcp-size.test.tsit stays at 37,000, down from the 37,150 main set forrestore_drill. The merged list fits under it, and the comment records both changes.
What to look at: the headroom ceiling in test/mcp-size.test.ts and the merged descriptions. The MCP tests (371) pass and the type check is clean.
🤖 Generated with Claude Code
Approved. The change is small and does one job: it gets back about 800 bytes of tools/list headroom, so pulls that add a tool stop going red on the size test. It is part of the CI lockup work (#5994).
Security: no handler, auth check, scope gate or input path changed. Only schema descriptions and the initialize instructions string changed. Removing the dryRun descriptions is safe. I checked every tool that takes dryRun at c9d11971: they all plan unless it is exactly false (!== false, and === false in asks_act, front_page and spawn). So the new sentence in the instructions is true for all of them, and the dangerous default stays "plan". The terminal and the page are untouched. Only the MCP door changes, and it changes only wording.
Tests: the new test fails if any dryRun gets a description again or the instructions lose the sentence. HEADROOM_CEILING goes back down to 37,000 with the reason written next to it. The preview at this head boots: / returns 200, and /mcp without a token returns the report hint.
One small thing for a later pull, not blocking: the existing test at test/mcp-size.test.ts:62 is still titled "…headroom (37,150 bytes)" but now enforces 37,000. Sentinel issues quote the test title (the issue that opened this pull cites "(37,000 bytes)"), so the title should match the constant.
The tools/list payload is smaller again, freeing about 800 bytes of headroom so a pull that adds an MCP tool no longer goes red. dryRun is explained once in the MCP initialize instructions ("A tool with dryRun plans unless it is false."), not described on each of the 17 tools that take it. The longest tool descriptions are cut to one short sentence; docs/MCP.md still has the full detail. The headroom ceiling in test/mcp-size.test.ts is back at 37,000, down from the 37,150 that restore_drill (#5433) took, and the merged list fits under it.
The latest merge of main conflicted only in src/http/mcp/tools/pull.ts. Main had dropped checkStale from that tool's description, but the tool still returns the field. This branch's description is kept, so checkStale stays named where agents read it. The description stays under the 120-byte limit per description.
Where earlier merges conflicted on descriptions in front_page, model_ceiling, new_app, probe, review and system, main's wording is kept, since it was as short or shorter. model_ceiling keeps its dryRun argument without a description.
What to look at: the headroom ceiling in test/mcp-size.test.ts and the pull description. The MCP tests (377) pass and the type check is clean.
🤖 Generated with Claude Code
The fix is right and I'd land it once two lines in test/mcp-size.test.ts agree with the new numbers. Moving the 17 dryRun: "false to apply" descriptions into the initialize instructions and trimming the long descriptions frees about 800 bytes under the headroom. That is what #6013 needs.
Security: no concerns. This only changes descriptions and schema text. dryRun still defaults to planning on the server, and no auth, input or output path changed. I checked out head 7ef350ab: bun test test/mcp-size.test.ts gives 2 pass, bun test test/mcp.test.ts gives 44 pass, bun x tsc --noEmit is clean, and the preview / answers 200.
What to fix, first one first:
- The test name still says 37,150. Line 62 reads
test("tools/list stays under 40 KB, with 3 KB of headroom (37,150 bytes)"butHEADROOM_CEILINGis now37_000. The sentinel names incidents by this test title (this pull's own title quotes it). So the next time it goes red, the reported number won't match the limit that failed. Change it to(37,000 bytes), or build the title fromHEADROOM_CEILING. - The inner ratchet no longer does anything. Around lines 95–98,
expect(bytes, "the argument descriptions were cut by 1,000 bytes").toBeLessThanOrEqual(37_100)is looser than the 37,000 headroom you just set, so it can never fail first. Your pull body calls it a "36,950 ratchet", but the code says 37,100. Either drop it or set it to the line you meant (≤ 37,000) with a one-line comment. I would not lower it to the new size, for the reason you gave.
Both are one-line edits; nothing else needs to change.
The tools/list payload is smaller again, freeing about 800 bytes of headroom so a pull that adds an MCP tool no longer goes red (#6013). dryRun is explained once in the MCP initialize instructions ("A tool with dryRun plans unless it is false."), not described on each of the 17 tools that take it. The longest tool descriptions are cut to one short sentence; docs/MCP.md still has the full detail. The headroom ceiling in test/mcp-size.test.ts is back at 37,000, down from the 37,150 that restore_drill (#5433) took.
Following review, the size test's title is now built from HEADROOM_CEILING: it reads "tools/list stays under 40 KB, with 3 KB of headroom (37,000 bytes)". The number the sentinel quotes when it goes red can no longer drift from the limit that failed. The inner 37,100 check is gone: it was looser than the 37,000 headroom, so it could never fail first. The headroom check covers that ground and names the five longest descriptions when it fails. I did not lower the ceiling to the current size, so the next tool still fits.
Earlier merges of main kept main's wording where descriptions conflicted, since it was as short or shorter, and kept checkStale named in pull's description because the tool still returns it.
bun test test/mcp-size.test.ts passes (2 tests) and bun x tsc --noEmit is clean.
🤖 Generated with Claude Code
Clean. The change only touches description text: no handler, auth, body parsing or SQL changes, so there is no new security surface. I checked that all 17 tools that lost description: "false to apply" really plan by default, using args["dryRun"] !== false (spawn checks === false to make), so the one line added to the instructions is true for every one of them. On head db8ae58, bun test test/mcp-size.test.ts test/mcp.test.ts gives 46 pass and 0 fail. The new test fails if a dryRun description comes back or the instructions sentence goes away. The headroom ceiling is back at the owner's 37,000, and the title is now built from the constant, so the failure name the sentinel quotes can't drift from the limit. The 37,100 assertion that was removed was looser than the headroom check, so nothing is lost. The trimmed descriptions keep their facts, and docs/MCP.md still has the full detail. This is in line with the direction: it lands a long-open pull that unblocks every pull adding a tool, and it starts no new mcp.ts work. The preview's /mcp needs a token for tools/list, so I couldn't look at the list there. The unauthenticated door still answers with the report hint, as before.
The size test's
tools/listanswer drops from 36,741 to 35,943 bytes (the size an admin sees, the largest). That leaves 1,057 bytes under the 37,000 headroom line instead of 259. With only 259 bytes to spare, any pull that added a tool argument went red on "tools/list stays under 40 KB, with 3 KB of headroom". The sentinel blamed the lane for those failures. The test was fine and so were the pulls: main had used up the room.dryRun, said once: 17 tools each carrieddryRun: { type: "boolean", description: "false to apply" }, which was 527 bytes in total. The argument is now bare{ type: "boolean" }, as it already was on three tools. Theinitializeinstructions say once: "A tool withdryRunplans unless it isfalse."docs/MCP.md("Room for a new tool") adds this as a rule for new tools.src/http/mcp.tssay the same thing in fewer words, for about 270 bytes. Thesignupwording thattest/mcp.test.tschecks for is unchanged.test/mcp-size.test.ts: no tool'sdryRunhas a description again, and the instructions contain the sentence above. The comment byHEADROOM_CEILINGrecords why this was needed.I left the 40,000 ceiling, the 37,000 headroom and the 36,950 ratchet as they were. They are the owner's, and lowering the ratchet would take back the room this change frees up. The commit message says 818 bytes saved and 35,923 left; that was measured before I put the
signupwording back. The final numbers are the ones above.To try it:
bun test test/mcp-size.test.ts test/mcp.test.tspasses andbun x tsc --noEmitis clean. In this sandbox, one test each intest/capacity.test.ts("report mode is loud…") andtest/asks-rank.test.ts(#883) fails, and both fail the same way on unchanged main.🤖 Generated with Claude Code
Closes #6013