allocation-fixtures.json 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. {
  2. "$comment": [
  3. "Regression fixtures for GitHub issue #1500 / epic CG-1 — relevance-proportional",
  4. "explore budget allocation. Run them with `node scripts/agent-eval/probe-allocation.mjs`",
  5. "against a built dist/.",
  6. "",
  7. "STATUS: CG-10 (relevance scoring) closed the RANKING half of both fixtures — nothing",
  8. "incidental reaches the envelope any more. What still fails is the BYTE SPLIT among the",
  9. "files that correctly ranked in, because the render loop spends by file size: a small",
  10. "weakly-relevant file ships whole while the strongly-relevant one is clipped at",
  11. "maxCharsPerFile. That is CG-12's gate. Each fixture's `baseline` records the pre-CG-10",
  12. "numbers; `afterCG10` records where it stands now.",
  13. "",
  14. "`groups` partitions the files explore rendered into `answer` (what the query is",
  15. "actually about) and `incidental` (what wins the envelope today on name collisions).",
  16. "Assertions are on the DELIVERED envelope unless suffixed `Allocated`; delivered is",
  17. "what the agent got, allocated is what the render loop chose before the hard ceiling.",
  18. "Shares are fractions of the whole response, meta-text included, so they never sum to 1."
  19. ],
  20. "fixtures": [
  21. {
  22. "id": "payroll-go",
  23. "title": "#1500 — generated Go CRUD beside a hand-written payroll workflow",
  24. "kind": "fixture",
  25. "path": "__tests__/fixtures/payroll-go",
  26. "query": "how does payroll cycle create and calculate payslips?",
  27. "rationale": [
  28. "The reporter's repo shape: a Go service whose generated FKIT CRUD layer sits",
  29. "beside the hand-written use-case that does the real work. The query deliberately",
  30. "does NOT name runPayrollCycleAll / BuildPayslip / Upsert — an architecture",
  31. "question phrased the way a newcomer would phrase it. The generated layer",
  32. "name-collides on every query term (CreatePayslip, PayrollCycleCreateRequest,",
  33. "CalculatePayrollCycleTotals, a second BuildPayslip, a second Upsert), so a",
  34. "scorer that rewards incidental name matches surfaces the CRUD path.",
  35. "Half the generated files carry ORDINARY names and are only detectable by their",
  36. "`// Code generated ... DO NOT EDIT.` header (CG-5), which is what makes this",
  37. "the #1500 case rather than a .pb.go case."
  38. ],
  39. "groups": {
  40. "answer": [
  41. "internal/usecase/**",
  42. "internal/store/**",
  43. "internal/transport/**",
  44. "internal/domain/**",
  45. "cmd/**"
  46. ],
  47. "incidental": ["internal/gen/**"]
  48. },
  49. "assert": {
  50. "answerShareAtLeast": 0.55,
  51. "incidentalShareAtMost": 0.25,
  52. "topFileGroup": "answer",
  53. "mustDeliverBytes": [
  54. "internal/usecase/payroll/cycle.go",
  55. "internal/usecase/payroll/payslip_builder.go"
  56. ],
  57. "$mustContainComment": "Needles are chosen to match the HAND-WRITTEN chain only — a bare `BuildPayslip`/`Upsert` also matches the generated collisions, which is the whole point of the fixture.",
  58. "mustContain": [
  59. "runPayrollCycleAll",
  60. "func (s *Service) BuildPayslip",
  61. "s.store.Upsert(ctx, slip)"
  62. ]
  63. },
  64. "baseline": {
  65. "measuredOn": "2026-08-03",
  66. "note": "19 files → very-tiny tier (13,000 budget); 23,020 chars allocated against it, cut to 16,011 by the 19,500 hard ceiling.",
  67. "delivered": {
  68. "internal/gen/fkit/payroll/payslip.go": 0.307,
  69. "internal/gen/fkit/payroll/payroll_cycle.go": 0.266,
  70. "internal/domain/payroll/payslip.go": 0.256,
  71. "internal/usecase/payroll/cycle.go": 0.0
  72. },
  73. "verdict": "The workflow file is allocated the single largest slice (30.6%) and delivers ZERO — the hard ceiling drops its whole section. Generated CRUD takes 57.4% of what the agent actually receives; runPayrollCycleAll, BuildPayslip and the real Upsert never reach the response."
  74. },
  75. "afterCG10": {
  76. "measuredOn": "2026-08-04",
  77. "delivered": {
  78. "internal/usecase/payroll/cycle.go": 0.389,
  79. "internal/gen/fkit/payroll/payroll_cycle.go": 0.235,
  80. "internal/domain/payroll/payslip.go": 0.226,
  81. "internal/gen/fkit/payroll/payslip.go": 0.0
  82. },
  83. "verdict": "PASSES answerShareAtLeast (61.5%), incidentalShareAtMost (23.5%), topFileGroup, and the cycle.go + runPayrollCycleAll + real-Upsert needles. The generated files now rank #3/#4 instead of #1/#2 — kind weighting plus a 0.3x generated penalty on BOTH the score and the graph mass, which is the key the comparator sorts on. STILL FAILING for CG-12: payslip_builder.go ranks #6 against the tier's maxFiles of 4, so `func (s *Service) BuildPayslip` never renders."
  84. }
  85. },
  86. {
  87. "id": "self-query",
  88. "title": "This repo — incidental `explore`/`BUDGET` matches in the agent-eval scripts",
  89. "kind": "self",
  90. "path": ".",
  91. "query": "how does explore allocate its output budget across files",
  92. "rationale": [
  93. "The same failure mode with no generated code in sight. `scripts/agent-eval/*.mjs`",
  94. "mention `explore` and `BUDGET` incidentally — they are eval harnesses, not the",
  95. "allocator — and they are small enough to ship WHOLE, while src/mcp/tools.ts (which",
  96. "carries getExploreOutputBudget and the render loop, and scores 4x higher on every",
  97. "signal) is large enough to be clipped at maxCharsPerFile. Allocation follows file",
  98. "size, not relevance.",
  99. "",
  100. "Unlike payroll-go this fixture reads THIS repo's live index, so its exact numbers",
  101. "move as the repo changes (indexed file count crossing 500 flips the budget tier).",
  102. "The assertions are therefore relative — answer-vs-incidental, not fixed percentages."
  103. ],
  104. "groups": {
  105. "answer": ["src/mcp/**"],
  106. "incidental": ["scripts/**"]
  107. },
  108. "assert": {
  109. "answerShareAtLeast": 0.5,
  110. "incidentalShareAtMost": 0.25,
  111. "topFileGroup": "answer",
  112. "mustDeliverBytes": ["src/mcp/tools.ts"]
  113. },
  114. "baseline": {
  115. "measuredOn": "2026-08-03",
  116. "note": "493 files → small tier (18,000 budget); 27,518 chars allocated against it, cut to 19,749 by the 25,000 hard ceiling.",
  117. "delivered": {
  118. "scripts/agent-eval/offload-eval-hook.mjs": 0.25,
  119. "scripts/agent-eval/offload-eval-metrics.mjs": 0.236,
  120. "scripts/agent-eval/parse-session.mjs": 0.232,
  121. "src/mcp/tools.ts": 0.185,
  122. "scripts/agent-eval/offload-eval-cost.mjs": 0.0
  123. },
  124. "verdict": "The script corpus takes 71.8% of the delivered envelope (79.4% of what was allocated) against tools.ts's 18.5%, despite tools.ts scoring 46 vs 10, carrying 2.3x the graph mass and 3x the distinct term hits."
  125. },
  126. "afterCG10": {
  127. "measuredOn": "2026-08-04",
  128. "delivered": {
  129. "src/resolution/memory-budget.ts": 0.512,
  130. "src/mcp/tools.ts": 0.329
  131. },
  132. "verdict": "PASSES incidentalShareAtMost: every scripts/agent-eval/*.mjs file is gone (0.0%), which is CG-10's acceptance bar — their sole match was an unused file-scope `explore`/`BUDGET` constant, worth 0.08x weight, and the relative floor (8.2) then cut them. tools.ts ranks #1. STILL FAILING for CG-12: memory-budget.ts scores 18 to tools.ts's 41 yet takes 51.2% of the envelope to tools.ts's 32.9%, purely because it is small enough to ship whole while tools.ts is clipped at maxCharsPerFile. Allocation still follows file size, not relevance."
  133. }
  134. }
  135. ]
  136. }