create-byan-agent 2.39.0 → 2.42.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/CHANGELOG.md +153 -1
- package/install/bin/byan-handoff.js +139 -0
- package/install/bin/create-byan-agent-v2.js +70 -9
- package/install/lib/codex-autodelegate-setup.js +100 -0
- package/install/lib/codex-native-setup.js +94 -2
- package/install/lib/project-handoff.js +300 -0
- package/install/lib/rtk-integration.js +81 -14
- package/install/templates/.claude/CLAUDE.md +16 -0
- package/install/templates/.claude/hooks/codex-autodelegate.js +74 -0
- package/install/templates/.claude/hooks/lib/autodelegate-decision.js +152 -0
- package/install/templates/.claude/hooks/lib/perf-routing.js +47 -0
- package/install/templates/.claude/hooks/lib/usage-estimator.js +262 -0
- package/install/templates/.claude/hooks/tier-script-guard.js +185 -0
- package/install/templates/.claude/rules/native-workflows.md +33 -7
- package/install/templates/.claude/settings.json +35 -22
- package/install/templates/.claude/skills/byan-byan/SKILL.md +21 -2
- package/install/templates/.claude/skills/byan-codex/SKILL.md +7 -0
- package/install/templates/.claude/skills/byan-hermes-dispatch/SKILL.md +3 -1
- package/install/templates/.claude/workflows/sprint-planning.js +2 -2
- package/install/templates/.claude/workflows/testarch-trace.js +3 -2
- package/install/templates/.codex/skills/byan/SKILL.md +77 -0
- package/install/templates/_byan/INDEX.md +6 -2
- package/install/templates/_byan/_config/workflow-manifest.csv +1 -1
- package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-tier-script.js +52 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/dispatch.js +22 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/native-tiers.js +26 -9
- package/install/templates/_byan/mcp/byan-mcp-server/lib/tier-script.js +104 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-lint.js +92 -6
- package/install/templates/_byan/mcp/byan-mcp-server/server.js +22 -7
- package/install/templates/_byan/mcp/byan-mcp-server/skill-bundles-manifest.json +3 -3
- package/install/templates/_byan/workflow/simple/byan/project-handoff-workflow.md +90 -0
- package/install/templates/dist/skill-bundles/byan-byan.zip +0 -0
- package/install/templates/dist/skill-bundles/byan-codex.zip +0 -0
- package/install/templates/dist/skill-bundles/byan-hermes-dispatch.zip +0 -0
- package/install/templates/docs/codex-auto-delegation.md +140 -0
- package/install/templates/docs/native-workflows-contract.md +55 -12
- package/package.json +2 -1
- package/src/loadbalancer/capability-matrix.js +14 -0
- package/src/loadbalancer/degradation-ladder.js +121 -0
- package/src/loadbalancer/loadbalancer.default.yaml +23 -1
- package/src/loadbalancer/mcp-server.js +200 -18
- package/src/loadbalancer/providers/codex-provider.js +260 -0
- package/src/loadbalancer/providers/factory.js +36 -0
- package/src/loadbalancer/subscription-window.js +142 -0
- package/src/loadbalancer/switch-tolerance.js +63 -0
- package/src/loadbalancer/tools/index.js +17 -2
|
@@ -26,16 +26,24 @@ A native workflow script mutates FD/strict state only through the `byan_fd_*` /
|
|
|
26
26
|
|
|
27
27
|
Each `agent()` leaf runs on the session model unless the call sets `opts.model`.
|
|
28
28
|
The tiering decision lives in one place — `_byan/mcp/byan-mcp-server/lib/native-tiers.js`
|
|
29
|
-
(tier vocabulary, leaf classifier, model map).
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
(tier vocabulary, leaf classifier, model map). Three tiers:
|
|
30
|
+
|
|
31
|
+
- **cheap (`model: 'haiku'`)** — a pure EXPLORATION leaf (read/load/parse/detect).
|
|
32
|
+
- **balanced (`model: 'sonnet'`)** — MECHANICAL verification, opt-in ONLY through
|
|
33
|
+
the `mech-` label prefix (`mech-validate-json`): a binary, judgment-free check
|
|
34
|
+
(JSON parses, schema matches, lint passes). Semantic/adversarial verification
|
|
35
|
+
is NOT mechanical and stays deep. The prefix is an authoring declaration the
|
|
36
|
+
linter holds the script to: a `mech-` leaf without `model: 'sonnet'` is a hard
|
|
37
|
+
violation (`mechanical-without-model` / `mechanical-below-tier`).
|
|
38
|
+
- **deep (OMIT `opts.model`)** — implementation / verification / analysis leaves
|
|
39
|
+
inherit the session model (no pin-up to opus).
|
|
33
40
|
|
|
34
41
|
The linter splits the two directions:
|
|
35
42
|
|
|
36
|
-
- **Floor (HARD, blocks the commit)** — a downgrade model on a PROTECTED leaf,
|
|
37
|
-
|
|
38
|
-
STRICT-2
|
|
43
|
+
- **Floor (HARD, blocks the commit)** — a downgrade model on a PROTECTED leaf, a
|
|
44
|
+
pin-up, or a half-applied `mech-` opt-in is a contract violation
|
|
45
|
+
(`modelRoutingViolations` + `mechanicalLabelViolations`). This is the STRICT-2
|
|
46
|
+
No Downgrade net.
|
|
39
47
|
- **Ceiling (ADVISORY, non-blocking)** — an exploration-labelled leaf that runs
|
|
40
48
|
deep is *reported* (`byan-lint-workflows.js --advise`), not forced. `classifyLeaf`
|
|
41
49
|
is permissive: many exploration-labelled leaves legitimately stay deep because
|
|
@@ -43,6 +51,24 @@ The linter splits the two directions:
|
|
|
43
51
|
consumed verbatim downstream. The human owns that per-leaf call. Forcing haiku
|
|
44
52
|
on them would be the very downgrade the floor forbids.
|
|
45
53
|
|
|
54
|
+
## Ad-hoc scripts — the tier gate hook
|
|
55
|
+
|
|
56
|
+
The repo linter only sees committed files. An AD-HOC script (written inline for
|
|
57
|
+
one run) crosses exactly one chokepoint before it executes: the Workflow tool
|
|
58
|
+
invocation. `.claude/hooks/tier-script-guard.js` (PreToolUse, matcher `Workflow`)
|
|
59
|
+
runs the same analysis there via `lib/tier-script.js` and DENIES ONCE when
|
|
60
|
+
exploration/`mech-` leaves carry no tier — with the exact leaf list to fix. The
|
|
61
|
+
`// BYAN-TIER: reviewed` comment marker acknowledges deliberate deep choices; an
|
|
62
|
+
identical resubmission passes (deny-once by design); registry (name-only)
|
|
63
|
+
invocations pass untouched. Every decision lands in
|
|
64
|
+
`_byan-output/tier-ledger.jsonl` with a per-model histogram — the measurement
|
|
65
|
+
basis for token gains. Escape hatch: `touch .byan-tier/off`.
|
|
66
|
+
|
|
67
|
+
Authoring flow: BEFORE writing a script, call `byan_dispatch` with
|
|
68
|
+
`{ leaves: [{ label, nature? }] }` (batch mode) to get the `opts.model` per leaf;
|
|
69
|
+
write `model:` only where non-null. Standalone report:
|
|
70
|
+
`node _byan/mcp/byan-mcp-server/bin/byan-tier-script.js <file> [--json]`.
|
|
71
|
+
|
|
46
72
|
A per-leaf "effort" knob is not available: the native `agent()` / Agent API exposes
|
|
47
73
|
only `model`, so model tier is the sole token lever. Effort-by-complexity reduces
|
|
48
74
|
to model-by-complexity.
|
|
@@ -6,15 +6,15 @@
|
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
|
8
8
|
"type": "command",
|
|
9
|
-
"command": "
|
|
9
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/inject-soul.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"type": "command",
|
|
13
|
-
"command": "
|
|
13
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/inject-tao.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"type": "command",
|
|
17
|
-
"command": "
|
|
17
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/soul-memory-check.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
18
18
|
}
|
|
19
19
|
]
|
|
20
20
|
}
|
|
@@ -25,23 +25,27 @@
|
|
|
25
25
|
"hooks": [
|
|
26
26
|
{
|
|
27
27
|
"type": "command",
|
|
28
|
-
"command": "
|
|
28
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/inject-voice-anchor.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"type": "command",
|
|
32
|
-
"command": "
|
|
32
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/inject-delivery-default.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"type": "command",
|
|
36
|
-
"command": "
|
|
36
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/soul-memory-triggers.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
"type": "command",
|
|
40
|
-
"command": "
|
|
40
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/fd-phase-guard.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
"type": "command",
|
|
44
|
-
"command": "
|
|
44
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/strict-context-inject.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"type": "command",
|
|
48
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/codex-autodelegate.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
45
49
|
}
|
|
46
50
|
]
|
|
47
51
|
}
|
|
@@ -52,35 +56,35 @@
|
|
|
52
56
|
"hooks": [
|
|
53
57
|
{
|
|
54
58
|
"type": "command",
|
|
55
|
-
"command": "
|
|
59
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/mantra-validate.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
56
60
|
},
|
|
57
61
|
{
|
|
58
62
|
"type": "command",
|
|
59
|
-
"command": "
|
|
63
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/fact-check-claims.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
60
64
|
},
|
|
61
65
|
{
|
|
62
66
|
"type": "command",
|
|
63
|
-
"command": "
|
|
67
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/fd-response-check.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
64
68
|
},
|
|
65
69
|
{
|
|
66
70
|
"type": "command",
|
|
67
|
-
"command": "
|
|
71
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/stage-to-byan.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
68
72
|
},
|
|
69
73
|
{
|
|
70
74
|
"type": "command",
|
|
71
|
-
"command": "
|
|
75
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/strict-stop-guard.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
72
76
|
},
|
|
73
77
|
{
|
|
74
78
|
"type": "command",
|
|
75
|
-
"command": "
|
|
79
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/autobench-stop-guard.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
76
80
|
},
|
|
77
81
|
{
|
|
78
82
|
"type": "command",
|
|
79
|
-
"command": "
|
|
83
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/punt-guard.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
80
84
|
},
|
|
81
85
|
{
|
|
82
86
|
"type": "command",
|
|
83
|
-
"command": "
|
|
87
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/drain-advisory.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
84
88
|
}
|
|
85
89
|
]
|
|
86
90
|
}
|
|
@@ -91,15 +95,24 @@
|
|
|
91
95
|
"hooks": [
|
|
92
96
|
{
|
|
93
97
|
"type": "command",
|
|
94
|
-
"command": "
|
|
98
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/tool-transparency.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
95
99
|
},
|
|
96
100
|
{
|
|
97
101
|
"type": "command",
|
|
98
|
-
"command": "
|
|
102
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/fact-check-absolutes.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
99
103
|
},
|
|
100
104
|
{
|
|
101
105
|
"type": "command",
|
|
102
|
-
"command": "
|
|
106
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/strict-scope-guard.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"matcher": "Workflow",
|
|
112
|
+
"hooks": [
|
|
113
|
+
{
|
|
114
|
+
"type": "command",
|
|
115
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/tier-script-guard.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
103
116
|
}
|
|
104
117
|
]
|
|
105
118
|
}
|
|
@@ -110,11 +123,11 @@
|
|
|
110
123
|
"hooks": [
|
|
111
124
|
{
|
|
112
125
|
"type": "command",
|
|
113
|
-
"command": "
|
|
126
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/tool-failure-guard.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
114
127
|
},
|
|
115
128
|
{
|
|
116
129
|
"type": "command",
|
|
117
|
-
"command": "
|
|
130
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/leantime-fd-sync.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
118
131
|
}
|
|
119
132
|
]
|
|
120
133
|
}
|
|
@@ -125,7 +138,7 @@
|
|
|
125
138
|
"hooks": [
|
|
126
139
|
{
|
|
127
140
|
"type": "command",
|
|
128
|
-
"command": "
|
|
141
|
+
"command": "p=\"$CLAUDE_PROJECT_DIR/.claude/hooks/pre-compact-save.js\"; [ -f \"$p\" ] || exit 0; exec node \"$p\""
|
|
129
142
|
}
|
|
130
143
|
]
|
|
131
144
|
}
|
|
@@ -18,6 +18,20 @@ Invoke this protocol when the user :
|
|
|
18
18
|
|
|
19
19
|
If the user request is a simple question or chat, stay out of FD — respond normally.
|
|
20
20
|
|
|
21
|
+
## 1.25. Claude/Codex handoff import trigger
|
|
22
|
+
|
|
23
|
+
When the user says `importe depuis claude` or `importe depuis codex`, handle it
|
|
24
|
+
before starting a new FD cycle:
|
|
25
|
+
|
|
26
|
+
1. Run `byan-handoff latest --from <requested source> --prompt`.
|
|
27
|
+
2. Use the generated prompt as resume context, inspect the listed files, then
|
|
28
|
+
continue the current work.
|
|
29
|
+
|
|
30
|
+
If no matching handoff exists, say that no handoff from that source was found and
|
|
31
|
+
offer `byan-handoff latest --prompt` as the fallback only if the user accepts
|
|
32
|
+
resuming from the newest handoff across all sources. Do not rely on native
|
|
33
|
+
Claude/Codex memory as the source of truth.
|
|
34
|
+
|
|
21
35
|
## 1.5. Freshness check (silent, once per session)
|
|
22
36
|
|
|
23
37
|
Before responding to the user's first activation message in a session, call the MCP tool `byan_update_check` once. It is read-only and cheap (single npm registry lookup, 5s timeout, no side effects).
|
|
@@ -64,9 +78,14 @@ Never call `byan_update_apply` without explicit user consent. That tool returns
|
|
|
64
78
|
- **Score ≥ 40** → main-thread (heavy) or delegate to `byan-hermes-dispatch`
|
|
65
79
|
- **Model tier** (WHICH model), from the task NATURE — not its size (`byan_dispatch` returns it as `model`, via native-tiers, the single source of truth) :
|
|
66
80
|
- nature `exploration` (load/read/scan/list/parse/fetch...) → `haiku`
|
|
81
|
+
- nature `mechanical` (binary judgment-free checks : JSON parses, schema matches, lint passes — label prefix `mech-`, explicit opt-in only) → `sonnet`
|
|
67
82
|
- nature `implementation` / `verification` / `analysis` / unknown → deep = **inherit the session model**
|
|
68
|
-
- Keep protected work (verify/analysis/implement) off haiku regardless of size ; no pin-up to opus. Pass an explicit `nature` to `byan_dispatch` when you know it.
|
|
69
|
-
- **Inside native workflow scripts** (`.claude/workflows/*.js`) the SAME tiering applies per `agent()` leaf via `opts.model`, enforced
|
|
83
|
+
- Keep protected work (verify/analysis/implement) off haiku/sonnet regardless of size ; no pin-up to opus. Pass an explicit `nature` to `byan_dispatch` when you know it.
|
|
84
|
+
- **Inside native workflow scripts** (`.claude/workflows/*.js` OR ad-hoc) the SAME tiering applies per `agent()` leaf via `opts.model`, enforced as a FLOOR not a ceiling on TWO nets :
|
|
85
|
+
- **Repo linter** (committed scripts, pre-commit) : `modelRoutingViolations` HARD-blocks a downgrade on a protected leaf, a pin-up, or a half-applied `mech-` opt-in (`mechanical-without-model` / `mechanical-below-tier`) ; an exploration-labelled leaf left deep is a NON-blocking ADVISORY (`byan-lint-workflows.js --advise`), since many such leaves bear a gate/classification/exact-conversion and must stay deep — the human owns that call.
|
|
86
|
+
- **Tier gate hook** (EVERY Workflow invocation, inline or scriptPath) : `tier-script-guard.js` (PreToolUse) runs the same analysis (`lib/tier-script.js`) and DENIES ONCE when exploration/`mech-` leaves have no tier, with the exact leaf list to fix. Acknowledge deliberate deep choices with the `// BYAN-TIER: reviewed` comment marker ; an identical resubmission passes (deny-once by design, no trap). Every decision lands in `_byan-output/tier-ledger.jsonl` (the measurement basis for token gains). Escape hatch : `.byan-tier/off`.
|
|
87
|
+
- **Authoring aid** : BEFORE writing a script, call `byan_dispatch` with `{ leaves: [{ label, nature? }] }` (batch mode) to get the `opts.model` per leaf ; write `model:` only where non-null. Report with `node _byan/mcp/byan-mcp-server/bin/byan-tier-script.js <file> [--json]`.
|
|
88
|
+
- No per-leaf effort knob exists (the API exposes only `model`), so effort-by-complexity reduces to model-by-complexity.
|
|
70
89
|
- **Output** : a table `{ feature → specialist → model → strategy → estimated_tokens }`.
|
|
71
90
|
- **If no specialist matches** : halt. Ask user whether to run INT (agent recruitment) first. Do NOT fallback silently to general-purpose.
|
|
72
91
|
- **Exit gate** : user validates the mapping.
|
|
@@ -19,3 +19,10 @@ description: "OpenCode/Codex integration specialist for BYAN skills Role: OpenCo
|
|
|
19
19
|
- Validate .codex/prompts/ structure
|
|
20
20
|
- Test skill detection before deployment
|
|
21
21
|
- Handle Codex-specific terminology (skills not agents)
|
|
22
|
+
- When the user says `importe depuis claude` or `importe depuis codex`, run
|
|
23
|
+
`byan-handoff latest --from <requested source> --prompt`, then resume from
|
|
24
|
+
the generated prompt after inspecting the listed files. If none matches,
|
|
25
|
+
report that no handoff from that source exists and offer
|
|
26
|
+
`byan-handoff latest --prompt` as fallback only if the user accepts resuming
|
|
27
|
+
from the newest handoff across all sources. Native Claude/Codex memory is not
|
|
28
|
+
the source of truth.
|
|
@@ -55,7 +55,9 @@ Call the `byan_dispatch` MCP tool with `{ task: <goal>, parallelizable: <bool>,
|
|
|
55
55
|
- `main-thread` — do it inline, no delegation
|
|
56
56
|
- `agent-subagent-worktree` — spawn Agent tool with isolation worktree
|
|
57
57
|
- `mcp-worker` — spawn Agent tool, no worktree
|
|
58
|
-
- **model** (WHICH model), from the task NATURE via native-tiers, not its size : `haiku` (exploration only) or `null` = deep (inherit the session model). Pass an explicit `nature` (`exploration`/`implementation`/`verification`/`analysis`) when you know it; protected natures stay off haiku.
|
|
58
|
+
- **model** (WHICH model), from the task NATURE via native-tiers, not its size : `haiku` (exploration), `sonnet` (mechanical — explicit binary judgment-free checks only), or `null` = deep (inherit the session model). Pass an explicit `nature` (`exploration`/`mechanical`/`implementation`/`verification`/`analysis`) when you know it; protected natures stay off haiku/sonnet.
|
|
59
|
+
|
|
60
|
+
**Batch mode (workflow authoring)** : before WRITING a workflow script, call `byan_dispatch` with `{ leaves: [{ label, nature? }, ...] }` — it returns the `opts.model` value per leaf from the same source of truth. Write `model:` only where it is non-null. The `tier-script-guard` PreToolUse hook gates every Workflow invocation against this contract (deny-once with the exact leaf list; acknowledge deliberate deep choices with the `// BYAN-TIER: reviewed` comment marker).
|
|
59
61
|
|
|
60
62
|
### 4. Spawn the work
|
|
61
63
|
|
|
@@ -6,7 +6,7 @@ export const meta = {
|
|
|
6
6
|
{ title: 'STRUCTURE', detail: 'build the ordered development_status map: epic, its stories, its retrospective' },
|
|
7
7
|
{ title: 'DETECT', detail: 'intelligent per-story status detection, never downgrade an existing status' },
|
|
8
8
|
{ title: 'GENERATE', detail: 'write sprint-status.yaml with metadata as comments AND as parseable fields' },
|
|
9
|
-
{ title: 'VALIDATE', detail: 'coverage + legal-status + YAML checks, then count totals and report' },
|
|
9
|
+
{ title: 'VALIDATE', detail: 'coverage + legal-status + YAML checks, then count totals and report', model: 'sonnet' },
|
|
10
10
|
],
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -236,7 +236,7 @@ const validation = await agent(
|
|
|
236
236
|
`- validYaml: the file parses as YAML.\n` +
|
|
237
237
|
`Count totals: epicCount, storyCount, epicsInProgress, storiesDone. ` +
|
|
238
238
|
`passed = true only if ALL six checks hold; otherwise list specific failures.`,
|
|
239
|
-
{ label: 'validate-
|
|
239
|
+
{ label: 'mech-validate-status', phase: 'VALIDATE', schema: VALIDATE_SCHEMA, model: 'sonnet' }
|
|
240
240
|
)
|
|
241
241
|
|
|
242
242
|
// Single top-level return — DATA only. The orchestrating skill presents this at
|
|
@@ -6,7 +6,7 @@ export const meta = {
|
|
|
6
6
|
{ title: 'DISCOVER_TESTS' },
|
|
7
7
|
{ title: 'MAP_CRITERIA' },
|
|
8
8
|
{ title: 'ANALYZE_GAPS' },
|
|
9
|
-
{ title: 'GATE_DECISION' }
|
|
9
|
+
{ title: 'GATE_DECISION', model: 'sonnet' }
|
|
10
10
|
]
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -260,8 +260,9 @@ const gate = await agent(
|
|
|
260
260
|
'Return the deterministic decision, the rationale string, and the gate criteria (p0 met?, overall status MET/PARTIAL/NOT MET).'
|
|
261
261
|
].join(' '),
|
|
262
262
|
{
|
|
263
|
-
label: 'gate-decision',
|
|
263
|
+
label: 'mech-gate-decision',
|
|
264
264
|
phase: 'GATE_DECISION',
|
|
265
|
+
model: 'sonnet',
|
|
265
266
|
schema: {
|
|
266
267
|
type: 'object',
|
|
267
268
|
required: ['decision', 'rationale', 'gateCriteria'],
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: byan
|
|
3
|
+
description: BYAN local project skill. Use when working in the BYAN repo, invoking BYAN agents/workflows/commands, enforcing BYAN Strict Mode, or needing the portable BYAN filesystem map.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# BYAN Local Skill
|
|
7
|
+
|
|
8
|
+
Use this skill when the user asks for BYAN behavior, mentions BYAN/BMAD, asks to
|
|
9
|
+
run an agent or workflow from this repo, or works on the BYAN platform itself.
|
|
10
|
+
|
|
11
|
+
## Source Of Truth
|
|
12
|
+
|
|
13
|
+
BYAN's portable core lives in this repository. Do not treat native assistant
|
|
14
|
+
memory, generated caches, or platform-specific projections as authoritative.
|
|
15
|
+
|
|
16
|
+
Read `_byan/INDEX.md` first to find agents, workflows, commands, and project
|
|
17
|
+
artefacts. Avoid broad filesystem scans unless the index is missing, stale, or
|
|
18
|
+
insufficient for the requested task.
|
|
19
|
+
|
|
20
|
+
Core references:
|
|
21
|
+
|
|
22
|
+
- `_byan/INDEX.md` — filesystem map for BYAN agents, workflows, commands, and projects.
|
|
23
|
+
- `AGENTS.md` — Codex adapter for BYAN Strict Mode and delivery defaults.
|
|
24
|
+
- `.claude/rules/portable-core.md` — portable-core doctrine: `_byan/` and
|
|
25
|
+
`_byan-output/` are the source of truth; native platform features are
|
|
26
|
+
write-through accelerators.
|
|
27
|
+
- `_byan/agent/byan/byan.md` — BYAN core meta-agent when the task requires the
|
|
28
|
+
full BYAN persona and FD workflow.
|
|
29
|
+
|
|
30
|
+
## Strict Mode
|
|
31
|
+
|
|
32
|
+
When BYAN Strict Mode is active, follow the audit protocol before delivery:
|
|
33
|
+
|
|
34
|
+
1. Lock scope with `byan_strict_lock_scope` before building.
|
|
35
|
+
2. Build the locked scope without silent downgrade.
|
|
36
|
+
3. Run at least three `byan_strict_self_verify` passes against the original
|
|
37
|
+
request and acceptance criteria.
|
|
38
|
+
4. Call `byan_strict_complete` only after the final pass is `ok`.
|
|
39
|
+
|
|
40
|
+
Surface gaps explicitly. Do not round skipped tests, blocked tools, or partial
|
|
41
|
+
work up to done.
|
|
42
|
+
|
|
43
|
+
## Working Rules
|
|
44
|
+
|
|
45
|
+
- Prefer BYAN's local manifests and `_byan/INDEX.md` over filesystem wandering.
|
|
46
|
+
- Keep Codex-specific material under `.codex/` or installed Codex skills under
|
|
47
|
+
`$CODEX_HOME/skills` / `~/.codex/skills`.
|
|
48
|
+
- Use existing BYAN agents and workflows instead of inventing parallel
|
|
49
|
+
conventions.
|
|
50
|
+
- If a public surface changes, update the matching doc, manifest, template, or
|
|
51
|
+
generated projection when applicable.
|
|
52
|
+
- Preserve BYAN's no-emoji convention in code, commits, docs, and prompts.
|
|
53
|
+
|
|
54
|
+
## Claude/Codex Handoff Import
|
|
55
|
+
|
|
56
|
+
When the user says `importe depuis claude` or `importe depuis codex`, handle it
|
|
57
|
+
without asking for more context if a matching handoff exists:
|
|
58
|
+
|
|
59
|
+
1. Run `byan-handoff latest --from <requested source> --prompt`.
|
|
60
|
+
2. Treat the generated prompt as the resume context, inspect the listed files,
|
|
61
|
+
then continue the work.
|
|
62
|
+
|
|
63
|
+
If no matching handoff exists, say that no handoff from that source was found and
|
|
64
|
+
offer `byan-handoff latest --prompt` as the fallback only if the user accepts
|
|
65
|
+
resuming from the newest handoff across all sources. Do not rely on native
|
|
66
|
+
Claude/Codex memory as the source of truth.
|
|
67
|
+
|
|
68
|
+
## Installed Bundles In This Repo
|
|
69
|
+
|
|
70
|
+
Prebuilt Codex skill bundles are available under `dist/skill-bundles/`, including:
|
|
71
|
+
|
|
72
|
+
- `byan-byan.zip` — full BYAN FD/meta-agent skill.
|
|
73
|
+
- `byan-strict.zip` — strict scope-lock and audit protocol.
|
|
74
|
+
- `byan-codex.zip` — Codex/OpenCode integration specialist.
|
|
75
|
+
|
|
76
|
+
Use those bundles when the user asks for a specific packaged BYAN skill. Use this
|
|
77
|
+
local `byan` skill as the general repo-aware entrypoint.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> Carte du systeme de fichiers BYAN. Genere automatiquement — ne pas editer a la main.
|
|
4
4
|
> Source : `_byan/_config/*-manifest.csv` + scan `_byan/projet/`. Regenerer : `byan-build-index`.
|
|
5
5
|
|
|
6
|
-
## Agents (
|
|
6
|
+
## Agents (28)
|
|
7
7
|
|
|
8
8
|
### bmb
|
|
9
9
|
- `agent-builder` — Agent Building Expert — `_byan/agent/agent-builder/agent-builder.md`
|
|
@@ -18,6 +18,8 @@
|
|
|
18
18
|
- `architect` — Architect — `_byan/agent/architect/architect.md`
|
|
19
19
|
- `dev` — Developer Agent — `_byan/agent/dev/dev.md`
|
|
20
20
|
- `expert-merise-agile` — Expert Merise Agile - Assistant de Conception & Rédaction — `_byan/agent/expert-merise-agile/expert-merise-agile.md`
|
|
21
|
+
- `jimmy` — Spécialiste Documentation Technique & Processus Internes — `_byan/agent/jimmy/jimmy.md`
|
|
22
|
+
- `mike` — Gestionnaire de Projet — Spécialiste Leantime — `_byan/agent/mike/mike.md`
|
|
21
23
|
- `pm` — Product Manager — `_byan/agent/pm/pm.md`
|
|
22
24
|
- `quick-flow-solo-dev` — Quick Flow Solo Dev — `_byan/agent/quick-flow-solo-dev/quick-flow-solo-dev.md`
|
|
23
25
|
- `quinn` — QA Engineer — `_byan/agent/quinn/quinn.md`
|
|
@@ -41,10 +43,11 @@
|
|
|
41
43
|
### tea
|
|
42
44
|
- `tea` — Master Test Architect and Quality Advisor — `_byan/agent/tea/tea.md`
|
|
43
45
|
|
|
44
|
-
## Workflows (
|
|
46
|
+
## Workflows (47)
|
|
45
47
|
|
|
46
48
|
### bmb
|
|
47
49
|
- `agent` — Tri-modal workflow for creating, editing, and validating BMAD Core compliant agents — `_byan/workflow/simple/agent/workflow.md`
|
|
50
|
+
- `byan-benchmark` — DATA-only benchmark engine for any decision fork: options x weighted-criteria matrix + best-first reco + dissent — `_byan/workflow/simple/bmb/byan-benchmark/workflow.md`
|
|
48
51
|
- `module` — Quad-modal workflow for creating BMAD modules (Brief + Create + Edit + Validate) — `_byan/workflow/simple/module/workflow.md`
|
|
49
52
|
- `turbo-whisper-configure` — Configure Turbo Whisper API, hotkeys, and preferences — `_byan/workflow/simple/turbo-whisper/configure-workflow.md`
|
|
50
53
|
- `turbo-whisper-docker-setup` — Setup self-hosted faster-whisper-server with Docker for privacy and cost-free transcription — `_byan/workflow/simple/turbo-whisper/docker-setup-workflow.md`
|
|
@@ -86,6 +89,7 @@
|
|
|
86
89
|
### core
|
|
87
90
|
- `brainstorming` — Facilitate interactive brainstorming sessions using diverse creative techniques and ideation methods — `_byan/workflow/simple/brainstorming/workflow.md`
|
|
88
91
|
- `party-mode` — Orchestrates group discussions between all installed BMAD agents, enabling natural multi-agent conversations — `_byan/workflow/simple/party-mode/workflow.md`
|
|
92
|
+
- `project-handoff` — Export/import portable Markdown project state between Claude Code and Codex — `_byan/workflow/simple/byan/project-handoff-workflow.md`
|
|
89
93
|
|
|
90
94
|
### tea
|
|
91
95
|
- `teach-me-testing` — Multi-session learning companion that teaches testing progressively through 7 structured sessions with state persistence — `_byan/workflow/simple/testarch/teach-me-testing/workflow.md`
|
|
@@ -45,4 +45,4 @@ name,description,module,path
|
|
|
45
45
|
"turbo-whisper-docker-setup","Setup self-hosted faster-whisper-server with Docker for privacy and cost-free transcription","bmb","_byan/workflow/simple/turbo-whisper/docker-setup-workflow.md"
|
|
46
46
|
"turbo-whisper-integrate","Integrate Turbo Whisper with GitHub Copilot CLI, Claude Code, and Codex platforms","bmb","_byan/workflow/simple/turbo-whisper/integrate-workflow.md"
|
|
47
47
|
"byan-benchmark","DATA-only benchmark engine for any decision fork: options x weighted-criteria matrix + best-first reco + dissent","bmb","_byan/workflow/simple/bmb/byan-benchmark/workflow.md"
|
|
48
|
-
|
|
48
|
+
"project-handoff","Export/import portable Markdown project state between Claude Code and Codex","core","_byan/workflow/simple/byan/project-handoff-workflow.md"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { analyzeScript, formatGateReason } from '../lib/tier-script.js';
|
|
4
|
+
|
|
5
|
+
// Per-script tiering report — works on ANY workflow script text: a committed
|
|
6
|
+
// .claude/workflows/*.js, an ad-hoc script persisted under the session dir, or
|
|
7
|
+
// a draft. One verdict per statically-labelled leaf against native-tiers.
|
|
8
|
+
//
|
|
9
|
+
// Exit codes (hook/CI friendly): 0 clean or acknowledged, 1 tier gaps,
|
|
10
|
+
// 2 violations (violations dominate gaps).
|
|
11
|
+
// Usage: node bin/byan-tier-script.js <script-file> [--json]
|
|
12
|
+
|
|
13
|
+
const args = process.argv.slice(2);
|
|
14
|
+
const jsonMode = args.includes('--json');
|
|
15
|
+
const file = args.find((a) => !a.startsWith('--'));
|
|
16
|
+
|
|
17
|
+
if (!file) {
|
|
18
|
+
process.stderr.write('usage: byan-tier-script <script-file> [--json]\n');
|
|
19
|
+
process.exit(2);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let src;
|
|
23
|
+
try {
|
|
24
|
+
src = fs.readFileSync(file, 'utf8');
|
|
25
|
+
} catch (e) {
|
|
26
|
+
process.stderr.write(`[byan-tier-script] cannot read ${file}: ${e.message}\n`);
|
|
27
|
+
process.exit(2);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const analysis = analyzeScript(src);
|
|
31
|
+
|
|
32
|
+
if (jsonMode) {
|
|
33
|
+
process.stdout.write(JSON.stringify(analysis, null, 2) + '\n');
|
|
34
|
+
} else {
|
|
35
|
+
process.stdout.write(
|
|
36
|
+
`[byan-tier-script] ${file}: ${analysis.agentCalls} agent() call(s), ` +
|
|
37
|
+
`${analysis.leaves.length} labelled leaf/leaves, ` +
|
|
38
|
+
`${analysis.gaps.length} gap(s), ${analysis.violations.length} violation(s)` +
|
|
39
|
+
`${analysis.acknowledged ? ', acknowledged (BYAN-TIER: reviewed)' : ''}\n`
|
|
40
|
+
);
|
|
41
|
+
for (const l of analysis.leaves) {
|
|
42
|
+
const model = l.model === null ? '(inherit)' : l.model;
|
|
43
|
+
process.stdout.write(` ${l.verdict.padEnd(12)} ${l.label} [${l.class}] model=${model} expected=${l.expectedModel ?? '(inherit)'}\n`);
|
|
44
|
+
}
|
|
45
|
+
if (analysis.gaps.length || analysis.violations.length) {
|
|
46
|
+
process.stdout.write(formatGateReason(analysis) + '\n');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (analysis.acknowledged) process.exit(0);
|
|
51
|
+
if (analysis.violations.length) process.exit(2);
|
|
52
|
+
process.exit(analysis.gaps.length ? 1 : 0);
|
|
@@ -73,3 +73,25 @@ export function dispatch({ task, complexity, parallelizable, nature } = {}) {
|
|
|
73
73
|
reasoning: `${strategyReason}. ${tierReason}.`,
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
// Batch tiering — the authoring aid for workflow scripts. The author passes the
|
|
78
|
+
// planned leaves BEFORE writing the script and gets the opts.model value per
|
|
79
|
+
// leaf from the same source of truth (native-tiers). No strategy axis here:
|
|
80
|
+
// the leaves all run inside one Workflow invocation, so WHERE they run is the
|
|
81
|
+
// script's concern, only WHICH model each deserves is answered. An explicit
|
|
82
|
+
// valid nature wins; otherwise the label classifies; a miss stays protected
|
|
83
|
+
// (implementation -> deep -> null), same conservative path as dispatch().
|
|
84
|
+
export function dispatchBatch(leaves) {
|
|
85
|
+
if (!Array.isArray(leaves)) return [];
|
|
86
|
+
return leaves.map((leaf) => {
|
|
87
|
+
const { label, nature } = leaf && typeof leaf === 'object' ? leaf : {};
|
|
88
|
+
const leafType = VALID_NATURES.has(nature) ? nature : classifyLeaf({ label: label || '' });
|
|
89
|
+
const tier = tierFor(leafType);
|
|
90
|
+
return {
|
|
91
|
+
label: label || '',
|
|
92
|
+
nature: leafType,
|
|
93
|
+
tier,
|
|
94
|
+
model: TIER_MODEL[tier],
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
@@ -28,7 +28,8 @@ export const TIERS = Object.freeze({ CHEAP: 'cheap', BALANCED: 'balanced', DEEP:
|
|
|
28
28
|
// session runs (Opus by default, but Sonnet if the user chose Sonnet). We never
|
|
29
29
|
// PIN UP — pinning a leaf to a fixed high tier would override the user's session
|
|
30
30
|
// choice and could silently DOWNGRADE a Sonnet/Opus session's heavy leaf. Only
|
|
31
|
-
// cheap/balanced carry a value
|
|
31
|
+
// cheap/balanced carry a value: exploration leaves get cheap, explicit mech-
|
|
32
|
+
// leaves get balanced, nothing else ever gets one.
|
|
32
33
|
//
|
|
33
34
|
// Values are the harness model-selection aliases (same set as the Agent tool:
|
|
34
35
|
// 'haiku' | 'sonnet' | 'opus'). They are version-independent. If a future
|
|
@@ -36,15 +37,26 @@ export const TIERS = Object.freeze({ CHEAP: 'cheap', BALANCED: 'balanced', DEEP:
|
|
|
36
37
|
// flags every script literal that drifts from it, so the fan-out stays bounded.
|
|
37
38
|
export const TIER_MODEL = Object.freeze({ cheap: 'haiku', balanced: 'sonnet', deep: null });
|
|
38
39
|
|
|
39
|
-
// Leaf task-type taxonomy. EXPLORATION
|
|
40
|
-
// other three are protected (never downgraded).
|
|
40
|
+
// Leaf task-type taxonomy. EXPLORATION and MECHANICAL are the two
|
|
41
|
+
// downgrade-safe classes; the other three are protected (never downgraded).
|
|
42
|
+
// MECHANICAL is verification whose outcome is binary and judgment-free (JSON
|
|
43
|
+
// parses, schema matches, lint passes, a test suite exits 0) — it earns the
|
|
44
|
+
// balanced tier. Semantic/adversarial verification stays VERIFICATION (deep).
|
|
41
45
|
export const LEAF_TYPES = Object.freeze({
|
|
42
46
|
EXPLORATION: 'exploration',
|
|
47
|
+
MECHANICAL: 'mechanical',
|
|
43
48
|
IMPLEMENTATION: 'implementation',
|
|
44
49
|
VERIFICATION: 'verification',
|
|
45
50
|
ANALYSIS: 'analysis',
|
|
46
51
|
});
|
|
47
52
|
|
|
53
|
+
// MECHANICAL is opt-in ONLY, through this label prefix ('mech-validate-json').
|
|
54
|
+
// No keyword fuzziness: 'validate-json' without the prefix stays VERIFICATION
|
|
55
|
+
// (protected). The prefix is an explicit authoring act — the author asserts
|
|
56
|
+
// "this check is binary and judgment-free", and the linter can then hold the
|
|
57
|
+
// script to it (a mech- leaf must carry model: 'sonnet', nothing else).
|
|
58
|
+
export const MECHANICAL_PREFIX = 'mech-';
|
|
59
|
+
|
|
48
60
|
// Label keyword sets, matched as substrings on the leaf LABEL (not the prompt —
|
|
49
61
|
// see classifyLeaf). Protected sets are checked first so any protected signal
|
|
50
62
|
// beats an exploration signal (conservative: when in doubt, do not downgrade).
|
|
@@ -73,6 +85,9 @@ function matchesAny(text, keywords) {
|
|
|
73
85
|
export function classifyLeaf(leaf) {
|
|
74
86
|
const label = String((leaf && leaf.label) || '').toLowerCase();
|
|
75
87
|
if (!label) return LEAF_TYPES.IMPLEMENTATION;
|
|
88
|
+
// Explicit opt-in beats every keyword class: 'mech-validate-json' contains a
|
|
89
|
+
// verification keyword, but the author's declared intent is the signal.
|
|
90
|
+
if (label.startsWith(MECHANICAL_PREFIX)) return LEAF_TYPES.MECHANICAL;
|
|
76
91
|
if (matchesAny(label, VERIFICATION_KEYWORDS)) return LEAF_TYPES.VERIFICATION;
|
|
77
92
|
if (matchesAny(label, ANALYSIS_KEYWORDS)) return LEAF_TYPES.ANALYSIS;
|
|
78
93
|
if (matchesAny(label, IMPLEMENTATION_KEYWORDS)) return LEAF_TYPES.IMPLEMENTATION;
|
|
@@ -80,13 +95,15 @@ export function classifyLeaf(leaf) {
|
|
|
80
95
|
return LEAF_TYPES.IMPLEMENTATION;
|
|
81
96
|
}
|
|
82
97
|
|
|
83
|
-
// tierFor(taskType) -> a TIERS value. Conservative auto-routing:
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
98
|
+
// tierFor(taskType) -> a TIERS value. Conservative auto-routing: EXPLORATION
|
|
99
|
+
// downgrades to cheap, MECHANICAL to balanced, every other type stays deep.
|
|
100
|
+
// BALANCED is reachable ONLY through the explicit mech- label opt-in (see
|
|
101
|
+
// MECHANICAL_PREFIX) — never through keyword classification — so automation
|
|
102
|
+
// still cannot land it on judgment-bearing work.
|
|
88
103
|
export function tierFor(taskType) {
|
|
89
|
-
|
|
104
|
+
if (taskType === LEAF_TYPES.EXPLORATION) return TIERS.CHEAP;
|
|
105
|
+
if (taskType === LEAF_TYPES.MECHANICAL) return TIERS.BALANCED;
|
|
106
|
+
return TIERS.DEEP;
|
|
90
107
|
}
|
|
91
108
|
|
|
92
109
|
// modelForLeaf({ label }) -> the opts.model value to write (a string) or null
|