create-byan-agent 2.45.0 → 2.47.1
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/CHANGELOG.md +86 -0
- package/install/templates/.claude/CLAUDE.md +12 -2
- package/install/templates/.claude/hooks/agent-gate-check.js +53 -0
- package/install/templates/.claude/hooks/inject-voice-anchor.js +15 -1
- package/install/templates/.claude/hooks/lib/agent-gate.js +127 -0
- package/install/templates/.claude/rules/agent-entry-gate.md +83 -0
- package/install/templates/.claude/settings.json +4 -0
- package/install/templates/.claude/skills/byan-byan/SKILL.md +14 -0
- package/install/templates/.claude/workflows/intelligent-dispatch.js +68 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/agent-matcher.js +167 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/codex-bridge.js +176 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/dispatch-blackboard.js +114 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/dispatch-orchestrator.js +116 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/dispatch-router.js +149 -0
- package/install/templates/_byan/mcp/byan-mcp-server/skill-bundles-manifest.json +1 -1
- package/install/templates/dist/skill-bundles/byan-byan.zip +0 -0
- package/install/templates/docs/intelligent-dispatch.md +84 -0
- package/package.json +1 -1
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// F1 — the dispatch BRAIN. Single source of truth for the intelligent dispatch:
|
|
2
|
+
// given a task's NATURE and COMPLEXITY, decide which RUNTIME runs it (Codex or
|
|
3
|
+
// Claude), which MODEL, and (Codex only) which reasoning EFFORT.
|
|
4
|
+
//
|
|
5
|
+
// It composes with, does not duplicate, native-tiers.js: the Claude-side model
|
|
6
|
+
// tier is delegated to that module's TIER_MODEL vocabulary (which, by design,
|
|
7
|
+
// only ever yields haiku / sonnet / null — so Fable can never leak in from the
|
|
8
|
+
// Claude side either). This module adds the two NEW axes the intelligent dispatch
|
|
9
|
+
// needs — runtime selection and Codex reasoning effort — on top of it.
|
|
10
|
+
//
|
|
11
|
+
// Routing table is the cross-checked result (5 independent sources, see
|
|
12
|
+
// docs / CHANGELOG): Codex wins autonomous execution, shell/CI/DevOps, deploy,
|
|
13
|
+
// browser/computer use ; Claude wins architecture, refactor-at-repo-scale,
|
|
14
|
+
// quality, planning, and ALL verification. Two hard red lines are enforced here,
|
|
15
|
+
// not left to the caller:
|
|
16
|
+
// 1. Fable is NEVER emitted (long-term product decision).
|
|
17
|
+
// 2. Verification is NEVER routed to Codex (a runtime must not grade its own
|
|
18
|
+
// work ; the reviewer stays on Claude).
|
|
19
|
+
//
|
|
20
|
+
// Pure: no I/O, no clock, deterministic. The Codex transport (F2) and the
|
|
21
|
+
// orchestrating loop (F4) consume this; they never re-decide routing.
|
|
22
|
+
|
|
23
|
+
import { TIER_MODEL } from './native-tiers.js';
|
|
24
|
+
|
|
25
|
+
export const RUNTIMES = Object.freeze({ CODEX: 'codex', CLAUDE: 'claude' });
|
|
26
|
+
|
|
27
|
+
// Codex runs on the ChatGPT-subscription entitled model. Kept as a named constant
|
|
28
|
+
// so a plan change is a one-line edit, not a scatter of string literals.
|
|
29
|
+
export const CODEX_MODEL = 'gpt-5.4';
|
|
30
|
+
|
|
31
|
+
export const EFFORTS = Object.freeze({ LOW: 'low', MEDIUM: 'medium', HIGH: 'high' });
|
|
32
|
+
|
|
33
|
+
// Models we refuse to emit, ever. Fable is excluded by explicit long-term
|
|
34
|
+
// decision; the guard makes that refusal mechanical rather than a convention.
|
|
35
|
+
export const FORBIDDEN_MODELS = Object.freeze(['fable', 'claude-fable-5']);
|
|
36
|
+
|
|
37
|
+
// Task natures that route to Codex. Everything NOT here (and not a verification
|
|
38
|
+
// nature) falls through to Claude — Claude is the safe default, so an unknown or
|
|
39
|
+
// ambiguous nature keeps judgment on Claude rather than gambling it on Codex.
|
|
40
|
+
const CODEX_NATURES = Object.freeze([
|
|
41
|
+
'execution', 'exec', 'shell', 'terminal', 'command',
|
|
42
|
+
'deploy', 'deployment', 'devops', 'ci', 'cd', 'pipeline',
|
|
43
|
+
'scripting', 'script', 'automation', 'browser', 'computer-use', 'e2e-run',
|
|
44
|
+
]);
|
|
45
|
+
|
|
46
|
+
// Natures that MUST stay on Claude even if a future edit mislabels them — the
|
|
47
|
+
// verification red line. Checked before the Codex table so it can never be
|
|
48
|
+
// overridden by a nature that also looks like execution (e.g. "run-and-verify").
|
|
49
|
+
const VERIFICATION_NATURES = Object.freeze([
|
|
50
|
+
'verification', 'verify', 'validate', 'review', 'audit', 'check', 'qa',
|
|
51
|
+
]);
|
|
52
|
+
|
|
53
|
+
function normalize(value) {
|
|
54
|
+
return String(value == null ? '' : value).trim().toLowerCase();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function matchesAny(text, list) {
|
|
58
|
+
return list.some((kw) => text.includes(kw));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// assertNoFable(model) — mechanical enforcement of red line #1. Throws rather
|
|
62
|
+
// than silently substituting, so a Fable request is a loud failure at the source.
|
|
63
|
+
export function assertNoFable(model) {
|
|
64
|
+
const m = normalize(model);
|
|
65
|
+
if (FORBIDDEN_MODELS.some((f) => m.includes(f))) {
|
|
66
|
+
throw new Error(`dispatch-router: forbidden model "${model}" (Fable is excluded by long-term policy)`);
|
|
67
|
+
}
|
|
68
|
+
return model;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// isVerification(nature) — red line #2 helper. A verification nature never leaves
|
|
72
|
+
// Claude.
|
|
73
|
+
export function isVerification(nature) {
|
|
74
|
+
return matchesAny(normalize(nature), VERIFICATION_NATURES);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// routeRuntime(nature) -> 'codex' | 'claude'. Verification wins first (stays
|
|
78
|
+
// Claude), then the Codex table, else Claude (safe default).
|
|
79
|
+
export function routeRuntime(nature) {
|
|
80
|
+
const n = normalize(nature);
|
|
81
|
+
if (isVerification(n)) return RUNTIMES.CLAUDE;
|
|
82
|
+
if (matchesAny(n, CODEX_NATURES)) return RUNTIMES.CODEX;
|
|
83
|
+
return RUNTIMES.CLAUDE;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Map a complexity input to a coarse bucket. Accepts a 0-100 number (the
|
|
87
|
+
// complexity-scorer scale) OR a label (trivial/low/medium/high/hard). Anything
|
|
88
|
+
// unrecognised is treated as medium — a safe middle that neither over-spends nor
|
|
89
|
+
// under-powers.
|
|
90
|
+
export function complexityBucket(complexity) {
|
|
91
|
+
if (typeof complexity === 'number' && Number.isFinite(complexity)) {
|
|
92
|
+
if (complexity < 34) return EFFORTS.LOW;
|
|
93
|
+
if (complexity < 67) return EFFORTS.MEDIUM;
|
|
94
|
+
return EFFORTS.HIGH;
|
|
95
|
+
}
|
|
96
|
+
const c = normalize(complexity);
|
|
97
|
+
if (['trivial', 'low', 'simple', 'easy'].includes(c)) return EFFORTS.LOW;
|
|
98
|
+
if (['high', 'hard', 'complex', 'frontier'].includes(c)) return EFFORTS.HIGH;
|
|
99
|
+
return EFFORTS.MEDIUM;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// effortForComplexity(complexity) -> a Codex reasoning-effort value. Codex is the
|
|
103
|
+
// only side with a real effort knob (`codex exec -c model_reasoning_effort=...`);
|
|
104
|
+
// this maps complexity onto it 1:1 with the bucket.
|
|
105
|
+
export function effortForComplexity(complexity) {
|
|
106
|
+
return complexityBucket(complexity);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// claudeModelForComplexity(complexity) -> 'haiku' | 'sonnet' | null(omit=inherit).
|
|
110
|
+
// Delegates to native-tiers' TIER_MODEL so the Claude vocabulary stays in one
|
|
111
|
+
// place: low -> cheap(haiku), medium -> balanced(sonnet), high -> deep(null =
|
|
112
|
+
// inherit the session model, i.e. Opus on an Opus session). Fable is structurally
|
|
113
|
+
// impossible here (TIER_MODEL has no Fable entry), but we still assert to make the
|
|
114
|
+
// guarantee explicit and catch a future TIER_MODEL drift.
|
|
115
|
+
export function claudeModelForComplexity(complexity) {
|
|
116
|
+
const bucket = complexityBucket(complexity);
|
|
117
|
+
const model = bucket === EFFORTS.LOW
|
|
118
|
+
? TIER_MODEL.cheap
|
|
119
|
+
: bucket === EFFORTS.MEDIUM
|
|
120
|
+
? TIER_MODEL.balanced
|
|
121
|
+
: TIER_MODEL.deep; // null = inherit (never pinned to Fable)
|
|
122
|
+
return model == null ? null : assertNoFable(model);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// dispatch({ nature, complexity }) -> the full routing decision:
|
|
126
|
+
// { runtime, model, effort, reasoning }
|
|
127
|
+
// - Codex: model = CODEX_MODEL, effort = complexity bucket (the real knob).
|
|
128
|
+
// - Claude: model = haiku/sonnet/null(inherit), effort = null (Claude has no
|
|
129
|
+
// effort knob — its "effort" IS the model tier).
|
|
130
|
+
// Both red lines are enforced here regardless of caller input.
|
|
131
|
+
export function dispatch({ nature, complexity } = {}) {
|
|
132
|
+
const runtime = routeRuntime(nature);
|
|
133
|
+
if (runtime === RUNTIMES.CODEX) {
|
|
134
|
+
return {
|
|
135
|
+
runtime,
|
|
136
|
+
model: assertNoFable(CODEX_MODEL),
|
|
137
|
+
effort: effortForComplexity(complexity),
|
|
138
|
+
reasoning: `nature "${normalize(nature)}" routes to Codex ; effort scaled to complexity`,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
runtime,
|
|
143
|
+
model: claudeModelForComplexity(complexity), // null = inherit session model
|
|
144
|
+
effort: null, // Claude effort = model tier, no separate knob
|
|
145
|
+
reasoning: isVerification(nature)
|
|
146
|
+
? 'verification stays on Claude (red line: a runtime never grades its own work)'
|
|
147
|
+
: `nature "${normalize(nature)}" stays on Claude (default-safe) ; model scaled to complexity`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"name": "byan-byan",
|
|
95
95
|
"module": "core",
|
|
96
96
|
"tier": "connector-bound",
|
|
97
|
-
"sourceHash": "
|
|
97
|
+
"sourceHash": "523ca56a08c8b85edba423e1bfdd0d9c777442bcb266b5a74e65c14814da128d"
|
|
98
98
|
},
|
|
99
99
|
"byan-byan-v2": {
|
|
100
100
|
"name": "byan-byan-v2",
|
|
Binary file
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Intelligent dispatch — Codex/Claude routing + architect-dev loop
|
|
2
|
+
|
|
3
|
+
Route each task to the runtime that is genuinely better for it (Codex or Claude),
|
|
4
|
+
on the right model and effort for its complexity, and let an architect (Claude)
|
|
5
|
+
and a dev (Codex or Claude) exchange turn by turn until the work converges.
|
|
6
|
+
|
|
7
|
+
This is "option B": a deterministic orchestration loop (the durable, testable
|
|
8
|
+
backbone), with the Codex transport behind a swappable adapter so the tighter
|
|
9
|
+
`codex mcp-server` coupling can slot in later without touching the core.
|
|
10
|
+
|
|
11
|
+
## The routing table (cross-checked, 5 independent sources)
|
|
12
|
+
|
|
13
|
+
| Task nature | Runtime | Why |
|
|
14
|
+
|-------------|---------|-----|
|
|
15
|
+
| execution / shell / terminal / deploy / devops / CI / scripting / browser / automation | Codex | Codex leads autonomous execution, terminal-task benchmarks, browser/computer use |
|
|
16
|
+
| architecture / design / planning / refactor / quality / analysis / exploration / anything unknown | Claude | Claude leads planning, repo-scale refactor, code quality ; unknown stays on Claude (safe default) |
|
|
17
|
+
| verification / review / validate / audit / qa | Claude (hard rule) | A runtime must not grade its own work |
|
|
18
|
+
|
|
19
|
+
The raw "who is better overall" score (SWE-bench Verified) is a near tie whose
|
|
20
|
+
leader flips by leaderboard, so it is left out of the routing signal — only the
|
|
21
|
+
task-type signal is used, which is stable across sources.
|
|
22
|
+
|
|
23
|
+
## Model and effort by complexity
|
|
24
|
+
|
|
25
|
+
- **Claude side**: complexity picks the model tier via `native-tiers` —
|
|
26
|
+
low -> haiku, medium -> sonnet, high -> inherit the session model (Opus). There
|
|
27
|
+
is no separate effort knob on Claude: the model tier IS the effort. Fable is
|
|
28
|
+
excluded (the router does not emit it).
|
|
29
|
+
- **Codex side**: fixed model (`gpt-5.4`, the entitled subscription model) with a
|
|
30
|
+
real reasoning-effort knob — low / medium / high — scaled to complexity via
|
|
31
|
+
`codex exec -c model_reasoning_effort=...`.
|
|
32
|
+
|
|
33
|
+
## The three red lines (enforced in code, not left to the caller)
|
|
34
|
+
|
|
35
|
+
1. **No Fable.** `assertNoFable` throws rather than emit a Fable model.
|
|
36
|
+
2. **Verification stays on Claude.** The router forces a verification nature to
|
|
37
|
+
Claude ; the orchestrator re-asserts it and throws if it ever regresses.
|
|
38
|
+
3. **Codex does not write.** Codex runs read-only and returns a unified diff ;
|
|
39
|
+
Claude applies it with `git apply`. This works under a locked-down sandbox
|
|
40
|
+
(e.g. Landlock) and keeps the apply + later verification on Claude.
|
|
41
|
+
|
|
42
|
+
## How the agents "talk" (the honest live-chat answer)
|
|
43
|
+
|
|
44
|
+
There is no simultaneous free-form chat between two models — that does not exist
|
|
45
|
+
natively. What delivers the same outcome is a turn-by-turn loop through a shared
|
|
46
|
+
board, like a chat server holding a conversation:
|
|
47
|
+
|
|
48
|
+
1. The architect (Claude) posts the design to the board.
|
|
49
|
+
2. The dev (Codex or Claude) reads the board, does the work, posts a result — or
|
|
50
|
+
a question.
|
|
51
|
+
3. If there is an open question, the architect answers ; the loop continues.
|
|
52
|
+
4. Convergence when the dev delivers a result with no open question (or a round
|
|
53
|
+
cap is hit). If the dev runtime fails (Codex unavailable/errored), the loop
|
|
54
|
+
reports `dev-failed` so the caller falls back to Claude.
|
|
55
|
+
|
|
56
|
+
## Files
|
|
57
|
+
|
|
58
|
+
| File | Role |
|
|
59
|
+
|------|------|
|
|
60
|
+
| `lib/dispatch-router.js` | F1 — pure routing brain (nature+complexity -> runtime+model+effort) |
|
|
61
|
+
| `lib/codex-bridge.js` | F2 — Codex transport: `codex exec` -> diff, `git apply`, adapter seam (exec shipped, mcp a V2 slot) |
|
|
62
|
+
| `lib/dispatch-blackboard.js` | F3 — the turn-by-turn shared board (build/render pure, JSONL I/O isolated) |
|
|
63
|
+
| `lib/dispatch-orchestrator.js` | F4 — the loop core (routes, runs architect<->dev, converges) ; executors injected |
|
|
64
|
+
| `.claude/workflows/intelligent-dispatch.js` | Native launch facade for one routed task (design -> implement -> verify) |
|
|
65
|
+
|
|
66
|
+
All four libs are pure/injectable and unit-tested under `test/dispatch-*.test.js`
|
|
67
|
+
and `test/codex-bridge.test.js`.
|
|
68
|
+
|
|
69
|
+
## Launching it
|
|
70
|
+
|
|
71
|
+
The orchestrator runs as full Node on the main thread (or an MCP worker), because
|
|
72
|
+
a native workflow script has no imports and no filesystem — it cannot use these
|
|
73
|
+
libs directly. So the main-thread FD / hermes skill decides routing with F1,
|
|
74
|
+
provides the executors (a Claude subagent for Claude turns, the Codex bridge for
|
|
75
|
+
Codex turns), and drives `orchestrate({ tasks, executors })`. The native workflow
|
|
76
|
+
script `intelligent-dispatch.js` is the thin facade for the single-task case: its
|
|
77
|
+
dev leaf holds the Bash tool and is what actually invokes `codex exec`.
|
|
78
|
+
|
|
79
|
+
## V2 slot — tighter coupling
|
|
80
|
+
|
|
81
|
+
`getAdapter('codex-mcp')` is a declared but unavailable adapter. When
|
|
82
|
+
`codex mcp-server` is wired, Codex becomes a tool Claude can call mid-reasoning
|
|
83
|
+
(and Codex can call BYAN tools back) — the closest thing to live. It drops in as a
|
|
84
|
+
new transport behind the same F2 seam, with no change to F1 or the loop.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-byan-agent",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.47.1",
|
|
4
4
|
"description": "BYAN v2.8 - Intelligent AI agent creator with ELO trust system + scientific fact-check + Hermes universal dispatcher + native Claude Code integration (hooks, skills, MCP server). Multi-platform (Claude Code, Codex). Merise Agile + TDD + 71 Mantras. ~54% LLM cost savings.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|