@@ -10,88 +10,89 @@ import {
1010
1111/**
1212 * Prompt size budget (CL-7664). Numeric asserts only — copy edits must not
13- * fail this test. Baselines were captured from the canonical fixture in
14- * src/agent/prompt-sizes.ts with a +2000 char / +3000 byte allowance; bytes
15- * get the larger headroom because multibyte copy can shift them faster.
13+ * fail this test. Baselines are a checked-in snapshot of the max measured
14+ * sizes across both families from the canonical fixture in
15+ * src/agent/prompt-sizes.ts; budgets add a +2000 char / +3000 byte allowance
16+ * (ceiling to 100) in code below. Bytes get the larger headroom because
17+ * multibyte copy can shift them faster. Adding a director is a type error
18+ * until its baseline lands here; growing a prompt past its allowance fails
19+ * until the baseline moves. Deliberate jumps above baseline + allowance
20+ * belong in PROMPT_SIZE_OVERRIDES with justification, not in the baseline.
1621 */
17- const CHAR_BUDGET : Record < DirectorId , number > = {
18- skywalker : 27000 ,
19- builder : 48800 ,
20- explorer : 14200 ,
21- counsel : 52700 ,
22- intern : 16800 ,
23- critic : 54400 ,
24- greybeard : 53600 ,
25- neckbeard : 72300 ,
26- bruckheimer : 23200 ,
27- // CL-7809: deliberate CL-7663 voice restore (PR #932) grew gaasbot to
28- // 52782 chars; budget = measured + 2000 allowance, ceiling to 100.
29- gaasbot : 54800 ,
30- // CL-7800: deliberate CMO full-fidelity restore grew draper to
31- // 16403 chars; budget = measured + 2000 allowance, ceiling to 100.
32- draper : 18500 ,
33- emil : 16600 ,
34- rand : 15000 ,
35- shakespeare : 54700 ,
36- testsmith : 16200 ,
37- tester : 13900 ,
38- // CL-7658: grok family is the max (13990 chars); budget = measured +
39- // 2000 allowance, ceiling to 100.
40- gauntlet : 16000 ,
41- // CL-7656: grok family is the max (13711 chars); budget = measured +
42- // 2000 allowance, ceiling to 100.
43- prober : 15800 ,
44- // CL-7671 scope-honesty sentences grew migrator past the 12300-char
45- // placeholder: measured-max (11202) + 2000 allowance, ceiling to 100.
46- migrator : 13300 ,
47- // CL-7657: measured 51410 default / 51926 grok chars; +2000 allowance, ceiling to 100.
48- warden : 53500 ,
22+ const PROMPT_SIZE_BASELINE : Record <
23+ DirectorId ,
24+ { chars : number ; bytes : number }
25+ > = {
26+ // Post-953 shared prompts.ts growth; re-measured on rebase.
27+ skywalker : { chars : 25243 , bytes : 25393 } ,
28+ builder : { chars : 47698 , bytes : 47856 } ,
29+ explorer : { chars : 12197 , bytes : 12259 } ,
30+ counsel : { chars : 50746 , bytes : 50918 } ,
31+ intern : { chars : 14612 , bytes : 14664 } ,
32+ // Post-953 shared prompts.ts growth; re-measured on rebase.
33+ critic : { chars : 52916 , bytes : 53096 } ,
34+ greybeard : { chars : 51786 , bytes : 51972 } ,
35+ neckbeard : { chars : 70211 , bytes : 70401 } ,
36+ bruckheimer : { chars : 21296 , bytes : 21394 } ,
37+ // CL-7809: includes the deliberate CL-7663 voice restore (PR #932).
38+ gaasbot : { chars : 52782 , bytes : 52970 } ,
39+ // CL-7800: deliberate CMO full-fidelity restore; re-measured on rebase.
40+ draper : { chars : 16403 , bytes : 16489 } ,
41+ emil : { chars : 14653 , bytes : 14765 } ,
42+ rand : { chars : 13021 , bytes : 13089 } ,
43+ shakespeare : { chars : 52774 , bytes : 52956 } ,
44+ testsmith : { chars : 14088 , bytes : 14166 } ,
45+ tester : { chars : 11975 , bytes : 12033 } ,
46+ // CL-7658: grok family is the max; re-measured on rebase.
47+ gauntlet : { chars : 13835 , bytes : 13897 } ,
48+ // CL-7656: grok family is the max; re-measured on rebase.
49+ prober : { chars : 13586 , bytes : 13656 } ,
50+ // CL-7671 scope-honesty sentences; grok family is the max.
51+ migrator : { chars : 11221 , bytes : 11277 } ,
52+ // CL-7657: grok family is the max; baseline + allowance covers it, so
53+ // main's tighter default-based budget needs no override.
54+ warden : { chars : 51926 , bytes : 52102 } ,
4955} ;
5056
51- const BYTE_BUDGET : Record < DirectorId , number > = {
52- skywalker : 28100 ,
53- builder : 50000 ,
54- explorer : 15200 ,
55- counsel : 53900 ,
56- intern : 17800 ,
57- critic : 55500 ,
58- greybeard : 54800 ,
59- neckbeard : 73400 ,
60- bruckheimer : 24300 ,
61- // CL-7809: deliberate CL-7663 voice restore (PR #932) grew gaasbot to
62- // 52970 bytes; budget = measured + 3000 allowance, ceiling to 100.
63- gaasbot : 56000 ,
64- // CL-7800: deliberate CMO full-fidelity restore grew draper to
65- // 16489 bytes; budget = measured + 3000 allowance, ceiling to 100.
66- draper : 19500 ,
67- emil : 17700 ,
68- rand : 16100 ,
69- shakespeare : 55900 ,
70- testsmith : 17200 ,
71- tester : 15000 ,
72- // CL-7658: grok family is the max (14050 bytes); budget = measured +
73- // 3000 allowance, ceiling to 100.
74- gauntlet : 17100 ,
75- // CL-7656: grok family is the max (13779 bytes); budget = measured +
76- // 3000 allowance, ceiling to 100.
77- prober : 16800 ,
78- // CL-7671 scope-honesty sentences grew migrator past the 13400-byte
79- // placeholder: measured-max (11258) + 3000 allowance, ceiling to 100.
80- migrator : 14300 ,
81- // CL-7657: measured 51584 default / 52102 grok bytes; +3000 allowance, ceiling to 100.
82- warden : 54600 ,
83- } ;
57+ /**
58+ * Deliberate budgets above baseline + allowance, with justification.
59+ * Empty after the origin/main rebase: every main budget fits within fresh
60+ * baseline + allowance (draper/warden included), and the entries where main
61+ * reads higher (intern, testsmith, gauntlet, prober) are stale-measurement
62+ * residue, not deliberate over-allowance.
63+ */
64+ const PROMPT_SIZE_OVERRIDES : Partial <
65+ Record < DirectorId , { chars : number ; bytes : number } >
66+ > = { } ;
67+
68+ const CHAR_ALLOWANCE = 2000 ;
69+ const BYTE_ALLOWANCE = 3000 ;
70+
71+ function ceil100 ( n : number ) : number {
72+ return Math . ceil ( n / 100 ) * 100 ;
73+ }
74+
75+ function budgetFor ( directorId : DirectorId ) : { chars : number ; bytes : number } {
76+ const override = PROMPT_SIZE_OVERRIDES [ directorId ] ;
77+ if ( override !== undefined ) return override ;
78+ const base = PROMPT_SIZE_BASELINE [ directorId ] ;
79+ return {
80+ chars : ceil100 ( base . chars + CHAR_ALLOWANCE ) ,
81+ bytes : ceil100 ( base . bytes + BYTE_ALLOWANCE ) ,
82+ } ;
83+ }
8484
8585function budgetMessage (
8686 directorId : DirectorId ,
8787 family : PromptSizeFamily ,
8888 chars : number ,
8989 bytes : number ,
9090) : string {
91+ const budget = budgetFor ( directorId ) ;
9192 return (
9293 `Director "${ directorId } " [${ family } ]: ${ chars } chars / ${ bytes } bytes ` +
93- `exceeds budget (${ CHAR_BUDGET [ directorId ] } chars / ` +
94- `${ BYTE_BUDGET [ directorId ] } bytes). Trim the prompt (preferred) or ` +
94+ `exceeds budget (${ budget . chars } chars / ` +
95+ `${ budget . bytes } bytes). Trim the prompt (preferred) or ` +
9596 `consciously raise the budget here with justification. ` +
9697 `Repro: bun -e 'import { directorPromptSizeTable, ` +
9798 `formatPromptSizeTable } from "./src/agent/prompt-sizes.ts"; ` +
@@ -115,8 +116,9 @@ describe("director prompt size budget", () => {
115116
116117 test ( "every assembled prompt stays within budget" , ( ) => {
117118 for ( const row of rows ) {
118- const overChars = row . chars > CHAR_BUDGET [ row . directorId ] ;
119- const overBytes = row . bytes > BYTE_BUDGET [ row . directorId ] ;
119+ const budget = budgetFor ( row . directorId ) ;
120+ const overChars = row . chars > budget . chars ;
121+ const overBytes = row . bytes > budget . bytes ;
120122 expect (
121123 overChars || overBytes ,
122124 budgetMessage ( row . directorId , row . family , row . chars , row . bytes ) ,
0 commit comments