create-byan-agent 2.9.4 → 2.9.5
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/install/bin/byan-cleanup.js +156 -0
- package/install/bin/byan-kanban.js +159 -0
- package/install/bin/byan-ledger.js +45 -0
- package/install/lib/cleanup/detector.js +154 -0
- package/install/lib/cleanup/executor.js +72 -0
- package/install/lib/subagent-generator.js +208 -0
- package/install/lib/token-ledger.js +131 -0
- package/install/templates/.claude/agents/bmad-bmad-master.md +14 -0
- package/install/templates/.claude/agents/bmad-bmb-agent-builder.md +14 -0
- package/install/templates/.claude/agents/bmad-bmb-module-builder.md +14 -0
- package/install/templates/.claude/agents/bmad-bmb-workflow-builder.md +14 -0
- package/install/templates/.claude/agents/bmad-bmm-analyst.md +14 -0
- package/install/templates/.claude/agents/bmad-bmm-architect.md +14 -0
- package/install/templates/.claude/agents/bmad-bmm-dev.md +14 -0
- package/install/templates/.claude/agents/bmad-bmm-pm.md +14 -0
- package/install/templates/.claude/agents/bmad-bmm-quick-flow-solo-dev.md +14 -0
- package/install/templates/.claude/agents/bmad-bmm-quinn.md +14 -0
- package/install/templates/.claude/agents/bmad-bmm-sm.md +14 -0
- package/install/templates/.claude/agents/bmad-bmm-tech-writer.md +14 -0
- package/install/templates/.claude/agents/bmad-bmm-ux-designer.md +14 -0
- package/install/templates/.claude/agents/bmad-byan-v2.md +14 -0
- package/install/templates/.claude/agents/bmad-byan.md +152 -0
- package/install/templates/.claude/agents/bmad-carmack.md +14 -0
- package/install/templates/.claude/agents/bmad-cis-brainstorming-coach.md +14 -0
- package/install/templates/.claude/agents/bmad-cis-creative-problem-solver.md +14 -0
- package/install/templates/.claude/agents/bmad-cis-design-thinking-coach.md +14 -0
- package/install/templates/.claude/agents/bmad-cis-innovation-strategist.md +14 -0
- package/install/templates/.claude/agents/bmad-cis-presentation-master.md +14 -0
- package/install/templates/.claude/agents/bmad-cis-storyteller.md +14 -0
- package/install/templates/.claude/agents/bmad-claude.md +26 -0
- package/install/templates/.claude/agents/bmad-codex.md +26 -0
- package/install/templates/.claude/agents/bmad-compliance.md +68 -0
- package/install/templates/.claude/agents/bmad-drawio.md +25 -0
- package/install/templates/.claude/agents/bmad-expert-merise-agile.md +54 -0
- package/install/templates/.claude/agents/bmad-fact-checker.md +14 -0
- package/install/templates/.claude/agents/bmad-forgeron.md +14 -0
- package/install/templates/.claude/agents/bmad-hermes.md +59 -0
- package/install/templates/.claude/agents/bmad-marc.md +25 -0
- package/install/templates/.claude/agents/bmad-patnote.md +26 -0
- package/install/templates/.claude/agents/bmad-rachid.md +25 -0
- package/install/templates/.claude/agents/bmad-tao.md +14 -0
- package/install/templates/.claude/agents/bmad-tea-tea.md +14 -0
- package/install/templates/.claude/agents/bmad-yanstaller.md +47 -0
- package/install/templates/.claude/hooks/fact-check-absolutes.js +185 -0
- package/install/templates/.claude/hooks/fd-phase-guard.js +87 -0
- package/install/templates/.claude/hooks/fd-response-check.js +92 -0
- package/install/templates/.claude/hooks/lib/failure-detector.js +14 -0
- package/install/templates/.claude/hooks/pre-compact-save.js +148 -0
- package/install/templates/.claude/hooks/tool-failure-guard.js +6 -0
- package/install/templates/.claude/hooks/tool-transparency.js +4 -0
- package/install/templates/.claude/settings.json +23 -0
- package/install/templates/.claude/skills/byan-byan/SKILL.md +115 -163
- package/install/templates/.claude/skills/byan-orchestrate/SKILL.md +100 -0
- package/install/templates/.githooks/pre-commit +75 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/copilot.js +148 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/fd-state.js +163 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/kanban.js +226 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/peer-review.js +187 -0
- package/install/templates/_byan/mcp/byan-mcp-server/server.js +463 -0
- package/install/templates/detector.js +154 -0
- package/package.json +6 -7
- package/src/loadbalancer/capability-matrix.js +157 -0
- package/src/loadbalancer/config.js +141 -0
- package/src/loadbalancer/graceful-degradation.js +212 -0
- package/src/loadbalancer/health-probe.js +151 -0
- package/src/loadbalancer/hooks/claude-hooks.js +53 -0
- package/src/loadbalancer/hooks/copilot-hooks.js +74 -0
- package/src/loadbalancer/index.js +81 -0
- package/src/loadbalancer/loadbalancer.default.yaml +65 -0
- package/src/loadbalancer/loadbalancer.js +324 -0
- package/src/loadbalancer/mcp-server.js +304 -0
- package/src/loadbalancer/metrics.js +146 -0
- package/src/loadbalancer/native/claude-integration.js +64 -0
- package/src/loadbalancer/native/copilot-integration.js +59 -0
- package/src/loadbalancer/pressure-score.js +102 -0
- package/src/loadbalancer/providers/base-provider.js +80 -0
- package/src/loadbalancer/providers/byan-api-provider.js +132 -0
- package/src/loadbalancer/providers/claude-provider.js +113 -0
- package/src/loadbalancer/providers/copilot-provider.js +104 -0
- package/src/loadbalancer/rate-limit-tracker.js +216 -0
- package/src/loadbalancer/session-bridge.js +179 -0
- package/src/loadbalancer/state/db.js +211 -0
- package/src/loadbalancer/state/migrations/001-initial.sql +50 -0
- package/src/loadbalancer/tools/index.js +123 -0
- package/src/loadbalancer/velocity-estimator.js +147 -0
- package/update-byan-agent/bin/update-byan-agent.js +27 -2
- package/API-BYAN-V2.md +0 -741
- package/BMAD-QUICK-REFERENCE.md +0 -370
- package/CHANGELOG-v2.1.0.md +0 -371
- package/MIGRATION-v2.0-to-v2.1.md +0 -430
- package/README-BYAN-V2.md +0 -446
- package/TEST-GUIDE-v2.3.2.md +0 -161
|
@@ -7,6 +7,33 @@ import {
|
|
|
7
7
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import { dispatch } from './lib/dispatch.js';
|
|
9
9
|
import { readSoul, appendSoulMemory } from './lib/soul.js';
|
|
10
|
+
import { listSessions, readSessionEvents, searchSessions } from './lib/copilot.js';
|
|
11
|
+
import {
|
|
12
|
+
start as fdStart,
|
|
13
|
+
status as fdStatus,
|
|
14
|
+
advance as fdAdvance,
|
|
15
|
+
update as fdUpdate,
|
|
16
|
+
abort as fdAbort,
|
|
17
|
+
ALL_PHASES as FD_PHASES,
|
|
18
|
+
} from './lib/fd-state.js';
|
|
19
|
+
import {
|
|
20
|
+
requestReview,
|
|
21
|
+
recordVerdict,
|
|
22
|
+
getReview,
|
|
23
|
+
listPending,
|
|
24
|
+
pickReviewer,
|
|
25
|
+
} from './lib/peer-review.js';
|
|
26
|
+
import {
|
|
27
|
+
createBoard,
|
|
28
|
+
addCard,
|
|
29
|
+
moveCard,
|
|
30
|
+
assignCard,
|
|
31
|
+
getBoard,
|
|
32
|
+
postStandup,
|
|
33
|
+
readStandups,
|
|
34
|
+
detectBlockedStreaks,
|
|
35
|
+
KANBAN_COLUMNS,
|
|
36
|
+
} from './lib/kanban.js';
|
|
10
37
|
import {
|
|
11
38
|
eloSummary,
|
|
12
39
|
eloContext,
|
|
@@ -205,6 +232,298 @@ const tools = [
|
|
|
205
232
|
additionalProperties: false,
|
|
206
233
|
},
|
|
207
234
|
},
|
|
235
|
+
{
|
|
236
|
+
name: 'byan_copilot_sessions',
|
|
237
|
+
description:
|
|
238
|
+
'List GitHub Copilot CLI sessions stored locally at ~/.copilot/session-state/. Returns sessionId, start/end time, cwd, branch, agent name, message and tool call counts. Sorted most-recent-first. Use to discover past Copilot CLI conversations for reference or import.',
|
|
239
|
+
inputSchema: {
|
|
240
|
+
type: 'object',
|
|
241
|
+
properties: {
|
|
242
|
+
limit: { type: 'number', description: 'Max sessions to return (default 20).' },
|
|
243
|
+
sinceIso: { type: 'string', description: 'ISO timestamp filter — only sessions started after this.' },
|
|
244
|
+
cwdFilter: { type: 'string', description: 'Substring match on session cwd (e.g. "byan_web").' },
|
|
245
|
+
},
|
|
246
|
+
additionalProperties: false,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
name: 'byan_copilot_session_events',
|
|
251
|
+
description:
|
|
252
|
+
'Read events of a specific Copilot CLI session (events.jsonl). Optionally filter by event type (user.message, assistant.message, tool.execution_start, etc.). Useful to inspect the flow of a past session.',
|
|
253
|
+
inputSchema: {
|
|
254
|
+
type: 'object',
|
|
255
|
+
properties: {
|
|
256
|
+
sessionId: { type: 'string', description: 'Session UUID from byan_copilot_sessions.' },
|
|
257
|
+
types: {
|
|
258
|
+
type: 'array',
|
|
259
|
+
items: { type: 'string' },
|
|
260
|
+
description: 'Filter to these event types only.',
|
|
261
|
+
},
|
|
262
|
+
limit: { type: 'number', description: 'Max events (default 200).' },
|
|
263
|
+
},
|
|
264
|
+
required: ['sessionId'],
|
|
265
|
+
additionalProperties: false,
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
name: 'byan_fd_start',
|
|
270
|
+
description:
|
|
271
|
+
'Start a new Feature Development (FD) cycle for BYAN. Writes _byan-output/fd-state.json with phase=BRAINSTORM. Rejects if another FD is already in progress (unless force=true).',
|
|
272
|
+
inputSchema: {
|
|
273
|
+
type: 'object',
|
|
274
|
+
properties: {
|
|
275
|
+
featureName: { type: 'string', description: 'Short slug for the feature.' },
|
|
276
|
+
force: { type: 'boolean', description: 'Overwrite an existing in-progress FD.' },
|
|
277
|
+
},
|
|
278
|
+
required: ['featureName'],
|
|
279
|
+
additionalProperties: false,
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
name: 'byan_fd_status',
|
|
284
|
+
description:
|
|
285
|
+
'Return the current FD state (phase, backlog, dispatch_table, history) or { active: false } if none. Use at the start of a turn to know which phase to be in.',
|
|
286
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
name: 'byan_fd_advance',
|
|
290
|
+
description:
|
|
291
|
+
'Transition the current FD session to another phase. Valid targets : BRAINSTORM | PRUNE | DISPATCH | BUILD | VALIDATE | COMPLETED | ABORTED. Rejects backward moves (except abort).',
|
|
292
|
+
inputSchema: {
|
|
293
|
+
type: 'object',
|
|
294
|
+
properties: {
|
|
295
|
+
to: {
|
|
296
|
+
type: 'string',
|
|
297
|
+
enum: ['BRAINSTORM', 'PRUNE', 'DISPATCH', 'BUILD', 'VALIDATE', 'COMPLETED', 'ABORTED'],
|
|
298
|
+
},
|
|
299
|
+
note: { type: 'string', description: 'Optional gate-crossing rationale.' },
|
|
300
|
+
},
|
|
301
|
+
required: ['to'],
|
|
302
|
+
additionalProperties: false,
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
name: 'byan_fd_update',
|
|
307
|
+
description:
|
|
308
|
+
'Patch fields on the active FD state. Allowed keys : backlog, dispatch_table, commits, notes, feature_name. Rejects unknown keys.',
|
|
309
|
+
inputSchema: {
|
|
310
|
+
type: 'object',
|
|
311
|
+
properties: {
|
|
312
|
+
patch: { type: 'object', description: 'Partial object of allowed keys.' },
|
|
313
|
+
},
|
|
314
|
+
required: ['patch'],
|
|
315
|
+
additionalProperties: false,
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
name: 'byan_fd_abort',
|
|
320
|
+
description:
|
|
321
|
+
'Abort the current FD session (phase → ABORTED). Preserves the state file for inspection.',
|
|
322
|
+
inputSchema: {
|
|
323
|
+
type: 'object',
|
|
324
|
+
properties: { reason: { type: 'string' } },
|
|
325
|
+
additionalProperties: false,
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
{
|
|
329
|
+
name: 'byan_review_request',
|
|
330
|
+
description:
|
|
331
|
+
'Open a peer review request for a task/commit. Another agent (≠ author) must subsequently call byan_review_verdict. Persists under _byan-output/reviews/<task_id>.json.',
|
|
332
|
+
inputSchema: {
|
|
333
|
+
type: 'object',
|
|
334
|
+
properties: {
|
|
335
|
+
task_id: { type: 'string', description: 'Unique id (commit sha or feature id).' },
|
|
336
|
+
author: { type: 'string', description: 'Agent name that produced the artefact.' },
|
|
337
|
+
artifact_paths: { type: 'array', items: { type: 'string' } },
|
|
338
|
+
description: { type: 'string' },
|
|
339
|
+
},
|
|
340
|
+
required: ['task_id', 'author'],
|
|
341
|
+
additionalProperties: false,
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
name: 'byan_review_verdict',
|
|
346
|
+
description:
|
|
347
|
+
'Record a verdict on an open review request. reviewer must differ from author (enforced). Valid verdicts : approve | changes | block.',
|
|
348
|
+
inputSchema: {
|
|
349
|
+
type: 'object',
|
|
350
|
+
properties: {
|
|
351
|
+
task_id: { type: 'string' },
|
|
352
|
+
reviewer: { type: 'string' },
|
|
353
|
+
verdict: { type: 'string', enum: ['approve', 'changes', 'block'] },
|
|
354
|
+
comments: { type: 'array', items: { type: 'string' } },
|
|
355
|
+
must_fix: { type: 'array', items: { type: 'string' } },
|
|
356
|
+
},
|
|
357
|
+
required: ['task_id', 'reviewer', 'verdict'],
|
|
358
|
+
additionalProperties: false,
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
name: 'byan_review_get',
|
|
363
|
+
description: 'Fetch the current state of a review by task_id.',
|
|
364
|
+
inputSchema: {
|
|
365
|
+
type: 'object',
|
|
366
|
+
properties: { task_id: { type: 'string' } },
|
|
367
|
+
required: ['task_id'],
|
|
368
|
+
additionalProperties: false,
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
{
|
|
372
|
+
name: 'byan_review_pending',
|
|
373
|
+
description: 'List all open (pending or changes_requested) reviews, newest first.',
|
|
374
|
+
inputSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
375
|
+
},
|
|
376
|
+
{
|
|
377
|
+
name: 'byan_review_pick_reviewer',
|
|
378
|
+
description:
|
|
379
|
+
'Suggest a reviewer distinct from the author. Uses domain pairs (dev↔quinn, architect↔tea, pm↔sm, ux↔pm) then falls back to the roster.',
|
|
380
|
+
inputSchema: {
|
|
381
|
+
type: 'object',
|
|
382
|
+
properties: {
|
|
383
|
+
author: { type: 'string' },
|
|
384
|
+
preferredDomain: { type: 'string' },
|
|
385
|
+
},
|
|
386
|
+
required: ['author'],
|
|
387
|
+
additionalProperties: false,
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
name: 'byan_kanban_create',
|
|
392
|
+
description:
|
|
393
|
+
'Create (or fetch existing) kanban board for a party-mode session. Columns : todo | doing | blocked | review | done. Persisted under _byan-output/party-mode-sessions/<session_id>/kanban.json.',
|
|
394
|
+
inputSchema: {
|
|
395
|
+
type: 'object',
|
|
396
|
+
properties: { sessionId: { type: 'string' } },
|
|
397
|
+
required: ['sessionId'],
|
|
398
|
+
additionalProperties: false,
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
{
|
|
402
|
+
name: 'byan_kanban_add',
|
|
403
|
+
description: 'Add a card to the kanban. card = { id, title, assignee?, priority? (P1|P2|P3), column? }.',
|
|
404
|
+
inputSchema: {
|
|
405
|
+
type: 'object',
|
|
406
|
+
properties: {
|
|
407
|
+
sessionId: { type: 'string' },
|
|
408
|
+
card: {
|
|
409
|
+
type: 'object',
|
|
410
|
+
properties: {
|
|
411
|
+
id: { type: 'string' },
|
|
412
|
+
title: { type: 'string' },
|
|
413
|
+
assignee: { type: 'string' },
|
|
414
|
+
priority: { type: 'string' },
|
|
415
|
+
column: { type: 'string' },
|
|
416
|
+
},
|
|
417
|
+
required: ['id', 'title'],
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
required: ['sessionId', 'card'],
|
|
421
|
+
additionalProperties: false,
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
name: 'byan_kanban_move',
|
|
426
|
+
description:
|
|
427
|
+
'Move a card between columns. toColumn must be one of todo | doing | blocked | review | done. Provide blocker_reason when moving to blocked.',
|
|
428
|
+
inputSchema: {
|
|
429
|
+
type: 'object',
|
|
430
|
+
properties: {
|
|
431
|
+
sessionId: { type: 'string' },
|
|
432
|
+
cardId: { type: 'string' },
|
|
433
|
+
toColumn: { type: 'string', enum: ['todo', 'doing', 'blocked', 'review', 'done'] },
|
|
434
|
+
blocker_reason: { type: 'string' },
|
|
435
|
+
},
|
|
436
|
+
required: ['sessionId', 'cardId', 'toColumn'],
|
|
437
|
+
additionalProperties: false,
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
name: 'byan_kanban_assign',
|
|
442
|
+
description: 'Assign a card to an agent.',
|
|
443
|
+
inputSchema: {
|
|
444
|
+
type: 'object',
|
|
445
|
+
properties: {
|
|
446
|
+
sessionId: { type: 'string' },
|
|
447
|
+
cardId: { type: 'string' },
|
|
448
|
+
assignee: { type: 'string' },
|
|
449
|
+
},
|
|
450
|
+
required: ['sessionId', 'cardId', 'assignee'],
|
|
451
|
+
additionalProperties: false,
|
|
452
|
+
},
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
name: 'byan_kanban_get',
|
|
456
|
+
description: 'Fetch the current kanban board for a session.',
|
|
457
|
+
inputSchema: {
|
|
458
|
+
type: 'object',
|
|
459
|
+
properties: { sessionId: { type: 'string' } },
|
|
460
|
+
required: ['sessionId'],
|
|
461
|
+
additionalProperties: false,
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
name: 'byan_standup_post',
|
|
466
|
+
description:
|
|
467
|
+
'Append a stand-up entry to _byan-output/party-mode-sessions/<session_id>/standup.jsonl. Format : { agent, did, blockers[], next }.',
|
|
468
|
+
inputSchema: {
|
|
469
|
+
type: 'object',
|
|
470
|
+
properties: {
|
|
471
|
+
sessionId: { type: 'string' },
|
|
472
|
+
agent: { type: 'string' },
|
|
473
|
+
did: { type: 'string' },
|
|
474
|
+
blockers: { type: 'array', items: { type: 'string' } },
|
|
475
|
+
next: { type: 'string' },
|
|
476
|
+
},
|
|
477
|
+
required: ['sessionId', 'agent'],
|
|
478
|
+
additionalProperties: false,
|
|
479
|
+
},
|
|
480
|
+
},
|
|
481
|
+
{
|
|
482
|
+
name: 'byan_standup_read',
|
|
483
|
+
description: 'Read the stand-up feed for a session, newest entries last.',
|
|
484
|
+
inputSchema: {
|
|
485
|
+
type: 'object',
|
|
486
|
+
properties: {
|
|
487
|
+
sessionId: { type: 'string' },
|
|
488
|
+
limit: { type: 'number' },
|
|
489
|
+
},
|
|
490
|
+
required: ['sessionId'],
|
|
491
|
+
additionalProperties: false,
|
|
492
|
+
},
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
name: 'byan_standup_blocked',
|
|
496
|
+
description:
|
|
497
|
+
'Return agents with >= minStreak consecutive blocked stand-ups (default minStreak=2). Hermes uses this to trigger redispatch.',
|
|
498
|
+
inputSchema: {
|
|
499
|
+
type: 'object',
|
|
500
|
+
properties: {
|
|
501
|
+
sessionId: { type: 'string' },
|
|
502
|
+
minStreak: { type: 'number' },
|
|
503
|
+
},
|
|
504
|
+
required: ['sessionId'],
|
|
505
|
+
additionalProperties: false,
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
name: 'byan_copilot_search',
|
|
510
|
+
description:
|
|
511
|
+
'Full-text search across all Copilot CLI sessions. Finds messages (user + assistant by default) containing the query string. Returns sessionId + timestamp + excerpt. Use to recall past discussions without knowing which session they were in.',
|
|
512
|
+
inputSchema: {
|
|
513
|
+
type: 'object',
|
|
514
|
+
properties: {
|
|
515
|
+
query: { type: 'string', description: 'Substring to search for (case-insensitive).' },
|
|
516
|
+
types: {
|
|
517
|
+
type: 'array',
|
|
518
|
+
items: { type: 'string' },
|
|
519
|
+
description: 'Event types to scan (default: user.message, assistant.message).',
|
|
520
|
+
},
|
|
521
|
+
limit: { type: 'number', description: 'Max matches (default 50).' },
|
|
522
|
+
},
|
|
523
|
+
required: ['query'],
|
|
524
|
+
additionalProperties: false,
|
|
525
|
+
},
|
|
526
|
+
},
|
|
208
527
|
];
|
|
209
528
|
|
|
210
529
|
const server = new Server(
|
|
@@ -331,6 +650,150 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
331
650
|
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
332
651
|
}
|
|
333
652
|
|
|
653
|
+
if (name === 'byan_copilot_sessions') {
|
|
654
|
+
const result = listSessions({
|
|
655
|
+
limit: args.limit,
|
|
656
|
+
sinceIso: args.sinceIso,
|
|
657
|
+
cwdFilter: args.cwdFilter,
|
|
658
|
+
});
|
|
659
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
if (name === 'byan_copilot_session_events') {
|
|
663
|
+
const result = readSessionEvents({
|
|
664
|
+
sessionId: args.sessionId,
|
|
665
|
+
types: args.types,
|
|
666
|
+
limit: args.limit,
|
|
667
|
+
});
|
|
668
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (name === 'byan_copilot_search') {
|
|
672
|
+
const result = searchSessions({
|
|
673
|
+
query: args.query,
|
|
674
|
+
types: args.types,
|
|
675
|
+
limit: args.limit,
|
|
676
|
+
});
|
|
677
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
if (name === 'byan_fd_start') {
|
|
681
|
+
const state = fdStart({ featureName: args.featureName, force: args.force });
|
|
682
|
+
return { content: [{ type: 'text', text: JSON.stringify(state, null, 2) }] };
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
if (name === 'byan_fd_status') {
|
|
686
|
+
const state = fdStatus();
|
|
687
|
+
return { content: [{ type: 'text', text: JSON.stringify(state, null, 2) }] };
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
if (name === 'byan_fd_advance') {
|
|
691
|
+
const state = fdAdvance({ to: args.to, note: args.note });
|
|
692
|
+
return { content: [{ type: 'text', text: JSON.stringify(state, null, 2) }] };
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (name === 'byan_fd_update') {
|
|
696
|
+
const state = fdUpdate({ patch: args.patch });
|
|
697
|
+
return { content: [{ type: 'text', text: JSON.stringify(state, null, 2) }] };
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
if (name === 'byan_fd_abort') {
|
|
701
|
+
const state = fdAbort({ reason: args.reason });
|
|
702
|
+
return { content: [{ type: 'text', text: JSON.stringify(state, null, 2) }] };
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
if (name === 'byan_review_request') {
|
|
706
|
+
const r = requestReview({
|
|
707
|
+
task_id: args.task_id,
|
|
708
|
+
author: args.author,
|
|
709
|
+
artifact_paths: args.artifact_paths,
|
|
710
|
+
description: args.description,
|
|
711
|
+
});
|
|
712
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
if (name === 'byan_review_verdict') {
|
|
716
|
+
const r = recordVerdict({
|
|
717
|
+
task_id: args.task_id,
|
|
718
|
+
reviewer: args.reviewer,
|
|
719
|
+
verdict: args.verdict,
|
|
720
|
+
comments: args.comments,
|
|
721
|
+
must_fix: args.must_fix,
|
|
722
|
+
});
|
|
723
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
if (name === 'byan_review_get') {
|
|
727
|
+
const r = getReview({ task_id: args.task_id });
|
|
728
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (name === 'byan_review_pending') {
|
|
732
|
+
const r = listPending();
|
|
733
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
if (name === 'byan_review_pick_reviewer') {
|
|
737
|
+
const r = pickReviewer({
|
|
738
|
+
author: args.author,
|
|
739
|
+
preferredDomain: args.preferredDomain,
|
|
740
|
+
});
|
|
741
|
+
return {
|
|
742
|
+
content: [{ type: 'text', text: JSON.stringify({ reviewer: r }, null, 2) }],
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
if (name === 'byan_kanban_create') {
|
|
747
|
+
const r = createBoard({ sessionId: args.sessionId });
|
|
748
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
749
|
+
}
|
|
750
|
+
if (name === 'byan_kanban_add') {
|
|
751
|
+
const r = addCard({ sessionId: args.sessionId, card: args.card });
|
|
752
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
753
|
+
}
|
|
754
|
+
if (name === 'byan_kanban_move') {
|
|
755
|
+
const r = moveCard({
|
|
756
|
+
sessionId: args.sessionId,
|
|
757
|
+
cardId: args.cardId,
|
|
758
|
+
toColumn: args.toColumn,
|
|
759
|
+
blocker_reason: args.blocker_reason,
|
|
760
|
+
});
|
|
761
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
762
|
+
}
|
|
763
|
+
if (name === 'byan_kanban_assign') {
|
|
764
|
+
const r = assignCard({
|
|
765
|
+
sessionId: args.sessionId,
|
|
766
|
+
cardId: args.cardId,
|
|
767
|
+
assignee: args.assignee,
|
|
768
|
+
});
|
|
769
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
770
|
+
}
|
|
771
|
+
if (name === 'byan_kanban_get') {
|
|
772
|
+
const r = getBoard({ sessionId: args.sessionId });
|
|
773
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
774
|
+
}
|
|
775
|
+
if (name === 'byan_standup_post') {
|
|
776
|
+
const r = postStandup({
|
|
777
|
+
sessionId: args.sessionId,
|
|
778
|
+
agent: args.agent,
|
|
779
|
+
did: args.did,
|
|
780
|
+
blockers: args.blockers,
|
|
781
|
+
next: args.next,
|
|
782
|
+
});
|
|
783
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
784
|
+
}
|
|
785
|
+
if (name === 'byan_standup_read') {
|
|
786
|
+
const r = readStandups({ sessionId: args.sessionId, limit: args.limit });
|
|
787
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
788
|
+
}
|
|
789
|
+
if (name === 'byan_standup_blocked') {
|
|
790
|
+
const r = detectBlockedStreaks({
|
|
791
|
+
sessionId: args.sessionId,
|
|
792
|
+
minStreak: args.minStreak,
|
|
793
|
+
});
|
|
794
|
+
return { content: [{ type: 'text', text: JSON.stringify(r, null, 2) }] };
|
|
795
|
+
}
|
|
796
|
+
|
|
334
797
|
throw new Error(`Unknown tool: ${name}`);
|
|
335
798
|
} catch (err) {
|
|
336
799
|
return {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BYAN cleanup detector.
|
|
3
|
+
*
|
|
4
|
+
* Two scans :
|
|
5
|
+
* - findStaleSkills(skillsDir) : Claude Code skills under .claude/skills/
|
|
6
|
+
* that look like auto-generated stubs with no real BYAN value (test
|
|
7
|
+
* agents, self-referential, platform skills, or tiny SKILL.md files).
|
|
8
|
+
* - findStaleDocs(projectRoot) : root-level .md files that look like
|
|
9
|
+
* historical artifacts (old version docs, sprint reports, test plans,
|
|
10
|
+
* interview summaries, announcement guides).
|
|
11
|
+
*
|
|
12
|
+
* All detection is pattern-based with a hard allowlist ; no file is
|
|
13
|
+
* flagged without a named reason.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const fs = require('fs');
|
|
17
|
+
const path = require('path');
|
|
18
|
+
|
|
19
|
+
const SKILL_ALLOWLIST = new Set([
|
|
20
|
+
'byan-fact-check',
|
|
21
|
+
'byan-elo-trust',
|
|
22
|
+
'byan-merise-agile',
|
|
23
|
+
'byan-hermes-dispatch',
|
|
24
|
+
'byan-forge',
|
|
25
|
+
'byan-byan', // BYAN itself as a skill — core, never flag
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
const SKILL_PATTERNS = [
|
|
29
|
+
{ re: /(^|-)test(ing|-dynamic)?$/i, reason: 'test/placeholder agent (not a real BYAN capability)' },
|
|
30
|
+
{ re: /^byan-byan-(v2|test)$/i, reason: 'versioned or test stub of BYAN itself' },
|
|
31
|
+
{ re: /^byan-(claude|codex)$/i, reason: 'platform name (not an agent role)' },
|
|
32
|
+
{ re: /^byan-skeptic$/i, reason: 'experimental agent not wired in menus' },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
const DOC_ALLOWLIST = new Set([
|
|
36
|
+
'README.md',
|
|
37
|
+
'LICENSE',
|
|
38
|
+
'LICENSE.md',
|
|
39
|
+
'CHANGELOG.md',
|
|
40
|
+
'CONTRIBUTING.md',
|
|
41
|
+
'CODE_OF_CONDUCT.md',
|
|
42
|
+
'CLAUDE.md',
|
|
43
|
+
'GUIDE-UTILISATION.md',
|
|
44
|
+
'NOTES.md',
|
|
45
|
+
]);
|
|
46
|
+
|
|
47
|
+
const DOC_PATTERNS = [
|
|
48
|
+
{ re: /^SPRINT\d+-.*\.md$/i, reason: 'sprint report' },
|
|
49
|
+
{ re: /^BYAN-V\d+(\.\d+)*-.*\.md$/i, reason: 'old version snapshot doc' },
|
|
50
|
+
{ re: /^CHANGELOG-v\d+(\.\d+)*\.md$/i, reason: 'versioned changelog (current is CHANGELOG.md)' },
|
|
51
|
+
{ re: /^MIGRATION-.*\.md$/i, reason: 'migration guide for an older version' },
|
|
52
|
+
{ re: /^README-BYAN-V\d+(\.\d+)*\.md$/i, reason: 'versioned README (current is README.md)' },
|
|
53
|
+
{ re: /^API-BYAN-V\d+(\.\d+)*\.md$/i, reason: 'versioned API doc' },
|
|
54
|
+
{ re: /^TEST-GUIDE-.*\.md$/i, reason: 'historical test guide' },
|
|
55
|
+
{ re: /-MANUAL-TEST-PLAN\.md$/i, reason: 'manual test plan' },
|
|
56
|
+
{ re: /-STATUS-REPORT\.md$/i, reason: 'status report' },
|
|
57
|
+
{ re: /-COMPLETE\.md$/i, reason: 'completion report' },
|
|
58
|
+
{ re: /-SUMMARY(\.txt|\.md)$/i, reason: 'summary artifact' },
|
|
59
|
+
{ re: /-DELIVERY-SUMMARY\.md$/i, reason: 'delivery summary' },
|
|
60
|
+
{ re: /^interview-summary-.*\.md$/i, reason: 'interview summary' },
|
|
61
|
+
{ re: /^fd-.*\.md$/i, reason: 'forge-persona session artifact' },
|
|
62
|
+
{ re: /^AGENT-LAUNCHER-DOC.*\.md$/i, reason: 'agent launcher legacy doc' },
|
|
63
|
+
{ re: /^ANNOUNCEMENT-GUIDE-.*\.md$/i, reason: 'announcement guide for older version' },
|
|
64
|
+
{ re: /^SESSION-RESUME-.*\.md$/i, reason: 'session resume artifact' },
|
|
65
|
+
{ re: /^BYAN-V2-.*\.md$/i, reason: 'v2-specific doc (keep only if still referenced)' },
|
|
66
|
+
{ re: /^BMAD-QUICK-REFERENCE.*\.md$/i, reason: 'legacy quick reference' },
|
|
67
|
+
{ re: /^100-PERCENT-.*\.md$/i, reason: 'milestone completion report' },
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
function readFrontmatter(filePath) {
|
|
71
|
+
try {
|
|
72
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
73
|
+
const m = raw.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
74
|
+
if (!m) return {};
|
|
75
|
+
const out = {};
|
|
76
|
+
for (const line of m[1].split('\n')) {
|
|
77
|
+
const kv = line.match(/^(\w[\w-]*)\s*:\s*(.*)$/);
|
|
78
|
+
if (kv) out[kv[1]] = kv[2].replace(/^["']|["']$/g, '').trim();
|
|
79
|
+
}
|
|
80
|
+
return out;
|
|
81
|
+
} catch {
|
|
82
|
+
return {};
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function findStaleSkills(skillsDir) {
|
|
87
|
+
if (!fs.existsSync(skillsDir)) return [];
|
|
88
|
+
const found = [];
|
|
89
|
+
const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
90
|
+
for (const e of entries) {
|
|
91
|
+
if (!e.isDirectory()) continue;
|
|
92
|
+
if (SKILL_ALLOWLIST.has(e.name)) continue;
|
|
93
|
+
|
|
94
|
+
const skillFile = path.join(skillsDir, e.name, 'SKILL.md');
|
|
95
|
+
if (!fs.existsSync(skillFile)) continue;
|
|
96
|
+
|
|
97
|
+
const reasons = [];
|
|
98
|
+
|
|
99
|
+
for (const { re, reason } of SKILL_PATTERNS) {
|
|
100
|
+
if (re.test(e.name)) reasons.push(reason);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const size = fs.statSync(skillFile).size;
|
|
104
|
+
if (size < 200) reasons.push(`tiny SKILL.md (${size} bytes — likely placeholder stub)`);
|
|
105
|
+
|
|
106
|
+
const fm = readFrontmatter(skillFile);
|
|
107
|
+
if (!fm.description || fm.description.length < 40) {
|
|
108
|
+
reasons.push('missing or too-short description in frontmatter');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (reasons.length > 0) {
|
|
112
|
+
found.push({
|
|
113
|
+
path: path.join(skillsDir, e.name),
|
|
114
|
+
name: e.name,
|
|
115
|
+
reasons,
|
|
116
|
+
size,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return found;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function findStaleDocs(projectRoot) {
|
|
124
|
+
if (!fs.existsSync(projectRoot)) return [];
|
|
125
|
+
const found = [];
|
|
126
|
+
const entries = fs.readdirSync(projectRoot, { withFileTypes: true });
|
|
127
|
+
for (const e of entries) {
|
|
128
|
+
if (!e.isFile()) continue;
|
|
129
|
+
if (!/\.(md|txt)$/i.test(e.name)) continue;
|
|
130
|
+
if (DOC_ALLOWLIST.has(e.name)) continue;
|
|
131
|
+
|
|
132
|
+
const reasons = [];
|
|
133
|
+
for (const { re, reason } of DOC_PATTERNS) {
|
|
134
|
+
if (re.test(e.name)) reasons.push(reason);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (reasons.length > 0) {
|
|
138
|
+
const p = path.join(projectRoot, e.name);
|
|
139
|
+
const size = fs.statSync(p).size;
|
|
140
|
+
found.push({ path: p, name: e.name, reasons, size });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return found;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = {
|
|
147
|
+
SKILL_ALLOWLIST,
|
|
148
|
+
SKILL_PATTERNS,
|
|
149
|
+
DOC_ALLOWLIST,
|
|
150
|
+
DOC_PATTERNS,
|
|
151
|
+
findStaleSkills,
|
|
152
|
+
findStaleDocs,
|
|
153
|
+
readFrontmatter,
|
|
154
|
+
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-byan-agent",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.5",
|
|
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 (Copilot CLI, Claude Code, Codex). Merise Agile + TDD + 64 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",
|
|
8
8
|
"byan-v2": "./install/bin/create-byan-agent-v2.js",
|
|
9
|
+
"byan-cleanup": "./install/bin/byan-cleanup.js",
|
|
10
|
+
"byan-ledger": "./install/bin/byan-ledger.js",
|
|
11
|
+
"byan-kanban": "./install/bin/byan-kanban.js",
|
|
9
12
|
"update-byan-agent": "./update-byan-agent/bin/update-byan-agent.js"
|
|
10
13
|
},
|
|
11
14
|
"scripts": {
|
|
@@ -47,16 +50,12 @@
|
|
|
47
50
|
"install/",
|
|
48
51
|
"README.md",
|
|
49
52
|
"CHANGELOG.md",
|
|
50
|
-
"CHANGELOG-v2.1.0.md",
|
|
51
|
-
"MIGRATION-v2.0-to-v2.1.md",
|
|
52
|
-
"README-BYAN-V2.md",
|
|
53
|
-
"API-BYAN-V2.md",
|
|
54
|
-
"BMAD-QUICK-REFERENCE.md",
|
|
55
|
-
"TEST-GUIDE-v2.3.2.md",
|
|
56
53
|
"LICENSE"
|
|
57
54
|
],
|
|
58
55
|
"dependencies": {
|
|
59
56
|
"@anthropic-ai/claude-code": "^2.1.114",
|
|
57
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
58
|
+
"better-sqlite3": "^12.9.0",
|
|
60
59
|
"chalk": "^4.1.2",
|
|
61
60
|
"commander": "^11.1.0",
|
|
62
61
|
"fs-extra": "^11.2.0",
|