create-byan-agent 2.25.0 → 2.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/CHANGELOG.md +155 -0
- package/README.md +9 -12
- package/install/bin/create-byan-agent-v2.js +29 -169
- package/install/lib/agent-generator.js +5 -5
- package/install/lib/byan-web-integration.js +1 -1
- package/install/lib/claude-native-setup.js +1 -1
- package/install/lib/phase2-chat.js +3 -10
- package/install/lib/platforms/claude-code.js +2 -2
- package/install/lib/platforms/index.js +0 -2
- package/install/lib/project-agents-generator.js +3 -3
- package/install/lib/staging-consent.js +3 -3
- package/install/lib/subagent-generator.js +3 -3
- package/install/lib/yanstaller/agent-launcher.js +1 -27
- package/install/lib/yanstaller/detector.js +4 -4
- package/install/lib/yanstaller/installer.js +0 -2
- package/install/lib/yanstaller/interviewer.js +1 -1
- package/install/lib/yanstaller/platform-selector.js +1 -13
- package/install/package.json +1 -1
- package/install/src/byan-v2/context/session-state.js +2 -2
- package/install/src/byan-v2/index.js +1 -5
- package/install/src/byan-v2/orchestrator/generation-state.js +4 -4
- package/install/src/webui/api.js +0 -2
- package/install/src/webui/chat/bridge.js +1 -13
- package/install/src/webui/chat/cli-detector.js +0 -23
- package/install/src/webui/public/app.js +1 -3
- package/install/src/webui/public/chat.html +0 -2
- package/install/src/webui/public/chat.js +0 -1
- package/install/src/webui/public/index.html +2 -2
- package/install/templates/.claude/CLAUDE.md +13 -2
- package/install/templates/.claude/agents/bmad-byan.md +1 -1
- package/install/templates/.claude/hooks/autobench-stop-guard.js +286 -0
- package/install/templates/.claude/hooks/fact-check-absolutes.js +1 -61
- package/install/templates/.claude/hooks/fact-check-claims.js +69 -0
- package/install/templates/.claude/hooks/fd-response-check.js +37 -46
- package/install/templates/.claude/hooks/inject-soul.js +64 -25
- package/install/templates/.claude/hooks/leantime-fd-sync.js +216 -0
- package/install/templates/.claude/hooks/lib/autobench-config.json +81 -0
- package/install/templates/.claude/hooks/lib/autobench-fc-enrich.js +251 -0
- package/install/templates/.claude/hooks/lib/autobench-ledger-report.js +253 -0
- package/install/templates/.claude/hooks/lib/autobench-runtime.js +199 -0
- package/install/templates/.claude/hooks/lib/fact-check-core.js +69 -0
- package/install/templates/.claude/hooks/lib/transcript-read.js +137 -0
- package/install/templates/.claude/hooks/soul-memory-check.js +49 -25
- package/install/templates/.claude/hooks/soul-memory-triggers.js +27 -8
- package/install/templates/.claude/hooks/stage-to-byan.js +25 -7
- package/install/templates/.claude/hooks/strict-stop-guard.js +4 -16
- package/install/templates/.claude/rules/benchmark.md +251 -0
- package/install/templates/.claude/rules/byan-agents.md +0 -1
- package/install/templates/.claude/rules/byan-api.md +64 -0
- package/install/templates/.claude/rules/fact-check.md +1 -1
- package/install/templates/.claude/rules/strict-mode.md +10 -9
- package/install/templates/.claude/settings.json +12 -0
- package/install/templates/.claude/skills/byan-benchmark/SKILL.md +159 -0
- package/install/templates/.claude/skills/byan-byan/SKILL.md +73 -12
- package/install/templates/.claude/skills/byan-fact-check/SKILL.md +1 -1
- package/install/templates/.claude/skills/byan-hermes-dispatch/SKILL.md +5 -6
- package/install/templates/.claude/skills/byan-orchestrate/SKILL.md +11 -3
- package/install/templates/.claude/skills/byan-strict/SKILL.md +4 -1
- package/install/templates/.claude/workflows/INDEX.md +2 -1
- package/install/templates/.claude/workflows/byan-benchmark.js +328 -0
- package/install/templates/_byan/_config/agent-manifest.csv +1 -1
- package/install/templates/_byan/_config/autobench.yaml +510 -0
- package/install/templates/_byan/_config/strict-mode.yaml +9 -3
- package/install/templates/_byan/_config/workflow-manifest.csv +1 -0
- package/install/templates/_byan/agent/byan/byan.md +1 -3
- package/install/templates/_byan/agent/byan-flat/byan.md +1 -3
- package/install/templates/_byan/agent/byan-test/byan-test.md +2 -2
- package/install/templates/_byan/agent/byan-test-flat/byan-test.md +2 -2
- package/install/templates/_byan/agent/byan.optimized/byan.optimized.md +2 -2
- package/install/templates/_byan/agent/byan.optimized-v2/byan.optimized-v2.md +2 -2
- package/install/templates/_byan/agent/claude/claude.md +0 -2
- package/install/templates/_byan/agent/codex/codex.md +0 -2
- package/install/templates/_byan/agent/rachid/rachid.md +2 -10
- package/install/templates/_byan/agent/rachid-flat/rachid.md +2 -11
- package/install/templates/_byan/agent/turbo-whisper/turbo-whisper.md +2 -5
- package/install/templates/_byan/agent/turbo-whisper-integration/turbo-whisper-integration.md +5 -13
- package/install/templates/_byan/agent/yanstaller/yanstaller.md +2 -24
- package/install/templates/_byan/config.yaml +0 -1
- package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-sync-rules.js +20 -4
- package/install/templates/_byan/mcp/byan-mcp-server/lib/advisory-autofeed.js +13 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/index-generator.js +1 -1
- package/install/templates/_byan/mcp/byan-mcp-server/lib/kanban.js +6 -3
- package/install/templates/_byan/mcp/byan-mcp-server/lib/leantime-fd-core.js +205 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/leantime-sync.js +415 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/precommit-gate.js +1 -1
- package/install/templates/_byan/mcp/byan-mcp-server/lib/strict-activation.js +1 -1
- package/install/templates/_byan/mcp/byan-mcp-server/lib/strict-mode.js +8 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/sync-rules.js +172 -23
- package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-generator.js +1 -0
- package/install/templates/_byan/mcp/byan-mcp-server/server.js +205 -82
- package/install/templates/_byan/worker/launchers/README.md +4 -24
- package/install/templates/_byan/worker/workers.md +0 -2
- package/install/templates/_byan/workflow/simple/bmb/byan-benchmark/workflow.md +86 -0
- package/install/templates/docs/leantime-integration.md +160 -0
- package/package.json +3 -7
- package/src/byan-v2/context/session-state.js +2 -2
- package/src/byan-v2/generation/mantra-validator.js +3 -3
- package/src/byan-v2/index.js +1 -5
- package/src/byan-v2/integration/voice-integration.js +1 -1
- package/src/byan-v2/orchestrator/generation-state.js +4 -4
- package/src/staging/staging.js +20 -6
- package/install/bin/build-copilot-stubs.js +0 -138
- package/install/lib/platforms/copilot-cli.js +0 -123
- package/install/lib/platforms/vscode.js +0 -51
- package/install/src/byan-v2/context/copilot-context.js +0 -79
- package/install/src/webui/chat/copilot-adapter.js +0 -68
- package/install/templates/.claude/agents/bmad-marc.md +0 -25
- package/install/templates/.claude/skills/byan-marc/SKILL.md +0 -20
- package/install/templates/.github/agents/bmad-agent-bmad-master.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmb-agent-builder.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmb-module-builder.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmb-workflow-builder.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmm-analyst.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmm-architect.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmm-dev.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmm-pm.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmm-quinn.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmm-sm.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmm-tech-writer.md +0 -16
- package/install/templates/.github/agents/bmad-agent-bmm-ux-designer.md +0 -16
- package/install/templates/.github/agents/bmad-agent-byan-test.md +0 -33
- package/install/templates/.github/agents/bmad-agent-byan-v2.md +0 -44
- package/install/templates/.github/agents/bmad-agent-byan.md +0 -1062
- package/install/templates/.github/agents/bmad-agent-carmack.md +0 -14
- package/install/templates/.github/agents/bmad-agent-cis-brainstorming-coach.md +0 -16
- package/install/templates/.github/agents/bmad-agent-cis-creative-problem-solver.md +0 -16
- package/install/templates/.github/agents/bmad-agent-cis-design-thinking-coach.md +0 -16
- package/install/templates/.github/agents/bmad-agent-cis-innovation-strategist.md +0 -16
- package/install/templates/.github/agents/bmad-agent-cis-presentation-master.md +0 -16
- package/install/templates/.github/agents/bmad-agent-cis-storyteller.md +0 -16
- package/install/templates/.github/agents/bmad-agent-claude.md +0 -49
- package/install/templates/.github/agents/bmad-agent-codex.md +0 -49
- package/install/templates/.github/agents/bmad-agent-drawio.md +0 -45
- package/install/templates/.github/agents/bmad-agent-fact-checker.md +0 -16
- package/install/templates/.github/agents/bmad-agent-forgeron.md +0 -15
- package/install/templates/.github/agents/bmad-agent-jimmy.md +0 -15
- package/install/templates/.github/agents/bmad-agent-marc.md +0 -49
- package/install/templates/.github/agents/bmad-agent-mike.md +0 -15
- package/install/templates/.github/agents/bmad-agent-patnote.md +0 -49
- package/install/templates/.github/agents/bmad-agent-rachid.md +0 -48
- package/install/templates/.github/agents/bmad-agent-skeptic.md +0 -16
- package/install/templates/.github/agents/bmad-agent-tao.md +0 -14
- package/install/templates/.github/agents/bmad-agent-tea-tea.md +0 -16
- package/install/templates/.github/agents/bmad-agent-test-dynamic.md +0 -22
- package/install/templates/.github/agents/bmad-agent-yanstaller-interview.md +0 -50
- package/install/templates/.github/agents/bmad-agent-yanstaller-phase2.md +0 -189
- package/install/templates/.github/agents/bmad-agent-yanstaller.md +0 -350
- package/install/templates/.github/agents/expert-merise-agile.md +0 -178
- package/install/templates/.github/agents/franck.md +0 -379
- package/install/templates/.github/agents/hermes.md +0 -575
- package/install/templates/.github/extensions/byan-staging/extension.mjs +0 -169
- package/install/templates/.github/extensions/byan-staging/package.json +0 -8
- package/install/templates/_byan/agent/marc/marc-soul.md +0 -47
- package/install/templates/_byan/agent/marc/marc-tao.md +0 -77
- package/install/templates/_byan/agent/marc/marc.md +0 -324
- package/install/templates/_byan/agent/marc-flat/marc.md +0 -387
- package/install/templates/_byan/mcp/byan-mcp-server/lib/copilot.js +0 -148
- package/install/templates/_byan/worker/launchers/launch-yanstaller-copilot.md +0 -173
- package/install/templates/workers/cost-optimizer.js +0 -169
- package/src/byan-v2/context/copilot-context.js +0 -79
|
@@ -19,7 +19,6 @@ Launcher workers are lightweight, single-purpose components that bridge the gap
|
|
|
19
19
|
```
|
|
20
20
|
┌─────────────────────────────────────────────────────────┐
|
|
21
21
|
│ USER INVOKES AGENT │
|
|
22
|
-
│ gh copilot @bmad-agent-marc │
|
|
23
22
|
│ claude --agent claude │
|
|
24
23
|
│ codex skill bmad-byan │
|
|
25
24
|
└─────────────┬───────────────────────────────────────────┘
|
|
@@ -54,18 +53,7 @@ Launcher workers are lightweight, single-purpose components that bridge the gap
|
|
|
54
53
|
|
|
55
54
|
## Workers
|
|
56
55
|
|
|
57
|
-
### 1. launch-yanstaller-
|
|
58
|
-
|
|
59
|
-
**Platform:** GitHub Copilot CLI
|
|
60
|
-
**Icon:** 🤖
|
|
61
|
-
**Command:** `npx create-byan-agent`
|
|
62
|
-
**Called by:** `@bmad-agent-marc`
|
|
63
|
-
|
|
64
|
-
**Purpose:** Launch yanstaller on Copilot CLI platform.
|
|
65
|
-
|
|
66
|
-
---
|
|
67
|
-
|
|
68
|
-
### 2. launch-yanstaller-claude.md
|
|
56
|
+
### 1. launch-yanstaller-claude.md
|
|
69
57
|
|
|
70
58
|
**Platform:** Claude Code
|
|
71
59
|
**Icon:** 🎭
|
|
@@ -79,7 +67,7 @@ Launcher workers are lightweight, single-purpose components that bridge the gap
|
|
|
79
67
|
|
|
80
68
|
---
|
|
81
69
|
|
|
82
|
-
###
|
|
70
|
+
### 2. launch-yanstaller-codex.md
|
|
83
71
|
|
|
84
72
|
**Platform:** Codex/OpenCode
|
|
85
73
|
**Icon:** 📝
|
|
@@ -107,7 +95,6 @@ Each worker has ONE task: Launch yanstaller command.
|
|
|
107
95
|
### Platform Hints
|
|
108
96
|
Workers set environment variables to help yanstaller detect platform:
|
|
109
97
|
```bash
|
|
110
|
-
BYAN_PLATFORM_HINT=copilot # For Copilot CLI
|
|
111
98
|
BYAN_PLATFORM_HINT=claude # For Claude Code
|
|
112
99
|
BYAN_PLATFORM_HINT=codex # For Codex
|
|
113
100
|
```
|
|
@@ -166,7 +153,7 @@ Can be run multiple times safely.
|
|
|
166
153
|
|
|
167
154
|
## Separation of Concerns
|
|
168
155
|
|
|
169
|
-
### Stub Agents (
|
|
156
|
+
### Stub Agents (claude/codex)
|
|
170
157
|
- Detect invocation
|
|
171
158
|
- Call launcher worker
|
|
172
159
|
- Minimal logic
|
|
@@ -185,7 +172,6 @@ Can be run multiple times safely.
|
|
|
185
172
|
- Platform-specific integration
|
|
186
173
|
- MCP server creation (Claude)
|
|
187
174
|
- Skill file creation (Codex)
|
|
188
|
-
- GitHub agent installation (Copilot)
|
|
189
175
|
|
|
190
176
|
---
|
|
191
177
|
|
|
@@ -196,7 +182,6 @@ _byan/
|
|
|
196
182
|
└── workers/
|
|
197
183
|
└── launchers/
|
|
198
184
|
├── README.md (this file)
|
|
199
|
-
├── launch-yanstaller-copilot.md
|
|
200
185
|
├── launch-yanstaller-claude.md
|
|
201
186
|
└── launch-yanstaller-codex.md
|
|
202
187
|
```
|
|
@@ -207,9 +192,6 @@ _byan/
|
|
|
207
192
|
|
|
208
193
|
### Manual Test
|
|
209
194
|
```bash
|
|
210
|
-
# Test Copilot launcher
|
|
211
|
-
node -e "require('./_byan/worker/launchers/worker-launch-yanstaller-copilot').launch()"
|
|
212
|
-
|
|
213
195
|
# Test Claude launcher
|
|
214
196
|
node -e "require('./_byan/worker/launchers/worker-launch-yanstaller-claude').launch()"
|
|
215
197
|
|
|
@@ -219,7 +201,7 @@ node -e "require('./_byan/worker/launchers/worker-launch-yanstaller-codex').laun
|
|
|
219
201
|
|
|
220
202
|
### Expected Output
|
|
221
203
|
```
|
|
222
|
-
|
|
204
|
+
🎭 Launching Yanstaller on Claude Code...
|
|
223
205
|
[Yanstaller interview UI appears]
|
|
224
206
|
```
|
|
225
207
|
|
|
@@ -287,7 +269,6 @@ install/
|
|
|
287
269
|
└── workers/
|
|
288
270
|
└── launchers/
|
|
289
271
|
├── README.md
|
|
290
|
-
├── launch-yanstaller-copilot.md
|
|
291
272
|
├── launch-yanstaller-claude.md
|
|
292
273
|
└── launch-yanstaller-codex.md
|
|
293
274
|
```
|
|
@@ -297,7 +278,6 @@ install/
|
|
|
297
278
|
## Version History
|
|
298
279
|
|
|
299
280
|
- **1.0.0** (2026-02-10): Initial release
|
|
300
|
-
- Copilot launcher
|
|
301
281
|
- Claude launcher
|
|
302
282
|
- Codex launcher
|
|
303
283
|
|
|
@@ -125,7 +125,6 @@ if (complexityScore < 30) {
|
|
|
125
125
|
**Utilisation :** Lancer yanstaller sur chaque plateforme
|
|
126
126
|
|
|
127
127
|
**Fichiers :**
|
|
128
|
-
- `_byan/worker/launchers/launch-yanstaller-copilot.md`
|
|
129
128
|
- `_byan/worker/launchers/launch-yanstaller-claude.md`
|
|
130
129
|
- `_byan/worker/launchers/launch-yanstaller-codex.md`
|
|
131
130
|
|
|
@@ -479,7 +478,6 @@ _byan/
|
|
|
479
478
|
└── workers/
|
|
480
479
|
└── launchers/
|
|
481
480
|
├── README.md
|
|
482
|
-
├── launch-yanstaller-copilot.md
|
|
483
481
|
├── launch-yanstaller-claude.md
|
|
484
482
|
└── launch-yanstaller-codex.md
|
|
485
483
|
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: byan-benchmark
|
|
3
|
+
description: 'DATA-only benchmark engine for any decision fork: options x weighted-criteria matrix + best-first reco + dissent. Markdown fallback for non-native platforms (dual-path).'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# byan-benchmark Workflow (markdown fallback)
|
|
7
|
+
|
|
8
|
+
**Goal:** Given a decision fork (>=2 non-substitutable options + weighted
|
|
9
|
+
criteria + an optional judge panel), produce a scored options-x-criteria matrix,
|
|
10
|
+
a best-first recommendation, and the dissenting view - as DATA. The human gate
|
|
11
|
+
and the rendered table live in the orchestrating `byan-benchmark` skill, not here.
|
|
12
|
+
|
|
13
|
+
**Your Role:** You are the benchmark engine. You score; the user decides. State
|
|
14
|
+
mutations (FD/strict) stay out of this workflow - that is the skill's job at the
|
|
15
|
+
gate.
|
|
16
|
+
|
|
17
|
+
This markdown is the dual-path FALLBACK. The native engine is
|
|
18
|
+
`.claude/workflows/byan-benchmark.js`; `resolveWorkflow('byan-benchmark')`
|
|
19
|
+
prefers the `.js` and falls back to this file on platforms without the native
|
|
20
|
+
Workflow tool.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## ARGS CONTRACT
|
|
25
|
+
|
|
26
|
+
- `question` - the fork stated as a question.
|
|
27
|
+
- `options` - array of `{ name, note? }` (>=2 for a real benchmark).
|
|
28
|
+
- `criteria` - array of `{ name, weight }` (>=1).
|
|
29
|
+
- `judges` - optional reusable panel `[{ key, lens, weighting }]`; default a
|
|
30
|
+
single neutral judge.
|
|
31
|
+
- `domain` - drives strict floors (`security`/`performance` -> L2, `compliance`
|
|
32
|
+
-> L1).
|
|
33
|
+
- `scope` - `internal` (no external links, coherence-first) or `external`
|
|
34
|
+
(sourcing allowed, but a URL only if opened this turn).
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## STEPS
|
|
39
|
+
|
|
40
|
+
### 1. RECON - parse the fork
|
|
41
|
+
|
|
42
|
+
Normalise `options` to `[{name, note?}]` and `criteria` to `[{name, weight}]`
|
|
43
|
+
(default weight 1). The fork is **valid** only if there are >=2 distinct,
|
|
44
|
+
non-substitutable options AND >=1 criterion. A degenerate / obvious-default fork
|
|
45
|
+
is not benchmarkable - return `degenerate: true` with a reason so the skill emits
|
|
46
|
+
a `BYAN-BENCH:skip` marker.
|
|
47
|
+
|
|
48
|
+
### 2. SOURCE - gather evidence per option
|
|
49
|
+
|
|
50
|
+
For each option, write one evidence note per criterion. Routing decides links
|
|
51
|
+
before depth: `internal` stays on model-knowledge with no external links;
|
|
52
|
+
`external` may cite a source, but a URL appears only if WebFetch opened it this
|
|
53
|
+
turn - otherwise the claim is `unverified: true`. Honour the strict domain floor.
|
|
54
|
+
|
|
55
|
+
### 3. JUDGE - score each cell
|
|
56
|
+
|
|
57
|
+
Per the judge panel (default neutral), score each option on each criterion 1-10,
|
|
58
|
+
grade the evidence level against the 5-level rubric (L1 95% spec -> L5 20%
|
|
59
|
+
opinion), and compute `weightedTotal = sum(score * weight)`. A cell below the
|
|
60
|
+
strict-domain floor is flagged `unverified: true`.
|
|
61
|
+
|
|
62
|
+
### 4. RECOMMEND - rank best-first + dissent
|
|
63
|
+
|
|
64
|
+
Consolidate the judges into one matrix, best-first by combined weighted total.
|
|
65
|
+
Recommend the winner with a one-line best-first reco. Use `confidence: assertive`
|
|
66
|
+
only when the winner leads by a wide margin and its key cells are verified;
|
|
67
|
+
otherwise use `confidence: lean` (low-confidence, hedged verb). Capture the
|
|
68
|
+
dissent: the runner-up a reasonable judge would defend and the criterion it wins on.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## RETURN (DATA only)
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{ "workflow": "byan-benchmark", "question": "...", "scope": "internal",
|
|
76
|
+
"domain": "general", "options": [...], "criteria": [...],
|
|
77
|
+
"matrix": [{ "option": "...", "cells": [{ "criterion": "...", "verdict": "...",
|
|
78
|
+
"level": "L2", "score": 8, "source": "...", "unverified": false }],
|
|
79
|
+
"total": 0 }],
|
|
80
|
+
"recommendation": { "best": "...", "line": "...", "confidence": "assertive|lean" },
|
|
81
|
+
"dissent": { "option": "...", "why": "..." },
|
|
82
|
+
"degenerate": false, "needsHumanGate": true }
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
No state mutation. No emoji. The skill renders the compact 1-table, emits the
|
|
86
|
+
BYAN-BENCH marker, and records state via MCP at the human gate.
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Leantime integration (one-way FD -> board)
|
|
2
|
+
|
|
3
|
+
BYAN can mirror its Feature Development (FD) lifecycle onto a self-hosted
|
|
4
|
+
Leantime board. The link is one-way: the FD workflow drives the Leantime board;
|
|
5
|
+
the board does not drive FD. The integration is optional and best-effort — when
|
|
6
|
+
it is not configured, or Leantime is unreachable, every FD phase still advances.
|
|
7
|
+
|
|
8
|
+
## What it does
|
|
9
|
+
|
|
10
|
+
When configured, the FD workflow fires `byan_leantime_*` MCP tools at phase
|
|
11
|
+
events:
|
|
12
|
+
|
|
13
|
+
| FD phase / event | Effect on the board |
|
|
14
|
+
|------------------|---------------------|
|
|
15
|
+
| DISCOVERY (project confirmed) | create-or-fetch the Leantime project |
|
|
16
|
+
| DISPATCH (per backlog feature) | one task per feature |
|
|
17
|
+
| BUILD (feature starts) | task -> column `doing` |
|
|
18
|
+
| REVIEW needs-rework / VALIDATE KO | task -> column `blocked` |
|
|
19
|
+
| VALIDATE OK | task -> column `review` |
|
|
20
|
+
| DOC done / feature completed | task -> column `done` |
|
|
21
|
+
|
|
22
|
+
The FD lifecycle columns (`todo|doing|blocked|review|done`) are resolved to the
|
|
23
|
+
project's configured Leantime status ids at call time (statuses are per-project
|
|
24
|
+
ints), with a conservative fallback when the labels cannot be read.
|
|
25
|
+
|
|
26
|
+
## Automatic sync (the leantime-fd-sync hook)
|
|
27
|
+
|
|
28
|
+
You do not call the `byan_leantime_*` tools by hand. A Claude Code `PostToolUse`
|
|
29
|
+
hook (`.claude/hooks/leantime-fd-sync.js`, registered in `.claude/settings.json`)
|
|
30
|
+
fires after `byan_fd_advance` / `byan_fd_update` and applies the table above with
|
|
31
|
+
no agent action:
|
|
32
|
+
|
|
33
|
+
- It reads the fd-state the MCP tool echoes (it does not read or write
|
|
34
|
+
`fd-state.json`) and keeps the Leantime id map in a gitignored sidecar
|
|
35
|
+
`.byan-leantime/map.json` keyed by `fd_id`.
|
|
36
|
+
- The sidecar is the idempotence ledger: a project or task is created only when
|
|
37
|
+
its id is absent, so a REFACTOR loop re-builds without a duplicate.
|
|
38
|
+
- It is best-effort and bounded: it exits 0 in every path (a sync issue does not
|
|
39
|
+
block the turn), no-ops when Leantime is off, and self-heals a dropped call on
|
|
40
|
+
the next phase event (a per-call timeout plus a hook wall-clock budget).
|
|
41
|
+
- It logs every attempt to `.byan-leantime/sync.jsonl` and surfaces a one-line
|
|
42
|
+
notice only on a real failure (`non_json` / `timeout` / `http_*` / `rpc_error`).
|
|
43
|
+
|
|
44
|
+
The pure decision logic lives in
|
|
45
|
+
`_byan/mcp/byan-mcp-server/lib/leantime-fd-core.js` (`decideActions`); the hook is
|
|
46
|
+
a thin I/O shell. Removing the hook from `.claude/settings.json` falls back to the
|
|
47
|
+
manual MCP tools below.
|
|
48
|
+
|
|
49
|
+
### Human visibility (auto-assign)
|
|
50
|
+
|
|
51
|
+
A project created through the API is owned by the API service user, so it stays
|
|
52
|
+
hidden from a person's project selector until that person is related to it. Set
|
|
53
|
+
`LEANTIME_ASSIGN_USER_ID` to your Leantime user id and the hook relates you to the
|
|
54
|
+
created project (and sets you as the default task assignee). The underlying RPC
|
|
55
|
+
(`editUserProjectRelations`) reconciles a user's whole project list, so the assign
|
|
56
|
+
reads your current projects first and writes the union — fail-closed if that read
|
|
57
|
+
is incomplete, to avoid unassigning your other projects.
|
|
58
|
+
|
|
59
|
+
## Configuration
|
|
60
|
+
|
|
61
|
+
Two environment variables drive the integration. They are distinct from
|
|
62
|
+
`BYAN_API_URL` (byan_web) — Leantime is a separate backend.
|
|
63
|
+
|
|
64
|
+
| Var | Role |
|
|
65
|
+
|-----|------|
|
|
66
|
+
| `LEANTIME_API_URL` | Base of the Leantime instance: the host that serves `/api/jsonrpc` (the backend), without a trailing `/api` — the client appends `/api/jsonrpc`. |
|
|
67
|
+
| `LEANTIME_API_TOKEN` | The Leantime API key, sent as the `x-api-key` header. |
|
|
68
|
+
| `LEANTIME_CLIENT_ID` | Optional. clientId for project creation (otherwise the first client returned, else 1). |
|
|
69
|
+
| `LEANTIME_ASSIGN_USER_ID` | Optional. Your Leantime user id; the hook relates you to the created project (so it shows in your selector) and sets you as the default task assignee. Absent -> the project is visible only to the API service user. |
|
|
70
|
+
|
|
71
|
+
Put the secret in `.claude/settings.local.json` (gitignored), out of any tracked
|
|
72
|
+
file:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"env": {
|
|
77
|
+
"LEANTIME_API_URL": "https://your-leantime-host",
|
|
78
|
+
"LEANTIME_API_TOKEN": "lt_xxxxxxxx"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`.mcp.json` references these as `${LEANTIME_API_URL}` / `${LEANTIME_API_TOKEN}`
|
|
84
|
+
(env expansion), so the secret stays out of version control. Reconnect the MCP
|
|
85
|
+
server after editing `settings.local.json`.
|
|
86
|
+
|
|
87
|
+
When the pair is absent, the `byan_leantime_*` tools report `enabled: false` and
|
|
88
|
+
the FD proceeds unchanged.
|
|
89
|
+
|
|
90
|
+
## Generating the Leantime API key
|
|
91
|
+
|
|
92
|
+
Verified against Leantime source (3.7.x). Two credential types, both sent as the
|
|
93
|
+
`x-api-key` header.
|
|
94
|
+
|
|
95
|
+
### API key (service account — recommended for BYAN)
|
|
96
|
+
|
|
97
|
+
1. Log in to Leantime with an Admin or Owner account.
|
|
98
|
+
2. Open **Company Settings** (cogs icon). In a French UI the tab is labeled
|
|
99
|
+
**"Cle d'API"** (i18n key `tabs.apiKeys`), not "API" — a common reason the
|
|
100
|
+
option seems missing.
|
|
101
|
+
3. Click **Generate API Key**, set a role + project scope, then Save.
|
|
102
|
+
4. Copy the secret at once — it is shown one time, then hashed in the database.
|
|
103
|
+
The value carries an `lt_` prefix.
|
|
104
|
+
|
|
105
|
+
Direct URL to the create form: `{host}/api/newApiKey`. A redirect to a 403 there
|
|
106
|
+
means the account is below the role gate (`NewApiKey::run()` requires
|
|
107
|
+
owner/admin); that gate is the usual reason a non-admin user does not see the
|
|
108
|
+
menu.
|
|
109
|
+
|
|
110
|
+
In Leantime an API key is implemented as a service user
|
|
111
|
+
(`zp_user.source='api'`), so there is no separate "api keys" database table.
|
|
112
|
+
|
|
113
|
+
### Personal Access Token (per user)
|
|
114
|
+
|
|
115
|
+
Profile -> "Personal Access Tokens" tab. This tab is present when the Advanced
|
|
116
|
+
Auth plugin is installed (self-hosted). Without it, use the API key above.
|
|
117
|
+
|
|
118
|
+
There is no `.env` flag to enable the API: `/api/jsonrpc` is part of Leantime
|
|
119
|
+
core; the access barrier is the role.
|
|
120
|
+
|
|
121
|
+
## Tools
|
|
122
|
+
|
|
123
|
+
| Tool | Role |
|
|
124
|
+
|------|------|
|
|
125
|
+
| `byan_leantime_ping` | Healthcheck: reports api_url, token_configured, enabled, reachable. Does not throw. |
|
|
126
|
+
| `byan_leantime_project_ensure` | Create-or-fetch a project by name (idempotent), returns the id. |
|
|
127
|
+
| `byan_leantime_task_create` | Create a task from a backlog item, returns the task id. |
|
|
128
|
+
| `byan_leantime_task_move` | Move a task to a column (`todo\|doing\|blocked\|review\|done`). |
|
|
129
|
+
| `byan_leantime_task_assign` | Set the assignee (editorId). |
|
|
130
|
+
| `byan_leantime_task_get` | Read a task by id. |
|
|
131
|
+
| `byan_leantime_board_get` | Read a project board grouped by column. |
|
|
132
|
+
|
|
133
|
+
Every tool except `byan_leantime_ping` is gated by `requireLeantime` (returns a
|
|
134
|
+
clear error when the env pair is absent rather than calling an unconfigured
|
|
135
|
+
host).
|
|
136
|
+
|
|
137
|
+
## Troubleshooting
|
|
138
|
+
|
|
139
|
+
Each call returns `{ ok, synced, reason? }`. A non-synced result surfaces a
|
|
140
|
+
reason instead of pretending the board moved:
|
|
141
|
+
|
|
142
|
+
| reason | meaning + fix |
|
|
143
|
+
|--------|---------------|
|
|
144
|
+
| `no_base` / `no_token` | The integration is off (env not set). Configure the pair. |
|
|
145
|
+
| `non_json` | `LEANTIME_API_URL` points at the Leantime UI host, which returned an HTML login page instead of JSON-RPC. Point it at the backend host that serves `/api/jsonrpc`. |
|
|
146
|
+
| `timeout` / `http_<status>` / `rpc_error` | Transient or wire issue. The FD phase still advances; the move retries at the next phase event. |
|
|
147
|
+
| `create_rejected` | The server returned a falsy id for a create. Inspect the returned data. |
|
|
148
|
+
| `unresolved_status` | A column could not be mapped to a Leantime status id for this project. |
|
|
149
|
+
|
|
150
|
+
## Security
|
|
151
|
+
|
|
152
|
+
The API key lives only in `.claude/settings.local.json` (gitignored at both repo
|
|
153
|
+
and global level). The tracked `.mcp.json` carries only `${...}` placeholders.
|
|
154
|
+
`byan_leantime_ping` reports `token_configured` as a boolean and does not echo
|
|
155
|
+
the token.
|
|
156
|
+
|
|
157
|
+
## See also
|
|
158
|
+
|
|
159
|
+
- Agent-facing reference (compact): `.claude/rules/byan-api.md` section 8.
|
|
160
|
+
- FD wiring (fire points per phase): `.claude/skills/byan-byan/SKILL.md` section 2.5.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-byan-agent",
|
|
3
|
-
"version": "2.
|
|
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 (
|
|
3
|
+
"version": "2.26.0",
|
|
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": {
|
|
7
7
|
"create-byan-agent": "./install/bin/create-byan-agent-v2.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"test:watch": "jest --watch",
|
|
18
18
|
"test:e2e": "jest install/__tests__/post-install.e2e.test.js",
|
|
19
19
|
"setup-turbo-whisper": "node install/setup-turbo-whisper.js",
|
|
20
|
-
"byan": "echo \"BYAN agent installed.
|
|
20
|
+
"byan": "echo \"BYAN agent installed. Open Claude Code (or Codex) in this project.\"",
|
|
21
21
|
"version": "node scripts/sync-install-version.js && git add install/package.json",
|
|
22
22
|
"app:dev": "npm --prefix app run dev",
|
|
23
23
|
"app:build": "npm --prefix app run build",
|
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
"ai",
|
|
30
30
|
"multi-agent",
|
|
31
31
|
"workflow",
|
|
32
|
-
"github-copilot",
|
|
33
32
|
"agent-builder",
|
|
34
33
|
"bmad",
|
|
35
34
|
"merise-agile",
|
|
@@ -118,8 +117,5 @@
|
|
|
118
117
|
"statements": 80
|
|
119
118
|
}
|
|
120
119
|
}
|
|
121
|
-
},
|
|
122
|
-
"optionalDependencies": {
|
|
123
|
-
"byan-copilot-router": "^1.0.1"
|
|
124
120
|
}
|
|
125
121
|
}
|
|
@@ -23,9 +23,9 @@ class MantraValidator {
|
|
|
23
23
|
this.agentContent = null;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// Strict-mode artifacts (the byan-strict skill, AGENTS.md block
|
|
27
|
-
//
|
|
28
|
-
//
|
|
26
|
+
// Strict-mode artifacts (the byan-strict skill, AGENTS.md block) are
|
|
27
|
+
// validated against the strict mantra set, not the 64 persona mantras.
|
|
28
|
+
// The set is generated by byan-sync-rules from strict-mode.yaml.
|
|
29
29
|
_loadStrictMantras() {
|
|
30
30
|
try {
|
|
31
31
|
const p = path.join(__dirname, '../data/strict-mantras.json');
|
package/src/byan-v2/index.js
CHANGED
|
@@ -182,16 +182,12 @@ class ByanV2 {
|
|
|
182
182
|
medium: 60
|
|
183
183
|
},
|
|
184
184
|
outputDir: './_byan-output',
|
|
185
|
-
env: customConfig.env ||
|
|
185
|
+
env: customConfig.env || 'standalone'
|
|
186
186
|
};
|
|
187
187
|
|
|
188
188
|
return { ...defaults, ...customConfig };
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
isCopilotContext() {
|
|
192
|
-
return this.config.env === 'copilot' || process.env.GITHUB_COPILOT === 'true';
|
|
193
|
-
}
|
|
194
|
-
|
|
195
191
|
async startSession() {
|
|
196
192
|
this.logger.info('Starting BYAN session', {
|
|
197
193
|
event: 'session_start',
|
|
@@ -9,7 +9,7 @@ const execAsync = promisify(exec);
|
|
|
9
9
|
* VoiceIntegration - Turbo Whisper voice input integration for BYAN v2
|
|
10
10
|
*
|
|
11
11
|
* Enables voice-driven agent interaction through Turbo Whisper transcription.
|
|
12
|
-
* Supports
|
|
12
|
+
* Supports Claude Code and Codex platforms.
|
|
13
13
|
*
|
|
14
14
|
* @version 2.1.0
|
|
15
15
|
* @module integration/voice-integration
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* GenerationState - Story 4.4
|
|
3
|
-
* Generates agent profile in BMAD
|
|
4
|
-
*
|
|
3
|
+
* Generates agent profile in BMAD format
|
|
4
|
+
*
|
|
5
5
|
* Format:
|
|
6
6
|
* - YAML frontmatter (name, description)
|
|
7
7
|
* - XML structure (<agent>, <persona>, <menu>, <capabilities>)
|
|
8
|
-
* -
|
|
8
|
+
* - Saved under the _byan/agent/ layout
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
const Logger = require('../observability/logger');
|
|
@@ -178,7 +178,7 @@ class GenerationState {
|
|
|
178
178
|
*/
|
|
179
179
|
getDefaultSavePath() {
|
|
180
180
|
const name = this.sessionState.agentProfileDraft?.name || 'agent';
|
|
181
|
-
return
|
|
181
|
+
return `_byan/agent/${name}/${name}.md`;
|
|
182
182
|
}
|
|
183
183
|
|
|
184
184
|
/**
|
package/src/staging/staging.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* BYAN staging core — extract / filter / dedup / queue / flush conversation
|
|
3
|
-
* knowledge from any supported CLI (claude-code,
|
|
3
|
+
* knowledge from any supported CLI (claude-code, codex) to a
|
|
4
4
|
* byan_web instance via POST /api/memory.
|
|
5
5
|
*
|
|
6
6
|
* Usage from a Claude Code Stop hook :
|
|
7
7
|
* const { processTurn } = require('./staging');
|
|
8
8
|
* await processTurn({ turn, cliSource: 'claude-code', config, projectRoot });
|
|
9
9
|
*
|
|
10
|
-
* Usage from a Copilot CLI extension.mjs :
|
|
11
|
-
* import { processTurn } from '<repo>/src/staging/staging.js';
|
|
12
|
-
* await processTurn({ turn, cliSource: 'copilot-cli', config, projectRoot });
|
|
13
|
-
*
|
|
14
10
|
* Contract :
|
|
15
11
|
* - processTurn() is idempotent (dedup by content hash)
|
|
16
12
|
* - never throws — errors go to the retry queue
|
|
@@ -304,7 +300,25 @@ async function postEntry({ entry, url, token, projectId }) {
|
|
|
304
300
|
err.status = res.status;
|
|
305
301
|
throw err;
|
|
306
302
|
}
|
|
307
|
-
|
|
303
|
+
// A 2xx is necessary but not sufficient: an authentik/SSO proxy answers an
|
|
304
|
+
// unauthenticated API call with 200 + an HTML login page. Swallowing that as
|
|
305
|
+
// success (the old res.json().catch(()=>({}))) silently drops the turn while
|
|
306
|
+
// reporting "flushed". Require the body to actually parse as JSON; otherwise
|
|
307
|
+
// treat it as a failure so it surfaces as a visible last_error in the queue.
|
|
308
|
+
const text = await res.text();
|
|
309
|
+
// An empty 2xx body (e.g. 204 No Content) is a benign success, not a wall —
|
|
310
|
+
// the SSO wall always carries an HTML body. Do not invert it into a failure.
|
|
311
|
+
if (!text || !text.trim()) return {};
|
|
312
|
+
try {
|
|
313
|
+
return JSON.parse(text);
|
|
314
|
+
} catch {
|
|
315
|
+
const ct = res.headers.get('content-type') || 'none';
|
|
316
|
+
const err = new Error(
|
|
317
|
+
`non-JSON 2xx (likely an auth/SSO wall; content-type ${ct}): ${text.slice(0, 120).replace(/\s+/g, ' ')}`
|
|
318
|
+
);
|
|
319
|
+
err.status = res.status;
|
|
320
|
+
throw err;
|
|
321
|
+
}
|
|
308
322
|
}
|
|
309
323
|
|
|
310
324
|
async function flush({ config, projectRoot, maxAttempts = 5 } = {}) {
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Build Copilot CLI agent stubs from BYAN source files.
|
|
5
|
-
*
|
|
6
|
-
* Copilot CLI treats .github/agents/*.md as system instructions.
|
|
7
|
-
* It does NOT dynamically load files referenced in the content.
|
|
8
|
-
* This script inlines the full agent + soul + tao content into
|
|
9
|
-
* each stub so Copilot CLI has everything it needs.
|
|
10
|
-
*
|
|
11
|
-
* Usage: node build-copilot-stubs.js [--agent byan] [--all]
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const fs = require('fs');
|
|
15
|
-
const path = require('path');
|
|
16
|
-
const layoutResolver = require('../../src/byan-v2/lib/layout-resolver');
|
|
17
|
-
|
|
18
|
-
const ROOT = path.resolve(__dirname, '..', '..');
|
|
19
|
-
const AGENTS_DIR = path.join(ROOT, '.github', 'agents');
|
|
20
|
-
const BYAN_DIR = path.join(ROOT, '_byan');
|
|
21
|
-
|
|
22
|
-
function readFile(filePath) {
|
|
23
|
-
try {
|
|
24
|
-
return fs.readFileSync(filePath, 'utf-8');
|
|
25
|
-
} catch {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function stripFrontmatter(content) {
|
|
31
|
-
return content.replace(/^---\s*\n[\s\S]*?\n---\s*\n?/, '');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function buildByanStub() {
|
|
35
|
-
// Layout resolver: Gen3 _byan/agent/byan/ first, Gen2 fallback.
|
|
36
|
-
const agentHit = layoutResolver.resolveAgent('byan', { projectRoot: ROOT });
|
|
37
|
-
const agentContent = agentHit ? readFile(agentHit.path) : null;
|
|
38
|
-
if (!agentContent) {
|
|
39
|
-
console.error('Cannot find the byan agent file (looked in Gen3 _byan/agent/byan/ and Gen2 layouts)');
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const soulHit = layoutResolver.resolveSoul('soul', { projectRoot: ROOT });
|
|
44
|
-
const taoHit = layoutResolver.resolveSoul('tao', { projectRoot: ROOT });
|
|
45
|
-
const soulContent = soulHit ? readFile(soulHit.path) : null;
|
|
46
|
-
const taoContent = taoHit ? readFile(taoHit.path) : null;
|
|
47
|
-
const soulActivation = readFile(path.join(BYAN_DIR, 'core', 'activation', 'soul-activation.md'));
|
|
48
|
-
|
|
49
|
-
const agentBody = stripFrontmatter(agentContent);
|
|
50
|
-
const soulBody = soulContent ? stripFrontmatter(soulContent) : '';
|
|
51
|
-
const taoBody = taoContent ? stripFrontmatter(taoContent) : '';
|
|
52
|
-
const activationBody = soulActivation ? stripFrontmatter(soulActivation) : '';
|
|
53
|
-
|
|
54
|
-
const stub = `---
|
|
55
|
-
name: 'byan'
|
|
56
|
-
description: 'BYAN - Builder of YAN - Agent Creator Specialist'
|
|
57
|
-
---
|
|
58
|
-
|
|
59
|
-
${agentBody}
|
|
60
|
-
|
|
61
|
-
<!-- ============================================================ -->
|
|
62
|
-
<!-- INLINED: Soul System (soul.md + tao.md + soul-activation.md) -->
|
|
63
|
-
<!-- ============================================================ -->
|
|
64
|
-
|
|
65
|
-
<soul-system>
|
|
66
|
-
|
|
67
|
-
<!-- soul.md -->
|
|
68
|
-
${soulBody}
|
|
69
|
-
|
|
70
|
-
<!-- tao.md -->
|
|
71
|
-
${taoBody}
|
|
72
|
-
|
|
73
|
-
<!-- soul-activation.md -->
|
|
74
|
-
${activationBody}
|
|
75
|
-
|
|
76
|
-
</soul-system>
|
|
77
|
-
`;
|
|
78
|
-
|
|
79
|
-
const outPath = path.join(AGENTS_DIR, 'bmad-agent-byan.md');
|
|
80
|
-
fs.writeFileSync(outPath, stub, 'utf-8');
|
|
81
|
-
|
|
82
|
-
const size = Buffer.byteLength(stub, 'utf-8');
|
|
83
|
-
console.log(`Built: ${outPath} (${(size / 1024).toFixed(1)} KB)`);
|
|
84
|
-
return outPath;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function buildModuleAgentStub(agentName, moduleName) {
|
|
88
|
-
// Resolve the agent across layouts (Gen3 _byan/agent/<name>/, Gen2 flat +
|
|
89
|
-
// per-module); fall back to the explicit module path passed on the CLI.
|
|
90
|
-
const agentHit = layoutResolver.resolveAgent(agentName, { projectRoot: ROOT });
|
|
91
|
-
const agentPath = agentHit ? agentHit.path : path.join(BYAN_DIR, moduleName, 'agents', `${agentName}.md`);
|
|
92
|
-
const agentContent = readFile(agentPath);
|
|
93
|
-
if (!agentContent) {
|
|
94
|
-
console.error(`Cannot read agent ${agentName} (looked via resolver and ${path.relative(ROOT, agentPath)})`);
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const agentBody = stripFrontmatter(agentContent);
|
|
99
|
-
|
|
100
|
-
// Soul sibling lives next to the resolved agent file.
|
|
101
|
-
const soulPath = path.join(path.dirname(agentPath), `${agentName}-soul.md`);
|
|
102
|
-
const soulContent = readFile(soulPath);
|
|
103
|
-
const soulSection = soulContent ? `\n<!-- soul: ${agentName}-soul.md -->\n${stripFrontmatter(soulContent)}\n` : '';
|
|
104
|
-
|
|
105
|
-
const stub = `---
|
|
106
|
-
name: '${agentName}'
|
|
107
|
-
description: '${agentName} agent'
|
|
108
|
-
---
|
|
109
|
-
|
|
110
|
-
${agentBody}
|
|
111
|
-
${soulSection}
|
|
112
|
-
`;
|
|
113
|
-
|
|
114
|
-
const outPath = path.join(AGENTS_DIR, `bmad-agent-${agentName}.md`);
|
|
115
|
-
fs.writeFileSync(outPath, stub, 'utf-8');
|
|
116
|
-
|
|
117
|
-
const size = Buffer.byteLength(stub, 'utf-8');
|
|
118
|
-
console.log(`Built: ${outPath} (${(size / 1024).toFixed(1)} KB)`);
|
|
119
|
-
return outPath;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// --- CLI ---
|
|
123
|
-
const args = process.argv.slice(2);
|
|
124
|
-
const agentArg = args.indexOf('--agent') >= 0 ? args[args.indexOf('--agent') + 1] : null;
|
|
125
|
-
const buildAll = args.includes('--all');
|
|
126
|
-
|
|
127
|
-
if (agentArg === 'byan' || buildAll || args.length === 0) {
|
|
128
|
-
buildByanStub();
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
if (agentArg && agentArg !== 'byan') {
|
|
132
|
-
const mod = args.indexOf('--module') >= 0 ? args[args.indexOf('--module') + 1] : 'bmm';
|
|
133
|
-
buildModuleAgentStub(agentArg, mod);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (buildAll || args.length === 0) {
|
|
137
|
-
console.log('\nDone. Run this after editing _byan/agents/byan.md, soul.md, or tao.md.');
|
|
138
|
-
}
|