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.
Files changed (62) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/install/bin/byan-kanban.js +1 -1
  3. package/install/bin/create-byan-agent-v2.js +111 -111
  4. package/install/lib/byan-leantime-integration.js +2 -2
  5. package/install/lib/byan-web-integration.js +5 -5
  6. package/install/lib/claude-native-setup.js +11 -11
  7. package/install/lib/codex-native-setup.js +3 -3
  8. package/install/lib/exchange/agent-packager.js +1 -1
  9. package/install/lib/mcp-extensions/gdrive.js +5 -5
  10. package/install/lib/mcp-extensions/index.js +5 -5
  11. package/install/lib/phase2-chat.js +21 -21
  12. package/install/lib/platforms/claude-code.js +2 -2
  13. package/install/lib/project-agents-generator.js +4 -4
  14. package/install/lib/staging-consent.js +1 -1
  15. package/install/lib/subagent-generator.js +2 -3
  16. package/install/lib/utils/logger.js +4 -4
  17. package/install/lib/utils/node-detector.js +1 -1
  18. package/install/lib/yanstaller/agent-launcher.js +1 -1
  19. package/install/lib/yanstaller/index.js +11 -116
  20. package/install/lib/yanstaller/platform-selector.js +11 -11
  21. package/install/src/byan-v2/dispatcher/task-router.js +1 -1
  22. package/install/src/index.js +1 -1
  23. package/install/src/webui/api.js +0 -13
  24. package/install/src/webui/chat/bridge.js +1 -1
  25. package/install/src/webui/chat/cli-detector.js +1 -1
  26. package/install/templates/.claude/rules/native-workflows.md +22 -14
  27. package/install/templates/_byan/COMPLETION-REPORT.md +0 -1
  28. package/install/templates/_byan/core/activation/soul-activation.md +3 -3
  29. package/install/templates/_byan/mcp/byan-mcp-server/bin/byan-lint-workflows.js +6 -3
  30. package/install/templates/_byan/mcp/byan-mcp-server/lib/native-tiers.js +35 -17
  31. package/install/templates/_byan/mcp/byan-mcp-server/lib/workflows-lint.js +38 -0
  32. package/install/templates/_byan/worker/workers.md +1 -1
  33. package/package.json +1 -1
  34. package/src/byan-v2/dispatcher/task-router.js +1 -1
  35. package/src/byan-v2/lib/layout-resolver.js +3 -6
  36. package/install/lib/yanstaller/installer.js +0 -138
  37. package/install/lib/yanstaller/interviewer.js +0 -88
  38. package/install/lib/yanstaller/recommender.js +0 -102
  39. package/install/lib/yanstaller/troubleshooter.js +0 -89
  40. package/install/lib/yanstaller/validator.js +0 -198
  41. package/install/lib/yanstaller/wizard.js +0 -109
  42. package/install/src/byan-v2/dispatcher/task-tool-interface-mock.js +0 -134
  43. package/install/src/byan-v2/dispatcher/task-tool-interface.js +0 -123
  44. package/install/templates/_bmad/bmb/agents/agent-builder.md +0 -59
  45. package/install/templates/_bmad/bmb/agents/byan-test.md +0 -116
  46. package/install/templates/_bmad/bmb/agents/byan.md +0 -215
  47. package/install/templates/_bmad/bmb/agents/marc.md +0 -303
  48. package/install/templates/_bmad/bmb/agents/module-builder.md +0 -60
  49. package/install/templates/_bmad/bmb/agents/patnote.md +0 -495
  50. package/install/templates/_bmad/bmb/agents/rachid.md +0 -184
  51. package/install/templates/_bmad/bmb/agents/workflow-builder.md +0 -61
  52. package/install/templates/_bmad/bmb/workflows/byan/data/mantras.yaml +0 -272
  53. package/install/templates/_bmad/bmb/workflows/byan/data/templates.yaml +0 -59
  54. package/install/templates/_bmad/bmb/workflows/byan/delete-agent-workflow.md +0 -657
  55. package/install/templates/_bmad/bmb/workflows/byan/edit-agent-workflow.md +0 -688
  56. package/install/templates/_bmad/bmb/workflows/byan/interview-workflow.md +0 -753
  57. package/install/templates/_bmad/bmb/workflows/byan/quick-create-workflow.md +0 -450
  58. package/install/templates/_bmad/bmb/workflows/byan/templates/base-agent-template.md +0 -79
  59. package/install/templates/_bmad/bmb/workflows/byan/validate-agent-workflow.md +0 -676
  60. package/install/templates/_bmad/core/agents/carmack.md +0 -238
  61. package/src/byan-v2/dispatcher/task-tool-interface-mock.js +0 -134
  62. 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('\nšŸŽÆ Platform Selection\n');
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: 'šŸŽÆ Choose your PRIMARY platform for native agent invocation:',
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: 'šŸ”§ Advanced: Install on multiple platforms',
87
+ name: 'Advanced: Install on multiple platforms',
88
88
  value: 'multi'
89
89
  },
90
90
  {
91
- name: 'ā­ļø Skip native integration (manual install only)',
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: `šŸš€ Auto (detect & install all available) - ${choices.length} platform(s)`,
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: 'šŸ”§ Custom (select multiple)',
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 ? '✨ Native' : 'šŸ’¬ Conversational';
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
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * TaskRouter - Routes tasks based on complexity
3
- * Integrates ComplexityScorer + TaskToolInterface
3
+ * Integrates ComplexityScorer
4
4
  *
5
5
  * Thresholds:
6
6
  * - < 30: task-tool only
@@ -59,7 +59,7 @@ class Dashboard {
59
59
  *
60
60
  * @example
61
61
  * const byan = createByanInstance({ workerCount: 2 });
62
- * await byan.executeWorkflow('_bmad/workflows/create-prd/workflow.yaml');
62
+ * await byan.executeWorkflow('_byan/workflows/create-prd/workflow.yaml');
63
63
  */
64
64
  function createByanInstance(options = {}) {
65
65
  const {
@@ -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, Gen1 _bmad/ fallback.
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' || layout === 'gen1') {
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'`)** — 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).
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 that runs
48
- deep is *reported* (`byan-lint-workflows.js --advise`), not forced. `classifyLeaf`
49
- is permissive: many exploration-labelled leaves legitimately stay deep because
50
- they bear a HALT/prerequisite gate, a classification, or an exact conversion
51
- consumed verbatim downstream. The human owns that per-leaf call. Forcing haiku
52
- on them would be the very downgrade the floor forbids.
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}/_bmad/{module}/workflows/{workflow}/workflow.md"`
148
- - Manifeste : `{project-root}/_bmad/_config/workflow-manifest.csv`
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}/_bmad/_config/agent-manifest.csv`
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} exploration leaf(s) run deep (rerun with --advise to list; keep deep if they bear a gate/judgment, else add model: 'haiku')\n`
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 — pinning a leaf to a fixed high tier would override the user's session
30
- // choice and could silently DOWNGRADE a Sonnet/Opus session's heavy leaf. Only
31
- // cheap/balanced carry a value: exploration leaves get cheap, explicit mech-
32
- // leaves get balanced, nothing else ever gets one.
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 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).
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 beats every keyword class: 'mech-validate-json' contains a
89
- // verification keyword, but the author's declared intent is the signal.
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. 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.
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:** `_bmad-output/conception/01-vision-et-principes.md`
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.42.0",
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": {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * TaskRouter - Routes tasks based on complexity
3
- * Integrates ComplexityScorer + TaskToolInterface
3
+ * Integrates ComplexityScorer
4
4
  *
5
5
  * Thresholds:
6
6
  * - < 30: task-tool only
@@ -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) and finally Gen1 (_bmad/). Every
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, then Gen1 _bmad/<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 > gen1). Soul/tao siblings are not agents and are skipped.
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
- };