ruvnet-brain 4.5.3 β 4.5.5
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 +2 -2
- package/bin/install.mjs +148 -31
- package/config/model-router/catalog.template.json +126 -52
- package/config/model-router/policy.default.mjs +94 -75
- package/config/model-router/qualification-contract.json +124 -0
- package/config/model-router/routing-eval-cases.json +275 -0
- package/config/model-router/routing-policy.template.json +76 -0
- package/config/model-router/weekly-analyst-instruction.md +60 -0
- package/data/model-catalog.json +44 -49
- package/package.json +3 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/hooks/codex-hooks.json +40 -3
- package/plugin/hooks/hook-contracts.json +218 -19
- package/plugin/hooks/hooks.json +51 -2
- package/plugin/scripts/agentdb-recall.mjs +101 -30
- package/plugin/scripts/codex-hook-adapter.mjs +18 -9
- package/plugin/scripts/continuity-hook-policy.mjs +9 -0
- package/plugin/scripts/continuity-journal.mjs +33 -33
- package/plugin/scripts/ground-ruvnet.sh +5 -5
- package/plugin/scripts/hook-shim.mjs +4 -30
- package/plugin/scripts/project-capture-queue.mjs +333 -0
- package/plugin/scripts/project-progression-contract.mjs +1 -1
- package/plugin/scripts/project-progression-hook.mjs +3 -3
- package/plugin/scripts/project-progression-producer.mjs +53 -28
- package/plugin/scripts/project-progression-session-start.mjs +44 -4
- package/plugin/scripts/project-progression-store.mjs +14 -0
- package/plugin/scripts/project-transition-hook.mjs +204 -0
- package/plugin/scripts/session-snapshot-hook.mjs +44 -272
- package/plugin/scripts/session-start-budget.mjs +2 -2
- package/plugin/scripts/turn-outcome-capture.mjs +125 -47
- package/plugin/scripts/turn-transport-journal.mjs +106 -0
- package/scripts/codex-hook-trust-reconcile.mjs +247 -0
- package/scripts/codex-routed.sh +3 -36
- package/scripts/goldie-weekly.sh +8 -64
- package/scripts/metaharness-router.mjs +7 -1
- package/scripts/model-analyst-sandbox.mjs +54 -0
- package/scripts/model-currency-evidence.mjs +139 -0
- package/scripts/model-currency.mjs +230 -0
- package/scripts/model-native-catalog.mjs +111 -0
- package/scripts/model-native-qualification.mjs +251 -0
- package/scripts/model-router-agent-hook.mjs +136 -0
- package/scripts/model-router-dispatch.mjs +161 -0
- package/scripts/model-router-engine.mjs +155 -104
- package/scripts/model-routing-eval.mjs +108 -0
- package/scripts/model-routing-gateway.mjs +420 -0
- package/scripts/model-routing-launchers.mjs +174 -0
- package/scripts/model-routing-policy-promotion.mjs +203 -0
- package/scripts/model-weekly-analyst.mjs +299 -0
- package/scripts/model-weekly-assessment.mjs +91 -0
- package/scripts/model-weekly-cycle.mjs +183 -0
- package/scripts/model-weekly-qualification.mjs +362 -0
- package/scripts/native-subscription-usage.mjs +57 -0
- package/scripts/release-qualification-contract.mjs +54 -0
- package/scripts/security-guidance-codex-compat.mjs +142 -0
- package/scripts/user-model-prompt-hook.mjs +69 -0
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Created: 2026-06-29 22:36:38 EDT
|
|
|
7
7
|
|
|
8
8
|
# π§ RuvNet Brain
|
|
9
9
|
|
|
10
|
-
### π§ RuvNet Brain β [](https://github.com/stuinfla/ruvnet-brain/blob/main/plugin/.claude-plugin/plugin.json)
|
|
11
11
|
|
|
12
12
|
**A portable, source-grounded brain over Reuven Cohen's (rUv's) RuvNet stack β delivered as a Claude Code plugin that makes Claude _use_ the stack instead of fighting it.**
|
|
13
13
|
|
|
@@ -562,7 +562,7 @@ node forge-ask-all.mjs --dir . --q "How does RuVector implement HNSW vector sear
|
|
|
562
562
|
|
|
563
563
|
This project versions in the open (see the live badge up top for the exact plugin version; the downloadable knowledge bundle is a separate track) β we don't claim βdone,β βcomplete,β or βzero hallucinations.β Where it stands:
|
|
564
564
|
|
|
565
|
-
- β
**The grounding brain is real and proven** β 199 public stores Β· 162,
|
|
565
|
+
- β
**The grounding brain is real and proven** β 199 public stores Β· 162,680 public source chunks, dual embeddings, cross-encoder rerank, plugin (MCP tool + explicit skills; automatic hooks retired), all re-runnable.
|
|
566
566
|
- β
**Code-level depth** β the code-rich repos are indexed to full function bodies; βhow is it implemented?β returns the implementation. Verified in the shipped bundle (clean-room 3/3).
|
|
567
567
|
- β
**Routing holds** β named 47/48, described 26/28, scenario 7/8; behavioral L1βL3 all pass (**L4 downgraded β it measures that the brain spoke, not that anything listened**); private stores fenced out of the public bundle (zero-leak verified).
|
|
568
568
|
- β οΈ **Two routing residuals** (above) β surfaced, not hidden.
|
package/bin/install.mjs
CHANGED
|
@@ -79,6 +79,8 @@ import {
|
|
|
79
79
|
} from '../scripts/console-runtime-identity.mjs';
|
|
80
80
|
import { shellDiff as pluginShellDiff } from '../plugin/scripts/host-shell-boundary.mjs';
|
|
81
81
|
import { codexTrustChanges, CODEX_TRUST_ACTION } from '../scripts/codex-hook-trust.mjs';
|
|
82
|
+
import { repairSecurityGuidance } from '../scripts/security-guidance-codex-compat.mjs';
|
|
83
|
+
import { installNativeLaunchers } from '../scripts/model-routing-launchers.mjs';
|
|
82
84
|
import { readConsoleReceipts, replaceStaleConsoles } from '../scripts/console-instances.mjs';
|
|
83
85
|
import { moveBrain, MoveRefused } from '../scripts/move-brain.mjs';
|
|
84
86
|
import { brainLocation } from '../plugin/scripts/brain-location.mjs';
|
|
@@ -2014,6 +2016,32 @@ export function codexPluginStatus(options = {}) {
|
|
|
2014
2016
|
};
|
|
2015
2017
|
}
|
|
2016
2018
|
|
|
2019
|
+
// User-scoped standing consent applies across projects, never implicitly to other installations.
|
|
2020
|
+
export function repairReleasedCodexHookTrust(status, { codexHome = codexHomeDir(), codexBin = process.env.CODEX_BIN || 'codex', cwd = process.cwd(), run = spawnSync } = {}) {
|
|
2021
|
+
if (TEST_MODE || !status?.installed || !status?.enabled) return { state: 'not-applicable', changed: false };
|
|
2022
|
+
let profile;
|
|
2023
|
+
try { profile = JSON.parse(fs.readFileSync(path.join(os.homedir(), '.claude', 'model-router', 'profile.json'), 'utf8')); } catch { return { state: 'not-authorized', changed: false }; }
|
|
2024
|
+
if (profile.automaticHookTrustUpdates !== true) return { state: 'not-authorized', changed: false };
|
|
2025
|
+
let compatibility;
|
|
2026
|
+
try { compatibility = repairSecurityGuidance({ codexHome, apply: true }); }
|
|
2027
|
+
catch (error) { compatibility = { status: 'blocked', reason: error.message }; }
|
|
2028
|
+
const installedRoot = codexInstalledPluginRoot({ codexHome, status });
|
|
2029
|
+
if (!installedRoot) return { state: 'blocked', changed: false, reason: 'Installed plugin root unavailable' };
|
|
2030
|
+
const helper = path.join(REPO_ROOT, 'scripts', 'codex-hook-trust-reconcile.mjs');
|
|
2031
|
+
const result = run(process.execPath, [helper, '--reconcile-installed'], {
|
|
2032
|
+
input: JSON.stringify({ installedVersion: status.version, hooksPath: path.join(installedRoot, 'hooks', 'codex-hooks.json'),
|
|
2033
|
+
configPath: path.join(codexHome, 'config.toml'), nativeBinary: codexBin, cwd }),
|
|
2034
|
+
encoding: 'utf8', timeout: 30000, maxBuffer: 128 * 1024, env: process.env,
|
|
2035
|
+
});
|
|
2036
|
+
try {
|
|
2037
|
+
const receipt = JSON.parse(result.stdout);
|
|
2038
|
+
if (!result.error && ['registry-verified', 'unchanged', 'blocked', 'degraded'].includes(receipt.state)) return { ...receipt, compatibility };
|
|
2039
|
+
} catch { /* a command exit alone never establishes hook trust */ }
|
|
2040
|
+
return result.error?.code === 'ENOENT'
|
|
2041
|
+
? { state: 'blocked', changed: false, reason: 'Verified hook trust helper could not start' }
|
|
2042
|
+
: { state: 'degraded', changed: 'unknown', reason: 'Hook trust helper acknowledgement unavailable; inspect native registry before retrying' };
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2017
2045
|
export function wireCodexPlugin({
|
|
2018
2046
|
codexDir = codexHomeDir(),
|
|
2019
2047
|
codexHome = codexDir,
|
|
@@ -2062,9 +2090,13 @@ export function wireCodexPlugin({
|
|
|
2062
2090
|
const hooksNeedingReview = codexHooksNeedingReview(before.installed
|
|
2063
2091
|
? codexInstalledPluginRoot({ codexHome, status: before }) : null, path.join(REPO_ROOT, 'plugin'));
|
|
2064
2092
|
if (before.installed && before.enabled && versionSatisfies(before.version, expectedVersion)) {
|
|
2065
|
-
|
|
2093
|
+
const hookTrust = runJson === runCodexJson ? repairReleasedCodexHookTrust(before, options) : null;
|
|
2094
|
+
if (announce) {
|
|
2095
|
+
ok(`Codex Brain plugin already installed and enabled (${before.version || 'version unknown'}).`);
|
|
2096
|
+
if (hookTrust && ['blocked', 'degraded'].includes(hookTrust.state)) warn(`Automatic Brain hook trust repair ${hookTrust.state}: ${hookTrust.reason}`);
|
|
2097
|
+
}
|
|
2066
2098
|
return {
|
|
2067
|
-
host: true, action: 'unchanged', ...before,
|
|
2099
|
+
host: true, action: 'unchanged', ...before, ...(hookTrust ? { hookTrust } : {}),
|
|
2068
2100
|
shellChanged: shellBoundary.changed, shellChangedPaths: shellBoundary.paths,
|
|
2069
2101
|
restartRequired: false,
|
|
2070
2102
|
};
|
|
@@ -2107,14 +2139,17 @@ export function wireCodexPlugin({
|
|
|
2107
2139
|
if (announce) warn('Codex accepted the install command but the Brain plugin is not installed and enabled.');
|
|
2108
2140
|
return { host: true, action: 'verification-failed', expectedVersion, ...after };
|
|
2109
2141
|
}
|
|
2142
|
+
const hookTrust = runJson === runCodexJson ? repairReleasedCodexHookTrust(after, options) : null;
|
|
2143
|
+
const trustVerified = hookTrust && ['registry-verified', 'unchanged'].includes(hookTrust.state);
|
|
2110
2144
|
if (announce) {
|
|
2111
2145
|
ok(`Codex Brain plugin installed and enabled (${after.version || 'version unknown'}).`);
|
|
2146
|
+
if (hookTrust && ['blocked', 'degraded'].includes(hookTrust.state)) warn(`Automatic Brain hook trust repair ${hookTrust.state}: ${hookTrust.reason}`);
|
|
2112
2147
|
if (shellBoundary.restartRequired) {
|
|
2113
2148
|
warn(`boot-level plugin declarations changed; restart Codex, then review them in /hooks (${shellBoundary.paths.join(', ') || shellBoundary.reason}).`);
|
|
2114
2149
|
} else if (before.installed && before.version !== after.version) {
|
|
2115
2150
|
info(' body-only update: the Stable Spine is live on the next hook/MCP call; no restart is required.');
|
|
2116
2151
|
}
|
|
2117
|
-
if (hooksNeedingReview.length) {
|
|
2152
|
+
if (hooksNeedingReview.length && !trustVerified) {
|
|
2118
2153
|
warn(`Codex will NOT run ${hooksNeedingReview.length} Brain hook${hooksNeedingReview.length === 1 ? '' : 's'} until you review`
|
|
2119
2154
|
+ ` ${hooksNeedingReview.length === 1 ? 'it' : 'them'} (${hooksNeedingReview.map((h) => `${h.key.split(':').slice(-3).join(':')} ${h.status}`).join(', ')}).`);
|
|
2120
2155
|
info(` ${CODEX_TRUST_ACTION}`);
|
|
@@ -2123,7 +2158,8 @@ export function wireCodexPlugin({
|
|
|
2123
2158
|
return {
|
|
2124
2159
|
host: true,
|
|
2125
2160
|
action: before.installed ? 'updated' : 'installed',
|
|
2126
|
-
hooksNeedingReview,
|
|
2161
|
+
hooksNeedingReview: trustVerified ? [] : hooksNeedingReview,
|
|
2162
|
+
...(hookTrust ? { hookTrust } : {}),
|
|
2127
2163
|
...after,
|
|
2128
2164
|
shellChanged: shellBoundary.changed,
|
|
2129
2165
|
shellChangedPaths: shellBoundary.paths,
|
|
@@ -2443,11 +2479,11 @@ export function automaticHookRetirementStatus(root = REPO_ROOT, { scope = 'sourc
|
|
|
2443
2479
|
if (pairs.length !== expectedPairs.length || expectedPairs.some((pair) => !pairs.includes(pair))) {
|
|
2444
2480
|
errors.push(`${contractsFile}: contracts must list exactly the continuity handlers (${expectedPairs.join(', ')})`);
|
|
2445
2481
|
}
|
|
2446
|
-
//
|
|
2447
|
-
|
|
2448
|
-
|
|
2482
|
+
// Matchers belong to a host registry: one host's exception grants no authority to another.
|
|
2483
|
+
const expectedMatchers = [['plugin', 'claude'], ['codex', 'codex']].flatMap(([layer, host]) =>
|
|
2484
|
+
[...new Set(continuityRegistrations(host).map((spec) => `${layer}:${spec.event}:${spec.matcher}`))]);
|
|
2449
2485
|
const declaredMatchers = Array.isArray(contracts.matcherAllowlist)
|
|
2450
|
-
? contracts.matcherAllowlist.map((row) => `${row?.event}:${row?.matcher}`) : [];
|
|
2486
|
+
? contracts.matcherAllowlist.map((row) => `${row?.layer}:${row?.event}:${row?.matcher}`) : [];
|
|
2451
2487
|
if (declaredMatchers.length !== expectedMatchers.length
|
|
2452
2488
|
|| expectedMatchers.some((entry) => !declaredMatchers.includes(entry))) {
|
|
2453
2489
|
errors.push(`${contractsFile}: matcherAllowlist must list exactly the continuity matchers (${expectedMatchers.join(', ')})`);
|
|
@@ -3934,6 +3970,7 @@ async function runUpdate() {
|
|
|
3934
3970
|
} catch (error) {
|
|
3935
3971
|
warn(`managed model additions were not merged (${error.message}); your catalog was left unchanged`);
|
|
3936
3972
|
}
|
|
3973
|
+
refreshManagedRouterDefault();
|
|
3937
3974
|
process.exitCode = 0;
|
|
3938
3975
|
return;
|
|
3939
3976
|
}
|
|
@@ -4207,6 +4244,8 @@ async function runUpdate() {
|
|
|
4207
4244
|
// updated. Additive and non-interactive; their overrides win, metered rows are never auto-enabled,
|
|
4208
4245
|
// and a failure here is reported but never fails an otherwise-good update.
|
|
4209
4246
|
if (updateStatus === 0) {
|
|
4247
|
+
const defaultReceipt = refreshManagedRouterDefault();
|
|
4248
|
+
recordRefreshAdvisory(refreshReceipt, 'managed-router-default', defaultReceipt.action === 'failed' ? 'SKIP' : 'PASS', defaultReceipt);
|
|
4210
4249
|
try {
|
|
4211
4250
|
const managed = applyManagedCatalogUpdate({
|
|
4212
4251
|
routerDir: path.join(os.homedir(), '.claude', 'model-router'),
|
|
@@ -4849,30 +4888,110 @@ export function parseNightlyAnswer(answer) {
|
|
|
4849
4888
|
// suppression flags) is testable in-process under RUVNET_BRAIN_IMPORT_ONLY=1 without a real install.
|
|
4850
4889
|
// Returns a status string; never throws (the caller also guards β a finished install must never
|
|
4851
4890
|
// be broken by an optional offer).
|
|
4891
|
+
// The default classifier is managed executable source; overrides belong in policy.mjs.
|
|
4892
|
+
// Preserve every prior default by its content digest before replacing it atomically.
|
|
4893
|
+
export function syncManagedRouterDefault({ routerDir = path.join(os.homedir(), '.claude', 'model-router'), packageRoot = REPO_ROOT } = {}) {
|
|
4894
|
+
const source = fs.readFileSync(path.join(packageRoot, 'config', 'model-router', 'policy.default.mjs'));
|
|
4895
|
+
const destination = path.join(routerDir, 'policy.default.mjs');
|
|
4896
|
+
fs.mkdirSync(routerDir, { recursive: true });
|
|
4897
|
+
const prior = fs.existsSync(destination) ? fs.readFileSync(destination) : null;
|
|
4898
|
+
if (prior?.equals(source)) return { action: 'unchanged' };
|
|
4899
|
+
let backup = null;
|
|
4900
|
+
if (prior) {
|
|
4901
|
+
backup = `${destination}.pre-managed-upgrade-${crypto.createHash('sha256').update(prior).digest('hex').slice(0, 16)}`;
|
|
4902
|
+
try { fs.writeFileSync(backup, prior, { flag: 'wx', mode: 0o600 }); }
|
|
4903
|
+
catch (error) {
|
|
4904
|
+
if (error.code !== 'EEXIST' || !fs.readFileSync(backup).equals(prior)) throw error;
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4907
|
+
const temporary = `${destination}.tmp-${process.pid}-${crypto.randomUUID()}`;
|
|
4908
|
+
try {
|
|
4909
|
+
fs.writeFileSync(temporary, source, { flag: 'wx', mode: prior ? fs.statSync(destination).mode & 0o777 : 0o600 });
|
|
4910
|
+
fs.renameSync(temporary, destination);
|
|
4911
|
+
} finally { fs.rmSync(temporary, { force: true }); }
|
|
4912
|
+
return { action: prior ? 'upgraded' : 'created', backup };
|
|
4913
|
+
}
|
|
4914
|
+
|
|
4915
|
+
export function refreshInstalledModelLaunchers({ sourceRoot = REPO_ROOT, home = os.homedir() } = {}) {
|
|
4916
|
+
const file = path.join(home, '.cache', 'ruvnet-brain', 'model-routing', 'launcher-config.json');
|
|
4917
|
+
if (!fs.existsSync(file)) return { action: 'not-installed' };
|
|
4918
|
+
const previous = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
4919
|
+
const receipt = installNativeLaunchers({ sourceRoot, home, extensionsRoot: previous.extensionsRoot, nodeBinary: previous.nodeBinary, apply: true });
|
|
4920
|
+
return { action: receipt.config.runtimeDigest === previous.runtimeDigest ? 'unchanged' : 'updated', runtimeDigest: receipt.config.runtimeDigest };
|
|
4921
|
+
}
|
|
4922
|
+
|
|
4923
|
+
export function syncManagedRouterTools({ routerDir = path.join(os.homedir(), '.claude', 'model-router'), packageRoot = REPO_ROOT } = {}) {
|
|
4924
|
+
const destination = path.join(routerDir, 'bin');
|
|
4925
|
+
fs.mkdirSync(destination, { recursive: true });
|
|
4926
|
+
let copied = 0;
|
|
4927
|
+
for (const name of ['model-router-engine.mjs', 'model-router-setup.mjs', 'model-router-status.mjs', 'model-router-outcome.mjs', 'subscription-hosts.mjs', 'review-model-defaults.mjs', 'dual-host-deliberation.mjs', 'dual-host-suggest.mjs', 'route-cheap.mjs', 'dispatch-receipt.mjs', 'metaharness-receipts.mjs', 'metaharness-router.mjs', 'model-router-dispatch.mjs', 'model-currency.mjs', 'model-currency-evidence.mjs', 'user-model-prompt-hook.mjs', 'model-router-agent-hook.mjs', 'model-weekly-assessment.mjs', 'model-weekly-analyst.mjs', 'model-weekly-cycle.mjs', 'model-weekly-qualification.mjs', 'model-native-qualification.mjs', 'model-routing-launchers.mjs', 'model-native-catalog.mjs', 'model-analyst-sandbox.mjs', 'model-routing-policy-promotion.mjs', 'model-routing-gateway.mjs', 'native-subscription-usage.mjs', 'codex-routed.sh', 'goldie-weekly.sh']) {
|
|
4928
|
+
const source = path.join(packageRoot, 'scripts', name);
|
|
4929
|
+
if (!fs.existsSync(source)) throw new Error(`Packaged router tool missing: ${name}`);
|
|
4930
|
+
const target = path.join(destination, name);
|
|
4931
|
+
const bytes = fs.readFileSync(source);
|
|
4932
|
+
if (fs.existsSync(target) && fs.readFileSync(target).equals(bytes)) continue;
|
|
4933
|
+
const temporary = `${target}.${crypto.randomUUID()}.tmp`;
|
|
4934
|
+
try { fs.writeFileSync(temporary, bytes, { mode: name.endsWith('.sh') ? 0o755 : 0o600 }); fs.renameSync(temporary, target); }
|
|
4935
|
+
finally { fs.rmSync(temporary, { force: true }); }
|
|
4936
|
+
copied++;
|
|
4937
|
+
}
|
|
4938
|
+
// Preserve the package-relative import used by the optional legacy routing helper.
|
|
4939
|
+
const runtimeRelative = path.join('plugin', 'scripts', 'runtime-preferences.mjs');
|
|
4940
|
+
const runtimeTarget = path.join(routerDir, runtimeRelative);
|
|
4941
|
+
const runtimeBytes = fs.readFileSync(path.join(packageRoot, runtimeRelative));
|
|
4942
|
+
if (!fs.existsSync(runtimeTarget) || !fs.readFileSync(runtimeTarget).equals(runtimeBytes)) {
|
|
4943
|
+
fs.mkdirSync(path.dirname(runtimeTarget), { recursive: true });
|
|
4944
|
+
const temporary = `${runtimeTarget}.${crypto.randomUUID()}.tmp`;
|
|
4945
|
+
try { fs.writeFileSync(temporary, runtimeBytes, { mode: 0o600 }); fs.renameSync(temporary, runtimeTarget); }
|
|
4946
|
+
finally { fs.rmSync(temporary, { force: true }); }
|
|
4947
|
+
copied++;
|
|
4948
|
+
}
|
|
4949
|
+
const qualificationSource = path.join(packageRoot, 'config', 'model-router', 'qualification-contract.json');
|
|
4950
|
+
const qualificationTarget = path.join(routerDir, 'qualification-contract.json');
|
|
4951
|
+
const qualificationBytes = fs.readFileSync(qualificationSource);
|
|
4952
|
+
if (!fs.existsSync(qualificationTarget) || !fs.readFileSync(qualificationTarget).equals(qualificationBytes)) {
|
|
4953
|
+
const temporary = `${qualificationTarget}.${crypto.randomUUID()}.tmp`;
|
|
4954
|
+
try { fs.writeFileSync(temporary, qualificationBytes, { mode: 0o600 }); fs.renameSync(temporary, qualificationTarget); }
|
|
4955
|
+
finally { fs.rmSync(temporary, { force: true }); }
|
|
4956
|
+
copied++;
|
|
4957
|
+
}
|
|
4958
|
+
const launchers = routerDir === path.join(os.homedir(), '.claude', 'model-router')
|
|
4959
|
+
? refreshInstalledModelLaunchers({ sourceRoot: packageRoot }) : { action: 'custom-router-directory' };
|
|
4960
|
+
return { action: copied ? 'updated' : 'unchanged', copied, launchers };
|
|
4961
|
+
}
|
|
4962
|
+
|
|
4963
|
+
function refreshManagedRouterDefault() {
|
|
4964
|
+
try {
|
|
4965
|
+
const receipt = syncManagedRouterDefault();
|
|
4966
|
+
syncManagedRouterTools();
|
|
4967
|
+
if (receipt.action === 'created') ok('installed managed model-router default (custom overrides belong in policy.mjs)');
|
|
4968
|
+
if (receipt.action === 'upgraded') ok(`upgraded managed model-router default; prior source preserved at ${receipt.backup}`);
|
|
4969
|
+
return receipt;
|
|
4970
|
+
} catch (error) {
|
|
4971
|
+
warn(`managed model-router default was not refreshed (${error.message}); native dispatch remains fail-closed`);
|
|
4972
|
+
return { action: 'failed' };
|
|
4973
|
+
}
|
|
4974
|
+
}
|
|
4975
|
+
|
|
4852
4976
|
// ββ MetaHarness router: config materialization + THIS user's subscription profile (2026-07-12) ββ
|
|
4853
4977
|
// Stuart's mandate: subscription-awareness must be per-user. Detect what the machine can PROVE
|
|
4854
4978
|
// (Codex auth mode from ~/.codex/auth.json's SHAPE β never its secrets), ASK what it can't (Claude
|
|
4855
4979
|
// plan tiers aren't probeable from disk), and RECORD both with their basis, so the router's
|
|
4856
4980
|
// $0-floor never assumes a plan this user doesn't have (billing them) or misses one they do
|
|
4857
4981
|
// (wasting it). Config templates ship in the npm package's config/; router tools are copied to
|
|
4858
|
-
// ~/.claude/model-router/bin/ because the npx run dir vanishes after install.
|
|
4859
|
-
// user-
|
|
4982
|
+
// ~/.claude/model-router/bin/ because the npx run dir vanishes after install. Managed defaults
|
|
4983
|
+
// upgrade with a backup; custom policy.mjs, profiles and reviewed allocation overrides remain user-owned. Non-fatal like every offer.
|
|
4860
4984
|
export async function offerRouterProfile() {
|
|
4861
4985
|
if (TEST_MODE) return 'suppressed';
|
|
4862
4986
|
const routerDir = path.join(os.homedir(), '.claude', 'model-router');
|
|
4863
4987
|
const pkgRoot = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
4864
4988
|
step(
|
|
4865
|
-
'
|
|
4866
|
-
"
|
|
4989
|
+
'Model router β appropriate intelligence for each task',
|
|
4990
|
+
"native subscription routes preserve your overrides; weekly analysis checks the evidence",
|
|
4867
4991
|
);
|
|
4868
4992
|
|
|
4869
4993
|
fs.mkdirSync(path.join(routerDir, 'bin'), { recursive: true });
|
|
4870
|
-
|
|
4871
|
-
const policyDst = path.join(routerDir, 'policy.default.mjs');
|
|
4872
|
-
if (fs.existsSync(policySrc) && !fs.existsSync(policyDst)) {
|
|
4873
|
-
fs.copyFileSync(policySrc, policyDst);
|
|
4874
|
-
ok('installed policy.default.mjs (edit freely β goldie keeps prices fresh where scheduled)');
|
|
4875
|
-
}
|
|
4994
|
+
refreshManagedRouterDefault();
|
|
4876
4995
|
// ONE implementation of the managed-catalog step, shared with runUpdate() (issue #87). It used to
|
|
4877
4996
|
// live here only, which is exactly why existing users never received managed additions.
|
|
4878
4997
|
try {
|
|
@@ -4882,19 +5001,17 @@ export async function offerRouterProfile() {
|
|
|
4882
5001
|
} catch (error) {
|
|
4883
5002
|
warn(`managed model additions were not merged (${error.message}); your existing catalog was left unchanged`);
|
|
4884
5003
|
}
|
|
4885
|
-
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
//
|
|
4889
|
-
//
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4894
|
-
|
|
4895
|
-
|
|
4896
|
-
ok(`${copied} router tools at ~/.claude/model-router/bin/ (stable path β the npx dir vanishes)`);
|
|
4897
|
-
}
|
|
5004
|
+
const toolsReceipt = syncManagedRouterTools({ routerDir, packageRoot: pkgRoot });
|
|
5005
|
+
if (toolsReceipt.copied) ok(`updated ${toolsReceipt.copied} managed routing tools`);
|
|
5006
|
+
|
|
5007
|
+
// Allocation is user-owned. A shipped seed retains its real review date; installation never
|
|
5008
|
+
// certifies it fresh or overwrites a reviewed user policy.
|
|
5009
|
+
const selectionSrc = path.join(pkgRoot, 'config', 'model-router', 'routing-policy.template.json');
|
|
5010
|
+
const selectionDst = path.join(routerDir, 'routing-policy.json');
|
|
5011
|
+
if (fs.existsSync(selectionSrc) && !fs.existsSync(selectionDst)) fs.copyFileSync(selectionSrc, selectionDst);
|
|
5012
|
+
const instructionSrc = path.join(pkgRoot, 'config', 'model-router', 'weekly-analyst-instruction.md');
|
|
5013
|
+
const instructionDst = path.join(routerDir, 'weekly-analyst-instruction.md');
|
|
5014
|
+
if (fs.existsSync(instructionSrc) && !fs.existsSync(instructionDst)) fs.copyFileSync(instructionSrc, instructionDst);
|
|
4898
5015
|
|
|
4899
5016
|
const profilePath = path.join(routerDir, 'profile.json');
|
|
4900
5017
|
if (fs.existsSync(profilePath)) { ok('subscription profile already exists β routing already uses it'); return 'already'; }
|
|
@@ -1,78 +1,60 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_comment": "Model candidate catalog for model-router-engine.mjs. EDIT ME freely. Pricing is $/Mtok. 'verified' names the source+date a price was confirmed live; null pricing means UNKNOWN \u2014 the engine will NOT invent a cost for it (same honesty rule as route-cheap.mjs). 'harness' = which agent(s) can launch each model \u2014 EMPTY [] means landscape-only: known to exist, but no wired execution path yet, so the engine will never select it (see model-router-engine.mjs pool filter). Do not add a real execution path (an entry to route-cheap.mjs PRICING or a harness value) until dispatch is actually implemented and tested \u2014 an engine that 'chooses' a model it can't run is worse than one that doesn't know the model exists. 'subscription' = harness(es) under which this model is covered by a flat subscription (Claude Max, Codex/ChatGPT), so its marginal cost to the user is ~$0 \u2014 the default policy treats those as free and will NOT prefer a billed model over them (never spend where the subscription is free).",
|
|
3
|
-
"managedVersion":
|
|
4
|
-
"updated": "2026-
|
|
3
|
+
"managedVersion": 3,
|
|
4
|
+
"updated": "2026-10-04 (five native subscription launch receipts; Fable remains landscape-only)",
|
|
5
5
|
"candidates": [
|
|
6
6
|
{
|
|
7
7
|
"id": "claude-haiku-4-5-20251001",
|
|
8
8
|
"provider": "anthropic",
|
|
9
|
-
"harness": [
|
|
10
|
-
|
|
11
|
-
],
|
|
12
|
-
"subscription": [
|
|
13
|
-
"claude-code"
|
|
14
|
-
],
|
|
9
|
+
"harness": [],
|
|
10
|
+
"subscription": [],
|
|
15
11
|
"tier": "cheap",
|
|
16
12
|
"costPerMTok": null,
|
|
17
13
|
"verified": null,
|
|
18
|
-
"note": "
|
|
14
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
19
15
|
},
|
|
20
16
|
{
|
|
21
17
|
"id": "claude-sonnet-5",
|
|
22
18
|
"provider": "anthropic",
|
|
23
|
-
"harness": [
|
|
24
|
-
|
|
25
|
-
],
|
|
26
|
-
"subscription": [
|
|
27
|
-
"claude-code"
|
|
28
|
-
],
|
|
19
|
+
"harness": [],
|
|
20
|
+
"subscription": [],
|
|
29
21
|
"tier": "mid",
|
|
30
22
|
"costPerMTok": null,
|
|
31
|
-
"verified": null
|
|
23
|
+
"verified": null,
|
|
24
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
32
25
|
},
|
|
33
26
|
{
|
|
34
27
|
"id": "claude-opus-4-8",
|
|
35
28
|
"provider": "anthropic",
|
|
36
|
-
"harness": [
|
|
37
|
-
|
|
38
|
-
],
|
|
39
|
-
"subscription": [
|
|
40
|
-
"claude-code"
|
|
41
|
-
],
|
|
29
|
+
"harness": [],
|
|
30
|
+
"subscription": [],
|
|
42
31
|
"tier": "frontier",
|
|
43
32
|
"costPerMTok": {
|
|
44
33
|
"in": 5,
|
|
45
34
|
"out": 25
|
|
46
35
|
},
|
|
47
|
-
"verified": "2026-07-07 route-cheap.mjs FRONTIER (API price; $0 under Max)"
|
|
36
|
+
"verified": "2026-07-07 route-cheap.mjs FRONTIER (API price; $0 under Max)",
|
|
37
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
48
38
|
},
|
|
49
39
|
{
|
|
50
40
|
"id": "claude-opus-5",
|
|
51
41
|
"provider": "anthropic",
|
|
52
|
-
"harness": [
|
|
53
|
-
|
|
54
|
-
],
|
|
55
|
-
"subscription": [
|
|
56
|
-
"claude-code"
|
|
57
|
-
],
|
|
42
|
+
"harness": [],
|
|
43
|
+
"subscription": [],
|
|
58
44
|
"tier": "frontier",
|
|
59
45
|
"costPerMTok": null,
|
|
60
46
|
"verified": "2026-08-02 Claude Code 2.1.220 subscription launch (canonicalModel claude-opus-5)",
|
|
61
|
-
"note": "
|
|
47
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
62
48
|
},
|
|
63
49
|
{
|
|
64
50
|
"id": "claude-fable-5",
|
|
65
51
|
"provider": "anthropic",
|
|
66
|
-
"harness": [
|
|
67
|
-
|
|
68
|
-
],
|
|
69
|
-
"subscription": [
|
|
70
|
-
"claude-code"
|
|
71
|
-
],
|
|
52
|
+
"harness": [],
|
|
53
|
+
"subscription": [],
|
|
72
54
|
"tier": "frontier",
|
|
73
55
|
"costPerMTok": null,
|
|
74
56
|
"verified": "2026-07-12 Artificial Analysis leaderboard (WebSearch) \u2014 listed as top-intelligence tier alongside GPT-5.6 Sol",
|
|
75
|
-
"note": "
|
|
57
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
76
58
|
},
|
|
77
59
|
{
|
|
78
60
|
"id": "deepseek/deepseek-chat",
|
|
@@ -123,16 +105,12 @@
|
|
|
123
105
|
{
|
|
124
106
|
"id": "gpt-5.5",
|
|
125
107
|
"provider": "openai",
|
|
126
|
-
"harness": [
|
|
127
|
-
|
|
128
|
-
],
|
|
129
|
-
"subscription": [
|
|
130
|
-
"codex"
|
|
131
|
-
],
|
|
108
|
+
"harness": [],
|
|
109
|
+
"subscription": [],
|
|
132
110
|
"tier": "frontier",
|
|
133
111
|
"costPerMTok": null,
|
|
134
112
|
"verified": null,
|
|
135
|
-
"note": "
|
|
113
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
136
114
|
},
|
|
137
115
|
{
|
|
138
116
|
"id": "gpt-5.6-sol",
|
|
@@ -142,7 +120,7 @@
|
|
|
142
120
|
"tier": "frontier",
|
|
143
121
|
"costPerMTok": null,
|
|
144
122
|
"verified": null,
|
|
145
|
-
"note": "
|
|
123
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
146
124
|
},
|
|
147
125
|
{
|
|
148
126
|
"id": "gpt-5.6-terra",
|
|
@@ -152,7 +130,7 @@
|
|
|
152
130
|
"tier": "mid",
|
|
153
131
|
"costPerMTok": null,
|
|
154
132
|
"verified": null,
|
|
155
|
-
"note": "
|
|
133
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
156
134
|
},
|
|
157
135
|
{
|
|
158
136
|
"id": "gpt-5.6-luna",
|
|
@@ -162,19 +140,17 @@
|
|
|
162
140
|
"tier": "cheap",
|
|
163
141
|
"costPerMTok": null,
|
|
164
142
|
"verified": null,
|
|
165
|
-
"note": "
|
|
143
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
166
144
|
},
|
|
167
145
|
{
|
|
168
146
|
"id": "gpt-5-mini",
|
|
169
147
|
"provider": "openai",
|
|
170
|
-
"harness": [
|
|
171
|
-
"codex",
|
|
172
|
-
"claude-code"
|
|
173
|
-
],
|
|
148
|
+
"harness": [],
|
|
174
149
|
"subscription": [],
|
|
175
150
|
"tier": "mid",
|
|
176
151
|
"costPerMTok": null,
|
|
177
|
-
"verified": null
|
|
152
|
+
"verified": null,
|
|
153
|
+
"note": "Historical model retained for inventory only. No default execution eligibility in this refreshed template."
|
|
178
154
|
},
|
|
179
155
|
{
|
|
180
156
|
"id": "x-ai/grok-4.5",
|
|
@@ -230,6 +206,104 @@
|
|
|
230
206
|
},
|
|
231
207
|
"verified": "2026-07-12 OpenRouter /models live (direct API check)",
|
|
232
208
|
"note": "LANDSCAPE-ONLY: 295B MoE Apache-2.0, strong generalist, second-tier coder (SWE-bench V 78.0 vs GLM-5.2 84.2, vendor numbers). IMPORTANT: this is the PAID slug on purpose \u2014 the tencent/hy3:free promo window closes ~2026-07-20 and would silently die/bill; never wire the :free slug. See goldie/2026-07-12.md Q3."
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"id": "claude-sonnet-5-5",
|
|
212
|
+
"provider": "anthropic",
|
|
213
|
+
"harness": [
|
|
214
|
+
"claude-code"
|
|
215
|
+
],
|
|
216
|
+
"subscription": [
|
|
217
|
+
"claude-code"
|
|
218
|
+
],
|
|
219
|
+
"tier": "mid",
|
|
220
|
+
"costPerMTok": {
|
|
221
|
+
"in": 2,
|
|
222
|
+
"out": 10
|
|
223
|
+
},
|
|
224
|
+
"verified": "2026-10-04 actual native subscription launch, exact modelUsage identity and MODEL_OK receipt; official API prices",
|
|
225
|
+
"note": "Verified native Claude subscription launch on the current machine. Per-user coverage still requires the router profile; higher effort settings are recommendations, not benchmark results."
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
"id": "claude-opus-5-5",
|
|
229
|
+
"provider": "anthropic",
|
|
230
|
+
"harness": [
|
|
231
|
+
"claude-code"
|
|
232
|
+
],
|
|
233
|
+
"subscription": [
|
|
234
|
+
"claude-code"
|
|
235
|
+
],
|
|
236
|
+
"tier": "frontier",
|
|
237
|
+
"costPerMTok": {
|
|
238
|
+
"in": 4,
|
|
239
|
+
"out": 20
|
|
240
|
+
},
|
|
241
|
+
"verified": "2026-10-04 actual native subscription launch, exact modelUsage identity and MODEL_OK receipt; official API prices",
|
|
242
|
+
"note": "Verified native Claude subscription launch on the current machine. Per-user coverage still requires the router profile; higher effort settings are recommendations, not benchmark results."
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"id": "claude-fable-5-1",
|
|
246
|
+
"provider": "anthropic",
|
|
247
|
+
"harness": [],
|
|
248
|
+
"subscription": [],
|
|
249
|
+
"tier": "frontier",
|
|
250
|
+
"costPerMTok": {
|
|
251
|
+
"in": 10,
|
|
252
|
+
"out": 50
|
|
253
|
+
},
|
|
254
|
+
"verified": "2026-10-04 official provider documentation + fresh native inventory",
|
|
255
|
+
"note": "Landscape only until native launch/coverage is verified. Account catalog presence or historical observation is not a fresh execution proof."
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"id": "gpt-6.1-sol",
|
|
259
|
+
"provider": "openai",
|
|
260
|
+
"harness": [
|
|
261
|
+
"codex"
|
|
262
|
+
],
|
|
263
|
+
"subscription": [
|
|
264
|
+
"codex"
|
|
265
|
+
],
|
|
266
|
+
"tier": "mid",
|
|
267
|
+
"costPerMTok": {
|
|
268
|
+
"in": 2,
|
|
269
|
+
"out": 10
|
|
270
|
+
},
|
|
271
|
+
"verified": "2026-10-04 actual native Codex subscription launch, requested model, completed turn and MODEL_OK receipt; official API prices",
|
|
272
|
+
"note": "Verified native Codex subscription launch on current machine. Coverage remains profile-scoped; selection does not switch the parent conversation."
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"id": "gpt-6-luna",
|
|
276
|
+
"provider": "openai",
|
|
277
|
+
"harness": [
|
|
278
|
+
"codex"
|
|
279
|
+
],
|
|
280
|
+
"subscription": [
|
|
281
|
+
"codex"
|
|
282
|
+
],
|
|
283
|
+
"tier": "cheap",
|
|
284
|
+
"costPerMTok": {
|
|
285
|
+
"in": 0.1,
|
|
286
|
+
"out": 0.5
|
|
287
|
+
},
|
|
288
|
+
"verified": "2026-10-04 actual native Codex subscription launch, requested model, completed turn and MODEL_OK receipt; official API prices",
|
|
289
|
+
"note": "Verified native Codex subscription launch on current machine. Coverage remains profile-scoped; selection does not switch the parent conversation."
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"id": "gpt-6-astra",
|
|
293
|
+
"provider": "openai",
|
|
294
|
+
"harness": [
|
|
295
|
+
"codex"
|
|
296
|
+
],
|
|
297
|
+
"subscription": [
|
|
298
|
+
"codex"
|
|
299
|
+
],
|
|
300
|
+
"tier": "frontier",
|
|
301
|
+
"costPerMTok": {
|
|
302
|
+
"in": 10,
|
|
303
|
+
"out": 50
|
|
304
|
+
},
|
|
305
|
+
"verified": "2026-10-04 actual native Codex subscription launch, requested model, completed turn and MODEL_OK receipt; official API prices",
|
|
306
|
+
"note": "Verified native Codex subscription launch on current machine. Coverage remains profile-scoped; selection does not switch the parent conversation."
|
|
233
307
|
}
|
|
234
308
|
]
|
|
235
309
|
}
|