pi-smart-router 0.9.2 → 0.10.0
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/README.md +97 -9
- package/package.json +8 -1
package/README.md
CHANGED
|
@@ -590,6 +590,11 @@ npm run routing:ingest-fc-rewardbench -- \
|
|
|
590
590
|
--output /tmp/fc-rewardbench-pack.jsonl
|
|
591
591
|
|
|
592
592
|
# Optional weak TwinRouterBench tier proxy (exclude from holdout ECE)
|
|
593
|
+
# Preferred input: checked-in CI subset (SP-199/SP-201); full-track after SP-200 is local-only.
|
|
594
|
+
npm run routing:ingest-twinrouterbench-weak -- \
|
|
595
|
+
--input tests/eval/corpus/twinrouterbench/ci-subset.json \
|
|
596
|
+
--output /tmp/trb-weak-from-ci-subset.jsonl
|
|
597
|
+
|
|
593
598
|
npm run routing:ingest-twinrouterbench-weak -- \
|
|
594
599
|
--input tests/eval/corpus/label-packs/twinrouterbench-weak/ci-fixture.jsonl \
|
|
595
600
|
--output /tmp/trb-weak-pack.jsonl
|
|
@@ -604,6 +609,11 @@ npm run routing:calibration-dry-run
|
|
|
604
609
|
# Operator packs (schema-valid JSONL)
|
|
605
610
|
npm run routing:calibration-dry-run -- --packs /tmp/swe-gym-pack.jsonl /tmp/fc-rewardbench-pack.jsonl
|
|
606
611
|
|
|
612
|
+
# Warm-start: weak / exclude_from_holdout_ece rows join the **fit** pool only
|
|
613
|
+
npm run routing:calibration-dry-run -- \
|
|
614
|
+
--packs /tmp/swe-gym-pack.jsonl /tmp/trb-weak-from-ci-subset.jsonl \
|
|
615
|
+
--include-excluded-in-fit
|
|
616
|
+
|
|
607
617
|
# Soft ECE advisory fail (threshold 0.25 calibrated ECE; not a release-gate absolute)
|
|
608
618
|
npm run routing:calibration-dry-run -- --packs /tmp/swe-gym-pack.jsonl --enforce-soft-ece
|
|
609
619
|
```
|
|
@@ -615,9 +625,10 @@ Dry-run behavior:
|
|
|
615
625
|
| < 30 ECE-eligible rows | `SAMPLE_STARVED` report-only (exit 0); no soft pass/fail |
|
|
616
626
|
| ≥ 30 ECE-eligible rows | Fit logistic + isotonic; report `holdout_ece_raw` / `holdout_ece_calibrated` |
|
|
617
627
|
| Rows with `exclude_from_holdout_ece` | Counted separately; **never** enter holdout ECE metrics (weak TwinRouterBench) |
|
|
628
|
+
| `--include-excluded-in-fit` | Weak rows may warm-start the fit pool; `ece_eligible` / holdout ECE stay verifier-grade |
|
|
618
629
|
| Soft threshold | Advisory `0.25` calibrated ECE — **does not** change `config/release-gates.json` |
|
|
619
630
|
|
|
620
|
-
**#96 / `modernbert_k4` advisory:** when deciding whether to enable ModernBERT K=4 heads, use **pack holdout ECE / Top-1 error on verifier-grade packs** (SWE-Gym + FC-RewardBench), not fixture-only QR. Weak TwinRouterBench rows are warm-start only. This task does **not** flip `modernbert_k4` defaults.
|
|
631
|
+
**#96 / `modernbert_k4` advisory:** when deciding whether to enable ModernBERT K=4 heads, use **pack holdout ECE / Top-1 error on verifier-grade packs** (SWE-Gym + FC-RewardBench), not fixture-only QR and **not** weak-fit ECE. Weak TwinRouterBench rows are warm-start only. This task does **not** flip `modernbert_k4` defaults.
|
|
621
632
|
|
|
622
633
|
### Operator tuning (frugality slider)
|
|
623
634
|
|
|
@@ -842,10 +853,10 @@ Contributors must run `npm run build` before publishing or consuming the library
|
|
|
842
853
|
| `npm run routing:train-calibration` | Train routing calibration artifact bundle |
|
|
843
854
|
| `npm run routing:train-p-success` | Train standalone `config/p-success-weights.json` (synthetic fixture by default) |
|
|
844
855
|
| `npm run routing:verify-calibration` | Verify calibration bundle against benchmark prompts |
|
|
845
|
-
| `npm run routing:calibration-dry-run` | Pack-fed isotonic dry-run: holdout ECE on label packs (CI fixtures by default) |
|
|
856
|
+
| `npm run routing:calibration-dry-run` | Pack-fed isotonic dry-run: holdout ECE on label packs (CI fixtures by default); optional `--include-excluded-in-fit` |
|
|
846
857
|
| `npm run routing:ingest-swe-gym` | Convert SWE-Gym verifier-style JSONL → privacy-safe label pack |
|
|
847
858
|
| `npm run routing:ingest-fc-rewardbench` | Convert FC-RewardBench JSONL → privacy-safe label pack |
|
|
848
|
-
| `npm run routing:ingest-twinrouterbench-weak` | Convert TwinRouterBench weak tier labels → pack (exclude from ECE) |
|
|
859
|
+
| `npm run routing:ingest-twinrouterbench-weak` | Convert TwinRouterBench weak tier labels → pack (prefer `ci-subset.json`; exclude from ECE) |
|
|
849
860
|
| `npm run routing:ingest-benchmarks` | Regenerate `config/benchmark-profiles.json` from leaderboard fixtures |
|
|
850
861
|
| `npm run routing:verify-benchmark-profiles` | CI smoke: assert checked-in profiles match fixture ingest |
|
|
851
862
|
| `npm run routing:eval-replay` | Counterfactual replay on eval trace fixtures |
|
|
@@ -853,7 +864,13 @@ Contributors must run `npm run build` before publishing or consuming the library
|
|
|
853
864
|
| `npm run routing:eval-harness:smoke` | Harness summary JSON only (CI smoke; no network) |
|
|
854
865
|
| `npm run routing:eval-harness:corpus-smoke` | Harness summary on TwinRouterBench CI corpus subset (`tests/eval/corpus/twinrouterbench`) |
|
|
855
866
|
| `npm run routing:assert-release-gates:corpus-report` | Soft-feed: assert corpus vs absolute gates with `--report-only` (exit 0; does not gate releases) |
|
|
867
|
+
| `npm run routing:twinrouterbench:full-track` | Local/nightly: pin fetch → full convert (no `--limit`) → harness + gates `--report-only` (gitignored cache) |
|
|
868
|
+
| `npm run routing:twinrouterbench:full-ingest` | Convert cached `question_bank.jsonl` → full static-track JSON (no `--limit`) |
|
|
869
|
+
| `npm run routing:twinrouterbench:full-report` | Harness summary + gates `--report-only` on cached full track |
|
|
856
870
|
| `npm run routing:ingest-twinrouterbench` | Convert TwinRouterBench `question_bank.jsonl` → CI subset / full corpus JSON |
|
|
871
|
+
| `npm run routing:ingest-llmrouterbench` | Convert LLMRouterBench BaselineRecord JSONL → static-track subset JSON |
|
|
872
|
+
| `npm run routing:llmrouterbench-regret` | Offline regret / CS report on vendored LLMRouterBench subset (optional; not PR CI) |
|
|
873
|
+
| `npm run routing:community-bench` | Privacy-safe community bench report (Track A TwinRouterBench + optional Track B/C) |
|
|
857
874
|
| `npm run benchmark:encoder` | Compare MiniLM vs Granite encoder latency on held-out agent turns |
|
|
858
875
|
|
|
859
876
|
### Offline eval harness (agent-native routing)
|
|
@@ -871,7 +888,7 @@ npm run routing:eval-harness
|
|
|
871
888
|
# CI-style summary only (default fixtures under tests/eval/fixtures)
|
|
872
889
|
npm run routing:eval-harness:smoke
|
|
873
890
|
|
|
874
|
-
# TwinRouterBench CI corpus subset (≤
|
|
891
|
+
# TwinRouterBench CI corpus subset (≤150 code/tool records; offline)
|
|
875
892
|
npm run routing:eval-harness:corpus-smoke
|
|
876
893
|
|
|
877
894
|
# Custom fixture directory (includes TwinRouterBench static track subdirs)
|
|
@@ -879,27 +896,98 @@ npm run routing:eval-harness -- --fixtures tests/eval/fixtures
|
|
|
879
896
|
|
|
880
897
|
# Counterfactual replay only (SP-151)
|
|
881
898
|
npm run routing:eval-replay
|
|
899
|
+
|
|
900
|
+
# Full ~970-row static track (local / nightly only — do not check JSON into git)
|
|
901
|
+
npm run routing:twinrouterbench:full-track
|
|
882
902
|
```
|
|
883
903
|
|
|
884
|
-
**CI smoke:** `.github/workflows/eval-harness-smoke.yml` runs on PRs that touch eval scripts, fixtures, or the workflow. It executes `routing:eval-harness:smoke`, `routing:eval-harness:corpus-smoke`, and eval unit tests — fast, offline, no provider network calls. Job timeout stays at 10 minutes.
|
|
904
|
+
**CI smoke:** `.github/workflows/eval-harness-smoke.yml` runs on PRs that touch eval scripts, fixtures, or the workflow. It executes `routing:eval-harness:smoke`, `routing:eval-harness:corpus-smoke`, and eval unit tests — fast, offline, no provider network calls. Job timeout stays at 10 minutes. The optional full-track nightly (`.github/workflows/twinrouterbench-full-nightly.yml`, `schedule` + `workflow_dispatch` only) is **not** on `pull_request` and must not be configured as a required status check — failures there do not gate PR CI or `release:functional-smoke`.
|
|
885
905
|
|
|
886
906
|
**TwinRouterBench static track:** import step-level router-visible prefixes with execution-verified target tiers (`track: "static"`). The adapter in `scripts/eval/twinrouterbench-adapter.ts` converts static track records into native eval fixtures for the three-track harness. See `docs/gemini-research.md` §9 for methodology context.
|
|
887
907
|
|
|
888
|
-
#### TwinRouterBench CI corpus (SP-186 / SP-187 / SP-188)
|
|
908
|
+
#### TwinRouterBench CI corpus (SP-186 / SP-187 / SP-188 / SP-199)
|
|
889
909
|
|
|
890
910
|
| Item | Location / command |
|
|
891
911
|
|------|--------------------|
|
|
892
912
|
| **Pinned upstream** | CommonstackAI/TwinRouterBench `@430acecac71141de77afd8e5e13690d236d58e93` (Apache-2.0) |
|
|
893
|
-
| **CI subset** | `tests/eval/corpus/twinrouterbench/ci-subset.json` (≤
|
|
913
|
+
| **CI subset** | `tests/eval/corpus/twinrouterbench/ci-subset.json` (≤150 code/tool records) |
|
|
894
914
|
| **Provenance** | `tests/eval/corpus/twinrouterbench/PROVENANCE.md` |
|
|
895
|
-
| **Regenerate** | `npm run routing:ingest-twinrouterbench -- --input <question_bank.jsonl> --output tests/eval/corpus/twinrouterbench/ci-subset.json --limit
|
|
915
|
+
| **Regenerate** | `npm run routing:ingest-twinrouterbench -- --input <question_bank.jsonl> --output tests/eval/corpus/twinrouterbench/ci-subset.json --limit 150 --prefer-code-tool` |
|
|
896
916
|
| **Harness smoke** | `npm run routing:eval-harness:corpus-smoke` |
|
|
897
917
|
| **Gate soft-feed** | `npm run routing:assert-release-gates:corpus-report` |
|
|
918
|
+
| **Human QA protocol** | [`docs/qa/shadow-dogfood-protocol.md`](docs/qa/shadow-dogfood-protocol.md) · `npm run qa:shadow-dogfood` |
|
|
898
919
|
|
|
899
|
-
**Absolute release gates stay on default fixtures.** `npm run release:functional-smoke` continues to assert `tests/eval/fixtures` against `config/release-gates.json` — do not point it at the corpus without operator review. Today the corpus subset fails `mean_over_routing_rate_max` (≈0.85 vs absolute max 0.15); that gap is intentional soft signal for the [#95](https://github.com/beettlle/pi-smart-router/issues/95) public static-track acceptance criteria alongside live dogfood traces. Use `--fixtures tests/eval/corpus/twinrouterbench` (or the corpus-report script) for #95 public-track scoring; keep absolute threshold edits out of band until operators approve.
|
|
920
|
+
**Absolute release gates stay on default fixtures.** `npm run release:functional-smoke` continues to assert `tests/eval/fixtures` against `config/release-gates.json` — do not point it at the corpus without operator review. Today the corpus subset fails `mean_over_routing_rate_max` (≈0.85 vs absolute max 0.15); that gap is intentional soft signal for the [#95](https://github.com/beettlle/pi-smart-router/issues/95) public static-track acceptance criteria alongside live dogfood traces. Use `--fixtures tests/eval/corpus/twinrouterbench` (or the corpus-report script) for #95 public-track scoring; keep absolute threshold edits out of band until operators approve. For live shadow dogfood steps and sign-off, see the [shadow dogfood protocol](docs/qa/shadow-dogfood-protocol.md).
|
|
921
|
+
|
|
922
|
+
#### TwinRouterBench full static track (SP-200 / #107)
|
|
923
|
+
|
|
924
|
+
First-class **local / optional nightly** path for the pinned ~970-row bank. **Do not check the full JSON into git.**
|
|
925
|
+
|
|
926
|
+
| Item | Location / command |
|
|
927
|
+
|------|--------------------|
|
|
928
|
+
| **One-shot** | `npm run routing:twinrouterbench:full-track` |
|
|
929
|
+
| **Cache (gitignored)** | `.pi-smart-router/eval-cache/twinrouterbench/` (override with `TRB_CACHE_DIR`) |
|
|
930
|
+
| **Steps** | pin fetch → `routing:ingest-twinrouterbench` **without** `--limit` → harness `--summary-only` + gates `--report-only` |
|
|
931
|
+
| **Nightly** | `.github/workflows/twinrouterbench-full-nightly.yml` (`schedule` + `workflow_dispatch`) — advisory only |
|
|
932
|
+
| **Provenance** | `tests/eval/corpus/twinrouterbench/PROVENANCE.md` |
|
|
933
|
+
|
|
934
|
+
PR corpus smoke remains the vendored ≤150 subset. Absolute `config/release-gates.json` thresholds and `release:functional-smoke` stay fixture-backed.
|
|
935
|
+
|
|
936
|
+
**[#95 dual-gate protocol](https://github.com/beettlle/pi-smart-router/issues/95):** (1) live shadow dogfood (`docs/qa/shadow-dogfood-protocol.md` · `npm run qa:shadow-dogfood`) and (2) public static-track soft-feed (CI subset report, or full-track report above). Neither path edits absolute release thresholds.
|
|
900
937
|
|
|
901
938
|
**Deferred:** RouterBench classic (outcome-matrix) smoke is out of scope for SP-188; prefer TwinRouterBench static track + dogfood for #95.
|
|
902
939
|
|
|
940
|
+
#### LLMRouterBench offline regret (SP-192 / SP-193)
|
|
941
|
+
|
|
942
|
+
Optional local / nightly report on the **pinned code/tool subset** — not part of PR CI (no full HF corpus download).
|
|
943
|
+
|
|
944
|
+
| Item | Location / command |
|
|
945
|
+
|------|--------------------|
|
|
946
|
+
| **Pinned upstream** | HF `NPULH/LLMRouterBench` `@0e5af1b84bf73437a01a1849c0f1d2468baa93fc` + git schema `@c77cb0506949d8f959e97967d2fefca0e8ff1b05` (MIT) |
|
|
947
|
+
| **CI subset** | `tests/eval/corpus/llmrouterbench/ci-subset.json` (≤20 synthetic offline records) |
|
|
948
|
+
| **Provenance / refresh** | `tests/eval/corpus/llmrouterbench/PROVENANCE.md` (quarterly pin refresh; re-run report after catalog/subset changes) |
|
|
949
|
+
| **Regenerate subset** | `npm run routing:ingest-llmrouterbench -- --input <jsonl> --output tests/eval/corpus/llmrouterbench/ci-subset.json --limit 20 --prefer-code-tool` |
|
|
950
|
+
| **Regret / CS report** | `npm run routing:llmrouterbench-regret` |
|
|
951
|
+
| **Community Track C** | `npm run routing:community-bench -- --llmrouterbench` (same vendored subset; optional) |
|
|
952
|
+
|
|
953
|
+
PR CI continues to smoke TwinRouterBench only (`routing:eval-harness:corpus-smoke`). Absolute `config/release-gates.json` thresholds are unchanged. See [Contribute a community bench report](#contribute-a-community-bench-report) for Track A + optional Track C sharing.
|
|
954
|
+
|
|
955
|
+
#### Contribute a community bench report
|
|
956
|
+
|
|
957
|
+
Share a privacy-safe setup fingerprint + Track A (TwinRouterBench) gate result with maintainers. No SMTP auto-send and no upload server — you copy artifacts yourself.
|
|
958
|
+
|
|
959
|
+
**Maintainer contact** (must match the CLI footer constant `COMMUNITY_BENCH_MAINTAINER_CONTACT`):
|
|
960
|
+
|
|
961
|
+
`https://github.com/beettlle/pi-smart-router/issues/new?labels=community-bench`
|
|
962
|
+
|
|
963
|
+
```bash
|
|
964
|
+
# Track A offline smoke (vendored TwinRouterBench corpus — no network)
|
|
965
|
+
npm run routing:community-bench -- \
|
|
966
|
+
--output /tmp/community-bench-report.json \
|
|
967
|
+
--email-file /tmp/community-bench-report.txt
|
|
968
|
+
|
|
969
|
+
# Optional Track C: offline LLMRouterBench regret/CS on the vendored subset (no full HF download)
|
|
970
|
+
npm run routing:community-bench -- \
|
|
971
|
+
--llmrouterbench \
|
|
972
|
+
--output /tmp/community-bench-report.json \
|
|
973
|
+
--email-file /tmp/community-bench-report.txt
|
|
974
|
+
```
|
|
975
|
+
|
|
976
|
+
**How to send:**
|
|
977
|
+
|
|
978
|
+
1. **Email `.txt`** — open `/tmp/community-bench-report.txt` (or your `--email-file` path). It includes a `Subject:` line, privacy blurb, fingerprint, Track A PASS/FAIL, and optional Track C metrics. Paste into your mail client; attach `community-bench-report.json` if useful. Do **not** expect the CLI to send mail.
|
|
979
|
+
2. **GitHub issue** — open the [maintainer contact](https://github.com/beettlle/pi-smart-router/issues/new?labels=community-bench) URL, or run with `--print-issue-body` and paste stdout into a new issue. Issues list: https://github.com/beettlle/pi-smart-router/issues
|
|
980
|
+
|
|
981
|
+
**Tracks:**
|
|
982
|
+
|
|
983
|
+
| Track | Corpus | When |
|
|
984
|
+
|-------|--------|------|
|
|
985
|
+
| **A (required)** | [TwinRouterBench CI corpus](#twinrouterbench-ci-corpus-sp-186--sp-187--sp-188) (`tests/eval/corpus/twinrouterbench`) | Always |
|
|
986
|
+
| **B (optional)** | Dogfood export (`--dogfood-export PATH`) | Skips with an explicit reason until [#95](https://github.com/beettlle/pi-smart-router/issues/95) adapter lands — never invents labels |
|
|
987
|
+
| **C (optional)** | [LLMRouterBench offline subset](#llmrouterbench-offline-regret-sp-192--sp-193) (`tests/eval/corpus/llmrouterbench`) | `--llmrouterbench` or `--full`; offline only |
|
|
988
|
+
|
|
989
|
+
PR CI does **not** download full TwinRouterBench / LLMRouterBench corpora. Absolute gate thresholds in `config/release-gates.json` are unchanged by this CLI.
|
|
990
|
+
|
|
903
991
|
Sample fixtures under `tests/eval/fixtures/twinrouterbench/` remain the small adapter unit-test inputs and are unchanged by corpus ingest.
|
|
904
992
|
|
|
905
993
|
Capability scores in `config/benchmark-profiles.json` are grounded from public leaderboard snapshots under `tests/fixtures/benchmark-leaderboards/` (and optional **recorded** live snapshots under `tests/fixtures/benchmark-leaderboards/recorded/`). Each artifact records provenance (`source_urls`, `scrape_date`, `catalog_freeze_date`) in its header.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-smart-router",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Auto-model router middleware for the pi.dev coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -73,13 +73,20 @@
|
|
|
73
73
|
"routing:eval-harness:smoke": "tsx scripts/eval/run-harness.ts --summary-only",
|
|
74
74
|
"routing:eval-harness:corpus-smoke": "tsx scripts/eval/run-harness.ts --fixtures tests/eval/corpus/twinrouterbench --summary-only",
|
|
75
75
|
"routing:assert-release-gates:corpus-report": "tsx scripts/eval/assert-release-gates.ts --fixtures tests/eval/corpus/twinrouterbench --report-only",
|
|
76
|
+
"routing:twinrouterbench:full-ingest": "bash -c 'set -euo pipefail; CACHE=\"${TRB_CACHE_DIR:-.pi-smart-router/eval-cache/twinrouterbench}\"; mkdir -p \"$CACHE\"; npm run routing:ingest-twinrouterbench -- --input \"$CACHE/question_bank.jsonl\" --output \"$CACHE/full-static-track.json\"'",
|
|
77
|
+
"routing:twinrouterbench:full-report": "bash -c 'set -euo pipefail; CACHE=\"${TRB_CACHE_DIR:-.pi-smart-router/eval-cache/twinrouterbench}\"; DIR=\"$CACHE/full-track\"; mkdir -p \"$DIR\"; cp \"$CACHE/full-static-track.json\" \"$DIR/full-static-track.json\"; npm run routing:eval-harness -- --fixtures \"$DIR\" --summary-only; npx tsx scripts/eval/assert-release-gates.ts --fixtures \"$DIR\" --report-only'",
|
|
78
|
+
"routing:twinrouterbench:full-track": "bash scripts/eval/twinrouterbench-full-track.sh",
|
|
79
|
+
"routing:community-bench": "tsx scripts/eval/community-bench.ts",
|
|
76
80
|
"routing:ingest-twinrouterbench": "tsx scripts/eval/ingest-twinrouterbench-corpus.ts",
|
|
81
|
+
"routing:ingest-llmrouterbench": "tsx scripts/eval/ingest-llmrouterbench-subset.ts",
|
|
82
|
+
"routing:llmrouterbench-regret": "tsx scripts/eval/llmrouterbench-regret-report.ts",
|
|
77
83
|
"routing:ingest-swe-gym": "tsx scripts/ingest-swe-gym-labels.ts",
|
|
78
84
|
"routing:ingest-fc-rewardbench": "tsx scripts/ingest-fc-rewardbench-labels.ts",
|
|
79
85
|
"routing:ingest-twinrouterbench-weak": "tsx scripts/ingest-twinrouterbench-weak-labels.ts",
|
|
80
86
|
"routing:capture-baseline": "tsx scripts/eval/capture-baseline.ts",
|
|
81
87
|
"routing:test-projection": "npm run build && node --experimental-strip-types scripts/test-hydra-projection.ts",
|
|
82
88
|
"benchmark:encoder": "tsx scripts/benchmark-encoder-latency.ts",
|
|
89
|
+
"qa:shadow-dogfood": "bash scripts/qa/shadow-dogfood-session.sh",
|
|
83
90
|
"verify:ci": "npm run build && npm run typecheck && npm run lint && npm test && npm run coverage:check"
|
|
84
91
|
},
|
|
85
92
|
"peerDependencies": {
|