create-byan-agent 2.42.0 ā 2.44.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 +93 -0
- package/install/bin/byan-kanban.js +1 -1
- package/install/bin/create-byan-agent-v2.js +111 -111
- package/install/lib/byan-leantime-integration.js +2 -2
- package/install/lib/byan-web-integration.js +5 -5
- package/install/lib/claude-native-setup.js +11 -11
- package/install/lib/codex-native-setup.js +3 -3
- package/install/lib/exchange/agent-packager.js +1 -1
- package/install/lib/mcp-extensions/gdrive.js +5 -5
- package/install/lib/mcp-extensions/index.js +5 -5
- package/install/lib/phase2-chat.js +21 -21
- package/install/lib/platforms/claude-code.js +2 -2
- package/install/lib/project-agents-generator.js +4 -4
- package/install/lib/staging-consent.js +1 -1
- package/install/lib/subagent-generator.js +2 -3
- package/install/lib/utils/logger.js +4 -4
- package/install/lib/utils/node-detector.js +1 -1
- package/install/lib/yanstaller/agent-launcher.js +1 -1
- package/install/lib/yanstaller/index.js +11 -116
- package/install/lib/yanstaller/platform-selector.js +11 -11
- package/install/src/byan-v2/dispatcher/task-router.js +1 -1
- package/install/src/index.js +1 -1
- package/install/src/webui/api.js +0 -13
- package/install/src/webui/chat/bridge.js +1 -1
- package/install/src/webui/chat/cli-detector.js +1 -1
- package/install/templates/.claude/rules/native-workflows.md +22 -14
- package/install/templates/_byan/COMPLETION-REPORT.md +0 -1
- package/install/templates/_byan/core/activation/soul-activation.md +3 -3
- package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-lint-workflows.js +6 -3
- package/install/templates/_byan/mcp/byan-mcp-server/lib/native-tiers.js +35 -17
- package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-lint.js +38 -0
- package/install/templates/_byan/worker/workers.md +1 -1
- package/package.json +1 -1
- package/src/byan-v2/dispatcher/task-router.js +1 -1
- package/src/byan-v2/lib/layout-resolver.js +3 -6
- package/install/lib/yanstaller/installer.js +0 -138
- package/install/lib/yanstaller/interviewer.js +0 -88
- package/install/lib/yanstaller/recommender.js +0 -102
- package/install/lib/yanstaller/troubleshooter.js +0 -89
- package/install/lib/yanstaller/validator.js +0 -198
- package/install/lib/yanstaller/wizard.js +0 -109
- package/install/src/byan-v2/dispatcher/task-tool-interface-mock.js +0 -134
- package/install/src/byan-v2/dispatcher/task-tool-interface.js +0 -123
- package/install/templates/_bmad/bmb/agents/agent-builder.md +0 -59
- package/install/templates/_bmad/bmb/agents/byan-test.md +0 -116
- package/install/templates/_bmad/bmb/agents/byan.md +0 -215
- package/install/templates/_bmad/bmb/agents/marc.md +0 -303
- package/install/templates/_bmad/bmb/agents/module-builder.md +0 -60
- package/install/templates/_bmad/bmb/agents/patnote.md +0 -495
- package/install/templates/_bmad/bmb/agents/rachid.md +0 -184
- package/install/templates/_bmad/bmb/agents/workflow-builder.md +0 -61
- package/install/templates/_bmad/bmb/workflows/byan/data/mantras.yaml +0 -272
- package/install/templates/_bmad/bmb/workflows/byan/data/templates.yaml +0 -59
- package/install/templates/_bmad/bmb/workflows/byan/delete-agent-workflow.md +0 -657
- package/install/templates/_bmad/bmb/workflows/byan/edit-agent-workflow.md +0 -688
- package/install/templates/_bmad/bmb/workflows/byan/interview-workflow.md +0 -753
- package/install/templates/_bmad/bmb/workflows/byan/quick-create-workflow.md +0 -450
- package/install/templates/_bmad/bmb/workflows/byan/templates/base-agent-template.md +0 -79
- package/install/templates/_bmad/bmb/workflows/byan/validate-agent-workflow.md +0 -676
- package/install/templates/_bmad/core/agents/carmack.md +0 -238
- package/src/byan-v2/dispatcher/task-tool-interface-mock.js +0 -134
- package/src/byan-v2/dispatcher/task-tool-interface.js +0 -123
|
@@ -33,13 +33,13 @@ const PLATFORM_INFO = {
|
|
|
33
33
|
displayName: 'Claude Code',
|
|
34
34
|
native: true,
|
|
35
35
|
specialist: 'claude',
|
|
36
|
-
icon: '
|
|
36
|
+
icon: ''
|
|
37
37
|
},
|
|
38
38
|
'codex': {
|
|
39
39
|
displayName: 'OpenCode/Codex',
|
|
40
40
|
native: true, // NOW NATIVE!
|
|
41
41
|
specialist: 'codex',
|
|
42
|
-
icon: '
|
|
42
|
+
icon: ''
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
45
|
|
|
@@ -50,7 +50,7 @@ const PLATFORM_INFO = {
|
|
|
50
50
|
* @returns {Promise<PlatformSelectionResult>}
|
|
51
51
|
*/
|
|
52
52
|
async function select(detectionResult) {
|
|
53
|
-
logger.info('\
|
|
53
|
+
logger.info('\nPlatform Selection\n');
|
|
54
54
|
|
|
55
55
|
// Build platform choices from detection
|
|
56
56
|
const choices = buildChoices(detectionResult.platforms);
|
|
@@ -75,7 +75,7 @@ async function select(detectionResult) {
|
|
|
75
75
|
{
|
|
76
76
|
type: 'list',
|
|
77
77
|
name: 'primary',
|
|
78
|
-
message: '
|
|
78
|
+
message: 'Choose your PRIMARY platform for native agent invocation:',
|
|
79
79
|
choices: [
|
|
80
80
|
...nativePlatforms.map(c => ({
|
|
81
81
|
name: `${c.icon} ${c.name} - ${c.agentSpecialist ? `@bmad-agent-${c.agentSpecialist}` : 'No specialist'}`,
|
|
@@ -84,11 +84,11 @@ async function select(detectionResult) {
|
|
|
84
84
|
})),
|
|
85
85
|
new inquirer.Separator(),
|
|
86
86
|
{
|
|
87
|
-
name: '
|
|
87
|
+
name: 'Advanced: Install on multiple platforms',
|
|
88
88
|
value: 'multi'
|
|
89
89
|
},
|
|
90
90
|
{
|
|
91
|
-
name: '
|
|
91
|
+
name: 'Skip native integration (manual install only)',
|
|
92
92
|
value: 'skip'
|
|
93
93
|
}
|
|
94
94
|
]
|
|
@@ -125,7 +125,7 @@ async function select(detectionResult) {
|
|
|
125
125
|
message: 'Choose installation target:',
|
|
126
126
|
choices: [
|
|
127
127
|
{
|
|
128
|
-
name:
|
|
128
|
+
name: `Auto (detect & install all available) - ${choices.length} platform(s)`,
|
|
129
129
|
value: 'auto'
|
|
130
130
|
},
|
|
131
131
|
...choices.map(c => ({
|
|
@@ -133,7 +133,7 @@ async function select(detectionResult) {
|
|
|
133
133
|
value: `single:${c.id}`
|
|
134
134
|
})),
|
|
135
135
|
{
|
|
136
|
-
name: '
|
|
136
|
+
name: 'Custom (select multiple)',
|
|
137
137
|
value: 'custom'
|
|
138
138
|
}
|
|
139
139
|
]
|
|
@@ -167,7 +167,7 @@ function buildChoices(detectedPlatforms) {
|
|
|
167
167
|
displayName: p.name,
|
|
168
168
|
native: false,
|
|
169
169
|
specialist: null,
|
|
170
|
-
icon: '
|
|
170
|
+
icon: ''
|
|
171
171
|
};
|
|
172
172
|
|
|
173
173
|
return {
|
|
@@ -189,8 +189,8 @@ function buildChoices(detectedPlatforms) {
|
|
|
189
189
|
* @returns {string}
|
|
190
190
|
*/
|
|
191
191
|
function formatPlatformChoice(choice) {
|
|
192
|
-
const nativeBadge = choice.native ? '
|
|
193
|
-
const statusBadge = choice.detected ? '
|
|
192
|
+
const nativeBadge = choice.native ? 'Native' : 'Conversational';
|
|
193
|
+
const statusBadge = choice.detected ? '[OK]' : '[x]';
|
|
194
194
|
|
|
195
195
|
return `${choice.icon} ${choice.name} (${nativeBadge}) ${statusBadge}`;
|
|
196
196
|
}
|
package/install/src/index.js
CHANGED
|
@@ -59,7 +59,7 @@ class Dashboard {
|
|
|
59
59
|
*
|
|
60
60
|
* @example
|
|
61
61
|
* const byan = createByanInstance({ workerCount: 2 });
|
|
62
|
-
* await byan.executeWorkflow('
|
|
62
|
+
* await byan.executeWorkflow('_byan/workflows/create-prd/workflow.yaml');
|
|
63
63
|
*/
|
|
64
64
|
function createByanInstance(options = {}) {
|
|
65
65
|
const {
|
package/install/src/webui/api.js
CHANGED
|
@@ -165,19 +165,6 @@ const routes = {
|
|
|
165
165
|
await sleep(300);
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
if (yanstaller) {
|
|
169
|
-
try {
|
|
170
|
-
await yanstaller.install({
|
|
171
|
-
mode: config.mode || 'full',
|
|
172
|
-
platforms: config.platforms,
|
|
173
|
-
yes: true,
|
|
174
|
-
projectRoot
|
|
175
|
-
});
|
|
176
|
-
} catch (err) {
|
|
177
|
-
server.broadcastLog('warn', `Yanstaller: ${err.message} (continuing with stub install)`);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
168
|
ensureDirectoryStructure(projectRoot);
|
|
182
169
|
writeBaseConfig(projectRoot, config);
|
|
183
170
|
|
|
@@ -26,7 +26,7 @@ class Bridge {
|
|
|
26
26
|
if (!agentName) return null;
|
|
27
27
|
|
|
28
28
|
// Layout resolver: Gen3 _byan/agent/<name>/ first, Gen2 flat +
|
|
29
|
-
// per-module
|
|
29
|
+
// per-module.
|
|
30
30
|
const hit = layoutResolver.resolveAgent(agentName, { projectRoot: this.projectRoot });
|
|
31
31
|
return hit ? hit.path : null;
|
|
32
32
|
}
|
|
@@ -96,7 +96,7 @@ function parseFrontmatter(content) {
|
|
|
96
96
|
// Map a resolver layout (+ rel) to the legacy source label, so API responses
|
|
97
97
|
// stay stable: Gen2 flat / Gen3 -> 'byan', Gen2 per-module -> 'bmad-<mod>'.
|
|
98
98
|
function sourceForLayout(layout, rel) {
|
|
99
|
-
if (layout === 'gen2-module'
|
|
99
|
+
if (layout === 'gen2-module') {
|
|
100
100
|
const mod = String(rel).split('/')[1];
|
|
101
101
|
return `bmad-${mod}`;
|
|
102
102
|
}
|
|
@@ -29,14 +29,20 @@ The tiering decision lives in one place ā `_byan/mcp/byan-mcp-server/lib/nativ
|
|
|
29
29
|
(tier vocabulary, leaf classifier, model map). Three tiers:
|
|
30
30
|
|
|
31
31
|
- **cheap (`model: 'haiku'`)** ā a pure EXPLORATION leaf (read/load/parse/detect).
|
|
32
|
-
- **balanced (`model: 'sonnet'`)** ā
|
|
33
|
-
the `mech-` label prefix (`mech-validate-json`):
|
|
34
|
-
(JSON parses, schema matches, lint passes).
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
-
|
|
39
|
-
|
|
32
|
+
- **balanced (`model: 'sonnet'`)** ā two classes land here. (1) MECHANICAL
|
|
33
|
+
verification, opt-in ONLY through the `mech-` label prefix (`mech-validate-json`):
|
|
34
|
+
a binary, judgment-free check (JSON parses, schema matches, lint passes). (2)
|
|
35
|
+
ANALYSIS leaves (score/rank/assess/design/nfr/coverage/recommend/synthesize),
|
|
36
|
+
auto-routed by keyword: judgment-bearing but rarely frontier, so sonnet by
|
|
37
|
+
default. This deliberately OVERRIDES the session model for analysis even on an
|
|
38
|
+
Opus / high-effort session (that is the cost lever) ā escape a frontier analysis
|
|
39
|
+
leaf with the `deep-` prefix. A `mech-` leaf without `model: 'sonnet'` is a hard violation; an analysis
|
|
40
|
+
leaf may carry `model: 'sonnet'` (its tier) but not `haiku` (`analysis-below-tier`).
|
|
41
|
+
Semantic/adversarial VERIFICATION is NOT analysis and stays deep.
|
|
42
|
+
- **deep (OMIT `opts.model`)** ā implementation + verification leaves inherit the
|
|
43
|
+
session model (no pin-up to opus). A genuinely frontier ANALYSIS leaf opts back to
|
|
44
|
+
deep with the `deep-` label prefix (`deep-assess-architecture`), the mirror of the
|
|
45
|
+
`mech-` opt-in.
|
|
40
46
|
|
|
41
47
|
The linter splits the two directions:
|
|
42
48
|
|
|
@@ -44,12 +50,14 @@ The linter splits the two directions:
|
|
|
44
50
|
pin-up, or a half-applied `mech-` opt-in is a contract violation
|
|
45
51
|
(`modelRoutingViolations` + `mechanicalLabelViolations`). This is the STRICT-2
|
|
46
52
|
No Downgrade net.
|
|
47
|
-
- **Ceiling (ADVISORY, non-blocking)** ā an exploration-labelled leaf
|
|
48
|
-
deep is *reported* (`byan-lint-workflows.js --advise
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
- **Ceiling (ADVISORY, non-blocking)** ā an exploration- OR analysis-labelled leaf
|
|
54
|
+
that runs deep is *reported* (`byan-lint-workflows.js --advise`:
|
|
55
|
+
`untiered-exploration` -> `model: 'haiku'`, `untiered-analysis` -> `model: 'sonnet'`),
|
|
56
|
+
not forced. `classifyLeaf` is permissive: many such leaves legitimately stay deep
|
|
57
|
+
because they bear a HALT/prerequisite gate, a classification, an exact conversion
|
|
58
|
+
consumed verbatim downstream, or genuinely frontier reasoning (`deep-` prefix). The
|
|
59
|
+
human owns that per-leaf call. Forcing a downgrade would be the very regression the
|
|
60
|
+
floor forbids.
|
|
53
61
|
|
|
54
62
|
## Ad-hoc scripts ā the tier gate hook
|
|
55
63
|
|
|
@@ -99,7 +99,6 @@ Suite Ć la migration `_byan` ā `_byan`, la structure BYAN v2 a Ć©tĆ© complĆ©t
|
|
|
99
99
|
- ComplexityScorer: Analyse complexité tâches (0.0-1.0)
|
|
100
100
|
- TaskRouter: Routage intelligent (local vs dƩlƩgation)
|
|
101
101
|
- LocalExecutor: ExƩcution locale
|
|
102
|
-
- TaskToolInterface: Interface avec sous-agents Copilot CLI
|
|
103
102
|
|
|
104
103
|
3. **Generation Worker** (`generation/`)
|
|
105
104
|
- ProfileTemplate: Templates markdown avec placeholders
|
|
@@ -144,14 +144,14 @@ Il n'est PAS un worker isole ā il est un orchestrateur dans l'ecosysteme BMAD.
|
|
|
144
144
|
|
|
145
145
|
L'agent peut executer n'importe quel workflow BMAD :
|
|
146
146
|
- Via commande : `@bmad-{module}-{workflow}` (ex: `@bmad-bmm-create-prd`)
|
|
147
|
-
- Via menu handler : `exec="{project-root}/
|
|
148
|
-
- Manifeste : `{project-root}/
|
|
147
|
+
- Via menu handler : `exec="{project-root}/_byan/{module}/workflows/{workflow}/workflow.md"`
|
|
148
|
+
- Manifeste : `{project-root}/_byan/_config/workflow-manifest.csv`
|
|
149
149
|
|
|
150
150
|
### Deleguer a d'autres Agents
|
|
151
151
|
|
|
152
152
|
L'agent peut invoquer n'importe quel agent specialise :
|
|
153
153
|
- Via commande : `@bmad-agent-{name}` (ex: `@bmad-agent-bmm-dev`)
|
|
154
|
-
- Via manifeste : `{project-root}/
|
|
154
|
+
- Via manifeste : `{project-root}/_byan/_config/agent-manifest.csv`
|
|
155
155
|
- L'agent delegue reprend le controle ā l'agent courant se retire
|
|
156
156
|
|
|
157
157
|
### Acceder aux Contextes
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { execFileSync } from 'node:child_process';
|
|
5
|
-
import { validateContract, untieredExplorationViolations } from '../lib/workflows-lint.js';
|
|
5
|
+
import { validateContract, untieredExplorationViolations, untieredAnalysisViolations } from '../lib/workflows-lint.js';
|
|
6
6
|
|
|
7
7
|
// Validate native workflow scripts under .claude/workflows/ against the full
|
|
8
8
|
// contract (state-coupling + clock/RNG + meta-literal) AND node --check syntax.
|
|
@@ -57,10 +57,13 @@ for (const file of files) {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
// Non-blocking tiering advisory: exploration leaves that run deep.
|
|
60
|
+
// Non-blocking tiering advisory: exploration + analysis leaves that run deep.
|
|
61
61
|
for (const a of untieredExplorationViolations(src)) {
|
|
62
62
|
advisories.push({ file, ...a });
|
|
63
63
|
}
|
|
64
|
+
for (const a of untieredAnalysisViolations(src)) {
|
|
65
|
+
advisories.push({ file, ...a });
|
|
66
|
+
}
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
// Tiering advisory is informational only ā it never changes the exit code.
|
|
@@ -71,7 +74,7 @@ if (advisories.length) {
|
|
|
71
74
|
}
|
|
72
75
|
} else {
|
|
73
76
|
process.stdout.write(
|
|
74
|
-
`[byan-lint-workflows] advisory: ${advisories.length}
|
|
77
|
+
`[byan-lint-workflows] advisory: ${advisories.length} downgrade-eligible leaf(s) run deep (rerun with --advise to list; exploration -> model: 'haiku', analysis -> model: 'sonnet', or keep deep if genuinely hard)\n`
|
|
75
78
|
);
|
|
76
79
|
}
|
|
77
80
|
}
|
|
@@ -26,10 +26,13 @@ export const TIERS = Object.freeze({ CHEAP: 'cheap', BALANCED: 'balanced', DEEP:
|
|
|
26
26
|
//
|
|
27
27
|
// deep MUST be null. Omitting opts.model lets the leaf inherit whatever model the
|
|
28
28
|
// session runs (Opus by default, but Sonnet if the user chose Sonnet). We never
|
|
29
|
-
// PIN UP
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
-
//
|
|
29
|
+
// PIN UP (nothing is ever forced to opus). cheap/balanced carry a value:
|
|
30
|
+
// exploration leaves get cheap (haiku); explicit mech- leaves AND analysis leaves
|
|
31
|
+
// get balanced (sonnet). Analysis routing to balanced is a deliberate downgrade of
|
|
32
|
+
// the session model for judgment-but-not-frontier work (score/rank/assess/nfr/
|
|
33
|
+
// coverage/recommend) ā the heaviest workflow prompts, which rarely need the top
|
|
34
|
+
// model; the 'deep-' label prefix opts a hard analysis leaf back to the session
|
|
35
|
+
// model. VERIFICATION and IMPLEMENTATION still inherit (deep).
|
|
33
36
|
//
|
|
34
37
|
// Values are the harness model-selection aliases (same set as the Agent tool:
|
|
35
38
|
// 'haiku' | 'sonnet' | 'opus'). They are version-independent. If a future
|
|
@@ -37,11 +40,14 @@ export const TIERS = Object.freeze({ CHEAP: 'cheap', BALANCED: 'balanced', DEEP:
|
|
|
37
40
|
// flags every script literal that drifts from it, so the fan-out stays bounded.
|
|
38
41
|
export const TIER_MODEL = Object.freeze({ cheap: 'haiku', balanced: 'sonnet', deep: null });
|
|
39
42
|
|
|
40
|
-
// Leaf task-type taxonomy. EXPLORATION and MECHANICAL
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
// parses, schema matches, lint passes,
|
|
44
|
-
//
|
|
43
|
+
// Leaf task-type taxonomy. EXPLORATION (cheap) and MECHANICAL + ANALYSIS
|
|
44
|
+
// (balanced) are the downgrade classes; VERIFICATION and IMPLEMENTATION stay
|
|
45
|
+
// protected (deep, inherit the session model). MECHANICAL is verification whose
|
|
46
|
+
// outcome is binary and judgment-free (JSON parses, schema matches, lint passes,
|
|
47
|
+
// a test suite exits 0). ANALYSIS bears judgment (score/rank/assess/design/nfr/
|
|
48
|
+
// coverage) but rarely the frontier reasoning that needs the top model, so it
|
|
49
|
+
// auto-routes to balanced (sonnet) ā escapable per-leaf via the 'deep-' prefix.
|
|
50
|
+
// Semantic/adversarial VERIFICATION stays deep (a wrong check corrupts silently).
|
|
45
51
|
export const LEAF_TYPES = Object.freeze({
|
|
46
52
|
EXPLORATION: 'exploration',
|
|
47
53
|
MECHANICAL: 'mechanical',
|
|
@@ -57,6 +63,14 @@ export const LEAF_TYPES = Object.freeze({
|
|
|
57
63
|
// script to it (a mech- leaf must carry model: 'sonnet', nothing else).
|
|
58
64
|
export const MECHANICAL_PREFIX = 'mech-';
|
|
59
65
|
|
|
66
|
+
// DEEP_PREFIX is the ANALYSIS escape hatch. Analysis auto-routes to balanced
|
|
67
|
+
// (sonnet); a 'deep-' label prefix opts a specific analysis leaf back OUT of that
|
|
68
|
+
// downgrade and onto the protected deep default (inherit the session model), for
|
|
69
|
+
// genuinely frontier reasoning. Parallel to MECHANICAL_PREFIX: an explicit
|
|
70
|
+
// authoring act the linter honours. 'deep-assess-architecture' rides the session
|
|
71
|
+
// model; 'assess-architecture' rides sonnet. The prefix wins over keyword class.
|
|
72
|
+
export const DEEP_PREFIX = 'deep-';
|
|
73
|
+
|
|
60
74
|
// Label keyword sets, matched as substrings on the leaf LABEL (not the prompt ā
|
|
61
75
|
// see classifyLeaf). Protected sets are checked first so any protected signal
|
|
62
76
|
// beats an exploration signal (conservative: when in doubt, do not downgrade).
|
|
@@ -66,7 +80,7 @@ export const MECHANICAL_PREFIX = 'mech-';
|
|
|
66
80
|
// check/review/gate/audit/assert/lint; a leaf that runs tests is labelled
|
|
67
81
|
// 'verify-*' in practice.
|
|
68
82
|
const VERIFICATION_KEYWORDS = ['verify', 'validate', 'check', 'assert', 'gate', 'lint', 'audit', 'review'];
|
|
69
|
-
const ANALYSIS_KEYWORDS = ['analy', 'design', 'architect', 'assess', 'evaluate', 'strategy', 'risk', 'nfr', 'recommend', 'judge', 'score', 'coverage'];
|
|
83
|
+
const ANALYSIS_KEYWORDS = ['analy', 'design', 'architect', 'assess', 'evaluate', 'strategy', 'risk', 'nfr', 'recommend', 'judge', 'score', 'coverage', 'synthes'];
|
|
70
84
|
const IMPLEMENTATION_KEYWORDS = ['implement', 'build', 'write', 'generate', 'create', 'dev', 'rgr', 'refactor', 'fix', 'scaffold', 'save', 'optimize', 'aggregate', 'report', 'present', 'plan', 'map', 'select', 'subprocess', 'sub-'];
|
|
71
85
|
const EXPLORATION_KEYWORDS = ['load', 'read', 'scan', 'list', 'parse', 'detect', 'discover', 'fetch', 'lookup', 'source-tree', 'mode-detection'];
|
|
72
86
|
|
|
@@ -85,9 +99,11 @@ function matchesAny(text, keywords) {
|
|
|
85
99
|
export function classifyLeaf(leaf) {
|
|
86
100
|
const label = String((leaf && leaf.label) || '').toLowerCase();
|
|
87
101
|
if (!label) return LEAF_TYPES.IMPLEMENTATION;
|
|
88
|
-
// Explicit opt-in
|
|
89
|
-
//
|
|
102
|
+
// Explicit opt-in prefixes beat every keyword class (the author's declared
|
|
103
|
+
// intent is the signal): mech- -> balanced; deep- -> the protected deep default
|
|
104
|
+
// (the analysis escape hatch, classified as the deep IMPLEMENTATION bucket).
|
|
90
105
|
if (label.startsWith(MECHANICAL_PREFIX)) return LEAF_TYPES.MECHANICAL;
|
|
106
|
+
if (label.startsWith(DEEP_PREFIX)) return LEAF_TYPES.IMPLEMENTATION;
|
|
91
107
|
if (matchesAny(label, VERIFICATION_KEYWORDS)) return LEAF_TYPES.VERIFICATION;
|
|
92
108
|
if (matchesAny(label, ANALYSIS_KEYWORDS)) return LEAF_TYPES.ANALYSIS;
|
|
93
109
|
if (matchesAny(label, IMPLEMENTATION_KEYWORDS)) return LEAF_TYPES.IMPLEMENTATION;
|
|
@@ -95,14 +111,16 @@ export function classifyLeaf(leaf) {
|
|
|
95
111
|
return LEAF_TYPES.IMPLEMENTATION;
|
|
96
112
|
}
|
|
97
113
|
|
|
98
|
-
// tierFor(taskType) -> a TIERS value.
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
114
|
+
// tierFor(taskType) -> a TIERS value. Auto-routing: EXPLORATION -> cheap (haiku);
|
|
115
|
+
// MECHANICAL and ANALYSIS -> balanced (sonnet); VERIFICATION and IMPLEMENTATION
|
|
116
|
+
// stay deep (inherit the session model). MECHANICAL reaches balanced only through
|
|
117
|
+
// the explicit mech- opt-in; ANALYSIS reaches it by keyword classification (it is
|
|
118
|
+
// the judgment-but-not-frontier class), with the deep- prefix as the per-leaf
|
|
119
|
+
// escape back to deep. No path ever lands opus (no pin-up).
|
|
103
120
|
export function tierFor(taskType) {
|
|
104
121
|
if (taskType === LEAF_TYPES.EXPLORATION) return TIERS.CHEAP;
|
|
105
122
|
if (taskType === LEAF_TYPES.MECHANICAL) return TIERS.BALANCED;
|
|
123
|
+
if (taskType === LEAF_TYPES.ANALYSIS) return TIERS.BALANCED;
|
|
106
124
|
return TIERS.DEEP;
|
|
107
125
|
}
|
|
108
126
|
|
|
@@ -181,6 +181,18 @@ export function modelRoutingViolations(src) {
|
|
|
181
181
|
}
|
|
182
182
|
continue;
|
|
183
183
|
}
|
|
184
|
+
// ANALYSIS floors at balanced (sonnet), like MECHANICAL: sonnet is its tier,
|
|
185
|
+
// haiku sits below it. Analysis auto-routes to sonnet (tierFor); a 'deep-'
|
|
186
|
+
// labelled analysis classifies as IMPLEMENTATION and never reaches here.
|
|
187
|
+
if (cls === LEAF_TYPES.ANALYSIS) {
|
|
188
|
+
if (model !== TIER_MODEL.balanced) {
|
|
189
|
+
out.push({
|
|
190
|
+
id: 'analysis-below-tier',
|
|
191
|
+
msg: `analysis leaf '${label}' carries '${model}' but the analysis tier is '${TIER_MODEL.balanced}' (sonnet); haiku sits below it ā prefix the label 'deep-' to keep a hard analysis on the session model instead`,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
184
196
|
out.push({
|
|
185
197
|
id: 'protected-leaf-downgraded',
|
|
186
198
|
msg: `leaf '${label}' is protected (${cls}) but carries downgrade model '${model}'; only exploration (read/load/parse/detect) and explicit mech- leaves may downgrade (STRICT-2 No Downgrade)`,
|
|
@@ -274,6 +286,32 @@ export function untieredExplorationViolations(src) {
|
|
|
274
286
|
return out;
|
|
275
287
|
}
|
|
276
288
|
|
|
289
|
+
// The ANALYSIS half of the same non-blocking advisory. An analysis-labelled leaf
|
|
290
|
+
// that pins no downgrade model runs on the session model (Opus, esp. under a
|
|
291
|
+
// high-effort session) for judgment-but-not-frontier work ā the single biggest
|
|
292
|
+
// source of the all-Opus workflow pattern. Surfaces 'add model: sonnet' (or the
|
|
293
|
+
// 'deep-' prefix to keep it deep on purpose). Same permissive-classifier caveat
|
|
294
|
+
// as exploration, so it ships as ADVISORY, not a hard contract rule: the human
|
|
295
|
+
// owns whether a given analysis leaf is truly frontier-hard.
|
|
296
|
+
export function untieredAnalysisViolations(src) {
|
|
297
|
+
const code = stripComments(src);
|
|
298
|
+
const out = [];
|
|
299
|
+
let m;
|
|
300
|
+
LABEL_RE.lastIndex = 0;
|
|
301
|
+
while ((m = LABEL_RE.exec(code))) {
|
|
302
|
+
const label = m[2];
|
|
303
|
+
if (classifyLeaf({ label }) !== LEAF_TYPES.ANALYSIS) continue;
|
|
304
|
+
const objText = sameOptsObjectText(code, m.index, m.index + m[0].length);
|
|
305
|
+
if (!objectHasDowngradeModel(objText)) {
|
|
306
|
+
out.push({
|
|
307
|
+
id: 'untiered-analysis',
|
|
308
|
+
msg: `analysis leaf '${label}' pins no downgrade model; add model: 'sonnet' so judgment-but-not-frontier analysis does not run on the session model (token waste), or prefix the label 'deep-' to keep it on the session model deliberately`,
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
return out;
|
|
313
|
+
}
|
|
314
|
+
|
|
277
315
|
// Shared parsing primitive ā every statically-labelled opts object with its
|
|
278
316
|
// order-independent model (or null). This is the ONE place that knows how to
|
|
279
317
|
// read agent() opts out of a script source; tier-script.js (the per-leaf
|
|
@@ -496,7 +496,7 @@ src/
|
|
|
496
496
|
- **Worker Pool Implementation:** `src/core/worker-pool/worker-pool.js`
|
|
497
497
|
- **Dispatcher Logic:** `src/byan-v2/dispatcher/`
|
|
498
498
|
- **Launcher Workers:** `_byan/worker/launchers/README.md`
|
|
499
|
-
- **Architecture:** `
|
|
499
|
+
- **Architecture:** `_byan-output/conception/01-vision-et-principes.md`
|
|
500
500
|
|
|
501
501
|
---
|
|
502
502
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-byan-agent",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.44.0",
|
|
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": {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
//
|
|
11
11
|
// This module is the single READ-side authority: "where does logical thing X
|
|
12
12
|
// physically live?". It answers Gen3-first, then falls back through the real
|
|
13
|
-
// on-disk Gen2 variants (flat AND per-module)
|
|
13
|
+
// on-disk Gen2 variants (flat AND per-module). Every
|
|
14
14
|
// lookup is a pure existence check ā no writes, no side effects ā so it is
|
|
15
15
|
// idempotent and additive: before migration it finds Gen2, after migration it
|
|
16
16
|
// finds Gen3, during migration either works. That is what lets the FS migrator
|
|
@@ -68,8 +68,7 @@ function locate(root, gen3rel, gen2rel) {
|
|
|
68
68
|
|
|
69
69
|
// Resolve an agent source file by name. Gen3 _byan/agent/<name>/<name>.md (or
|
|
70
70
|
// agent.md) first, then Gen2 flat _byan/agents/<name>.md, then Gen2 per-module
|
|
71
|
-
// _byan/<module>/agents/<name>.md,
|
|
72
|
-
// Returns {path, rel, layout} or null.
|
|
71
|
+
// _byan/<module>/agents/<name>.md. Returns {path, rel, layout} or null.
|
|
73
72
|
function resolveAgent(name, opts = {}) {
|
|
74
73
|
const root = resolveProjectRoot(opts.projectRoot);
|
|
75
74
|
const candidates = [
|
|
@@ -78,7 +77,6 @@ function resolveAgent(name, opts = {}) {
|
|
|
78
77
|
{ rel: `_byan/agents/${name}.md`, layout: 'gen2-flat' },
|
|
79
78
|
];
|
|
80
79
|
for (const m of MODULES) candidates.push({ rel: `_byan/${m}/agents/${name}.md`, layout: 'gen2-module' });
|
|
81
|
-
for (const m of MODULES) candidates.push({ rel: `_bmad/${m}/agents/${name}.md`, layout: 'gen1' });
|
|
82
80
|
return firstExisting(root, candidates);
|
|
83
81
|
}
|
|
84
82
|
|
|
@@ -95,7 +93,6 @@ function agentDirs(opts = {}) {
|
|
|
95
93
|
push('_byan/agent', 'gen3', true);
|
|
96
94
|
push('_byan/agents', 'gen2-flat', false);
|
|
97
95
|
for (const m of MODULES) push(`_byan/${m}/agents`, 'gen2-module', false);
|
|
98
|
-
for (const m of MODULES) push(`_bmad/${m}/agents`, 'gen1', false);
|
|
99
96
|
return out;
|
|
100
97
|
}
|
|
101
98
|
|
|
@@ -105,7 +102,7 @@ function isSoulSibling(fileName) {
|
|
|
105
102
|
|
|
106
103
|
// Discover all agents across layouts. Returns [{name, path, rel, layout}],
|
|
107
104
|
// deduped by name with the highest-priority directory winning (Gen3 > flat >
|
|
108
|
-
// module
|
|
105
|
+
// module). Soul/tao siblings are not agents and are skipped.
|
|
109
106
|
function listAgents(opts = {}) {
|
|
110
107
|
const root = resolveProjectRoot(opts.projectRoot);
|
|
111
108
|
const seen = new Map();
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* INSTALLER Module
|
|
3
|
-
*
|
|
4
|
-
* Installs BYAN agents across multiple platforms.
|
|
5
|
-
* Most complex module: 56h development.
|
|
6
|
-
*
|
|
7
|
-
* Phase 3: 56h development
|
|
8
|
-
*
|
|
9
|
-
* @module yanstaller/installer
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const path = require('path');
|
|
13
|
-
const fileUtils = require('../utils/file-utils');
|
|
14
|
-
const logger = require('../utils/logger');
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @typedef {Object} InstallConfig
|
|
18
|
-
* @property {string} mode - 'full' | 'minimal' | 'custom'
|
|
19
|
-
* @property {string[]} agents - Agent names to install
|
|
20
|
-
* @property {string} userName - User's name
|
|
21
|
-
* @property {string} language - 'Francais' | 'English'
|
|
22
|
-
* @property {string[]} targetPlatforms - Platforms to install on
|
|
23
|
-
* @property {string} outputFolder - Output folder path
|
|
24
|
-
* @property {string} projectRoot - Project root directory
|
|
25
|
-
*/
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @typedef {Object} InstallResult
|
|
29
|
-
* @property {boolean} success
|
|
30
|
-
* @property {number} agentsInstalled - Number of agents installed
|
|
31
|
-
* @property {string[]} platforms - Platforms installed on
|
|
32
|
-
* @property {string[]} errors - Installation errors
|
|
33
|
-
* @property {number} duration - Duration in ms
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Install BYAN agents
|
|
38
|
-
*
|
|
39
|
-
* @param {InstallConfig} config - Installation configuration
|
|
40
|
-
* @returns {Promise<InstallResult>}
|
|
41
|
-
*/
|
|
42
|
-
async function install(config) {
|
|
43
|
-
const startTime = Date.now();
|
|
44
|
-
const errors = [];
|
|
45
|
-
|
|
46
|
-
try {
|
|
47
|
-
// TODO: Implement installation
|
|
48
|
-
// 1. Create _bmad/ structure
|
|
49
|
-
// 2. Copy agent files from templates/
|
|
50
|
-
// 3. Generate platform-specific stubs
|
|
51
|
-
// 4. Create config files
|
|
52
|
-
|
|
53
|
-
logger.info(`Installing ${config.agents.length} agents...`);
|
|
54
|
-
|
|
55
|
-
// Placeholder
|
|
56
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
success: true,
|
|
60
|
-
agentsInstalled: config.agents.length,
|
|
61
|
-
platforms: config.targetPlatforms,
|
|
62
|
-
errors,
|
|
63
|
-
duration: Date.now() - startTime
|
|
64
|
-
};
|
|
65
|
-
} catch (error) {
|
|
66
|
-
errors.push(error.message);
|
|
67
|
-
return {
|
|
68
|
-
success: false,
|
|
69
|
-
agentsInstalled: 0,
|
|
70
|
-
platforms: [],
|
|
71
|
-
errors,
|
|
72
|
-
duration: Date.now() - startTime
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Create _bmad/ directory structure
|
|
79
|
-
*
|
|
80
|
-
* @param {string} projectRoot - Project root directory
|
|
81
|
-
* @returns {Promise<void>}
|
|
82
|
-
*/
|
|
83
|
-
async function createBmadStructure(projectRoot) {
|
|
84
|
-
// TODO: Create directories
|
|
85
|
-
// _bmad/
|
|
86
|
-
// āāā _config/
|
|
87
|
-
// āāā _memory/
|
|
88
|
-
// āāā core/
|
|
89
|
-
// āāā bmm/
|
|
90
|
-
// āāā bmb/
|
|
91
|
-
// āāā tea/
|
|
92
|
-
// āāā cis/
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Copy agent file from template
|
|
97
|
-
*
|
|
98
|
-
* @param {string} agentName - Agent name
|
|
99
|
-
* @param {string} targetPath - Target directory
|
|
100
|
-
* @returns {Promise<void>}
|
|
101
|
-
*/
|
|
102
|
-
async function copyAgentFile(agentName, targetPath) {
|
|
103
|
-
// TODO: Copy from lib/templates/agents/{agentName}.md
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Generate platform-specific stub
|
|
108
|
-
*
|
|
109
|
-
* @param {string} agentName - Agent name
|
|
110
|
-
* @param {string} platform - Platform name
|
|
111
|
-
* @param {string} targetPath - Target directory
|
|
112
|
-
* @returns {Promise<void>}
|
|
113
|
-
*/
|
|
114
|
-
async function generateStub(agentName, platform, targetPath) {
|
|
115
|
-
// TODO: Generate stub based on platform
|
|
116
|
-
// - Claude Code: MCP config JSON
|
|
117
|
-
// - Codex: .codex/prompts/{agentName}.md
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Create module config file
|
|
122
|
-
*
|
|
123
|
-
* @param {string} moduleName - Module name (core, bmm, bmb, tea, cis)
|
|
124
|
-
* @param {InstallConfig} config - Installation config
|
|
125
|
-
* @param {string} targetPath - Target directory
|
|
126
|
-
* @returns {Promise<void>}
|
|
127
|
-
*/
|
|
128
|
-
async function createModuleConfig(moduleName, config, targetPath) {
|
|
129
|
-
// TODO: Generate config.yaml with user settings
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
module.exports = {
|
|
133
|
-
install,
|
|
134
|
-
createBmadStructure,
|
|
135
|
-
copyAgentFile,
|
|
136
|
-
generateStub,
|
|
137
|
-
createModuleConfig
|
|
138
|
-
};
|