@polderlabs/bizar 10.25.2 → 10.26.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 +34 -41
- package/cli/bin.mjs +0 -43
- package/cli/commands/hook.mjs +0 -7
- package/cli/commands/setup-provider.mjs +4 -2
- package/cli/commands/tools.mjs +19 -6
- package/cli/commands/upgrade-defaults.mjs +6 -33
- package/cli/commands/util.mjs +1 -1
- package/cli/commands/validate.mjs +26 -20
- package/cli/commands/worker.mjs +30 -21
- package/cli/commands/workflow.mjs +14 -100
- package/cli/config-paths.mjs +0 -12
- package/cli/core/workflow-state.mjs +2 -5
- package/cli/doctor.mjs +33 -23
- package/cli/install/interactive-setup.mjs +5 -4
- package/cli/provision.mjs +46 -186
- package/config/agents/model-assignment.mjs +45 -97
- package/config/claude/CLAUDE.md +213 -0
- package/config/claude/agents/_shared/SKILLS.md +4 -2
- package/config/claude/agents/office-manager.md +28 -27
- package/config/claude/agents/planner.md +18 -15
- package/config/claude/commands/setup-provider.md +8 -2
- package/config/claude/hooks/README.md +14 -2
- package/config/claude/hooks/worker-suggest.mjs +1 -1
- package/config/claude/hooks/workflow-route-guard.mjs +4 -3
- package/config/claude/settings.json +12 -1
- package/config/skills/bizar/README.md +9 -0
- package/config/skills/bizar/SKILL.md +48 -0
- package/config/workflows/bizar-debug.js +17 -25
- package/config/workflows/bizar-implement.js +15 -24
- package/config/workflows/bizar-research.js +14 -24
- package/config/workflows/lib/dispatch.js +219 -998
- package/config/workflows/ultracode-research.js +14 -23
- package/config/workflows/ultracode-review.js +14 -23
- package/config/workflows/ultracode.js +15 -24
- package/package.json +1 -1
- package/packages/sdk/dist/autonomy/outcome-record.d.ts +1 -1
- package/packages/sdk/dist/autonomy/outcome-record.js +1 -1
- package/packages/sdk/dist/bench/auto-reduction.d.ts +3 -3
- package/packages/sdk/dist/bench/auto-reduction.js +3 -3
- package/packages/sdk/dist/mcp/server.js +0 -17
- package/packages/sdk/dist/release/known-good-releases.d.ts +7 -0
- package/packages/sdk/dist/release/known-good-releases.js +43 -1
- package/packages/sdk/package.json +1 -1
- package/cli/commands/model.mjs +0 -189
- package/cli/commands/models.mjs +0 -2808
- package/cli/commands/tier.mjs +0 -159
- package/config/claude/hooks/agent-model-guard.mjs +0 -304
- package/config/claude/hooks/sessionstart-model-sync.mjs +0 -312
- package/config/claude/hooks/thinking-route.mjs +0 -311
- package/packages/sdk/dist/router/agent-model-registry.d.ts +0 -323
- package/packages/sdk/dist/router/agent-model-registry.js +0 -492
- package/packages/sdk/dist/router/codemod-intent.d.ts +0 -68
- package/packages/sdk/dist/router/codemod-intent.js +0 -112
- package/packages/sdk/dist/router/dispatch-evidence.d.ts +0 -176
- package/packages/sdk/dist/router/dispatch-evidence.js +0 -505
- package/packages/sdk/dist/router/failover-mirror.mjs +0 -315
- package/packages/sdk/dist/router/failover.d.ts +0 -188
- package/packages/sdk/dist/router/failover.js +0 -255
- package/packages/sdk/dist/router/index.d.ts +0 -176
- package/packages/sdk/dist/router/index.js +0 -238
- package/packages/sdk/dist/router/model-profile.d.ts +0 -229
- package/packages/sdk/dist/router/model-profile.js +0 -199
- package/packages/sdk/dist/router/model-router.d.ts +0 -113
- package/packages/sdk/dist/router/model-router.js +0 -268
- package/packages/sdk/dist/router/outcome-learner.d.ts +0 -180
- package/packages/sdk/dist/router/outcome-learner.js +0 -506
- package/packages/sdk/dist/router/q-learning-router.d.ts +0 -83
- package/packages/sdk/dist/router/q-learning-router.js +0 -277
- package/packages/sdk/dist/router/select-dispatch-model.d.ts +0 -227
- package/packages/sdk/dist/router/select-dispatch-model.js +0 -532
package/README.md
CHANGED
|
@@ -35,21 +35,22 @@ the project you happen to be working on.
|
|
|
35
35
|
|
|
36
36
|
| You want | Bizar provides |
|
|
37
37
|
| --- | --- |
|
|
38
|
-
| A clean way to begin | A guided installer and
|
|
39
|
-
| Your own gateway models |
|
|
38
|
+
| A clean way to begin | A guided installer and a static four-alias dispatch surface |
|
|
39
|
+
| Your own gateway models | Four native aliases (`haiku`/`sonnet`/`opus`/`fable`) with OmniRoute handling ordered failover between configured full IDs |
|
|
40
40
|
| Useful parallel work | Isolated worktrees, scoped tasks, and specialist roles |
|
|
41
41
|
| Fewer surprises | Explicit safety checks for releases, publication, deployment, pushes, and destructive operations |
|
|
42
42
|
| Confidence at the end | Tests, architecture checks, E2E checks, and evidence-aware handoff |
|
|
43
43
|
|
|
44
44
|
## Start here
|
|
45
45
|
|
|
46
|
-
Install Bizar globally
|
|
47
|
-
|
|
46
|
+
Install Bizar globally and its Claude Code integration. Bizar dispatches
|
|
47
|
+
through four static native aliases — `haiku`, `sonnet`, `opus`, `fable` —
|
|
48
|
+
and OmniRoute handles ordered failover between configured full IDs for the
|
|
49
|
+
chosen alias, so there is no model picker step.
|
|
48
50
|
|
|
49
51
|
```sh
|
|
50
52
|
npm install -g @polderlabs/bizar
|
|
51
53
|
bizar install
|
|
52
|
-
bizar models
|
|
53
54
|
```
|
|
54
55
|
|
|
55
56
|
Restart Claude Code after installation. The installer adds Bizar's agents, skills, commands, hooks, settings, and the
|
|
@@ -59,19 +60,18 @@ for Bizar and OpenKan, not for the Claude Code CLI.
|
|
|
59
60
|
It preserves your configured gateway endpoint and credential values during a
|
|
60
61
|
clean reinstall.
|
|
61
62
|
|
|
62
|
-
On a new interactive install, Bizar also asks
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
63
|
+
On a new interactive install, Bizar also asks whether Claude Code agent teams
|
|
64
|
+
should be enabled, the OpenKan install directory, and whether the current
|
|
65
|
+
project should receive a `.ok/` workspace. OpenKan is installed from npm as
|
|
66
|
+
`@polderlabs/openkan@latest`; its package-owned agent and skill are
|
|
67
|
+
installed into the same Claude configuration. Use `bizar install --yes` for
|
|
68
|
+
CI or a prompt-free refresh.
|
|
68
69
|
|
|
69
70
|
For a completely fresh Bizar-managed Claude setup while retaining endpoint and
|
|
70
71
|
authentication settings:
|
|
71
72
|
|
|
72
73
|
```sh
|
|
73
74
|
bizar install --force
|
|
74
|
-
bizar models
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
Then open any repository in Claude Code and describe the outcome you want.
|
|
@@ -107,40 +107,36 @@ foregrounded.
|
|
|
107
107
|
|
|
108
108
|
## Your models, everywhere Bizar dispatches
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
the
|
|
110
|
+
Bizar dispatches through four static native aliases — `haiku`, `sonnet`,
|
|
111
|
+
`opus`, `fable`. Claude Code's native per-call `model` field accepts one of
|
|
112
|
+
these aliases. OmniRoute handles ordered failover between the configured full
|
|
113
|
+
gateway IDs for the chosen alias, so the operator never picks a picker-style
|
|
114
|
+
gateway ID per agent at this layer. There is no `bizar models` picker, no
|
|
115
|
+
`model-router.json`, no `userSelected` block, and no Agent-model-guard hook.
|
|
113
116
|
|
|
114
|
-
|
|
115
|
-
~/.claude/model-router.json
|
|
116
|
-
```
|
|
117
|
+
The four aliases are the entire dispatch surface:
|
|
117
118
|
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
- `haiku` — trivial / cheap micro-edits
|
|
120
|
+
- `sonnet` — ordinary implementation, research, planning lanes
|
|
121
|
+
- `opus` — hard / architectural / adversarial / debug / high-risk review lanes
|
|
122
|
+
- `fable` — explicit Anthropic OpenAI-compat surfaces
|
|
123
|
+
|
|
124
|
+
Workflow scripts (`config/workflows/*.js`) inline a tiny `dispatchAgent`
|
|
125
|
+
wrapper that picks the alias from a static policy; agent definitions stay
|
|
126
|
+
model-agnostic so the harness, not the agent, owns alias selection.
|
|
120
127
|
|
|
121
128
|
```mermaid
|
|
122
129
|
flowchart TD
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
Definitions --> Team["Agent-team teammates"]
|
|
130
|
+
Policy["Static alias policy\n(office-manager.md + workflow routeModel)"] --> Aliases["haiku · sonnet · opus · fable"]
|
|
131
|
+
Aliases --> OmniRoute["OmniRoute ordered failover\nper configured full ID"]
|
|
132
|
+
OmniRoute --> Agent["Subagents"]
|
|
133
|
+
OmniRoute --> Workflow["Workflow workers"]
|
|
134
|
+
OmniRoute --> Team["Agent-team teammates"]
|
|
129
135
|
```
|
|
130
136
|
|
|
131
|
-
Claude Code's native per-call model field has a small alias vocabulary. Bizar
|
|
132
|
-
avoids making that vocabulary a limitation: it projects each selected gateway
|
|
133
|
-
model into a global subagent definition whose frontmatter contains the full
|
|
134
|
-
model ID. The agent, workflow, and team routes use that definition. The four
|
|
135
|
-
native aliases are compatibility shortcuts only; they do not enable an
|
|
136
|
-
unselected provider or reduce your selected-model pool to four choices.
|
|
137
|
-
|
|
138
137
|
Useful inspection commands:
|
|
139
138
|
|
|
140
139
|
```sh
|
|
141
|
-
bizar models --list
|
|
142
|
-
bizar models --agent-types --json
|
|
143
|
-
bizar models explain todd
|
|
144
140
|
bizar doctor
|
|
145
141
|
```
|
|
146
142
|
|
|
@@ -153,9 +149,7 @@ also ships 80 skills for planning, debugging, verification, review,
|
|
|
153
149
|
worktrees, and implementation practice.
|
|
154
150
|
|
|
155
151
|
The coordinator selects specialists when their expertise reduces a concrete
|
|
156
|
-
risk. It does not create parallel workers merely to look busy.
|
|
157
|
-
the installed specialist definition names through `bizar models --agent-types
|
|
158
|
-
--json` and use a relevant Bizar specialist directly when needed.
|
|
152
|
+
risk. It does not create parallel workers merely to look busy.
|
|
159
153
|
|
|
160
154
|
```text
|
|
161
155
|
Core coordination Specialist coverage
|
|
@@ -195,7 +189,7 @@ point where an external or difficult-to-reverse decision belongs to you.
|
|
|
195
189
|
├── rules/ focused guidance for common development work
|
|
196
190
|
├── workflows/ native workflow definitions
|
|
197
191
|
├── settings.json Bizar-managed Claude Code integration
|
|
198
|
-
└──
|
|
192
|
+
└── agents/ Bizar agent definitions (alias-agnostic)
|
|
199
193
|
|
|
200
194
|
~/.config/bizar/
|
|
201
195
|
├── installed.json install record
|
|
@@ -217,7 +211,6 @@ plane, background daemon, or general-purpose note vault.
|
|
|
217
211
|
| `bizar install` | Install or refresh Bizar, OpenKan, and the global Claude configuration |
|
|
218
212
|
| `bizar openkan install` | Refresh the managed `@polderlabs/openkan` npm runtime and its agent/skill |
|
|
219
213
|
| `bizar openkan init` | Initialise `.ok/` planning state in the current project |
|
|
220
|
-
| `bizar models` | Discover and select the models Bizar may dispatch |
|
|
221
214
|
| `bizar doctor` | Diagnose the global installation and provider connectivity |
|
|
222
215
|
| `bizar validate` | Run an install-focused health check |
|
|
223
216
|
| `ok task` | Inspect or coordinate scoped worktree tasks (OpenKan-native) |
|
package/cli/bin.mjs
CHANGED
|
@@ -108,7 +108,6 @@ function showHelp() {
|
|
|
108
108
|
artifact Toggle global browser completion artifacts
|
|
109
109
|
learn Manage bounded global preferences and project lessons
|
|
110
110
|
tools Inventory installed agents, skills, hooks, commands, and MCP tools
|
|
111
|
-
tier Explain the explicit configured model tier for a task
|
|
112
111
|
upgrade-defaults Reapply safe Bizar-owned Claude defaults
|
|
113
112
|
backup Create / list / verify / delete backups of BizarHarness state
|
|
114
113
|
restore Restore BizarHarness from a backup
|
|
@@ -136,12 +135,10 @@ function showHelp() {
|
|
|
136
135
|
hook <name> Run a portable Claude Code hook
|
|
137
136
|
worktree-merge <branch> Merge a feature branch with archive tag (no work lost)
|
|
138
137
|
worker <subcommand> Run an exact-model Claude process worker in a worktree
|
|
139
|
-
models Configure the global model picker and Models.dev metadata
|
|
140
138
|
evidence <subcommand> Inspect model-routing evidence
|
|
141
139
|
improve <subcommand> Propose and verify bounded self-edits
|
|
142
140
|
sandbox <subcommand> Manage local execution sandboxes
|
|
143
141
|
explain-run <id> Explain a recorded run
|
|
144
|
-
model Deprecated alias for models
|
|
145
142
|
|
|
146
143
|
Examples:
|
|
147
144
|
bizar install
|
|
@@ -452,22 +449,6 @@ async function main() {
|
|
|
452
449
|
break;
|
|
453
450
|
}
|
|
454
451
|
|
|
455
|
-
case 'models': {
|
|
456
|
-
const mod = await importCommand('models');
|
|
457
|
-
if (!mod) {
|
|
458
|
-
console.error(chalk.red(` ✗ Could not load models command module`));
|
|
459
|
-
process.exit(EXIT_ERROR);
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
dbg('loaded command module:', 'models');
|
|
463
|
-
const found = await mod.run(cmd, cmdArgs, isHelpRequest);
|
|
464
|
-
if (found === false) {
|
|
465
|
-
console.error(chalk.red(` ✗ Usage: bizar models [--list|--set|--clear|--json] — run 'bizar models --help'`));
|
|
466
|
-
process.exit(EXIT_USAGE);
|
|
467
|
-
}
|
|
468
|
-
break;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
452
|
case 'artifact': {
|
|
472
453
|
const mod = await importCommand('artifact');
|
|
473
454
|
if (!mod) { process.exit(EXIT_ERROR); return; }
|
|
@@ -483,7 +464,6 @@ async function main() {
|
|
|
483
464
|
}
|
|
484
465
|
|
|
485
466
|
case 'tools':
|
|
486
|
-
case 'tier':
|
|
487
467
|
case 'upgrade-defaults': {
|
|
488
468
|
const mod = await importCommand(cmd);
|
|
489
469
|
if (!mod) { process.exit(EXIT_ERROR); return; }
|
|
@@ -615,29 +595,6 @@ async function main() {
|
|
|
615
595
|
break;
|
|
616
596
|
}
|
|
617
597
|
|
|
618
|
-
case 'model': {
|
|
619
|
-
// Deprecated alias. Routes to the original `model.mjs` so the
|
|
620
|
-
// legacy JSON shape (`{ providers: { ... }, total: N }`) and table
|
|
621
|
-
// output keep working for existing scripts and tests. New code
|
|
622
|
-
// should use `bizar models` (see `case 'models'`).
|
|
623
|
-
const mod = await importCommand('model');
|
|
624
|
-
if (!mod) {
|
|
625
|
-
console.error(chalk.red(` ✗ Could not load model command module`));
|
|
626
|
-
process.exit(EXIT_ERROR);
|
|
627
|
-
return;
|
|
628
|
-
}
|
|
629
|
-
dbg('loaded command module (deprecated alias):', 'model');
|
|
630
|
-
if (!isHelpRequest) {
|
|
631
|
-
console.error(chalk.yellow(' ! `bizar model` is deprecated; use `bizar models` for the new picker surface.'));
|
|
632
|
-
}
|
|
633
|
-
const found = await mod.run(cmd, cmdArgs, isHelpRequest);
|
|
634
|
-
if (found === false) {
|
|
635
|
-
console.error(chalk.red(` ✗ Usage: bizar model <subcommand> — run 'bizar model --help'`));
|
|
636
|
-
process.exit(EXIT_USAGE);
|
|
637
|
-
}
|
|
638
|
-
break;
|
|
639
|
-
}
|
|
640
|
-
|
|
641
598
|
case 'workflow': {
|
|
642
599
|
const mod = await importCommand('workflow');
|
|
643
600
|
if (!mod) {
|
package/cli/commands/hook.mjs
CHANGED
|
@@ -18,14 +18,12 @@ const HOOK_ROOT = resolve(PACKAGE_ROOT, 'config', 'claude', 'hooks');
|
|
|
18
18
|
const PRETOOL_SAFETY_LEAVES = new Set([
|
|
19
19
|
'pretooluse-editwrite', 'path-ownership-guard',
|
|
20
20
|
'pretooluse-bash', 'git-workflow-guard',
|
|
21
|
-
'agent-model-guard',
|
|
22
21
|
'workflow-route-guard',
|
|
23
22
|
]);
|
|
24
23
|
|
|
25
24
|
export const HOOK_PROGRAMS = Object.freeze({
|
|
26
25
|
'advisor-context': 'advisor-context.mjs',
|
|
27
26
|
'agent-grounding': 'agent-grounding.mjs',
|
|
28
|
-
'agent-model-guard': 'agent-model-guard.mjs',
|
|
29
27
|
'content-style-guard': 'content-style-guard.mjs',
|
|
30
28
|
'completion-artifact': 'completion-artifact.mjs',
|
|
31
29
|
'control-inbox': 'control-inbox.mjs',
|
|
@@ -40,11 +38,9 @@ export const HOOK_PROGRAMS = Object.freeze({
|
|
|
40
38
|
'pretooluse-bash': 'pretooluse-bash.mjs',
|
|
41
39
|
'pretooluse-editwrite': 'pretooluse-editwrite.mjs',
|
|
42
40
|
'sessionend-recall': 'sessionend-recall.mjs',
|
|
43
|
-
'sessionstart-model-sync': 'sessionstart-model-sync.mjs',
|
|
44
41
|
'sessionstart-prime': 'sessionstart-prime.mjs',
|
|
45
42
|
'simplify-guard': 'simplify-guard.mjs',
|
|
46
43
|
telemetry: 'telemetry.mjs',
|
|
47
|
-
'thinking-route': 'thinking-route.mjs',
|
|
48
44
|
'team-lifecycle': 'team-lifecycle.mjs',
|
|
49
45
|
'verify-deliverables': 'verify-deliverables.mjs',
|
|
50
46
|
'worker-suggest': 'worker-suggest.mjs',
|
|
@@ -59,12 +55,10 @@ export const EVENT_CHAINS = Object.freeze({
|
|
|
59
55
|
'keyword-router',
|
|
60
56
|
'workflow-route-guard',
|
|
61
57
|
'worker-suggest',
|
|
62
|
-
'thinking-route',
|
|
63
58
|
'telemetry',
|
|
64
59
|
]),
|
|
65
60
|
'session-start': Object.freeze([
|
|
66
61
|
'control-inbox',
|
|
67
|
-
'sessionstart-model-sync',
|
|
68
62
|
'sessionstart-prime',
|
|
69
63
|
'persistent-mode',
|
|
70
64
|
'telemetry',
|
|
@@ -238,7 +232,6 @@ export function selectEventChain(eventKey, input = '') {
|
|
|
238
232
|
if (toolName === 'Bash') {
|
|
239
233
|
return ['workflow-route-guard', 'pretooluse-bash', 'git-workflow-guard'];
|
|
240
234
|
}
|
|
241
|
-
if (toolName === 'Agent') return ['workflow-route-guard', 'agent-model-guard'];
|
|
242
235
|
return [];
|
|
243
236
|
}
|
|
244
237
|
|
|
@@ -43,7 +43,9 @@ export function updateProviderSettings(current, options) {
|
|
|
43
43
|
const next = { ...current, env: { ...(current.env || {}) } };
|
|
44
44
|
if (options.gateway !== undefined) {
|
|
45
45
|
next.env.ANTHROPIC_BASE_URL = options.gateway;
|
|
46
|
-
|
|
46
|
+
// Legacy compatibility: drop any pre-existing router-URL mirror so the
|
|
47
|
+
// install surface converges on a single provider URL.
|
|
48
|
+
delete next.env.BIZAR_MODEL_ROUTER_URL;
|
|
47
49
|
}
|
|
48
50
|
if (options.key !== undefined) next.env.ANTHROPIC_AUTH_TOKEN = options.key;
|
|
49
51
|
if (options.model !== undefined) next.env.ANTHROPIC_MODEL = options.model;
|
|
@@ -87,7 +89,7 @@ export async function runSetupProvider(args = []) {
|
|
|
87
89
|
|
|
88
90
|
if (options.list) {
|
|
89
91
|
console.log(` Settings: ${path}`);
|
|
90
|
-
console.log(` Gateway: ${current.env?.ANTHROPIC_BASE_URL ||
|
|
92
|
+
console.log(` Gateway: ${current.env?.ANTHROPIC_BASE_URL || '(Anthropic default)'}`);
|
|
91
93
|
console.log(` Model: ${current.env?.ANTHROPIC_MODEL || '(Claude Code default)'}`);
|
|
92
94
|
console.log(` API key: ${redact(current.env?.ANTHROPIC_AUTH_TOKEN || current.env?.ANTHROPIC_API_KEY)}`);
|
|
93
95
|
return { ok: true, path, settings: current };
|
package/cli/commands/tools.mjs
CHANGED
|
@@ -15,7 +15,7 @@ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
|
15
15
|
import { join, resolve } from 'node:path';
|
|
16
16
|
import { fileURLToPath } from 'node:url';
|
|
17
17
|
|
|
18
|
-
import { resolveClaudeConfigDir
|
|
18
|
+
import { resolveClaudeConfigDir } from '../config-paths.mjs';
|
|
19
19
|
const __filename = fileURLToPath(import.meta.url);
|
|
20
20
|
const __dirname = resolve(__filename, '..', '..');
|
|
21
21
|
const CLAUDE_DIR = resolveClaudeConfigDir();
|
|
@@ -80,8 +80,6 @@ export async function runTools(cmdArgs) {
|
|
|
80
80
|
|
|
81
81
|
const settingsPath = join(CLAUDE_DIR, 'settings.json');
|
|
82
82
|
const hasSettings = existsSync(settingsPath);
|
|
83
|
-
const modelRouterPath = resolveGlobalModelRouter();
|
|
84
|
-
const hasModelRouter = existsSync(modelRouterPath);
|
|
85
83
|
|
|
86
84
|
const summary = {
|
|
87
85
|
userLevel: CLAUDE_DIR,
|
|
@@ -92,7 +90,6 @@ export async function runTools(cmdArgs) {
|
|
|
92
90
|
wiredCommands,
|
|
93
91
|
mcpTools,
|
|
94
92
|
settings: { path: settingsPath, present: hasSettings },
|
|
95
|
-
modelRouter: { path: modelRouterPath, present: hasModelRouter },
|
|
96
93
|
};
|
|
97
94
|
|
|
98
95
|
if (asJson) {
|
|
@@ -118,8 +115,24 @@ export async function runTools(cmdArgs) {
|
|
|
118
115
|
section(`wired bizar commands (${wiredCommands.length})`, wiredCommands.map((c) => 'bizar ' + c));
|
|
119
116
|
console.log(chalk.bold('\n settings'));
|
|
120
117
|
console.log(` ${hasSettings ? '✓' : '✗'} ${settingsPath}`);
|
|
121
|
-
|
|
122
|
-
|
|
118
|
+
if (hasSettings) {
|
|
119
|
+
try {
|
|
120
|
+
const parsed = JSON.parse(readFileSync(settingsPath, 'utf8'));
|
|
121
|
+
const env = (parsed && parsed.env) || {};
|
|
122
|
+
const aliases = {
|
|
123
|
+
sonnet: env.ANTHROPIC_DEFAULT_SONNET_MODEL,
|
|
124
|
+
haiku: env.ANTHROPIC_DEFAULT_HAIKU_MODEL,
|
|
125
|
+
opus: env.ANTHROPIC_DEFAULT_OPUS_MODEL,
|
|
126
|
+
fable: env.ANTHROPIC_DEFAULT_FABLE_MODEL,
|
|
127
|
+
};
|
|
128
|
+
console.log(chalk.bold(' alias map'));
|
|
129
|
+
for (const [key, value] of Object.entries(aliases)) {
|
|
130
|
+
console.log(` ${key.padEnd(8)} → ${value || '(unset)'}`);
|
|
131
|
+
}
|
|
132
|
+
const model = parsed?.model;
|
|
133
|
+
if (model) console.log(chalk.dim(` default model: ${model}`));
|
|
134
|
+
} catch { /* ignore malformed settings */ }
|
|
135
|
+
}
|
|
123
136
|
}
|
|
124
137
|
|
|
125
138
|
export async function run(name, args, isHelpRequest) {
|
|
@@ -35,42 +35,18 @@
|
|
|
35
35
|
import chalk from 'chalk';
|
|
36
36
|
import { existsSync, readFileSync, writeFileSync, copyFileSync } from 'node:fs';
|
|
37
37
|
import { join } from 'node:path';
|
|
38
|
-
import { resolveClaudeConfigDir
|
|
39
|
-
import { configuredFallbackModels } from './models.mjs';
|
|
38
|
+
import { resolveClaudeConfigDir } from '../config-paths.mjs';
|
|
40
39
|
|
|
41
40
|
const CLAUDE_DIR = resolveClaudeConfigDir();
|
|
42
41
|
const SETTINGS_PATH = join(CLAUDE_DIR, 'settings.json');
|
|
43
|
-
// 10.22.0 / Phase 4 spirit-of-constraint: the install model id comes
|
|
44
|
-
// from the operator's `userSelected.models[0]`, not a hardcoded literal.
|
|
45
|
-
// The Bizar global router is the sole model-policy source.
|
|
46
|
-
const BIZAR_ROUTER_PATH = resolveGlobalModelRouter();
|
|
47
|
-
|
|
48
|
-
function readConfiguredModels() {
|
|
49
|
-
for (const path of [BIZAR_ROUTER_PATH]) {
|
|
50
|
-
if (!existsSync(path)) continue;
|
|
51
|
-
try {
|
|
52
|
-
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
53
|
-
const list = Array.isArray(parsed?.userSelected?.models)
|
|
54
|
-
? parsed.userSelected.models.filter((id) => typeof id === 'string' && id.trim())
|
|
55
|
-
: [];
|
|
56
|
-
if (list.length > 0) return list;
|
|
57
|
-
const fallback = configuredFallbackModels(parsed);
|
|
58
|
-
if (fallback.length > 0) return fallback;
|
|
59
|
-
// An explicit empty selection is an intentional global policy.
|
|
60
|
-
if (path === BIZAR_ROUTER_PATH && parsed && typeof parsed === 'object'
|
|
61
|
-
&& Array.isArray(parsed.userSelected?.models)) {
|
|
62
|
-
return [];
|
|
63
|
-
}
|
|
64
|
-
} catch { /* keep falling through */ }
|
|
65
|
-
}
|
|
66
|
-
return [];
|
|
67
|
-
}
|
|
68
42
|
|
|
69
43
|
const STATIC_FAVORED = {
|
|
70
44
|
permissions: { defaultMode: 'bypassPermissions' },
|
|
71
45
|
worktree: { bgIsolation: 'worktree' },
|
|
72
|
-
// `model` is intentionally absent —
|
|
73
|
-
//
|
|
46
|
+
// `model` is intentionally absent — settings.json ships the alias
|
|
47
|
+
// binding (model + modelOverrides + the four ANTHROPIC_DEFAULT_*_MODEL
|
|
48
|
+
// env vars) as the canonical source. `upgrade-defaults` only re-applies
|
|
49
|
+
// the safe Bizar-owned UX defaults, not model policy.
|
|
74
50
|
alwaysThinkingEnabled: true,
|
|
75
51
|
effortLevel: 'high',
|
|
76
52
|
skipDangerousModePermissionPrompt: true,
|
|
@@ -79,10 +55,7 @@ const STATIC_FAVORED = {
|
|
|
79
55
|
};
|
|
80
56
|
|
|
81
57
|
function buildFavored() {
|
|
82
|
-
|
|
83
|
-
const picks = readConfiguredModels();
|
|
84
|
-
if (picks[0]) out.model = picks[0];
|
|
85
|
-
return out;
|
|
58
|
+
return { ...STATIC_FAVORED };
|
|
86
59
|
}
|
|
87
60
|
|
|
88
61
|
export async function run(name, args, isHelpRequest) {
|
package/cli/commands/util.mjs
CHANGED
|
@@ -82,7 +82,7 @@ export function showDoctorHelp() {
|
|
|
82
82
|
• hook wiring
|
|
83
83
|
• installed agents and skills
|
|
84
84
|
• required local tools
|
|
85
|
-
•
|
|
85
|
+
• alias map (ANTHROPIC_DEFAULT_*_MODEL)
|
|
86
86
|
|
|
87
87
|
Prints ✓/✗ for each check and a final summary. Exits non-zero
|
|
88
88
|
if any check fails. Use \`bizar doctor\` after installation or
|
|
@@ -26,8 +26,7 @@ import chalk from 'chalk';
|
|
|
26
26
|
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
27
27
|
import { join } from 'node:path';
|
|
28
28
|
import { spawnSync } from 'node:child_process';
|
|
29
|
-
import { resolveBizarHome, resolveClaudeConfigDir
|
|
30
|
-
import { configuredEnabledModels, listModels, resolveEndpoint } from './models.mjs';
|
|
29
|
+
import { resolveBizarHome, resolveClaudeConfigDir } from '../config-paths.mjs';
|
|
31
30
|
|
|
32
31
|
function claudeDir() { return resolveClaudeConfigDir(); }
|
|
33
32
|
function bizarHome() { return resolveBizarHome(); }
|
|
@@ -54,9 +53,13 @@ export const REQUIRED_COMMANDS = [
|
|
|
54
53
|
];
|
|
55
54
|
|
|
56
55
|
// v6.3.0 — Claude Code hook adapter scripts (executable, .mjs extension).
|
|
56
|
+
// OmniRoute alias-routing overhaul (10.25.x): `agent-model-guard.mjs` and
|
|
57
|
+
// `sessionstart-model-sync.mjs` are removed from active registration AND
|
|
58
|
+
// from required-hook validation. Settings.json's model + modelOverrides
|
|
59
|
+
// is the sole alias binding; native Claude Code validates the alias/model
|
|
60
|
+
// setting on its own.
|
|
57
61
|
export const REQUIRED_HOOKS = [
|
|
58
62
|
'agent-grounding.mjs',
|
|
59
|
-
'agent-model-guard.mjs',
|
|
60
63
|
'advisor-context.mjs',
|
|
61
64
|
'bizar-hook-wrapper.sh',
|
|
62
65
|
'completion-artifact.mjs',
|
|
@@ -73,12 +76,10 @@ export const REQUIRED_HOOKS = [
|
|
|
73
76
|
'pretooluse-bash.mjs',
|
|
74
77
|
'pretooluse-editwrite.mjs',
|
|
75
78
|
'sessionend-recall.mjs',
|
|
76
|
-
'sessionstart-model-sync.mjs',
|
|
77
79
|
'sessionstart-prime.mjs',
|
|
78
80
|
'simplify-guard.mjs',
|
|
79
81
|
'team-lifecycle.mjs',
|
|
80
82
|
'telemetry.mjs',
|
|
81
|
-
'thinking-route.mjs',
|
|
82
83
|
'verify-deliverables.mjs',
|
|
83
84
|
'worker-suggest.mjs',
|
|
84
85
|
'workflow-route-guard.mjs',
|
|
@@ -350,22 +351,27 @@ const CHECKS = {
|
|
|
350
351
|
},
|
|
351
352
|
|
|
352
353
|
'provider-reachable': async () => {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
354
|
+
// The picker/router is gone. Provider reachability is the operator's
|
|
355
|
+
// concern — Claude Code (or any HTTP client) probes its own gateway.
|
|
356
|
+
// We only confirm an operator-configured gateway URL is present and
|
|
357
|
+
// that the four alias env vars map to the four OmniRoute combos.
|
|
358
|
+
const path = settingsJsonPath();
|
|
359
|
+
const settings = readJsonSafe(path);
|
|
360
|
+
const env = (settings && typeof settings === 'object' && settings.env) || {};
|
|
361
|
+
const aliasMap = {
|
|
362
|
+
sonnet: env.ANTHROPIC_DEFAULT_SONNET_MODEL,
|
|
363
|
+
haiku: env.ANTHROPIC_DEFAULT_HAIKU_MODEL,
|
|
364
|
+
opus: env.ANTHROPIC_DEFAULT_OPUS_MODEL,
|
|
365
|
+
fable: env.ANTHROPIC_DEFAULT_FABLE_MODEL,
|
|
366
|
+
};
|
|
367
|
+
const missing = Object.entries(aliasMap).filter(([, v]) => typeof v !== 'string' || !v.trim()).map(([k]) => k);
|
|
368
|
+
if (missing.length > 0) {
|
|
369
|
+
throw new Error(`alias env map missing entries in ${path}: ${missing.join(', ')}`);
|
|
368
370
|
}
|
|
371
|
+
const endpoint = env.ANTHROPIC_BASE_URL;
|
|
372
|
+
return endpoint
|
|
373
|
+
? `provider gateway configured at ${endpoint}; aliases: sonnet→${aliasMap.sonnet}, haiku→${aliasMap.haiku}, opus→${aliasMap.opus}, fable→${aliasMap.fable}`
|
|
374
|
+
: `no gateway URL configured; default provider is Anthropic; aliases: sonnet→${aliasMap.sonnet}, haiku→${aliasMap.haiku}, opus→${aliasMap.opus}, fable→${aliasMap.fable}`;
|
|
369
375
|
},
|
|
370
376
|
|
|
371
377
|
'claude-md-mirrored': async () => {
|
package/cli/commands/worker.mjs
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Process workers spawned with a native Claude alias.
|
|
3
3
|
*
|
|
4
4
|
* This command is the separately launched alternative: it creates an isolated
|
|
5
|
-
* worktree and starts a top-level Claude process with
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* worktree and starts a top-level Claude process with a native alias
|
|
6
|
+
* (default `sonnet`). No global settings are rewritten per worker, so
|
|
7
|
+
* parallel workers cannot race each other's model selection. The alias is
|
|
8
|
+
* passed through to `claude --model <alias>`; native Claude Code is the
|
|
9
|
+
* sole authority on alias-to-combo resolution.
|
|
8
10
|
*/
|
|
9
11
|
import { spawn, spawnSync } from 'node:child_process';
|
|
10
12
|
import { createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
|
|
11
13
|
import { basename, dirname, join } from 'node:path';
|
|
12
14
|
import { randomUUID } from 'node:crypto';
|
|
13
|
-
import { resolveBizarHome, resolveClaudeConfigDir
|
|
15
|
+
import { resolveBizarHome, resolveClaudeConfigDir } from '../config-paths.mjs';
|
|
16
|
+
|
|
17
|
+
const NATIVE_ALIASES = Object.freeze(new Set(['sonnet', 'haiku', 'opus', 'fable']));
|
|
18
|
+
const DEFAULT_ALIAS = 'sonnet';
|
|
14
19
|
|
|
15
20
|
function runGit(args, cwd) {
|
|
16
21
|
const result = spawnSync('git', args, { cwd, encoding: 'utf8' });
|
|
@@ -18,14 +23,18 @@ function runGit(args, cwd) {
|
|
|
18
23
|
return result.stdout.trim();
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
function
|
|
22
|
-
const
|
|
23
|
-
|
|
26
|
+
function normalizeAlias(value) {
|
|
27
|
+
const alias = typeof value === 'string' && value.trim() ? value.trim().toLowerCase() : DEFAULT_ALIAS;
|
|
28
|
+
if (!NATIVE_ALIASES.has(alias)) {
|
|
29
|
+
throw new Error(`worker start requires a native alias (sonnet | haiku | opus | fable); got "${alias}"`);
|
|
30
|
+
}
|
|
31
|
+
return alias;
|
|
24
32
|
}
|
|
25
33
|
|
|
26
|
-
export function enabledModels(
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
export function enabledModels() {
|
|
35
|
+
// Retained for backwards compatibility with `cli/commands/worker.test.mjs`.
|
|
36
|
+
// The picker is gone; native aliases are the only legal `model` values.
|
|
37
|
+
return [...NATIVE_ALIASES];
|
|
29
38
|
}
|
|
30
39
|
|
|
31
40
|
function workerRoot() { return join(resolveBizarHome(), 'workers'); }
|
|
@@ -36,23 +45,21 @@ function writeState(state) {
|
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
export function buildWorkerPlan({ repoRoot = process.cwd(), model, task, agent = 'todd' } = {}) {
|
|
39
|
-
if (!model || typeof model !== 'string') throw new Error('worker start requires --model <selected gateway model id>.');
|
|
40
48
|
if (!task || typeof task !== 'string') throw new Error('worker start requires --task <bounded task>.');
|
|
41
|
-
const
|
|
42
|
-
if (!enabledModels(router).includes(model)) throw new Error(`Model ${model} is not an enabled global bizar models selection.`);
|
|
49
|
+
const normalized = normalizeAlias(model);
|
|
43
50
|
const root = runGit(['rev-parse', '--show-toplevel'], repoRoot);
|
|
44
51
|
const id = `worker-${randomUUID().slice(0, 8)}`;
|
|
45
52
|
const branch = `wt/${id}`;
|
|
46
53
|
const worktree = join(dirname(root), `${basename(root)}-${id}`);
|
|
47
54
|
const logPath = join(workerRoot(), `${id}.log`);
|
|
48
|
-
return { id, root, branch, worktree, model, task: task.trim(), agent, logPath };
|
|
55
|
+
return { id, root, branch, worktree, model: normalized, task: task.trim(), agent, logPath };
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
export function workerClaudeArgs(plan) {
|
|
52
59
|
return [
|
|
53
60
|
'--print', '--name', `bizar-${plan.id}`, '--model', plan.model,
|
|
54
61
|
'--permission-mode', 'acceptEdits', '--agent', plan.agent,
|
|
55
|
-
`${plan.task}\n\nYou are an
|
|
62
|
+
`${plan.task}\n\nYou are an isolated Bizar process worker in ${plan.worktree}, running with the native "${plan.model}" alias. Work only in this worktree. Do not spawn subagents. Implement and test the bounded task, commit one logical change locally, never push, then report the commit and verification.`,
|
|
56
63
|
];
|
|
57
64
|
}
|
|
58
65
|
|
|
@@ -75,12 +82,14 @@ function listWorkers() {
|
|
|
75
82
|
|
|
76
83
|
function usage() {
|
|
77
84
|
console.log(`
|
|
78
|
-
bizar worker start --model <
|
|
85
|
+
bizar worker start --model <sonnet|haiku|opus|fable> --task <task> [--agent todd] [--background]
|
|
79
86
|
bizar worker list [--json]
|
|
80
87
|
|
|
81
|
-
Starts an isolated top-level Claude Code process in a wt/ worktree with
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
Starts an isolated top-level Claude Code process in a wt/ worktree with a
|
|
89
|
+
native alias. Default alias is "sonnet". Native Claude Code maps the
|
|
90
|
+
alias to an OmniRoute combo via the four ANTHROPIC_DEFAULT_*_MODEL
|
|
91
|
+
env vars in config/claude/settings.json. Merge completed branches with
|
|
92
|
+
bizar worktree-merge <branch>.
|
|
84
93
|
`);
|
|
85
94
|
}
|
|
86
95
|
|
|
@@ -108,7 +117,7 @@ export async function run(name, args, isHelpRequest) {
|
|
|
108
117
|
});
|
|
109
118
|
child.once('error', (error) => {
|
|
110
119
|
writeState({ ...state, status: 'failed', exitedAt: new Date().toISOString(), error: error.message });
|
|
111
|
-
console.error(`Unable to start
|
|
120
|
+
console.error(`Unable to start isolated worker: ${error.message}`);
|
|
112
121
|
});
|
|
113
122
|
state.pid = child.pid || null;
|
|
114
123
|
writeState(state);
|