create-byan-agent 2.35.0 → 2.38.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 +139 -0
- package/install/bin/create-byan-agent-v2.js +15 -0
- package/install/lib/claude-native-setup.js +12 -38
- package/install/lib/platforms/claude-code.js +28 -19
- package/install/package.json +1 -1
- package/install/packages/platform-config/lib/mcp-config.js +71 -5
- package/install/templates/.claude/CLAUDE.md +1 -0
- package/install/templates/.claude/hooks/inject-delivery-default.js +46 -0
- package/install/templates/.claude/hooks/leantime-fd-sync.js +12 -1
- package/install/templates/.claude/hooks/lib/delivery-contract.js +143 -0
- package/install/templates/.claude/hooks/lib/punt-detect.js +143 -0
- package/install/templates/.claude/hooks/punt-guard.js +126 -0
- package/install/templates/.claude/hooks/strict-stop-guard.js +29 -6
- package/install/templates/.claude/settings.json +8 -0
- package/install/templates/_byan/_config/delivery-default.json +22 -0
- package/install/templates/_byan/mcp/byan-mcp-server/channel-entry.js +46 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/channel-poll.js +128 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/channel-server.js +234 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/completeness-evidence.js +159 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/leantime-fd-core.js +60 -2
- package/install/templates/_byan/mcp/byan-mcp-server/lib/leantime-sync.js +4 -1
- package/install/templates/_byan/mcp/byan-mcp-server/lib/precommit-gate.js +68 -2
- package/install/templates/_byan/mcp/byan-mcp-server/lib/strict-mode.js +78 -1
- package/install/templates/docs/leantime-integration.md +11 -1
- package/node_modules/byan-platform-config/lib/mcp-config.js +71 -5
- package/package.json +1 -1
- package/install/templates/.mcp.json.tmpl +0 -8
|
@@ -1,6 +1,66 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
1
3
|
import { getStatus, MIN_PASSES } from './strict-mode.js';
|
|
2
4
|
import { fetchSession, syncEnabled } from './strict-sync.js';
|
|
3
5
|
|
|
6
|
+
// F2 (additive): the completeness-evidence gate at commit time. Reads the
|
|
7
|
+
// completeness ledger written by strict complete(). It only ever BLOCKS when
|
|
8
|
+
// delivery-default.json completenessGate.armed === true (default false). With
|
|
9
|
+
// the gate disarmed this is a no-op and the gate decision is exactly as before.
|
|
10
|
+
const DELIVERY_CONFIG_REL = path.join('_byan', '_config', 'delivery-default.json');
|
|
11
|
+
const COMPLETENESS_LEDGER_REL = path.join('_byan-output', 'completeness-ledger.jsonl');
|
|
12
|
+
|
|
13
|
+
function completenessGateArmed(projectRoot) {
|
|
14
|
+
try {
|
|
15
|
+
const p = path.join(projectRoot || process.cwd(), DELIVERY_CONFIG_REL);
|
|
16
|
+
if (!fs.existsSync(p)) return false;
|
|
17
|
+
const cfg = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
18
|
+
return !!(cfg && cfg.completenessGate && cfg.completenessGate.armed === true);
|
|
19
|
+
} catch {
|
|
20
|
+
return false; // A broken/absent config never arms the gate.
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Last completeness-ledger entry for the given scope_hash, or null. Best-effort.
|
|
25
|
+
function lastCompletenessEntry(projectRoot, scopeHash) {
|
|
26
|
+
try {
|
|
27
|
+
const p = path.join(projectRoot || process.cwd(), COMPLETENESS_LEDGER_REL);
|
|
28
|
+
if (!fs.existsSync(p)) return null;
|
|
29
|
+
const lines = fs
|
|
30
|
+
.readFileSync(p, 'utf8')
|
|
31
|
+
.split('\n')
|
|
32
|
+
.filter((l) => l.trim());
|
|
33
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
34
|
+
try {
|
|
35
|
+
const e = JSON.parse(lines[i]);
|
|
36
|
+
if (!scopeHash || e.scope_hash === scopeHash) return e;
|
|
37
|
+
} catch {
|
|
38
|
+
// skip a malformed line
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
// unreadable ledger -> treat as no evidence record
|
|
43
|
+
}
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Pure overlay: given a base decision (PASS), apply the armed completeness gate.
|
|
48
|
+
// Returns the base decision untouched when disarmed or when the base already
|
|
49
|
+
// blocks; otherwise blocks when the completeness ledger shows missing criteria.
|
|
50
|
+
export function applyCompletenessGate(base, { armed, entry }) {
|
|
51
|
+
if (!base.pass || !armed) return base;
|
|
52
|
+
if (entry && Array.isArray(entry.missing) && entry.missing.length) {
|
|
53
|
+
return {
|
|
54
|
+
pass: false,
|
|
55
|
+
reason:
|
|
56
|
+
`Completeness gate ARMED: the completed strict session left ` +
|
|
57
|
+
`${entry.missing.length} code-shaped criteria without evidence ` +
|
|
58
|
+
`(${entry.missing.join('; ')}). Provide the artifacts before committing.`,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return base;
|
|
62
|
+
}
|
|
63
|
+
|
|
4
64
|
// BYAN Strict Mode pre-commit gate.
|
|
5
65
|
//
|
|
6
66
|
// The final, platform-agnostic net. Claude Code has in-session hooks; Codex
|
|
@@ -104,6 +164,7 @@ export async function evaluateGate({ projectRoot, fetchImpl } = {}) {
|
|
|
104
164
|
const local = getStatus({ projectRoot });
|
|
105
165
|
const normalizedLocal = normalizeLocal(local);
|
|
106
166
|
|
|
167
|
+
let base;
|
|
107
168
|
// Consult the authority when there is a session to check and a token is set.
|
|
108
169
|
if (normalizedLocal.sessionId && syncEnabled()) {
|
|
109
170
|
const remote = await fetchSession(
|
|
@@ -111,10 +172,15 @@ export async function evaluateGate({ projectRoot, fetchImpl } = {}) {
|
|
|
111
172
|
fetchImpl ? { fetchImpl } : {}
|
|
112
173
|
);
|
|
113
174
|
if (remote.ok && remote.data) {
|
|
114
|
-
|
|
175
|
+
base = decide(normalizeApi(remote.data));
|
|
115
176
|
}
|
|
116
177
|
// API unreachable / not found -> fall back to local mirror.
|
|
117
178
|
}
|
|
179
|
+
if (!base) base = decide(normalizedLocal);
|
|
118
180
|
|
|
119
|
-
|
|
181
|
+
// F2 overlay: disarmed by default -> returns `base` unchanged.
|
|
182
|
+
const armed = completenessGateArmed(projectRoot);
|
|
183
|
+
if (!armed) return base;
|
|
184
|
+
const entry = lastCompletenessEntry(projectRoot, local.scope_hash);
|
|
185
|
+
return applyCompletenessGate(base, { armed, entry });
|
|
120
186
|
}
|
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import crypto from 'node:crypto';
|
|
4
|
+
import { buildEvidence } from './completeness-evidence.js';
|
|
4
5
|
|
|
5
6
|
const STRICT_DIR = '.byan-strict';
|
|
6
7
|
const STATE_FILE = 'state.json';
|
|
7
8
|
const AUDIT_FILE = 'audit.log';
|
|
8
9
|
const MIN_SELF_VERIFY_PASSES = 3;
|
|
9
10
|
|
|
11
|
+
// F2 completeness-evidence gate. complete() ATTACHES an evidence report and, when
|
|
12
|
+
// the gate is ARMED (delivery-default.json completenessGate.armed === true),
|
|
13
|
+
// hard-rejects a completion that leaves code-shaped criteria without evidence.
|
|
14
|
+
// Default DISARMED: complete() behaves exactly as before (passCount >= 3 + last
|
|
15
|
+
// verdict ok), the report is pure observation, and every completion appends one
|
|
16
|
+
// line to the completeness ledger so arming later is data-informed.
|
|
17
|
+
const DELIVERY_CONFIG_REL = path.join('_byan', '_config', 'delivery-default.json');
|
|
18
|
+
const COMPLETENESS_LEDGER_REL = path.join('_byan-output', 'completeness-ledger.jsonl');
|
|
19
|
+
|
|
20
|
+
function readDeliveryConfig(projectRoot) {
|
|
21
|
+
try {
|
|
22
|
+
const p = path.join(resolveRoot(projectRoot), DELIVERY_CONFIG_REL);
|
|
23
|
+
if (fs.existsSync(p)) {
|
|
24
|
+
const cfg = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
25
|
+
if (cfg && typeof cfg === 'object') return cfg;
|
|
26
|
+
}
|
|
27
|
+
} catch {
|
|
28
|
+
// A broken config must NOT arm the gate — fail safe toward disarmed.
|
|
29
|
+
}
|
|
30
|
+
return {};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function completenessGateArmed(config) {
|
|
34
|
+
const g = config && config.completenessGate;
|
|
35
|
+
return !!(g && g.armed === true);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function appendCompletenessLedger(entry, projectRoot) {
|
|
39
|
+
try {
|
|
40
|
+
const p = path.join(resolveRoot(projectRoot), COMPLETENESS_LEDGER_REL);
|
|
41
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
42
|
+
fs.appendFileSync(p, JSON.stringify(entry) + '\n');
|
|
43
|
+
} catch {
|
|
44
|
+
// The observation ledger is best-effort — never break completion.
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
10
48
|
function resolveRoot(projectRoot) {
|
|
11
49
|
return projectRoot || process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
12
50
|
}
|
|
@@ -234,7 +272,7 @@ export function selfVerify({
|
|
|
234
272
|
};
|
|
235
273
|
}
|
|
236
274
|
|
|
237
|
-
export function complete({ projectRoot, now = new Date() } = {}) {
|
|
275
|
+
export function complete({ projectRoot, now = new Date(), context = {}, evidenceIo } = {}) {
|
|
238
276
|
const state = readState(projectRoot);
|
|
239
277
|
if (!state || !state.active) {
|
|
240
278
|
throw new Error('No active strict session.');
|
|
@@ -258,6 +296,42 @@ export function complete({ projectRoot, now = new Date() } = {}) {
|
|
|
258
296
|
);
|
|
259
297
|
}
|
|
260
298
|
|
|
299
|
+
// F2 (additive): collect the completeness-evidence report over the locked
|
|
300
|
+
// criteria + allowed paths. Always observed + ledgered; only ENFORCED when the
|
|
301
|
+
// gate is armed in delivery-default.json (default false -> behaviour unchanged).
|
|
302
|
+
const deliveryConfig = readDeliveryConfig(projectRoot);
|
|
303
|
+
const gateArmed = completenessGateArmed(deliveryConfig);
|
|
304
|
+
const evidence = buildEvidence({
|
|
305
|
+
criteria: state.scope_lock.acceptance_criteria || [],
|
|
306
|
+
allowedPaths: state.scope_lock.allowed_paths || [],
|
|
307
|
+
context,
|
|
308
|
+
projectRoot: resolveRoot(projectRoot),
|
|
309
|
+
io: evidenceIo,
|
|
310
|
+
});
|
|
311
|
+
appendCompletenessLedger(
|
|
312
|
+
{
|
|
313
|
+
ts: now.toISOString(),
|
|
314
|
+
event: gateArmed ? (evidence.missing.length ? 'would-reject' : 'pass') : 'observed-disarmed',
|
|
315
|
+
strict_session_id: state.strict_session_id,
|
|
316
|
+
scope_hash: state.scope_lock.scope_hash,
|
|
317
|
+
armed: gateArmed,
|
|
318
|
+
missing: evidence.missing,
|
|
319
|
+
per_criterion: evidence.perCriterion.map((c) => ({
|
|
320
|
+
criterion: c.criterion,
|
|
321
|
+
kind: c.kind,
|
|
322
|
+
hasEvidence: c.hasEvidence,
|
|
323
|
+
})),
|
|
324
|
+
},
|
|
325
|
+
projectRoot
|
|
326
|
+
);
|
|
327
|
+
if (gateArmed && evidence.missing.length) {
|
|
328
|
+
throw new Error(
|
|
329
|
+
`Cannot complete: completeness gate is ARMED and ${evidence.missing.length} ` +
|
|
330
|
+
`code-shaped criteria have no evidence (file / green test / diff): ` +
|
|
331
|
+
`${evidence.missing.join('; ')}. Provide the missing artifacts or re-lock the scope.`
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
|
|
261
335
|
const auditEntries = readAuditLog(projectRoot);
|
|
262
336
|
const auditPayload = JSON.stringify({
|
|
263
337
|
scope_hash: state.scope_lock.scope_hash,
|
|
@@ -296,6 +370,9 @@ export function complete({ projectRoot, now = new Date() } = {}) {
|
|
|
296
370
|
// Surfaced for the C3 learning-loop feed: an explicit ELO domain on the
|
|
297
371
|
// locked scope means a completed session is a VALIDATED outcome.
|
|
298
372
|
domain: state.scope_lock.domain || '',
|
|
373
|
+
// F2 (additive): the completeness-evidence report. Attached whether or not
|
|
374
|
+
// the gate is armed; with the gate disarmed it is pure observation.
|
|
375
|
+
evidence,
|
|
299
376
|
};
|
|
300
377
|
}
|
|
301
378
|
|
|
@@ -13,7 +13,7 @@ events:
|
|
|
13
13
|
| FD phase / event | Effect on the board |
|
|
14
14
|
|------------------|---------------------|
|
|
15
15
|
| DISCOVERY (project confirmed) | create-or-fetch the Leantime project |
|
|
16
|
-
| DISPATCH (per backlog feature) | one task per feature |
|
|
16
|
+
| DISPATCH (per backlog feature) | one task per feature, with effort (storypoints), priority and a description |
|
|
17
17
|
| BUILD (feature starts) | task -> column `doing` |
|
|
18
18
|
| REVIEW needs-rework / VALIDATE KO | task -> column `blocked` |
|
|
19
19
|
| VALIDATE OK | task -> column `review` |
|
|
@@ -23,6 +23,16 @@ The FD lifecycle columns (`todo|doing|blocked|review|done`) are resolved to the
|
|
|
23
23
|
project's configured Leantime status ids at call time (statuses are per-project
|
|
24
24
|
ints), with a conservative fallback when the labels cannot be read.
|
|
25
25
|
|
|
26
|
+
Each created task also carries the BYAN signal, not just a bare title:
|
|
27
|
+
|
|
28
|
+
- **effort** -- `storypoints` from the feature's complexity: a finite `complexity`
|
|
29
|
+
(0-100) bucketed on the Fibonacci scale (`<=15->2`, `16-39->5`, `40-69->8`,
|
|
30
|
+
`>=70->13`), else derived from priority (`P1->8`, `P2->5`, `P3->3`, default 3).
|
|
31
|
+
- **priority** -- `P1`/`P2`/`P3` mapped to Leantime `3`/`2`/`1` (omitted when unknown).
|
|
32
|
+
- **description** -- `BYAN FD <id> -- <headline>`, plus `[complexity:N]` when known.
|
|
33
|
+
It also carries the complexity if the Leantime effort field name differs from
|
|
34
|
+
the presumed `storypoints` (a `[UNVERIFIED]` wire detail, see Troubleshooting).
|
|
35
|
+
|
|
26
36
|
## Automatic sync (the leantime-fd-sync hook)
|
|
27
37
|
|
|
28
38
|
You do not call the `byan_leantime_*` tools by hand. A Claude Code `PostToolUse`
|
|
@@ -27,6 +27,13 @@ const path = require('path');
|
|
|
27
27
|
const fs = require('fs-extra');
|
|
28
28
|
|
|
29
29
|
const MCP_SERVER_REL_PATH = '_byan/mcp/byan-mcp-server/server.js';
|
|
30
|
+
// Channel entrypoint: a SEPARATE MCP server (research preview) spawned by Claude
|
|
31
|
+
// Code via --dangerously-load-development-channels. Same relative-path discipline
|
|
32
|
+
// as the main server (relative to projectRoot, never absolute) so the entry is
|
|
33
|
+
// portable across machines/OSes and stays valid when the repo is moved or shipped
|
|
34
|
+
// via npm. The entry is INERT by default: registering it in .mcp.json does NOT
|
|
35
|
+
// enable the channel (that needs the explicit --dangerously-load flag at launch).
|
|
36
|
+
const MCP_CHANNEL_REL_PATH = '_byan/mcp/byan-mcp-server/channel-entry.js';
|
|
30
37
|
const TOKEN_PLACEHOLDER = '${BYAN_API_TOKEN}';
|
|
31
38
|
const LEANTIME_URL_PLACEHOLDER = '${LEANTIME_API_URL}';
|
|
32
39
|
const LEANTIME_TOKEN_PLACEHOLDER = '${LEANTIME_API_TOKEN}';
|
|
@@ -87,15 +94,66 @@ function mergeByanEntry(existingConfig, { apiUrl, token } = {}) {
|
|
|
87
94
|
delete env.BYAN_API_URL;
|
|
88
95
|
delete env.BYAN_API_TOKEN;
|
|
89
96
|
|
|
97
|
+
// The canonical RELATIVE path is forced on `args` AFTER ...existing so it always
|
|
98
|
+
// wins -- this REPAIRS a stale entry that carried an absolute path (a pre-2.37.x
|
|
99
|
+
// install): relative survives a moved / npm-shipped repo, absolute does not, and
|
|
100
|
+
// Claude Code spawns the server with cwd=projectRoot so the relative path resolves
|
|
101
|
+
// identically. `command` is only F1-orthogonal (the interpreter, not a path), so a
|
|
102
|
+
// user-chosen command is preserved; we default to 'node' only when absent. Other
|
|
103
|
+
// pre-existing keys are still preserved.
|
|
90
104
|
const entry = {
|
|
91
|
-
command: 'node',
|
|
92
|
-
args: [MCP_SERVER_REL_PATH],
|
|
93
105
|
...existing,
|
|
106
|
+
command: existing.command || 'node',
|
|
107
|
+
args: [MCP_SERVER_REL_PATH],
|
|
94
108
|
};
|
|
95
109
|
if (Object.keys(env).length > 0) entry.env = env;
|
|
96
110
|
else delete entry.env;
|
|
97
111
|
|
|
98
112
|
cfg.mcpServers.byan = entry;
|
|
113
|
+
|
|
114
|
+
// The channel entry is written alongside byan from the SAME merge so there is
|
|
115
|
+
// a single source of truth for the byan MCP registration. It is inert.
|
|
116
|
+
return mergeChannelEntry(cfg);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Pure merge — no I/O. Adds the `byan-channel` MCP server entry alongside byan.
|
|
121
|
+
*
|
|
122
|
+
* This entry is a Claude Code research-preview channel (CC v2.1.80+). It is
|
|
123
|
+
* INERT by default: present in .mcp.json but only loaded when the user launches
|
|
124
|
+
* with `claude --dangerously-load-development-channels server:byan-channel`.
|
|
125
|
+
* Registering it does NOT auto-activate anything — this function writes NO
|
|
126
|
+
* channelsEnabled / allowedChannelPlugins / --dangerously-load flag.
|
|
127
|
+
*
|
|
128
|
+
* Same portability discipline as the byan entry: a RELATIVE path (never
|
|
129
|
+
* absolute), no secret in env (the channel resolves its own config at boot via
|
|
130
|
+
* resolve-config.js: env -> ~/.byan/credentials.json -> defaults). An existing
|
|
131
|
+
* byan-channel entry is preserved (command/args/env) so the merge is idempotent.
|
|
132
|
+
*
|
|
133
|
+
* @param {object} existingConfig — current parsed config
|
|
134
|
+
* @returns {object} new merged config
|
|
135
|
+
*/
|
|
136
|
+
function mergeChannelEntry(existingConfig) {
|
|
137
|
+
const cfg = existingConfig && typeof existingConfig === 'object' ? { ...existingConfig } : {};
|
|
138
|
+
cfg.mcpServers = { ...(cfg.mcpServers || {}) };
|
|
139
|
+
|
|
140
|
+
const existing = cfg.mcpServers['byan-channel'] || {};
|
|
141
|
+
|
|
142
|
+
// The canonical RELATIVE path + the empty (secret-free) env are forced AFTER
|
|
143
|
+
// ...existing so they always win, normalizing a stale entry (absolute path, or
|
|
144
|
+
// a stray env) while preserving any other pre-existing key. env stays empty: the
|
|
145
|
+
// channel resolves BYAN_API_URL/TOKEN itself via resolve-config.js -- writing a
|
|
146
|
+
// secret here would land it in tracked git, and the channel has no legitimate
|
|
147
|
+
// env contract of its own (Leantime refs live on the byan entry). `command` is
|
|
148
|
+
// F1-orthogonal so a user-chosen interpreter is preserved, 'node' only as the
|
|
149
|
+
// default. Idempotent: re-running yields the same entry.
|
|
150
|
+
cfg.mcpServers['byan-channel'] = {
|
|
151
|
+
...existing,
|
|
152
|
+
command: existing.command || 'node',
|
|
153
|
+
args: [MCP_CHANNEL_REL_PATH],
|
|
154
|
+
env: {},
|
|
155
|
+
};
|
|
156
|
+
|
|
99
157
|
return cfg;
|
|
100
158
|
}
|
|
101
159
|
|
|
@@ -141,14 +199,20 @@ function mergeLeantimeRefs(existingConfig) {
|
|
|
141
199
|
env.LEANTIME_API_URL = LEANTIME_URL_PLACEHOLDER;
|
|
142
200
|
env.LEANTIME_API_TOKEN = LEANTIME_TOKEN_PLACEHOLDER;
|
|
143
201
|
|
|
202
|
+
// Same discipline as mergeByanEntry: args forced to the canonical RELATIVE path
|
|
203
|
+
// (normalizes a stale absolute one), command preserved (F1-orthogonal), env
|
|
204
|
+
// carries the merged Leantime refs.
|
|
144
205
|
cfg.mcpServers.byan = {
|
|
145
|
-
command: 'node',
|
|
146
|
-
args: [MCP_SERVER_REL_PATH],
|
|
147
206
|
...existing,
|
|
207
|
+
command: existing.command || 'node',
|
|
208
|
+
args: [MCP_SERVER_REL_PATH],
|
|
148
209
|
env,
|
|
149
210
|
};
|
|
150
211
|
|
|
151
|
-
|
|
212
|
+
// Keep the channel entry coherent with the byan entry: ensureLeantimeRefs runs
|
|
213
|
+
// after ensureMcpConfig in the installer, but routing through mergeChannelEntry
|
|
214
|
+
// here makes the byan-channel registration robust to call order (idempotent).
|
|
215
|
+
return mergeChannelEntry(cfg);
|
|
152
216
|
}
|
|
153
217
|
|
|
154
218
|
/**
|
|
@@ -252,12 +316,14 @@ module.exports = {
|
|
|
252
316
|
ensureMcpConfig,
|
|
253
317
|
readMcpConfig,
|
|
254
318
|
mergeByanEntry,
|
|
319
|
+
mergeChannelEntry,
|
|
255
320
|
mergeLeantimeRefs,
|
|
256
321
|
ensureLeantimeRefs,
|
|
257
322
|
addMcpEntry,
|
|
258
323
|
removeMcpEntry,
|
|
259
324
|
looksLikeSecret,
|
|
260
325
|
MCP_SERVER_REL_PATH,
|
|
326
|
+
MCP_CHANNEL_REL_PATH,
|
|
261
327
|
TOKEN_PLACEHOLDER,
|
|
262
328
|
LEANTIME_URL_PLACEHOLDER,
|
|
263
329
|
LEANTIME_TOKEN_PLACEHOLDER,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-byan-agent",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.38.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": {
|