@bongos/core 1.19.1037 → 1.19.1039
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.
- package/.bongos-core.json +52 -22
- package/docs/adr/0089-modular-multi-model-adversarial-grader.md +2 -0
- package/docs/module-api-changelog.md +4 -0
- package/docs/recipes/core-release-pipeline.md +1 -1
- package/docs/recipes/private-npm-distribution.md +1 -1
- package/modules/government/protected-surfaces.json +2 -0
- package/modules/grading/grader-model.js +50 -5
- package/modules/grading/grader-providers.neutral.json +4 -0
- package/modules/grading/grader-rubric.json +5 -0
- package/modules/grading/grader-subagent.js +17 -1
- package/modules/grading/model-provider.js +257 -0
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +16 -0
- package/scripts/gds/plain-cards.js +5 -0
- package/scripts/gds/publish-integration-gate.js +142 -0
- package/scripts/gds/ship-land.js +72 -6
- package/src/module-api.js +1 -1
- package/tests/government_protected_surfaces.mjs +14 -0
- package/tests/grade_model_provider.mjs +217 -0
- package/tests/publish_integration_gate.mjs +198 -0
- package/tests/ship_land_ci_not_started.mjs +168 -0
package/.bongos-core.json
CHANGED
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
"artifact": "bongos-core",
|
|
3
3
|
"manifest_schema": 1,
|
|
4
4
|
"generator": "scripts/gds/package-core.js",
|
|
5
|
-
"core_version": "1.19.
|
|
6
|
-
"core_contract": "1.19.
|
|
7
|
-
"source_commit": "
|
|
5
|
+
"core_version": "1.19.1039",
|
|
6
|
+
"core_contract": "1.19.1039",
|
|
7
|
+
"source_commit": "dc9e168d73f9ec605af32419b0b638cca7539418",
|
|
8
8
|
"source_ref": "HEAD",
|
|
9
|
-
"built_at": "2026-09-
|
|
9
|
+
"built_at": "2026-09-26T08:16:22.165Z",
|
|
10
10
|
"redaction": {
|
|
11
11
|
"model": "docs-redacted+functional-verbatim",
|
|
12
12
|
"docs_redacted": 542,
|
|
13
13
|
"agent_docs_stubbed": 26,
|
|
14
|
-
"functional_verbatim":
|
|
14
|
+
"functional_verbatim": 2496,
|
|
15
15
|
"rules": 3,
|
|
16
16
|
"gate_literals": 3,
|
|
17
17
|
"gate": "passed"
|
|
18
18
|
},
|
|
19
|
-
"file_count":
|
|
20
|
-
"tree_sha256": "
|
|
19
|
+
"file_count": 3065,
|
|
20
|
+
"tree_sha256": "e4228541e27d69f8e2578edadb43181228ced5f21cc7b6dbe0102de50c3917be",
|
|
21
21
|
"files": [
|
|
22
22
|
{
|
|
23
23
|
"path": ".claude/skills/ask-for-help/SKILL.md",
|
|
@@ -907,7 +907,7 @@
|
|
|
907
907
|
{
|
|
908
908
|
"path": "docs/adr/0089-modular-multi-model-adversarial-grader.md",
|
|
909
909
|
"mode": "0000644",
|
|
910
|
-
"sha256": "
|
|
910
|
+
"sha256": "4ec01143da7055676994ec4351c71a1321d41224076f0c4639c451fba28e62b9"
|
|
911
911
|
},
|
|
912
912
|
{
|
|
913
913
|
"path": "docs/adr/0090-metic-task-authoring.md",
|
|
@@ -2767,7 +2767,7 @@
|
|
|
2767
2767
|
{
|
|
2768
2768
|
"path": "docs/module-api-changelog.md",
|
|
2769
2769
|
"mode": "0000644",
|
|
2770
|
-
"sha256": "
|
|
2770
|
+
"sha256": "3d636e0870231f27697b67900e7feedff8e82b751cdd9771509cfe792d7157d6"
|
|
2771
2771
|
},
|
|
2772
2772
|
{
|
|
2773
2773
|
"path": "docs/modules-contract.md",
|
|
@@ -2887,7 +2887,7 @@
|
|
|
2887
2887
|
{
|
|
2888
2888
|
"path": "docs/recipes/core-release-pipeline.md",
|
|
2889
2889
|
"mode": "0000644",
|
|
2890
|
-
"sha256": "
|
|
2890
|
+
"sha256": "4f006e07e58a861399d8d04ab0b52a1752f4ff605475288d60b60bffb7e123e7"
|
|
2891
2891
|
},
|
|
2892
2892
|
{
|
|
2893
2893
|
"path": "docs/recipes/failed-ship-recovery-proof.md",
|
|
@@ -2967,7 +2967,7 @@
|
|
|
2967
2967
|
{
|
|
2968
2968
|
"path": "docs/recipes/private-npm-distribution.md",
|
|
2969
2969
|
"mode": "0000644",
|
|
2970
|
-
"sha256": "
|
|
2970
|
+
"sha256": "0125fca7ef4c910f87a03e20ccfb06ae8a81cf5ebc8f9821e4bc3e8a8d0a7ea1"
|
|
2971
2971
|
},
|
|
2972
2972
|
{
|
|
2973
2973
|
"path": "docs/recipes/redteam-patrol.md",
|
|
@@ -4597,7 +4597,7 @@
|
|
|
4597
4597
|
{
|
|
4598
4598
|
"path": "modules/government/protected-surfaces.json",
|
|
4599
4599
|
"mode": "0000644",
|
|
4600
|
-
"sha256": "
|
|
4600
|
+
"sha256": "e703a0c652d40d8d8f5578fbcb4b08dde9afd4f97ecef0b99db5e3a181b05aae"
|
|
4601
4601
|
},
|
|
4602
4602
|
{
|
|
4603
4603
|
"path": "modules/government/ranks.js",
|
|
@@ -4662,7 +4662,7 @@
|
|
|
4662
4662
|
{
|
|
4663
4663
|
"path": "modules/grading/grader-model.js",
|
|
4664
4664
|
"mode": "0000644",
|
|
4665
|
-
"sha256": "
|
|
4665
|
+
"sha256": "4141bc9e7ff90ab474af51bc78c0805af982b610c91ec90a8441e2b89a7596ce"
|
|
4666
4666
|
},
|
|
4667
4667
|
{
|
|
4668
4668
|
"path": "modules/grading/grader-no-artifact.js",
|
|
@@ -4674,10 +4674,15 @@
|
|
|
4674
4674
|
"mode": "0000644",
|
|
4675
4675
|
"sha256": "d845b8785b39c89777e9cb9cdf5e869b51e8eae11c76288d9be4790239fd5e13"
|
|
4676
4676
|
},
|
|
4677
|
+
{
|
|
4678
|
+
"path": "modules/grading/grader-providers.neutral.json",
|
|
4679
|
+
"mode": "0000644",
|
|
4680
|
+
"sha256": "1e1313c9bf157ce4b380c89e59832da4ee5573a18e1b70aa730c3826923b67eb"
|
|
4681
|
+
},
|
|
4677
4682
|
{
|
|
4678
4683
|
"path": "modules/grading/grader-rubric.json",
|
|
4679
4684
|
"mode": "0000644",
|
|
4680
|
-
"sha256": "
|
|
4685
|
+
"sha256": "58c445d96348ea0e9ee7d0603b88aa684fd7ad478a9de46c6668696ce8cd13f0"
|
|
4681
4686
|
},
|
|
4682
4687
|
{
|
|
4683
4688
|
"path": "modules/grading/grader-score.js",
|
|
@@ -4687,7 +4692,7 @@
|
|
|
4687
4692
|
{
|
|
4688
4693
|
"path": "modules/grading/grader-subagent.js",
|
|
4689
4694
|
"mode": "0000644",
|
|
4690
|
-
"sha256": "
|
|
4695
|
+
"sha256": "a7e7c0cd702ff1a6b83d12ce0310de72ed601c6a4b8e886f1a873eeaeaaecadd"
|
|
4691
4696
|
},
|
|
4692
4697
|
{
|
|
4693
4698
|
"path": "modules/grading/grader-workers/efficiency.js",
|
|
@@ -4749,6 +4754,11 @@
|
|
|
4749
4754
|
"mode": "0000644",
|
|
4750
4755
|
"sha256": "e223155c25f1fe4a66d7e3dd03b10632b76d4a7b851182df4afd05f5ae9d40bd"
|
|
4751
4756
|
},
|
|
4757
|
+
{
|
|
4758
|
+
"path": "modules/grading/model-provider.js",
|
|
4759
|
+
"mode": "0000644",
|
|
4760
|
+
"sha256": "608f90bb52ed2fb9341021c02c6ae0f44ed41192c0050ce3052861e9216bd2ad"
|
|
4761
|
+
},
|
|
4752
4762
|
{
|
|
4753
4763
|
"path": "modules/grading/module.json",
|
|
4754
4764
|
"mode": "0000644",
|
|
@@ -8442,12 +8452,12 @@
|
|
|
8442
8452
|
{
|
|
8443
8453
|
"path": "package-lock.json",
|
|
8444
8454
|
"mode": "0000644",
|
|
8445
|
-
"sha256": "
|
|
8455
|
+
"sha256": "3a6d785e2391594909ba62c1e5dcf1c250096d802da67b1033353c8ced7bfac8"
|
|
8446
8456
|
},
|
|
8447
8457
|
{
|
|
8448
8458
|
"path": "package.json",
|
|
8449
8459
|
"mode": "0000644",
|
|
8450
|
-
"sha256": "
|
|
8460
|
+
"sha256": "9ef9e201b3c2d1326f37ecd30eb7ed0ebbb56f8360608128e4b04974798cf4d0"
|
|
8451
8461
|
},
|
|
8452
8462
|
{
|
|
8453
8463
|
"path": "public-docs/index.html",
|
|
@@ -8467,7 +8477,7 @@
|
|
|
8467
8477
|
{
|
|
8468
8478
|
"path": "release-notes.json",
|
|
8469
8479
|
"mode": "0000644",
|
|
8470
|
-
"sha256": "
|
|
8480
|
+
"sha256": "d39efdd82af8f39bf10ff6b145838d57dd6ab9eea277836ff1b7bd67a06f61ca"
|
|
8471
8481
|
},
|
|
8472
8482
|
{
|
|
8473
8483
|
"path": "scripts/bongos-mcp.js",
|
|
@@ -9372,7 +9382,7 @@
|
|
|
9372
9382
|
{
|
|
9373
9383
|
"path": "scripts/gds/plain-cards.js",
|
|
9374
9384
|
"mode": "0000644",
|
|
9375
|
-
"sha256": "
|
|
9385
|
+
"sha256": "b253a6c0e34cac3d18fb031b9a445d4db0589484da016309ecd7481a1ec1f311"
|
|
9376
9386
|
},
|
|
9377
9387
|
{
|
|
9378
9388
|
"path": "scripts/gds/portability-smoke-art.sh",
|
|
@@ -9469,6 +9479,11 @@
|
|
|
9469
9479
|
"mode": "0000644",
|
|
9470
9480
|
"sha256": "3fbf7c20f83e3de8b47f834414c2bec9ba35f528cfb93995db73d627c8d46e73"
|
|
9471
9481
|
},
|
|
9482
|
+
{
|
|
9483
|
+
"path": "scripts/gds/publish-integration-gate.js",
|
|
9484
|
+
"mode": "0000644",
|
|
9485
|
+
"sha256": "f797bfe1b72d0bb50587093ab93f32fd86b916f644dbf782cedf0b0e177b2b25"
|
|
9486
|
+
},
|
|
9472
9487
|
{
|
|
9473
9488
|
"path": "scripts/gds/publish-manifest.js",
|
|
9474
9489
|
"mode": "0000644",
|
|
@@ -9862,7 +9877,7 @@
|
|
|
9862
9877
|
{
|
|
9863
9878
|
"path": "scripts/gds/ship-land.js",
|
|
9864
9879
|
"mode": "0000644",
|
|
9865
|
-
"sha256": "
|
|
9880
|
+
"sha256": "699e58b44e1be60c9e17acf108f7cd895a75d43a2854dac494583df35f522dbc"
|
|
9866
9881
|
},
|
|
9867
9882
|
{
|
|
9868
9883
|
"path": "scripts/gds/ship-memory-sync.js",
|
|
@@ -10522,7 +10537,7 @@
|
|
|
10522
10537
|
{
|
|
10523
10538
|
"path": "src/module-api.js",
|
|
10524
10539
|
"mode": "0000644",
|
|
10525
|
-
"sha256": "
|
|
10540
|
+
"sha256": "ef1f931d2bcea8854e341858cc0b0d7d347ede63bcc77377c71695f6600852fa"
|
|
10526
10541
|
},
|
|
10527
10542
|
{
|
|
10528
10543
|
"path": "src/module-loader/catalog.js",
|
|
@@ -12352,7 +12367,7 @@
|
|
|
12352
12367
|
{
|
|
12353
12368
|
"path": "tests/government_protected_surfaces.mjs",
|
|
12354
12369
|
"mode": "0000644",
|
|
12355
|
-
"sha256": "
|
|
12370
|
+
"sha256": "3b022d77647dd871c43cdcfd8855932cc5d2c8a40fb061babcbae0d86e225097"
|
|
12356
12371
|
},
|
|
12357
12372
|
{
|
|
12358
12373
|
"path": "tests/government_rank_sync.mjs",
|
|
@@ -12439,6 +12454,11 @@
|
|
|
12439
12454
|
"mode": "0000644",
|
|
12440
12455
|
"sha256": "b638a9fc43d9a1b8ca92ee20b9d0b6cc92104581d4f5d3af7bfd4bf9b310e508"
|
|
12441
12456
|
},
|
|
12457
|
+
{
|
|
12458
|
+
"path": "tests/grade_model_provider.mjs",
|
|
12459
|
+
"mode": "0000644",
|
|
12460
|
+
"sha256": "11cfa2deade2db1f88f643d9aa310d34bdd0f37423944db4a68fa0ea2b2eba77"
|
|
12461
|
+
},
|
|
12442
12462
|
{
|
|
12443
12463
|
"path": "tests/grade_server_authoritative.mjs",
|
|
12444
12464
|
"mode": "0000644",
|
|
@@ -14049,6 +14069,11 @@
|
|
|
14049
14069
|
"mode": "0000644",
|
|
14050
14070
|
"sha256": "3e3b97d2c7e4e67a412eaa04bbf3d8fd4ad649ae46f9e194c8e07eedfc2349bb"
|
|
14051
14071
|
},
|
|
14072
|
+
{
|
|
14073
|
+
"path": "tests/publish_integration_gate.mjs",
|
|
14074
|
+
"mode": "0000644",
|
|
14075
|
+
"sha256": "f220032a0e9d58bfc07316f4192744294d2eef023677e602c23fc2c775e87390"
|
|
14076
|
+
},
|
|
14052
14077
|
{
|
|
14053
14078
|
"path": "tests/publish_manifest.mjs",
|
|
14054
14079
|
"mode": "0000644",
|
|
@@ -14604,6 +14629,11 @@
|
|
|
14604
14629
|
"mode": "0000644",
|
|
14605
14630
|
"sha256": "a3b7858c255f1c7ea692866dbadd7321f77bd88c8380c429b7cb5f6b1b65496b"
|
|
14606
14631
|
},
|
|
14632
|
+
{
|
|
14633
|
+
"path": "tests/ship_land_ci_not_started.mjs",
|
|
14634
|
+
"mode": "0000644",
|
|
14635
|
+
"sha256": "9d7902dfb2183713a06ecc845c4f466d3dc04fcf7d34a0f79cb2c6b6f89587af"
|
|
14636
|
+
},
|
|
14607
14637
|
{
|
|
14608
14638
|
"path": "tests/ship_land_conflict.mjs",
|
|
14609
14639
|
"mode": "0000644",
|
|
@@ -187,6 +187,8 @@ Roll out behind a flag (the [ADR 0079](0079-value-gated-autonomous-engagement.md
|
|
|
187
187
|
|
|
188
188
|
**Progress (2026-09-25).** Step 3's engine and registry landed first, ahead of steps 1–2, because both build on it: `modules/grading/grade-engine.js` names the pipeline (`select → pre_pass → evidence → fan_out → aggregate → gate → persist`), owns both deterministic pre-passes and a deterministic veto no work-type's aggregate can override, and resolves work-types from its own registry or a module's `grader.workType.<key>` seam provider. The code panel is registered as work-type `code`, the default. Proven a no-op: a before/after run of 27 grading scenarios came out byte-identical, and a replay of 376 recorded production grades reproduced every stored decision except 22 from June 2026, which an older grader produced before two deliberate gate changes (the task 943 "grader unavailable" outcome and the task 574 missing-security-lens block). Task 1002839; the replay tool is `scripts/gds/grade-replay.js`.
|
|
189
189
|
|
|
190
|
+
**Progress (2026-09-26).** Step 1 landed (task 1002840): `modules/grading/model-provider.js` is the `ModelProvider` port at `runSubagent`, with the Claude spawn as the default `anthropic-cli` provider (a before/after run of 29 grading scenarios came out byte-identical) and an `openai-compatible` adapter tested against a local stub. `selectGraderModel`'s if/else is now the rubric's `judge_by_builder_family` table, refused at load if a judge would grade its own family or leave Claude. Providers are instance config (`config/grader-providers.json`); the core declares none, so no open model is called and nothing is spent until the owner adds one. The error-correlation audit (step 5) also landed early (task 1002843, `scripts/gds/grade-correlation-audit.js`).
|
|
191
|
+
|
|
190
192
|
---
|
|
191
193
|
|
|
192
194
|
## Sources
|
|
@@ -2553,5 +2553,9 @@ is load-bearing: the script throws rather than guess if it is missing, and
|
|
|
2553
2553
|
landed since 1.19.1035 with no explicit bump. run 36226955285. (task 1002620)
|
|
2554
2554
|
1.19.1037 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2555
2555
|
landed since 1.19.1036 with no explicit bump. run 36227523642. (task 1002620)
|
|
2556
|
+
1.19.1038 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2557
|
+
landed since 1.19.1037 with no explicit bump. run 36228854271. (task 1002620)
|
|
2558
|
+
1.19.1039 — CI auto-patch (publish-on-merge, ADR 0161): carrier for merges
|
|
2559
|
+
landed since 1.19.1038 with no explicit bump. run 36229255566. (task 1002620)
|
|
2556
2560
|
---------------------------------------------------------------------------
|
|
2557
2561
|
```
|
|
@@ -99,7 +99,7 @@ node scripts/gds/package-core.js --ref main --self-verify
|
|
|
99
99
|
|
|
100
100
|
### 2c. Publish — automatic on merge
|
|
101
101
|
|
|
102
|
-
**Every merge to `main` publishes** ([ADR 0161](../adr/0161-publish-on-merge.md), superseding ADR 0137's manual gate): once the required `unit` check succeeds on a main push, the `publish` workflow auto-bumps a **patch** if nobody bumped (via `scripts/gds/bump-version.js`, which writes the literal AND appends the ledger entry to [`docs/module-api-changelog.md`](../module-api-changelog.md) — ADR 0203; the carrier commit stages both), builds through the fail-closed no-leak gate with `--self-verify`, publishes, and tags `core-v<version>`. A **minor/major is still a human in-task bump** — CI never makes that call, because it decides what patch-channel subscribers receive unattended.
|
|
102
|
+
**Every merge to `main` publishes** ([ADR 0161](../adr/0161-publish-on-merge.md), superseding ADR 0137's manual gate): once the required `unit` check succeeds on a main push — and the `integration` lane is green on the commit being released, which carries the packaged-core empty-database proof (task 1002863; the wait is task 1004290) — the `publish` workflow auto-bumps a **patch** if nobody bumped (via `scripts/gds/bump-version.js`, which writes the literal AND appends the ledger entry to [`docs/module-api-changelog.md`](../module-api-changelog.md) — ADR 0203; the carrier commit stages both), builds through the fail-closed no-leak gate with `--self-verify`, publishes, and tags `core-v<version>`. A **minor/major is still a human in-task bump** — CI never makes that call, because it decides what patch-channel subscribers receive unattended.
|
|
103
103
|
|
|
104
104
|
The lane is armed by the owner via the `PUBLISH_ON_MERGE=1` repo variable + two secrets (`NPM_TOKEN`, `RELEASE_PUSH_TOKEN`); while disarmed it no-ops loudly. Manual fallback, same command CI runs:
|
|
105
105
|
|
|
@@ -55,7 +55,7 @@ npm publish ./clients/bongos-client # real (publishConfig makes it
|
|
|
55
55
|
|
|
56
56
|
## Cutting a core release (the policy — [ADR 0161](../adr/0161-publish-on-merge.md), superseding ADR 0137)
|
|
57
57
|
|
|
58
|
-
**Publishing is automatic on merge** as of 2026-08-08: the `publish` workflow rides behind the required `unit` check, auto-bumps a patch when nobody bumped, builds through the fail-closed no-leak gate, publishes, and tags — see the workflow header (`.github/workflows/publish.yml`) and ADR 0161. It ships inert until the owner arms it: repo variable `PUBLISH_ON_MERGE=1`, a **trusted publisher** registered on npmjs.com for `@bongos/core` naming this repo + `publish.yml`, and the secret `RELEASE_PUSH_TOKEN` (contents:write, for the bump commit). There is deliberately **no** `NPM_TOKEN` — the lane authenticates by OIDC, and the workflow sets neither `NPM_TOKEN` nor `NODE_AUTH_TOKEN` because either one would send npm down the legacy token path and skip the OIDC exchange entirely. A **minor/major bump stays a human in-task edit**. The update subscription ([ADR 0136](../adr/0136-update-channel-subscription-policy.md)) consumes whatever is published, on its next sweep.
|
|
58
|
+
**Publishing is automatic on merge** as of 2026-08-08: the `publish` workflow rides behind the required `unit` check and waits for the `integration` lane's verdict on the commit it releases (task 1004290), auto-bumps a patch when nobody bumped, builds through the fail-closed no-leak gate, publishes, and tags — see the workflow header (`.github/workflows/publish.yml`) and ADR 0161. It ships inert until the owner arms it: repo variable `PUBLISH_ON_MERGE=1`, a **trusted publisher** registered on npmjs.com for `@bongos/core` naming this repo + `publish.yml`, and the secret `RELEASE_PUSH_TOKEN` (contents:write, for the bump commit). There is deliberately **no** `NPM_TOKEN` — the lane authenticates by OIDC, and the workflow sets neither `NPM_TOKEN` nor `NODE_AUTH_TOKEN` because either one would send npm down the legacy token path and skip the OIDC exchange entirely. A **minor/major bump stays a human in-task edit**. The update subscription ([ADR 0136](../adr/0136-update-channel-subscription-policy.md)) consumes whatever is published, on its next sweep.
|
|
59
59
|
|
|
60
60
|
The steps below remain as the **manual fallback** (lane disarmed, npm outage, or a deliberate out-of-band release):
|
|
61
61
|
|
|
@@ -60,6 +60,8 @@
|
|
|
60
60
|
{ "glob": "modules/grading/grader-score.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
61
61
|
{ "glob": "modules/grading/grader-subagent.js", "group": "pipeline", "why": "task 1004024. Carved out of grader.js: the deterministic permission-path pre-pass, the server-side score guards a model cannot talk past, the subagent spawn and the prompt. grader.js alone protected the facade and none of the gate." },
|
|
62
62
|
{ "glob": "modules/grading/grade-engine.js", "group": "pipeline", "why": "task 1002839. The central grading engine every work-type is graded through: it runs the deterministic route-rank and permission-path pre-passes and applies the deterministic veto, so editing it can switch off the protected-path gate for every grade at once." },
|
|
63
|
+
{ "glob": "modules/grading/model-provider.js", "group": "pipeline", "why": "task 1002840. The ModelProvider port every grader model call goes through: it decides which vendor receives the diff under review and with which key, so editing it can re-route or blind the whole panel." },
|
|
64
|
+
{ "glob": "modules/grading/grader-providers.neutral.json", "group": "pipeline", "why": "task 1002840. The core's neutral provider set (none): an entry here would send every instance's diffs to a vendor by default." },
|
|
63
65
|
{ "glob": "modules/grading/grader-workers/", "group": "pipeline", "why": "the adversarial panel (Narc/Hacker/Quality/Efficiency) — blunting these blunts the gate" },
|
|
64
66
|
{ "glob": "modules/grading/grader-rubric.json", "group": "pipeline", "why": "the grader's scoring rubric (ADR 0058)" },
|
|
65
67
|
{ "glob": "scripts/gds/ship.js", "group": "pipeline", "why": "the ship lifecycle driver" },
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
-
const { ASSUMED_BUILDER_MODEL, DEFAULT_GRADER_MODEL, WORKER_MODEL_TIERS, api } = require('./grader-config.js');
|
|
11
|
+
const { ASSUMED_BUILDER_MODEL, DEFAULT_GRADER_MODEL, V4, WORKER_MODEL_TIERS, api } = require('./grader-config.js');
|
|
12
12
|
|
|
13
13
|
function r1(n) {
|
|
14
14
|
return Math.round(Number(n) * 10) / 10;
|
|
@@ -93,12 +93,14 @@ function isTrivialDiff({ changedFiles, diffStats } = {}) {
|
|
|
93
93
|
// misconfiguration it guarded. Unknown ids now warn loudly and grade on
|
|
94
94
|
// DEFAULT_GRADER_MODEL; the id still reaches signals.builder_model_assumed,
|
|
95
95
|
// so /grader-health can spot the drift.
|
|
96
|
+
//
|
|
97
|
+
// task 1002840 (ADR 0089 §3): the Claude-only if/else is now DATA — the judge
|
|
98
|
+
// table below, first matching row wins, in the old branch order.
|
|
96
99
|
function selectGraderModel({ builderModel } = {}) {
|
|
97
100
|
const bm = (builderModel || ASSUMED_BUILDER_MODEL).toLowerCase();
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (bm.includes('haiku')) return 'claude-opus-5';
|
|
101
|
+
for (const row of JUDGE_TABLE) {
|
|
102
|
+
if (row.builder_families.some((f) => bm.includes(f))) return row.judge_model;
|
|
103
|
+
}
|
|
102
104
|
console.error(
|
|
103
105
|
`selectGraderModel: unrecognized builder model ${JSON.stringify(builderModel)} — ` +
|
|
104
106
|
`no 'fable'/'mythos'/'opus'/'sonnet'/'haiku' token; grading on the default ` +
|
|
@@ -112,6 +114,46 @@ function selectGraderModel({ builderModel } = {}) {
|
|
|
112
114
|
// back to graderModel) when it lands on the BUILDER's own family: tiering is
|
|
113
115
|
// a cost lever, never a hole in the ADR 0024 cross-model guarantee.
|
|
114
116
|
const MODEL_FAMILY_TOKENS = ['fable', 'mythos', 'opus', 'sonnet', 'haiku'];
|
|
117
|
+
|
|
118
|
+
// task 1002840: the judge table — which grader model each builder family gets.
|
|
119
|
+
// Read from the rubric (v4.judge_by_builder_family) and VALIDATED at load. A
|
|
120
|
+
// row is refused when its judge shares a family with a builder it serves (the
|
|
121
|
+
// ADR 0024 cross-model guarantee: no resolution may land the judge in the
|
|
122
|
+
// builder's own family) or is not a plain Claude model id — the GATING panel
|
|
123
|
+
// stays on Claude, the quality floor ADR 0089 keeps; an open model joins only as
|
|
124
|
+
// an advisory judge (task 1003858). A table that fails is replaced WHOLE by the
|
|
125
|
+
// built-in one below, which is the mapping the old if/else hard-coded, so a bad
|
|
126
|
+
// rubric edit degrades to today's behaviour instead of to a throw at grade time.
|
|
127
|
+
const BUILTIN_JUDGE_TABLE = Object.freeze([
|
|
128
|
+
Object.freeze({ builder_families: Object.freeze(['fable', 'mythos', 'opus']), judge_model: 'claude-sonnet-5' }),
|
|
129
|
+
Object.freeze({ builder_families: Object.freeze(['sonnet', 'haiku']), judge_model: 'claude-opus-5' }),
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
function judgeTableProblems(table) {
|
|
133
|
+
if (!Array.isArray(table) || table.length === 0) return ['judge_by_builder_family must be a non-empty array'];
|
|
134
|
+
const problems = [];
|
|
135
|
+
table.forEach((row, i) => {
|
|
136
|
+
const fams = row && Array.isArray(row.builder_families) ? row.builder_families : null;
|
|
137
|
+
const judge = row && typeof row.judge_model === 'string' ? row.judge_model.toLowerCase() : null;
|
|
138
|
+
if (!fams || fams.length === 0 || !fams.every((f) => MODEL_FAMILY_TOKENS.includes(f))) {
|
|
139
|
+
problems.push(`row ${i}: builder_families must list family tokens (${MODEL_FAMILY_TOKENS.join('/')})`);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const judgeFamily = judge && !judge.includes(':') ? MODEL_FAMILY_TOKENS.find((t) => judge.includes(t)) : null;
|
|
143
|
+
if (!judgeFamily) problems.push(`row ${i}: judge_model must be a plain Claude model id (the gating panel stays on Claude)`);
|
|
144
|
+
else if (fams.includes(judgeFamily)) problems.push(`row ${i}: judge '${row.judge_model}' is in the '${judgeFamily}' family it would grade (ADR 0024)`);
|
|
145
|
+
});
|
|
146
|
+
return problems;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function resolveJudgeTable(table) {
|
|
150
|
+
const problems = judgeTableProblems(table);
|
|
151
|
+
if (problems.length === 0) return table;
|
|
152
|
+
console.error(`grader: rubric v4.judge_by_builder_family refused (${problems.join('; ')}) — grading on the built-in judge table`);
|
|
153
|
+
return BUILTIN_JUDGE_TABLE;
|
|
154
|
+
}
|
|
155
|
+
const JUDGE_TABLE = resolveJudgeTable(V4.judge_by_builder_family);
|
|
156
|
+
|
|
115
157
|
function workerModelFor(kind, graderModel, builderModel) {
|
|
116
158
|
const tier = WORKER_MODEL_TIERS[kind];
|
|
117
159
|
if (!tier) return graderModel;
|
|
@@ -137,12 +179,15 @@ const LLM_PROJECT = (() => {
|
|
|
137
179
|
|
|
138
180
|
|
|
139
181
|
module.exports = {
|
|
182
|
+
BUILTIN_JUDGE_TABLE,
|
|
183
|
+
JUDGE_TABLE,
|
|
140
184
|
LLM_PROJECT,
|
|
141
185
|
MODEL_FAMILY_TOKENS,
|
|
142
186
|
TRIVIAL_MAX_FILES,
|
|
143
187
|
TRIVIAL_MAX_LINES,
|
|
144
188
|
clamp,
|
|
145
189
|
isTrivialDiff,
|
|
190
|
+
judgeTableProblems,
|
|
146
191
|
median,
|
|
147
192
|
r1,
|
|
148
193
|
selectGraderModel,
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_comment": "The core's neutral starter for grader model providers (task 1002840, ADR 0089 §3): NONE, so a vanilla instance grades on Claude alone. An instance declares its own in config/grader-providers.json at the instance root. Each entry is { kind: 'openai-compatible', base_url: https://…, api_key_env: <ENV VAR NAME, never the key>, price_per_mtok: { <model>: { input, output } } }. Declaring one is an owner decision: it sends the diff under review to that vendor and costs money per call.",
|
|
3
|
+
"providers": {}
|
|
4
|
+
}
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
"active_panel": ["narc", "quality", "hacker", "efficiency"],
|
|
15
15
|
"worker_model_tiers": { "quality": "claude-sonnet-5", "reader": "claude-sonnet-5" },
|
|
16
16
|
"worker_model_tiers_note": "task 1002660: per-worker cost tiering. Quality was 41% of panel spend with 75% nit findings — its cq/economy lens ran on the haiku tier. task 1003318: moved to claude-sonnet-5 — haiku 4.5's 200k window overflows on any diff over ~150 KB (`Prompt is too long`, deterministic; tasks 1003297 and 1003298 each lost three ~$5 panel runs to it) and a Quality worker that never starts is missing signal on a GATING lens. For fable/opus builders the panel model is already claude-sonnet-5, so the tier coincides with default_model and acts as a floor — a future default_model bump must not pin Quality back onto a smaller window; it stays a live cost lever only for haiku builders (whose panel runs on opus-5). workerModelFor refuses an override that lands on the builder's own model family (the ADR 0024 cross-model guarantee outranks the cost lever); gate semantics unchanged — Quality's verdict still gates identically. task 1003977: the READER is pinned to claude-sonnet-5 for the same task-1003318 reason — it is Read-heavy by construction (the voice guide, then the render paths that decide whether a string is user-facing), and a small window fails deterministically with PROMPT_TOO_LONG. For a NON-GATING worker that means silently reading no copy at all on exactly the biggest copy diffs, with nothing blocking to reveal it.",
|
|
17
|
+
"judge_by_builder_family": [
|
|
18
|
+
{ "builder_families": ["fable", "mythos", "opus"], "judge_model": "claude-sonnet-5" },
|
|
19
|
+
{ "builder_families": ["sonnet", "haiku"], "judge_model": "claude-opus-5" }
|
|
20
|
+
],
|
|
21
|
+
"judge_by_builder_family_note": "task 1002840 (ADR 0089 §3): the cross-family judge choice selectGraderModel used to hard-code as an if/else — the first row whose family token appears in the builder's model id wins. Validated at load (grader-model.js judgeTableProblems): a judge in the family it grades (ADR 0024) or anything but a plain Claude id is refused and the whole table falls back to the built-in copy of exactly these two rows. An unmatched builder still grades on default_model with a warning (task 1002659).",
|
|
17
22
|
"fallthrough_confidence": 0.3,
|
|
18
23
|
"low_confidence_threshold": 0.4,
|
|
19
24
|
"rationale": "GDS-V3 task #410 (MAS Phase 2.0), 2026-05-29. Supersedes v3 (single-prompt 3-shot generalist). Phase 1 calibration showed minimal between-shot disagreement on the same prompt — the strict gate fired correctly but the diversity signal was weak. v4 trades sampling-variance for lens-specialization: replace 3 identical-prompt shots with N workers (each a distinct prompt focused on one axis). Phase 2.0 ships 2 of the 3 planned workers (narc for completion, quality for cq + advisory economy) — keeps the gate at the same strictness while the framework calibrates. Phase 2.1 adds hacker (security; wraps /builder-redteam as a CI gate). Phase 2.2 adds efficiency_monger.",
|
|
@@ -12,8 +12,13 @@ const path = require('node:path');
|
|
|
12
12
|
const fs = require('node:fs');
|
|
13
13
|
const { spawn } = require('node:child_process');
|
|
14
14
|
const { DEFAULT_GRADER_MODEL, api } = require('./grader-config.js');
|
|
15
|
+
// task 1002840: the ModelProvider port (ADR 0089 §3) — runSubagent below routes
|
|
16
|
+
// through it; the Claude spawn is its default provider.
|
|
17
|
+
const modelProvider = require('./model-provider.js');
|
|
15
18
|
|
|
16
|
-
|
|
19
|
+
// The `claude -p` spawn — the anthropic-cli ModelProvider. Body unchanged by
|
|
20
|
+
// task 1002840; only its name moved, so runSubagent could become the port.
|
|
21
|
+
function runClaudeCli({ prompt, opts = {} }) {
|
|
17
22
|
return new Promise((resolve, reject) => {
|
|
18
23
|
const timeoutMs = opts.timeoutMs ?? 240_000;
|
|
19
24
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -119,6 +124,17 @@ function runSubagent({ prompt, opts = {} }) {
|
|
|
119
124
|
child.stdin.end();
|
|
120
125
|
});
|
|
121
126
|
}
|
|
127
|
+
modelProvider.registerModelProvider({ name: modelProvider.DEFAULT_PROVIDER, kind: 'anthropic-cli', run: runClaudeCli });
|
|
128
|
+
|
|
129
|
+
// runSubagent — the ModelProvider port every platform LLM call goes through
|
|
130
|
+
// (the panel workers, the no-artifact shots, architect-audit, the agents module
|
|
131
|
+
// via the grade port). A model with no registered provider prefix — every id in
|
|
132
|
+
// use today — runs on the Claude spawn exactly as before; `<provider>:<model>`
|
|
133
|
+
// runs on that provider, which answers in the same envelope + error codes.
|
|
134
|
+
function runSubagent({ prompt, opts = {} }) {
|
|
135
|
+
const ref = modelProvider.parseModelRef(opts.model ?? DEFAULT_GRADER_MODEL);
|
|
136
|
+
return modelProvider.resolveModelProvider(ref.provider).run({ prompt, opts: { ...opts, model: ref.model } });
|
|
137
|
+
}
|
|
122
138
|
|
|
123
139
|
// ---------- task 1002660: shared context bundle ----------
|
|
124
140
|
//
|