@bongos/core 1.19.1033 → 1.19.1035

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/.bongos-core.json +204 -99
  2. package/.claude/skills/builder-start/SKILL.md +1 -1
  3. package/.claude/skills/grade-recover/SKILL.md +2 -1
  4. package/.claude/skills/grader-health/SKILL.md +4 -0
  5. package/.claude/skills/merge-mode/SKILL.md +1 -1
  6. package/clients/bongos-client/README.md +1 -1
  7. package/clients/bongos-client/bongos-client.global.js +6 -0
  8. package/clients/bongos-client/index.cjs +6 -0
  9. package/clients/bongos-client/index.d.ts +8 -0
  10. package/clients/bongos-client/index.mjs +6 -0
  11. package/docs/adr/0089-modular-multi-model-adversarial-grader.md +15 -0
  12. package/docs/adr/README.md +1 -1
  13. package/docs/api/openapi.json +120 -4
  14. package/docs/api-reference.md +9 -2
  15. package/docs/architecture.md +3 -2
  16. package/docs/canonical-permissions.md +2 -2
  17. package/docs/copy-inventory.md +34 -30
  18. package/docs/copy-registry.json +69 -33
  19. package/docs/module-api-changelog.md +5 -1
  20. package/docs/recipes/local-dev.md +45 -3
  21. package/docs/recipes/packaging-the-core.md +1 -1
  22. package/modules/autonomy/cadence.js +52 -0
  23. package/modules/autonomy/db.js +19 -0
  24. package/modules/autonomy/routes/autonomy.js +28 -0
  25. package/modules/government/catalog.js +2 -2
  26. package/modules/government/protected-surfaces.json +1 -0
  27. package/modules/grading/grade-engine.js +267 -0
  28. package/modules/grading/grader-subagent.js +4 -3
  29. package/modules/grading/grader-workers/index.js +67 -11
  30. package/modules/grading/grader-workers/worker-verdict.js +32 -2
  31. package/modules/grading/grader.js +109 -88
  32. package/modules/hall-ui/public/deploy.js +35 -0
  33. package/modules/hall-ui/public/project-settings.css +7 -0
  34. package/modules/lifecycle/routes/tasks.js +19 -4
  35. package/modules/lifecycle/ship-assurance.js +17 -1
  36. package/modules/provisioning/control-plane-guard.js +14 -13
  37. package/modules/provisioning/core-upgrade.js +30 -17
  38. package/modules/provisioning/public-refusal.js +44 -0
  39. package/modules/provisioning/routes/disconnect.js +2 -1
  40. package/modules/provisioning/routes/env-manifest.js +5 -4
  41. package/modules/provisioning/routes/provisioning.js +16 -15
  42. package/modules/provisioning/routes/repo-private.js +2 -1
  43. package/package-lock.json +2 -2
  44. package/package.json +1 -1
  45. package/release-notes.json +80 -0
  46. package/scripts/gds/autobongos-run.js +10 -2
  47. package/scripts/gds/backfill-cost.js +20 -9
  48. package/scripts/gds/claim.js +2 -2
  49. package/scripts/gds/credential-presence.js +281 -0
  50. package/scripts/gds/deploy-main-audit-gate.sh +11 -4
  51. package/scripts/gds/dev-lib.js +212 -5
  52. package/scripts/gds/dev.js +102 -50
  53. package/scripts/gds/doctor.js +3 -2
  54. package/scripts/gds/grade-correlation-audit.js +280 -0
  55. package/scripts/gds/grade-replay.js +237 -0
  56. package/scripts/gds/hooks/pre-push.js +7 -3
  57. package/scripts/gds/main-audit.js +19 -10
  58. package/scripts/gds/memory-map.js +3 -1
  59. package/scripts/gds/onboarding-config.js +3 -2
  60. package/scripts/gds/plain-cards.js +4 -0
  61. package/scripts/gds/preflight.js +12 -4
  62. package/scripts/gds/provision-core-upgrade.js +155 -4
  63. package/scripts/gds/provision-repo-auth.js +15 -0
  64. package/scripts/gds/provision.js +1 -1
  65. package/scripts/gds/publish-credential-check.js +3 -0
  66. package/scripts/gds/push-main.js +14 -3
  67. package/scripts/gds/push-path-brief.js +3 -2
  68. package/scripts/gds/run-routine.js +18 -5
  69. package/scripts/gds/run-unit-tests.js +14 -3
  70. package/scripts/gds/session-cost.js +12 -3
  71. package/scripts/gds/ship-deploy-target.js +11 -6
  72. package/scripts/gds/ship-grade-steps.js +33 -0
  73. package/scripts/gds/ship-land.js +157 -11
  74. package/scripts/gds/ship-merge.js +3 -2
  75. package/scripts/gds/ship-preflight-steps.js +30 -8
  76. package/scripts/gds/ship.js +1 -1
  77. package/scripts/gds/upgrade.js +3 -3
  78. package/scripts/hall-preview/README.md +20 -3
  79. package/scripts/hall-preview/live-identity.js +1 -1
  80. package/scripts/hall-preview/refresh-fixtures.js +71 -11
  81. package/scripts/hall-preview/scrub-identity.js +296 -0
  82. package/src/bongos/core-update.js +23 -1
  83. package/src/bongos/routes/core-update.js +27 -2
  84. package/src/bongos/routes/security.js +3 -3
  85. package/src/build-info.js +4 -2
  86. package/src/module-api.js +1 -1
  87. package/tests/adr_0089_scope.mjs +70 -0
  88. package/tests/autobongos_cadence.mjs +74 -0
  89. package/tests/consumer_layout_boot.mjs +363 -31
  90. package/tests/core_upgrade_door.mjs +40 -6
  91. package/tests/core_upgrade_runner.mjs +240 -4
  92. package/tests/credential_presence.mjs +153 -0
  93. package/tests/deploy_audit_gate.mjs +5 -2
  94. package/tests/deploy_page_projects.mjs +63 -2
  95. package/tests/dev_lib.mjs +2 -1
  96. package/tests/dev_windows.mjs +324 -0
  97. package/tests/env_knobs_neutral_prefix.mjs +203 -0
  98. package/tests/fixtures/grade-replay/recorded-panel-grades.json +27 -0
  99. package/tests/government_protected_surfaces.mjs +10 -0
  100. package/tests/grade_correlation_audit.mjs +159 -0
  101. package/tests/grade_engine.mjs +249 -0
  102. package/tests/grade_engine_replay.mjs +99 -0
  103. package/tests/grader_prompt_window_bound.mjs +132 -0
  104. package/tests/grader_unbacked_score.mjs +194 -0
  105. package/tests/hall_preview_scrub.mjs +214 -0
  106. package/tests/integration_parked_ratchet.mjs +24 -1
  107. package/tests/provisioning_public_refusal.mjs +195 -0
  108. package/tests/publish_status_branch.mjs +128 -0
  109. package/tests/routine_observability_api.mjs +195 -0
  110. package/tests/ship_assurance.mjs +86 -3
  111. package/tests/ship_land_red_pr.mjs +236 -0
  112. package/tests/ship_preflight.mjs +67 -1
  113. package/tests/start_env_guard.mjs +16 -0
  114. package/tests/upgrade.mjs +20 -1
@@ -0,0 +1,27 @@
1
+ {"note":"Recorded panel grades for the differential replay (tests/grade_engine_replay.mjs). Generated by scripts/gds/grade-replay.js --live --write-fixture: only grades whose replay agreed with the stored row, one per panel shape. Issue summaries, their files and stderr are hashed.",
2
+ "grades":[
3
+ {"task_id":"1004274","graded_at":"2026-09-25T21:46:43.130Z","recorded":{"panel_outcome":"pass","pass_count":4,"concerns_count":0,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":3.0816240000000006,"confidence":0.8,"rubric":{"functional_fidelity":9,"code_quality":8,"economy":8,"security_score":9,"efficiency_score":8}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":9},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":0.433313,"retried":false,"issues":[]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":8,"code_quality":8},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":1.7134175000000003,"retried":false,"issues":[{"severity":"nit","file":"h:127350d220","summary":"h:3305acb211"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.8,"model":"claude-sonnet-5","cost_usd":0.493828,"retried":false,"issues":[{"severity":"nit","file":"h:a00915aecd","summary":"h:bd972ce028"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":8},"confidence":0.8,"model":"claude-sonnet-5","cost_usd":0.4410655,"retried":false,"issues":[{"severity":"minor","file":"h:127350d220","summary":"h:e96dc885ad"}]}]},
4
+ {"task_id":"1001436","graded_at":"2026-09-25T21:40:47.504Z","recorded":{"panel_outcome":"pass","pass_count":4,"concerns_count":0,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":2.76109025,"confidence":0.825,"rubric":{"functional_fidelity":10,"code_quality":8,"economy":6,"security_score":9,"efficiency_score":8}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":10},"confidence":0.9,"model":"claude-sonnet-5","cost_usd":0.43844425,"retried":true,"issues":[]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":6,"code_quality":8},"confidence":0.8,"model":"claude-sonnet-5","cost_usd":1.46089875,"retried":false,"issues":[{"severity":"minor","file":"h:d3eb82782a","summary":"h:35c1a97948"},{"severity":"minor","file":"h:d3eb82782a","summary":"h:ec38cb5123"},{"severity":"nit","file":"h:9b13fff019","summary":"h:c7a56db356"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.40146299999999996,"retried":false,"issues":[]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":8},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":0.46028425,"retried":false,"issues":[{"severity":"minor","file":"h:d3eb82782a","summary":"h:0ba7cc5a2a"}]}]},
5
+ {"task_id":"1003353","graded_at":"2026-09-25T20:42:26.827Z","recorded":{"panel_outcome":"pass","pass_count":3,"concerns_count":1,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":3.6595056,"confidence":0.7849999999999999,"rubric":{"functional_fidelity":7,"code_quality":8,"economy":8,"security_score":9,"efficiency_score":10}},"workers":[{"kind":"narc","verdict":"concerns","error":null,"scores":{"functional_fidelity":7},"confidence":0.6,"model":"claude-sonnet-5","cost_usd":0.766103,"retried":false,"issues":[{"severity":"minor","file":"h:63ee851ae2","summary":"h:6c36c72067"},{"severity":"minor","file":"h:411c4cd89b","summary":"h:165ac64e1e"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":8,"code_quality":8},"confidence":0.72,"model":"claude-sonnet-5","cost_usd":1.1870192,"retried":false,"issues":[{"severity":"minor","file":"h:63ee851ae2","summary":"h:1ec56d00d6"},{"severity":"minor","file":"h:63ee851ae2","summary":"h:e80eb42770"},{"severity":"nit","file":"h:63ee851ae2","summary":"h:ead9e52ba9"},{"severity":"nit","file":"h:503a1e4a26","summary":"h:a8aebc6618"},{"severity":"nit","file":"h:c1df437481","summary":"h:67c5f63451"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.73215,"retried":false,"issues":[{"severity":"nit","file":"h:f4a2e1bea9","summary":"h:06a8e88ec8"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":10},"confidence":0.92,"model":"claude-sonnet-5","cost_usd":0.3183964,"retried":false,"issues":[]},{"kind":"reader","verdict":"advisory","error":null,"scores":{"copy_score":8},"confidence":0.7,"model":"claude-sonnet-5","cost_usd":0.655837,"retried":false,"issues":[{"severity":"nit","file":"h:f4a2e1bea9","summary":"h:effa6ed6c5"}]}]},
6
+ {"task_id":"1004233","graded_at":"2026-09-25T00:55:57.826Z","recorded":{"panel_outcome":"pass","pass_count":5,"concerns_count":0,"fail_count":0,"error_count":0,"worker_count":5,"panel_cost_usd":5.059474600000001,"confidence":0.75,"rubric":{"functional_fidelity":10,"code_quality":8,"economy":8,"security_score":8,"efficiency_score":8}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":10},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":1.2121266,"retried":false,"issues":[]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":8,"code_quality":8},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":2.0584278000000005,"retried":false,"issues":[{"severity":"minor","file":"h:3777db4de5","summary":"h:623cf4fc2f"},{"severity":"minor","file":"h:ccd049c40a","summary":"h:0a2979d4f5"},{"severity":"nit","file":"h:b1e6394ff9","summary":"h:fa25fe295b"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":8},"confidence":0.72,"model":"claude-sonnet-5","cost_usd":0.5786758000000001,"retried":false,"issues":[{"severity":"minor","file":"h:5551af7021","summary":"h:b8d3018634"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":8},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":0.5601807999999999,"retried":false,"issues":[{"severity":"minor","file":"h:3777db4de5","summary":"h:5b67a83015"}]},{"kind":"reader","verdict":"advisory","error":null,"scores":{"copy_score":8},"confidence":0.8,"model":"claude-sonnet-5","cost_usd":0.6500636,"retried":false,"issues":[{"severity":"nit","file":"h:1fd827b51f","summary":"h:c3c3b9ab36"}]},{"kind":"route-rank","verdict":"pass","error":null,"scores":{},"confidence":1,"model":"deterministic","cost_usd":null,"retried":false,"issues":[]}]},
7
+ {"task_id":"1004232","graded_at":"2026-09-25T00:31:54.069Z","recorded":{"panel_outcome":"pass","pass_count":4,"concerns_count":0,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":5.747325999999999,"confidence":0.8,"rubric":{"functional_fidelity":9,"code_quality":7,"economy":7,"security_score":9,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":1.1428184,"retried":false,"issues":[{"severity":"nit","file":"h:2fa74b4ef2","summary":"h:1c2a97f3f8"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":7,"code_quality":7},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":1.3643480000000001,"retried":false,"issues":[{"severity":"nit","file":"h:2fa74b4ef2","summary":"h:07170cd687"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":1.137575,"retried":false,"issues":[{"severity":"nit","file":"h:71ebac794f","summary":"h:c088bc7c82"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":0.9614498,"retried":false,"issues":[]},{"kind":"reader","verdict":"advisory","error":null,"scores":{"copy_score":10},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":1.1411348,"retried":false,"issues":[]}]},
8
+ {"task_id":"1004231","graded_at":"2026-09-24T23:23:35.527Z","recorded":{"panel_outcome":"pass","pass_count":4,"concerns_count":1,"fail_count":0,"error_count":0,"worker_count":5,"panel_cost_usd":7.8164818,"confidence":0.7,"rubric":{"functional_fidelity":7,"code_quality":8,"economy":7,"security_score":8,"efficiency_score":8}},"workers":[{"kind":"narc","verdict":"concerns","error":null,"scores":{"functional_fidelity":7},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":1.5480209999999999,"retried":false,"issues":[{"severity":"major","file":"h:157e25dda2","summary":"h:b0912bc039"},{"severity":"nit","file":"h:82b2beaae5","summary":"h:8fc2ce463e"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":7,"code_quality":8},"confidence":0.65,"model":"claude-sonnet-5","cost_usd":1.8102475999999998,"retried":false,"issues":[{"severity":"nit","file":"h:2fa74b4ef2","summary":"h:1ad62f6d68"},{"severity":"nit","file":"h:2a01d47f8b","summary":"h:c86d0c45e3"},{"severity":"nit","file":"h:0470f0809f","summary":"h:77e0342f1f"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":8},"confidence":0.7,"model":"claude-sonnet-5","cost_usd":1.3475988,"retried":false,"issues":[]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":8},"confidence":0.62,"model":"claude-sonnet-5","cost_usd":1.5321918,"retried":false,"issues":[{"severity":"minor","file":"h:db18fe0df6","summary":"h:e2cd3addcb"}]},{"kind":"reader","verdict":"advisory","error":null,"scores":{"copy_score":6},"confidence":0.65,"model":"claude-sonnet-5","cost_usd":1.5784226,"retried":false,"issues":[{"severity":"major","file":"h:144d00738e","summary":"h:1879492c5b"},{"severity":"minor","file":"h:2a01d47f8b","summary":"h:22b84fb977"}]},{"kind":"route-rank","verdict":"pass","error":null,"scores":{},"confidence":1,"model":"deterministic","cost_usd":null,"retried":false,"issues":[]}]},
9
+ {"task_id":"1004230","graded_at":"2026-09-24T22:12:49.539Z","recorded":{"panel_outcome":"pass","pass_count":4,"concerns_count":1,"fail_count":0,"error_count":0,"worker_count":5,"panel_cost_usd":2.8529818000000002,"confidence":0.85,"rubric":{"functional_fidelity":8,"code_quality":9,"economy":8,"security_score":8,"efficiency_score":8}},"workers":[{"kind":"narc","verdict":"concerns","error":null,"scores":{"functional_fidelity":8},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.42845880000000003,"retried":false,"issues":[{"severity":"minor","file":"h:5551af7021","summary":"h:f0686d9966"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":8,"code_quality":9},"confidence":0.9,"model":"claude-sonnet-5","cost_usd":1.4735852000000003,"retried":false,"issues":[{"severity":"nit","file":"h:5551af7021","summary":"h:8f9ef63f56"},{"severity":"nit","file":"h:de87550524","summary":"h:518535f1bf"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":8},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.516923,"retried":false,"issues":[{"severity":"minor","file":"h:5551af7021","summary":"h:c7e9e1feeb"},{"severity":"nit","file":"h:5551af7021","summary":"h:1291c756bc"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":8},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.4340148,"retried":false,"issues":[{"severity":"minor","file":"h:de87550524","summary":"h:ad0dba5181"},{"severity":"minor","file":"h:5551af7021","summary":"h:b9bc712665"},{"severity":"nit","file":"h:5551af7021","summary":"h:d15c9545af"}]},{"kind":"route-rank","verdict":"pass","error":null,"scores":{},"confidence":1,"model":"deterministic","cost_usd":null,"retried":false,"issues":[]}]},
10
+ {"task_id":"1004148","graded_at":"2026-09-24T14:55:32.886Z","recorded":{"panel_outcome":"pass","pass_count":5,"concerns_count":0,"fail_count":0,"error_count":0,"worker_count":5,"panel_cost_usd":3.6300847999999997,"confidence":0.85,"rubric":{"functional_fidelity":8,"code_quality":8,"economy":8,"security_score":9,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":8},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":0.9732858,"retried":false,"issues":[{"severity":"nit","file":"h:10d87c6f85","summary":"h:c87690ef35"},{"severity":"nit","file":"h:9f21143ae6","summary":"h:8d7a2cdcd0"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":8,"code_quality":8},"confidence":0.72,"model":"claude-sonnet-5","cost_usd":0.9691062,"retried":false,"issues":[{"severity":"minor","file":"h:10d87c6f85","summary":"h:bbe06ff066"},{"severity":"minor","file":"h:9f21143ae6","summary":"h:7e29754bf6"},{"severity":"nit","file":"h:10d87c6f85","summary":"h:077ba4aae2"},{"severity":"nit","file":"h:b1e6394ff9","summary":"h:700e676a78"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.847472,"retried":false,"issues":[{"severity":"nit","file":"h:10d87c6f85","summary":"h:f48d7c3fe5"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.8402208,"retried":false,"issues":[{"severity":"nit","file":"h:10d87c6f85","summary":"h:c2bb909961"}]},{"kind":"route-rank","verdict":"pass","error":null,"scores":{},"confidence":1,"model":"deterministic","cost_usd":null,"retried":false,"issues":[]}]},
11
+ {"task_id":"1004175","graded_at":"2026-09-23T02:06:16.884Z","recorded":{"panel_outcome":"pass","pass_count":3,"concerns_count":1,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":1.784195,"confidence":0.8999999999999999,"rubric":{"functional_fidelity":6,"code_quality":9,"economy":9,"security_score":10,"efficiency_score":10}},"workers":[{"kind":"narc","verdict":"concerns","error":null,"scores":{"functional_fidelity":6},"confidence":0.6,"model":"claude-sonnet-5","cost_usd":0.45443649999999997,"retried":false,"issues":[{"severity":"major","file":"h:3aa650846e","summary":"h:490ff4daf7"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":9,"code_quality":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.5501855,"retried":false,"issues":[{"severity":"nit","file":"h:c50d619d83","summary":"h:7365cebeec"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":10},"confidence":0.95,"model":"claude-sonnet-5","cost_usd":0.41305525000000004,"retried":false,"issues":[{"severity":"nit","file":"h:53b8a2c4db","summary":"h:5f66c3fee9"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":10},"confidence":0.95,"model":"claude-sonnet-5","cost_usd":0.36651775000000003,"retried":false,"issues":[]}]},
12
+ {"task_id":"1001426","graded_at":"2026-09-19T10:43:45.991Z","recorded":{"panel_outcome":"pass","pass_count":3,"concerns_count":1,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":2.5981449999999997,"confidence":0.85,"rubric":{"functional_fidelity":9,"code_quality":8,"economy":7,"security_score":8,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"concerns","error":null,"scores":{"functional_fidelity":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.52210075,"retried":false,"issues":[{"severity":"nit","file":"h:6727d747e4","summary":"h:4a6dab43da"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":7,"code_quality":8},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":1.1843039999999998,"retried":false,"issues":[{"severity":"nit","file":"h:6727d747e4","summary":"h:7695813db0"},{"severity":"nit","file":"h:2ad12a56c4","summary":"h:266cf3b18c"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":8},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":0.46327075,"retried":true,"issues":[{"severity":"nit","file":"h:2ad12a56c4","summary":"h:b954545f5d"},{"severity":"nit","file":"h:f071ccee8e","summary":"h:53ab92e62a"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.4284695,"retried":false,"issues":[]}]},
13
+ {"task_id":"1003878","graded_at":"2026-09-14T01:52:49.556Z","recorded":{"panel_outcome":"pass","pass_count":3,"concerns_count":0,"fail_count":0,"error_count":1,"worker_count":4,"panel_cost_usd":3.1948585000000005,"confidence":0.875,"rubric":{"functional_fidelity":null,"code_quality":9,"economy":8,"security_score":9,"efficiency_score":10}},"workers":[{"kind":"narc","verdict":"fail","error":"SUBAGENT_TIMEOUT","scores":{},"confidence":0,"model":"claude-sonnet-5","cost_usd":null,"retried":false,"issues":[]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":8,"code_quality":9},"confidence":0.9,"model":"claude-sonnet-5","cost_usd":1.6250995000000001,"retried":false,"issues":[{"severity":"nit","file":"h:492eba910a","summary":"h:1aad1668d5"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.8037920000000001,"retried":false,"issues":[{"severity":"nit","file":"h:93b12b601e","summary":"h:feb13a1e17"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":10},"confidence":0.9,"model":"claude-sonnet-5","cost_usd":0.7659670000000001,"retried":false,"issues":[]}]},
14
+ {"task_id":"1003750","graded_at":"2026-09-09T06:49:24.763Z","recorded":{"panel_outcome":"concerns","pass_count":4,"concerns_count":0,"fail_count":1,"error_count":0,"worker_count":5,"panel_cost_usd":3.9950229999999998,"confidence":0.3,"rubric":{"functional_fidelity":5,"code_quality":9,"economy":9,"security_score":9,"efficiency_score":10}},"workers":[{"kind":"narc","verdict":"fail","error":null,"scores":{"functional_fidelity":5},"confidence":0.78,"model":"claude-sonnet-5","cost_usd":0.68180775,"retried":false,"issues":[{"severity":"major","file":"h:84177396b5","summary":"h:41853eebb7"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":9,"code_quality":9},"confidence":0.9,"model":"claude-sonnet-5","cost_usd":1.4039994999999998,"retried":false,"issues":[{"severity":"nit","file":"h:972fc09ade","summary":"h:93e2e92f70"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.72,"model":"claude-sonnet-5","cost_usd":1.33469425,"retried":false,"issues":[{"severity":"nit","file":"h:0e40eaa3b8","summary":"h:b148aec4ef"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":10},"confidence":0.92,"model":"claude-sonnet-5","cost_usd":0.5745215,"retried":false,"issues":[]},{"kind":"route-rank","verdict":"pass","error":null,"scores":{},"confidence":1,"model":"deterministic","cost_usd":null,"retried":false,"issues":[]}]},
15
+ {"task_id":"1003445","graded_at":"2026-09-03T19:18:35.956Z","recorded":{"panel_outcome":"pass","pass_count":4,"concerns_count":0,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":2.2818312,"confidence":0.85,"rubric":{"functional_fidelity":9,"code_quality":9,"economy":8,"security_score":9,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.5429154,"retried":false,"issues":[{"severity":"nit","file":"h:470c02c760","summary":"h:f1c63e97a3"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":8,"code_quality":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.671361,"retried":false,"issues":[]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.5381194,"retried":true,"issues":[{"severity":"nit","file":"h:facfae576a","summary":"h:75321410be"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.5294354,"retried":false,"issues":[]}]},
16
+ {"task_id":"1003175","graded_at":"2026-09-02T17:52:46.502Z","recorded":{"panel_outcome":"pass","pass_count":5,"concerns_count":0,"fail_count":0,"error_count":0,"worker_count":5,"panel_cost_usd":1.7976148,"confidence":0.85,"rubric":{"functional_fidelity":10,"code_quality":9,"economy":8,"security_score":9,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":10},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.387192,"retried":false,"issues":[]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":8,"code_quality":9},"confidence":0.9,"model":"claude-sonnet-5","cost_usd":0.5571676000000001,"retried":true,"issues":[{"severity":"nit","file":"h:87d810e524","summary":"h:ecfffdd5a6"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.4811592,"retried":false,"issues":[]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.8,"model":"claude-sonnet-5","cost_usd":0.372096,"retried":false,"issues":[]},{"kind":"route-rank","verdict":"pass","error":null,"scores":{},"confidence":1,"model":"deterministic","cost_usd":null,"retried":false,"issues":[]}]},
17
+ {"task_id":"1003298","graded_at":"2026-08-27T23:12:53.322Z","recorded":{"panel_outcome":"concerns","pass_count":4,"concerns_count":0,"fail_count":0,"error_count":1,"worker_count":5,"panel_cost_usd":3.2470860000000004,"confidence":0.3,"rubric":{"functional_fidelity":9,"code_quality":0,"economy":null,"security_score":9,"efficiency_score":8}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":1.1821806000000001,"retried":false,"issues":[{"severity":"nit","file":"h:3180859548","summary":"h:2e9a36938f"}]},{"kind":"quality","verdict":"fail","error":"SUBAGENT_NONZERO_EXIT","scores":{},"confidence":0,"model":"claude-haiku-4-5-20251001","cost_usd":null,"retried":true,"issues":[],"exit_code":1,"stderr_tail":"h:daafa47568"},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":0.9619244000000001,"retried":false,"issues":[{"severity":"nit","file":"h:6e356932ba","summary":"h:fbac6e060e"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":8},"confidence":0.75,"model":"claude-sonnet-5","cost_usd":1.102981,"retried":false,"issues":[{"severity":"nit","file":"h:6e356932ba","summary":"h:db7256c9a5"}]},{"kind":"route-rank","verdict":"pass","error":null,"scores":{},"confidence":1,"model":"deterministic","cost_usd":null,"retried":false,"issues":[]}]},
18
+ {"task_id":"1003297","graded_at":"2026-08-27T17:59:20.501Z","recorded":{"panel_outcome":"concerns","pass_count":3,"concerns_count":0,"fail_count":0,"error_count":1,"worker_count":4,"panel_cost_usd":2.1315774,"confidence":0.3,"rubric":{"functional_fidelity":9,"code_quality":0,"economy":null,"security_score":10,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.7508158,"retried":false,"issues":[{"severity":"nit","file":"h:1f689d0b84","summary":"h:59dc4a5843"}]},{"kind":"quality","verdict":"fail","error":"SUBAGENT_NONZERO_EXIT","scores":{},"confidence":0,"model":"claude-haiku-4-5-20251001","cost_usd":null,"retried":true,"issues":[]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":10},"confidence":0.95,"model":"claude-sonnet-5","cost_usd":0.6944058,"retried":false,"issues":[]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.6863558,"retried":false,"issues":[]}]},
19
+ {"task_id":"1003224","graded_at":"2026-08-24T01:31:09.496Z","recorded":{"panel_outcome":"pass","pass_count":5,"concerns_count":0,"fail_count":0,"error_count":0,"worker_count":5,"panel_cost_usd":1.471463,"confidence":0.85,"rubric":{"functional_fidelity":9,"code_quality":8,"economy":9,"security_score":9,"efficiency_score":10}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.44815799999999995,"retried":true,"issues":[{"severity":"nit","file":"h:f0aae9b1f0","summary":"h:b1417a465b"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":9,"code_quality":8},"confidence":0.95,"model":"claude-haiku-4-5-20251001","cost_usd":0.2275078,"retried":false,"issues":[]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.45007579999999997,"retried":false,"issues":[{"severity":"nit","file":"h:f0aae9b1f0","summary":"h:3e9bc71e3e"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":10},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.3457214,"retried":false,"issues":[]},{"kind":"route-rank","verdict":"pass","error":null,"scores":{},"confidence":1,"model":"deterministic","cost_usd":null,"retried":false,"issues":[]}]},
20
+ {"task_id":"1002567","graded_at":"2026-08-15T03:40:05.655Z","recorded":{"panel_outcome":"fail","pass_count":2,"concerns_count":0,"fail_count":2,"error_count":0,"worker_count":4,"panel_cost_usd":2.6416746,"confidence":0,"rubric":{"functional_fidelity":4,"code_quality":9,"economy":9,"security_score":8,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"fail","error":null,"scores":{"functional_fidelity":4},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.6630807000000001,"retried":false,"issues":[{"severity":"blocker","file":"h:61d7acf831","summary":"h:0db1adea60"}]},{"kind":"quality","verdict":"fail","error":null,"scores":{"economy":9,"code_quality":9},"confidence":0.8,"model":"claude-haiku-4-5-20251001","cost_usd":0.1602525,"retried":false,"issues":[{"severity":"blocker","file":"h:61d7acf831","summary":"h:b0b7c5a8d5"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":8},"confidence":0.8,"model":"claude-sonnet-5","cost_usd":1.2236937,"retried":false,"issues":[{"severity":"nit","file":"h:61d7acf831","summary":"h:66eb617721"},{"severity":"nit","file":"h:0ac4f005a4","summary":"h:090043980b"},{"severity":"nit","file":"h:19d7a758ef","summary":"h:321fcfbbb1"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.9,"model":"claude-sonnet-5","cost_usd":0.5946477,"retried":false,"issues":[{"severity":"minor","file":"h:0ac4f005a4","summary":"h:2f3a34b24a"}]}]},
21
+ {"task_id":"1001916","graded_at":"2026-08-15T03:20:41.228Z","recorded":{"panel_outcome":"fail","pass_count":3,"concerns_count":0,"fail_count":1,"error_count":0,"worker_count":4,"panel_cost_usd":1.8740299,"confidence":0,"rubric":{"functional_fidelity":10,"code_quality":0,"economy":0,"security_score":9,"efficiency_score":10}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":10},"confidence":0.95,"model":"claude-sonnet-5","cost_usd":1.146498,"retried":false,"issues":[]},{"kind":"quality","verdict":"fail","error":null,"scores":{"economy":0,"code_quality":0},"confidence":1,"model":"claude-haiku-4-5-20251001","cost_usd":0.16489269999999998,"retried":false,"issues":[{"severity":"blocker","file":"h:2d89f98489","summary":"h:a086d0d4e9"},{"severity":"blocker","file":"h:2d89f98489","summary":"h:047523a0d1"},{"severity":"blocker","file":"h:2d89f98489","summary":"h:b55f2c92cd"},{"severity":"blocker","file":"h:2d89f98489","summary":"h:93545e2b5c"},{"severity":"blocker","file":"h:8a81fbc705","summary":"h:14244e5e2b"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.85,"model":"claude-sonnet-5","cost_usd":0.2887386,"retried":false,"issues":[]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":10},"confidence":0.9,"model":"claude-sonnet-5","cost_usd":0.2739006,"retried":false,"issues":[]}]},
22
+ {"task_id":"1002737","graded_at":"2026-08-12T23:35:40.270Z","recorded":{"panel_outcome":"unavailable","pass_count":0,"concerns_count":0,"fail_count":0,"error_count":4,"worker_count":4,"panel_cost_usd":0,"confidence":0.3,"rubric":{"functional_fidelity":null,"code_quality":0,"economy":null,"security_score":null,"efficiency_score":null}},"workers":[{"kind":"narc","verdict":"fail","error":"SUBAGENT_NONZERO_EXIT","scores":{},"confidence":0,"model":"claude-opus-5","cost_usd":null,"retried":true,"issues":[]},{"kind":"quality","verdict":"fail","error":"SUBAGENT_NONZERO_EXIT","scores":{},"confidence":0,"model":"claude-haiku-4-5-20251001","cost_usd":null,"retried":true,"issues":[]},{"kind":"hacker","verdict":"fail","error":"SUBAGENT_NONZERO_EXIT","scores":{},"confidence":0,"model":"claude-opus-5","cost_usd":null,"retried":true,"issues":[]},{"kind":"efficiency","verdict":"fail","error":"SUBAGENT_NONZERO_EXIT","scores":{},"confidence":0,"model":"claude-opus-5","cost_usd":null,"retried":true,"issues":[]}]},
23
+ {"task_id":"1002653","graded_at":"2026-08-11T14:19:49.327Z","recorded":{"panel_outcome":"concerns","pass_count":3,"concerns_count":1,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":2.2648416,"confidence":0.3,"rubric":{"functional_fidelity":9,"code_quality":8,"economy":7,"security_score":8,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":9},"confidence":0.72,"model":"claude-sonnet-4-6","cost_usd":0.8756592,"retried":false,"issues":[]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":7,"code_quality":8},"confidence":0.85,"model":"claude-sonnet-4-6","cost_usd":0.5879475000000001,"retried":false,"issues":[{"severity":"nit","file":"h:332822d131","summary":"h:6c3215c552"}]},{"kind":"hacker","verdict":"concerns","error":null,"scores":{"security_score":8},"confidence":0.78,"model":"claude-sonnet-4-6","cost_usd":0.5962068,"retried":false,"issues":[{"severity":"major","file":"h:332822d131","summary":"h:832e4bf1a7"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.88,"model":"claude-sonnet-4-6","cost_usd":0.2050281,"retried":false,"issues":[]}]},
24
+ {"task_id":"1002554","graded_at":"2026-08-05T23:04:34.451Z","recorded":{"panel_outcome":"fail","pass_count":3,"concerns_count":0,"fail_count":1,"error_count":0,"worker_count":4,"panel_cost_usd":1.8783215999999998,"confidence":0,"rubric":{"functional_fidelity":4,"code_quality":8,"economy":7,"security_score":8,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"fail","error":null,"scores":{"functional_fidelity":4},"confidence":0.9,"model":"claude-sonnet-4-6","cost_usd":0.4524978,"retried":false,"issues":[{"severity":"blocker","file":"h:0f2f745307","summary":"h:5a16de420b"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":7,"code_quality":8},"confidence":0.9,"model":"claude-sonnet-4-6","cost_usd":0.5554047,"retried":false,"issues":[{"severity":"minor","file":"h:0f2f745307","summary":"h:cddbd7df8e"},{"severity":"nit","file":"h:eea03bad91","summary":"h:50263ab993"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":8},"confidence":0.72,"model":"claude-sonnet-4-6","cost_usd":0.6754245,"retried":false,"issues":[{"severity":"minor","file":"h:3a72359d4c","summary":"h:16a58096be"},{"severity":"minor","file":"h:2d211b60f4","summary":"h:38f437afc9"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.85,"model":"claude-sonnet-4-6","cost_usd":0.1949946,"retried":false,"issues":[]}]},
25
+ {"task_id":"1002553","graded_at":"2026-07-30T18:34:51.581Z","recorded":{"panel_outcome":"pass","pass_count":3,"concerns_count":1,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":3.4621722,"confidence":0.835,"rubric":{"functional_fidelity":7,"code_quality":8,"economy":8,"security_score":9,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"concerns","error":null,"scores":{"functional_fidelity":7},"confidence":0.75,"model":"claude-sonnet-4-6","cost_usd":0.405582,"retried":true,"issues":[{"severity":"major","file":"h:ae3930574d","summary":"h:6e98ed3323"}]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":8,"code_quality":8},"confidence":0.82,"model":"claude-sonnet-4-6","cost_usd":1.8247271999999997,"retried":false,"issues":[{"severity":"minor","file":"h:9efc99d028","summary":"h:003a5e3c43"},{"severity":"minor","file":"h:9efc99d028","summary":"h:33b97e99b5"},{"severity":"minor","file":"h:ae3930574d","summary":"h:c47a0a25af"}]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.88,"model":"claude-sonnet-4-6","cost_usd":0.779004,"retried":false,"issues":[{"severity":"minor","file":"h:9efc99d028","summary":"h:66243d8143"},{"severity":"nit","file":"h:9efc99d028","summary":"h:230e1c2756"}]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.85,"model":"claude-sonnet-4-6","cost_usd":0.452859,"retried":false,"issues":[]}]},
26
+ {"task_id":"1002525","graded_at":"2026-07-29T16:00:37.887Z","recorded":{"panel_outcome":"pass","pass_count":4,"concerns_count":0,"fail_count":0,"error_count":0,"worker_count":4,"panel_cost_usd":1.5763158,"confidence":0.875,"rubric":{"functional_fidelity":9,"code_quality":9,"economy":9,"security_score":9,"efficiency_score":9}},"workers":[{"kind":"narc","verdict":"pass","error":null,"scores":{"functional_fidelity":9},"confidence":0.85,"model":"claude-sonnet-4-6","cost_usd":0.46919940000000004,"retried":false,"issues":[]},{"kind":"quality","verdict":"pass","error":null,"scores":{"economy":9,"code_quality":9},"confidence":0.85,"model":"claude-sonnet-4-6","cost_usd":0.7438973999999999,"retried":true,"issues":[]},{"kind":"hacker","verdict":"pass","error":null,"scores":{"security_score":9},"confidence":0.9,"model":"claude-sonnet-4-6","cost_usd":0.17472000000000001,"retried":false,"issues":[]},{"kind":"efficiency","verdict":"pass","error":null,"scores":{"efficiency_score":9},"confidence":0.95,"model":"claude-sonnet-4-6","cost_usd":0.188499,"retried":false,"issues":[]}]}
27
+ ]}
@@ -295,6 +295,16 @@ const ADDED_SINCE_R101 = [
295
295
  'ship-surprise', 'ship-visual'],
296
296
  'the 2026-08-23 ship.js carve: the land path, the ship state machine, the grade gate '
297
297
  + 'steps and pushVia, ~6,200 lines behind a 373-line protected entry point.'),
298
+ // task 1002839 (ADR 0089 §1). Not a `grader-*.js` sibling, so the carve tripwire
299
+ // below would not demand it — registered by hand because it owns the gate.
300
+ {
301
+ after: 'modules/grading/grader-subagent.js',
302
+ glob: 'modules/grading/grade-engine.js',
303
+ why: 'the central grading engine every work-type is graded through. It runs the '
304
+ + 'deterministic route-rank and permission-path pre-passes and applies the '
305
+ + 'deterministic veto, so an edit here can switch off the protected-path gate '
306
+ + 'for every grade at once.',
307
+ },
298
308
  ];
299
309
 
300
310
  // Surfaces RENAMED since R101 — still protected, under a new path. Distinct from
@@ -0,0 +1,159 @@
1
+ // tests/grade_correlation_audit.mjs — the grader error-correlation audit
2
+ // (task 1002843, ADR 0089 §5).
3
+ //
4
+ // Pins the arithmetic against hand-computed values, the vote and label rules,
5
+ // and — the load-bearing part — the minimum-N guard: a kappa over too few
6
+ // observations, or over a rater that never changes its mind, is REFUSED with a
7
+ // reason, never printed as a number. The CLI is exercised end to end on a saved
8
+ // dataset, so the report path needs no network.
9
+ //
10
+ // Run: node --test tests/grade_correlation_audit.mjs
11
+
12
+ import { test } from 'node:test';
13
+ import assert from 'node:assert/strict';
14
+ import fs from 'node:fs';
15
+ import os from 'node:os';
16
+ import path from 'node:path';
17
+ import { execFileSync } from 'node:child_process';
18
+ import { createRequire } from 'node:module';
19
+ import { fileURLToPath } from 'node:url';
20
+
21
+ const require = createRequire(import.meta.url);
22
+ const A = require('../scripts/gds/grade-correlation-audit.js');
23
+ const ROOT = fileURLToPath(new URL('..', import.meta.url));
24
+
25
+ const close = (a, b, eps = 1e-9) => assert.ok(Math.abs(a - b) < eps, `${a} != ${b}`);
26
+ const repeat = (n, v) => Array.from({ length: n }, () => v);
27
+
28
+ // A dataset row with the four panel workers' verdicts.
29
+ const W = (kind, verdict, extra = {}) => ({ kind, verdict, error: null, issues: [], ...extra });
30
+ function row(id, { narc = 'pass', quality = 'pass', hacker = 'pass', efficiency = 'pass', status = 'shipped', passed = true } = {}) {
31
+ return { task_id: String(id), task_status: status, passed, workers: [W('narc', narc), W('quality', quality), W('hacker', hacker), W('efficiency', efficiency)] };
32
+ }
33
+
34
+ test('agreementStats matches a hand-computed 2x2 table', () => {
35
+ // both object 20, only first 5, only second 10, both clear 15 (n = 50)
36
+ const pairs = [...repeat(20, [1, 1]), ...repeat(5, [1, 0]), ...repeat(10, [0, 1]), ...repeat(15, [0, 0])];
37
+ const s = A.agreementStats(pairs);
38
+ assert.equal(s.n, 50);
39
+ close(s.agreement, 0.7);
40
+ close(s.kappa, 0.4); // po 0.7, pe 0.5*0.6 + 0.5*0.4 = 0.5 → (0.7-0.5)/(1-0.5)
41
+ close(s.phi, 250 / Math.sqrt(25 * 25 * 30 * 20));
42
+ assert.deepEqual(s.table, { both_object: 20, only_first: 5, only_second: 10, both_clear: 15 });
43
+ });
44
+
45
+ test('a vote: pass clears, concerns/fail objects, an errored worker with no finding casts none', () => {
46
+ assert.equal(A.voteOf(W('quality', 'pass')), 0);
47
+ assert.equal(A.voteOf(W('quality', 'concerns')), 1);
48
+ assert.equal(A.voteOf(W('quality', 'fail')), 1);
49
+ assert.equal(A.voteOf(W('quality', 'fail', { error: 'SUBAGENT_TIMEOUT' })), null, 'missing signal is not a vote');
50
+ assert.equal(A.voteOf(W('hacker', 'fail', { error: 'parse_error', issues: [{ severity: 'blocker' }] })), 1,
51
+ 'an errored worker that still raised a blocker is a real objection (#473)');
52
+ assert.deepEqual(A.panelVotes([W('narc', 'pass'), W('reader', 'advisory'), { kind: 'route-rank', verdict: 'fail', model: 'deterministic' }]),
53
+ { narc: 0 }, 'the reader and the deterministic pseudo-judges are not panel voters');
54
+ });
55
+
56
+ test('owner labels: overrides and manual confirms only — an auto-landed pass is never a label', () => {
57
+ const labels = A.ownerLabels({
58
+ grades: [
59
+ { task_id: '1', task_status: 'shipped', passed: false }, // confirmed by hand after a non-pass
60
+ { task_id: '2', task_status: 'shipped', passed: true }, // auto-landed: the grader agreeing with itself
61
+ { task_id: '3', task_status: 'completed', passed: false }, // still parked: no decision yet
62
+ { task_id: '4', task_status: 'shipped', passed: false },
63
+ ],
64
+ overrides: [{ task_id: '4', status: 'denied' }, { task_id: '4', status: 'approved' }, { task_id: '5', status: 'denied' }],
65
+ });
66
+ assert.deepEqual(Object.fromEntries(labels), {
67
+ 4: { label: 'accept', source: 'override_approved' }, // the approval outranks the earlier denial
68
+ 5: { label: 'reject', source: 'override_denied' },
69
+ 1: { label: 'accept', source: 'manual_confirm_after_fail' },
70
+ });
71
+ });
72
+
73
+ test('THE GUARD: a kappa over too few observations, or over a constant rater, is refused — never printed', () => {
74
+ const few = { grades: repeat(5, 0).map((_, i) => row(i, { narc: i % 2 ? 'fail' : 'pass' })), overrides: [] };
75
+ const r = A.audit(few);
76
+ assert.equal(r.min_n, A.MIN_N);
77
+ for (const p of r.pairwise) {
78
+ assert.match(p.refused, /below the minimum of 30/);
79
+ assert.equal(p.kappa, undefined, 'no number rides along with a refusal');
80
+ }
81
+ assert.equal(r.effective_votes, null);
82
+
83
+ // Plenty of panels, but hacker never objects: every pair with it is undefined.
84
+ const constant = { grades: repeat(60, 0).map((_, i) => row(i, { narc: i % 3 ? 'pass' : 'concerns', quality: i % 4 ? 'pass' : 'fail' })), overrides: [] };
85
+ const rc = A.audit(constant);
86
+ const nh = rc.pairwise.find((p) => p.a === 'narc' && p.b === 'hacker');
87
+ assert.match(nh.refused, /only 0 of one class/);
88
+ assert.ok(!rc.pairwise.find((p) => p.a === 'narc' && p.b === 'quality').refused, 'a pair of changing raters is computed');
89
+ assert.equal(rc.effective_votes, null, 'the panel figure needs every pair');
90
+
91
+ assert.equal(A.audit(few, { minN: 3 }).min_n, A.MIN_N, '--min-n can raise the bar, never lower it');
92
+ assert.equal(A.audit(few, { minN: 80 }).min_n, 80);
93
+ });
94
+
95
+ test('two workers that always vote alike read as redundant; unrelated ones as independent', () => {
96
+ const grades = repeat(80, 0).map((_, i) => row(i, {
97
+ narc: i % 2 ? 'fail' : 'pass',
98
+ quality: i % 2 ? 'fail' : 'pass', // a copy of narc
99
+ hacker: i % 4 < 2 ? 'concerns' : 'pass', // unrelated to narc's parity
100
+ efficiency: i % 5 ? 'pass' : 'fail',
101
+ }));
102
+ const r = A.audit({ grades, overrides: [] });
103
+ const nq = r.pairwise.find((p) => p.a === 'narc' && p.b === 'quality');
104
+ close(nq.kappa, 1);
105
+ assert.equal(nq.reading, 'redundant');
106
+ const nh = r.pairwise.find((p) => p.a === 'narc' && p.b === 'hacker');
107
+ close(nh.kappa, 0);
108
+ assert.equal(nh.reading, 'independent');
109
+ assert.ok(r.effective_votes > 1 && r.effective_votes < 4);
110
+ });
111
+
112
+ test('per-worker kappa against the owner, and error correlation, once there are enough labels', () => {
113
+ // 40 labelled tasks: the owner accepted 20, rejected 20. Quality objects to
114
+ // exactly the rejected ones (kappa 1); narc objects to everything (constant → refused).
115
+ const grades = repeat(40, 0).map((_, i) => row(i, { narc: 'concerns', quality: i < 20 ? 'fail' : 'pass', status: 'shipped', passed: false }));
116
+ const overrides = repeat(40, 0).map((_, i) => ({ task_id: String(i), status: i < 20 ? 'denied' : 'approved' }));
117
+ const r = A.audit({ grades, overrides });
118
+ assert.deepEqual(r.labels, { total: 40, accept: 20, reject: 20 });
119
+ close(r.vs_owner.find((w) => w.kind === 'quality').kappa, 1);
120
+ assert.match(r.vs_owner.find((w) => w.kind === 'narc').refused, /only 0 of one class/);
121
+ const qh = r.pairwise.find((p) => p.a === 'quality' && p.b === 'hacker');
122
+ assert.ok(qh.errors.n === 40, 'errors are paired on the labelled tasks both voted on');
123
+ });
124
+
125
+ test('effectiveVotes: 4 uncorrelated votes are 4, perfectly correlated are 1, negative is clamped', () => {
126
+ close(A.effectiveVotes(4, 0), 4);
127
+ close(A.effectiveVotes(4, 1), 1);
128
+ close(A.effectiveVotes(4, -0.3), 4);
129
+ close(A.effectiveVotes(4, 1 / 3), 2);
130
+ });
131
+
132
+ test('toAuditRow keeps the fate and the verdicts, and hashes the review prose', () => {
133
+ const r = A.toAuditRow({ task_id: 9, task_status: 'shipped', grade: { passed: false, signals: { workers: [
134
+ { kind: 'quality', verdict: 'fail', error: null, issues: [{ severity: 'major', file: 'a.js', summary: 'real words' }], notes_md: 'prose' },
135
+ ] } } });
136
+ assert.equal(r.task_id, '9');
137
+ assert.equal(r.task_status, 'shipped');
138
+ assert.equal(r.passed, false);
139
+ assert.equal(r.workers[0].verdict, 'fail');
140
+ assert.match(r.workers[0].issues[0].summary, /^h:[0-9a-f]{10}$/);
141
+ assert.equal(r.workers[0].notes_md, undefined);
142
+ assert.equal(A.toAuditRow({ task_id: 1, grade: { signals: {} } }), null, 'not a panel grade');
143
+ });
144
+
145
+ test('the CLI reports a saved dataset — refusals by name, and --json — with no network', () => {
146
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'grade-audit-'));
147
+ const file = path.join(dir, 'dataset.json');
148
+ fs.writeFileSync(file, JSON.stringify({ grades: [row(1), row(2, { quality: 'fail' })], overrides: [] }));
149
+ try {
150
+ const text = execFileSync(process.execPath, ['scripts/gds/grade-correlation-audit.js', '--file', file], { cwd: ROOT, encoding: 'utf8' });
151
+ assert.match(text, /2 recorded panel grade\(s\), minimum n = 30/);
152
+ assert.match(text, /narc × quality\s+REFUSED — n=2 is below the minimum of 30/);
153
+ const json = JSON.parse(execFileSync(process.execPath, ['scripts/gds/grade-correlation-audit.js', '--file', file, '--json'], { cwd: ROOT, encoding: 'utf8' }));
154
+ assert.equal(json.panels, 2);
155
+ assert.equal(json.pairwise.length, 6);
156
+ } finally {
157
+ fs.rmSync(dir, { recursive: true, force: true });
158
+ }
159
+ });
@@ -0,0 +1,249 @@
1
+ // tests/grade_engine.mjs — the central grading engine (task 1002839, ADR 0089 §1).
2
+ //
3
+ // Pins the four things the extraction promised: (1) the pipeline is NAMED and
4
+ // runs in the ADR's order; (2) there is a registry with two doors — the grading
5
+ // module's own work-types and any other module's, through the seam port
6
+ // grader.workType.<key> — and the code panel is registered in it as the default;
7
+ // (3) the deterministic pre-passes and the veto belong to the ENGINE, so a
8
+ // work-type whose own aggregate would pass a protected-path fail still fails;
9
+ // (4) the code panel graded through the engine is wired exactly as gradeSubagent
10
+ // was — same judges, models, timeouts, prompts and record — including through the
11
+ // real default model call (a fake `claude` binary; POSIX only).
12
+ //
13
+ // Run: node --test tests/grade_engine.mjs
14
+
15
+ import { test } from 'node:test';
16
+ import assert from 'node:assert/strict';
17
+ import fs from 'node:fs';
18
+ import os from 'node:os';
19
+ import path from 'node:path';
20
+ import { createRequire } from 'node:module';
21
+
22
+ const require = createRequire(import.meta.url);
23
+ const grader = require('../modules/grading/grader.js');
24
+ const engine = grader.gradeEngine;
25
+ const api = require('../src/module-api');
26
+ const llmCache = require('../src/bongos/llm-cache.js');
27
+
28
+ const TASK = { id: 4242, title: 'Fixture task', description: 'Add helper X. Acceptance: X exported.', kind: 'feature', discipline: 'engineer', version_id: 'BONGOS-V2', est_minutes: 60 };
29
+ const DIFF = 'diff --git a/modules/example/a.js b/modules/example/a.js\n--- a/modules/example/a.js\n+++ b/modules/example/a.js\n@@ -1 +1 @@\n-const a = 1;\n+const a = 2; // changed value here\n';
30
+ const DS = { files_changed: 1, lines_added: 1, lines_removed: 1 };
31
+
32
+ // Which judge a prompt belongs to — every worker prompt opens with its identity.
33
+ const KIND_MARKS = [['**Narc**', 'narc'], ['**Quality**', 'quality'], ['**Hacker**', 'hacker'], ['**Efficiency Monger**', 'efficiency'], ['**Reader**', 'reader']];
34
+ const kindOf = (prompt) => (KIND_MARKS.find(([m]) => prompt.slice(0, 400).includes(m)) || [null, 'unknown'])[1];
35
+ const PASSING = {
36
+ narc: { functional_fidelity: 9, confidence: 0.8, issues: [], ac_checklist: [{ ac: 'X exported', status: 'satisfied' }] },
37
+ quality: { code_quality: 8, economy: 8, confidence: 0.8, issues: [] },
38
+ hacker: { security_score: 9, confidence: 0.8, issues: [] },
39
+ efficiency: { efficiency_score: 9, confidence: 0.8, issues: [] },
40
+ };
41
+ const envelope = (payload) => JSON.stringify({ type: 'result', result: JSON.stringify(payload), total_cost_usd: 0.01 });
42
+
43
+ // An injected model call that records what each judge was asked.
44
+ function recordingRunner(replies = PASSING) {
45
+ const calls = [];
46
+ const run = async ({ prompt, opts }) => {
47
+ const kind = kindOf(prompt);
48
+ calls.push({ kind, prompt, opts });
49
+ return { stdout: envelope(replies[kind] || {}), stderr: '', run_ms: 1, exit_code: 0, cost_usd: 0.01 };
50
+ };
51
+ return { run, calls };
52
+ }
53
+
54
+ // A work-type with every hook, whose aggregate PASSES no matter what it is handed —
55
+ // the shape a careless or hostile module could register.
56
+ function alwaysPassWorkType(seen = {}) {
57
+ return {
58
+ key: 'always-pass',
59
+ resolveJudges: () => ['judge-a'],
60
+ modelFor: () => 'model-x',
61
+ runJudge: async (judge, ctx) => { seen.ctx = ctx; return { kind: judge, verdict: 'pass', scores: {}, issues: [], confidence: 1, model: 'model-x' }; },
62
+ aggregate: (results) => { seen.results = results; return { passed: true, score: 10, signals: { panel_outcome: 'pass', confidence: 1 }, notes_md: 'always pass', issues: [] }; },
63
+ unavailable: ({ reason }) => ({ passed: false, signals: { panel_outcome: 'unavailable', reason } }),
64
+ };
65
+ }
66
+
67
+ test('the pipeline is named, in ADR 0089 §1 order', () => {
68
+ assert.deepEqual(engine.PIPELINE_STAGES, ['select', 'pre_pass', 'evidence', 'fan_out', 'aggregate', 'gate', 'persist']);
69
+ });
70
+
71
+ test('the code panel is registered as work-type #1 and is the default', () => {
72
+ assert.ok(engine.listWorkTypes().includes('code'));
73
+ const code = engine.resolveWorkType({ workType: 'code' });
74
+ assert.equal(code.key, 'code');
75
+ assert.equal(code.aggregate, grader.aggregatePanel, 'the code work-type aggregates with the v4 panel gate');
76
+ assert.equal(code.unavailable, grader.graderUnavailableResult);
77
+ assert.equal(code.cacheTaskType, 'grade_worker', 'kept at the pre-engine value so cached worker replies stay hits');
78
+ // Everything that is not a registered key lands on the default rather than
79
+ // throwing inside the grade step (the task 1002659 posture).
80
+ assert.equal(engine.resolveWorkType({}), code);
81
+ assert.equal(engine.resolveWorkType({ workType: 'no-such-type' }), code);
82
+ assert.equal(engine.resolveWorkType({ task: { discipline: 'engineer', kind: 'feature' } }), code);
83
+ });
84
+
85
+ test('registerWorkType refuses a malformed or conflicting work-type at registration', () => {
86
+ assert.throws(() => engine.registerWorkType({ ...alwaysPassWorkType(), key: 'Bad Key' }), /must match/);
87
+ const { aggregate, ...noAggregate } = alwaysPassWorkType();
88
+ assert.throws(() => engine.registerWorkType({ ...noAggregate, key: 'half-built' }), /missing hook\(s\): aggregate/);
89
+ assert.throws(() => engine.registerWorkType({ ...alwaysPassWorkType(), key: 'bad-optional', gatherEvidence: 'not a function' }), /gatherEvidence/);
90
+ const code = engine.resolveWorkType({ workType: 'code' });
91
+ assert.equal(engine.registerWorkType(code), code, 'the same definition again is a no-op');
92
+ assert.throws(() => engine.registerWorkType({ ...code }), /already registered/, 'a second definition for a key is a wiring bug');
93
+ });
94
+
95
+ test('another module contributes a work-type through the seam port, and a broken one degrades to the default', () => {
96
+ const def = { ...alwaysPassWorkType(), key: 'test-seam-art' };
97
+ api.registerProvider(engine.workTypePort('test-seam-art'), def);
98
+ assert.equal(engine.resolveWorkType({ task: { discipline: 'test-seam-art' } }), def, 'resolved by the task discipline');
99
+ assert.ok(engine.listWorkTypes().includes('test-seam-art'));
100
+
101
+ api.registerProvider(engine.workTypePort('test-seam-broken'), { key: 'test-seam-broken', aggregate: () => ({}) });
102
+ const logged = [];
103
+ const orig = console.error;
104
+ console.error = (...a) => { logged.push(a.join(' ')); };
105
+ try {
106
+ assert.equal(engine.resolveWorkType({ workType: 'test-seam-broken' }).key, 'code');
107
+ } finally { console.error = orig; }
108
+ assert.match(logged.join('\n'), /ignoring invalid work-type on port grader\.workType\.test-seam-broken/);
109
+ assert.ok(!engine.listWorkTypes().includes('test-seam-broken'));
110
+
111
+ // Tests reset the seam registry; the grading module's own default must survive it.
112
+ require('../src/module-seams')._reset();
113
+ assert.equal(engine.resolveWorkType({}).key, 'code', 'a seam reset cannot lose the default work-type');
114
+ assert.deepEqual(engine.listWorkTypes(), ['code']);
115
+ });
116
+
117
+ test('the ENGINE owns the pre-passes: a work-type that never names them still gets them, in order', async () => {
118
+ const seen = {};
119
+ await engine.runGrade({
120
+ workType: alwaysPassWorkType(seen), task: TASK, diff: DIFF, diffStats: DS,
121
+ changedFiles: ['src/bongos/routes/x.js', 'src/bongos/auth.js'], builderRank: 'thetes',
122
+ });
123
+ assert.deepEqual(seen.results.map((r) => r.kind), ['judge-a', 'route-rank', 'permission-path'],
124
+ 'deterministic pseudo-judges join after the model judges, route-rank first');
125
+ assert.ok(seen.ctx.deterministicFindings.length > 0, 'the judges are handed the pre-pass findings');
126
+ });
127
+
128
+ test('the gate: no verdict upgrades a deterministic fail — whatever the work-type aggregate said', async () => {
129
+ const r = await engine.runGrade({
130
+ workType: alwaysPassWorkType(), task: TASK, diff: DIFF, diffStats: DS,
131
+ changedFiles: ['src/bongos/auth.js'], builderRank: 'xenos',
132
+ });
133
+ assert.equal(r.passed, false);
134
+ assert.equal(r.signals.panel_outcome, 'fail');
135
+ assert.equal(r.signals.confidence, 0, 'forwarded confidence 0 → the server gate fails it too');
136
+ assert.deepEqual(r.signals.deterministic_veto, ['permission-path']);
137
+ assert.match(r.notes_md, /DETERMINISTIC VETO/);
138
+
139
+ // The veto enforces the deterministic checks and nothing else: with no
140
+ // protected path touched, the work-type's own pass stands.
141
+ const clean = await engine.runGrade({
142
+ workType: alwaysPassWorkType(), task: TASK, diff: DIFF, diffStats: DS,
143
+ changedFiles: ['modules/example/a.js'], builderRank: 'xenos',
144
+ });
145
+ assert.equal(clean.passed, true);
146
+ assert.equal(clean.signals.deterministic_veto, undefined);
147
+ });
148
+
149
+ test('replay rebuilds the pre-passes from the recorded pseudo-judges, so its gate judges what the live gate judged', () => {
150
+ const recorded = [
151
+ { kind: 'judge-a', verdict: 'pass', scores: {}, issues: [], model: 'model-x' },
152
+ { kind: 'permission-path', verdict: 'fail', scores: {}, issues: [{ severity: 'blocker', file: 'src/bongos/auth.js', summary: 'x' }], model: 'deterministic' },
153
+ ];
154
+ const r = engine.replayRecorded({ signals: { workers: recorded }, workType: alwaysPassWorkType() });
155
+ assert.equal(r.passed, false);
156
+ assert.deepEqual(r.signals.deterministic_veto, ['permission-path']);
157
+ // A judge merely NAMED like a pre-pass, but produced by a model, is not one.
158
+ const forged = [{ ...recorded[1], model: 'claude-sonnet-5' }];
159
+ assert.equal(engine.replayRecorded({ signals: { workers: forged }, workType: alwaysPassWorkType() }).passed, true);
160
+ });
161
+
162
+ test('the gate returns an already-failed aggregate UNTOUCHED — why it is a no-op for the code panel', () => {
163
+ const failed = { passed: false, signals: { panel_outcome: 'fail', confidence: 0 }, notes_md: 'x' };
164
+ const prePass = { findings: [], workerResult: { kind: 'permission-path', verdict: 'fail', model: 'deterministic' } };
165
+ assert.equal(engine.applyDeterministicGate(failed, [prePass]), failed);
166
+ const passed = { passed: true, signals: { panel_outcome: 'pass' } };
167
+ assert.equal(engine.applyDeterministicGate(passed, []), passed, 'nothing to enforce → the same object');
168
+ });
169
+
170
+ test('the code panel through the engine: same judges, models, timeouts, prompts and record as gradeSubagent', async () => {
171
+ const { run, calls } = recordingRunner();
172
+ const prior = { round: 2, findings_md: '- [major] x', response_md: 'fixed in abc', interim_md: '1 file' };
173
+ const r = await engine.runGrade({
174
+ workType: 'code', task: TASK, valueSummary: 'Adds X.', diff: DIFF, diffStats: DS,
175
+ changedFiles: ['src/bongos/auth.js'], builderRank: 'xenos', priorRound: prior,
176
+ runOpts: { cwd: process.cwd(), timeoutMs: 1234 },
177
+ }, { runSubagent: run });
178
+
179
+ assert.deepEqual(calls.map((c) => c.kind).sort(), ['efficiency', 'hacker', 'narc', 'quality']);
180
+ for (const c of calls) {
181
+ assert.equal(c.opts.model, grader.workerModelFor(c.kind, grader.selectGraderModel({}), undefined));
182
+ assert.equal(c.opts.timeoutMs, 360000, `${c.kind}: the per-worker budget overrides runOpts.timeoutMs`);
183
+ assert.equal(c.opts.cwd, process.cwd());
184
+ assert.match(c.prompt, /## Prior panel round \(this is re-grade round 2\)/, `${c.kind} sees the prior round`);
185
+ assert.match(c.prompt, /## Post-change file contents \(1 of 1 changed files, bundled\)/, `${c.kind} sees the bundle`);
186
+ }
187
+ const hacker = calls.find((c) => c.kind === 'hacker');
188
+ assert.match(hacker.prompt, /## Deterministic route-rank pre-check/, 'the Hacker is handed the permission-path findings');
189
+
190
+ assert.deepEqual(r.signals.workers.map((w) => w.kind), ['narc', 'quality', 'hacker', 'efficiency', 'permission-path']);
191
+ assert.equal(r.signals.panel_outcome, 'fail', 'a sub-Metic protected-path edit fails the code panel on its own gate');
192
+ assert.equal(r.signals.deterministic_veto, undefined, 'aggregatePanel already failed it — the engine veto had nothing to do');
193
+ const keys = Object.keys(r.signals);
194
+ assert.deepEqual(keys.slice(-4), ['builder_model_assumed', 'grader_model', 'total_ms', 'context_bundle'],
195
+ 'the run meta lands last, exactly where aggregatePanel put it when handed the meta directly');
196
+ assert.equal(r.signals.builder_model_assumed, grader.ASSUMED_BUILDER_MODEL);
197
+ assert.equal(r.signals.context_bundle.read_root, path.resolve(process.cwd()));
198
+ assert.deepEqual(r.signals.context_bundle.bundled.map((b) => b.file), ['src/bongos/auth.js']);
199
+ assert.equal(r.panel_cost_usd, 0.04);
200
+ });
201
+
202
+ test('bypass short-circuits BEFORE any judge is asked (#943)', async () => {
203
+ const { run, calls } = recordingRunner();
204
+ const r = await engine.runGrade({ workType: 'code', task: TASK, diff: DIFF, changedFiles: ['a.js'], judges: ['narc', 'no-such-worker'], runOpts: { bypass: true } }, { runSubagent: run });
205
+ assert.equal(calls.length, 0);
206
+ assert.equal(r.signals.panel_outcome, 'unavailable');
207
+ assert.equal(r.signals.grader_unavailable_reason, 'bypass_requested');
208
+ });
209
+
210
+ test('gradeSubagent grades through the engine\'s DEFAULT model call — a fake claude binary end to end',
211
+ { skip: process.platform === 'win32' && 'the fake CLI is a shebang script; spawn runs it through cmd.exe on win32' },
212
+ async () => {
213
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'grade-engine-'));
214
+ const bin = path.join(dir, 'claude');
215
+ fs.writeFileSync(bin, `#!/usr/bin/env node
216
+ let s = '';
217
+ process.stdin.on('data', (d) => { s += d; }).on('end', () => {
218
+ const replies = ${JSON.stringify(PASSING)};
219
+ const kinds = ${JSON.stringify(KIND_MARKS)};
220
+ const hit = kinds.find(([m]) => s.slice(0, 400).includes(m));
221
+ const argv = process.argv.slice(2);
222
+ const payload = { ...(hit ? replies[hit[1]] : {}), notes_md: 'model=' + argv[argv.indexOf('--model') + 1] };
223
+ process.stdout.write(JSON.stringify({ type: 'result', result: JSON.stringify(payload), total_cost_usd: 0.02 }));
224
+ });
225
+ `);
226
+ fs.chmodSync(bin, 0o755);
227
+ // The cache is exercised for its KEY (task_type) but never touches a database.
228
+ const origWithCache = llmCache.withCache;
229
+ const origSpec = llmCache.makeCacheSpec;
230
+ const taskTypes = [];
231
+ llmCache.makeCacheSpec = (args) => { taskTypes.push(args.task_type); return origSpec(args); };
232
+ llmCache.withCache = async (spec, producer) => ({ ...(await producer()), cached: false });
233
+ try {
234
+ const r = await grader.gradeSubagent({
235
+ task: TASK, valueSummary: 'Adds X.', diff: DIFF, diffStats: DS, changedFiles: ['modules/example/a.js'],
236
+ runOpts: { claudeBin: bin, cwd: process.cwd() },
237
+ });
238
+ assert.equal(r.signals.panel_outcome, 'pass', r.notes_md);
239
+ assert.equal(r.passed, true);
240
+ assert.deepEqual(r.signals.workers.map((w) => w.kind), ['narc', 'quality', 'hacker', 'efficiency']);
241
+ for (const w of r.signals.workers) assert.match(w.notes_md, new RegExp(`model=${w.model}$`), 'the spawned CLI got the worker model');
242
+ assert.deepEqual(taskTypes, ['grade_worker', 'grade_worker', 'grade_worker', 'grade_worker']);
243
+ assert.equal(r.panel_cost_usd, 0.08);
244
+ } finally {
245
+ llmCache.withCache = origWithCache;
246
+ llmCache.makeCacheSpec = origSpec;
247
+ fs.rmSync(dir, { recursive: true, force: true });
248
+ }
249
+ });