create-byan-agent 2.29.2 → 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 +361 -0
- package/install/bin/create-byan-agent-v2.js +44 -1
- package/install/lib/claude-native-setup.js +12 -38
- package/install/lib/gdoc-setup.js +210 -0
- package/install/lib/mcp-extensions/gdrive.js +27 -2
- package/install/lib/platforms/claude-code.js +28 -19
- package/install/lib/rtk-integration.js +18 -8
- package/install/package.json +1 -1
- package/install/packages/platform-config/lib/credentials.js +13 -1
- package/install/packages/platform-config/lib/mcp-config.js +71 -5
- package/install/setup-gdoc.js +41 -0
- package/install/setup-rtk.js +1 -1
- package/install/templates/.claude/CLAUDE.md +16 -4
- package/install/templates/.claude/hooks/inject-delivery-default.js +46 -0
- package/install/templates/.claude/hooks/inject-soul.js +4 -3
- package/install/templates/.claude/hooks/inject-tao.js +65 -25
- package/install/templates/.claude/hooks/inject-voice-anchor.js +102 -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/rules/portable-core.md +81 -0
- package/install/templates/.claude/settings.json +13 -1
- package/install/templates/.claude/skills/byan-hermes-dispatch/SKILL.md +16 -2
- 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/gdoc-client.js +203 -0
- package/install/templates/_byan/mcp/byan-mcp-server/lib/gdoc-content.js +203 -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/resolve-config.js +15 -2
- package/install/templates/_byan/mcp/byan-mcp-server/lib/strict-mode.js +78 -1
- package/install/templates/_byan/mcp/byan-mcp-server/lib/sync-rules.js +1 -1
- package/install/templates/_byan/mcp/byan-mcp-server/package.json +2 -0
- package/install/templates/_byan/mcp/byan-mcp-server/server.js +70 -0
- package/install/templates/_byan/mcp/byan-mcp-server/skill-bundles-manifest.json +1 -1
- package/install/templates/dist/skill-bundles/byan-hermes-dispatch.zip +0 -0
- package/install/templates/docs/google-docs-publish.md +121 -0
- package/install/templates/docs/leantime-integration.md +11 -1
- package/node_modules/byan-platform-config/lib/credentials.js +13 -1
- package/node_modules/byan-platform-config/lib/mcp-config.js +71 -5
- package/package.json +3 -1
- package/install/templates/.mcp.json.tmpl +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,367 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [2.38.0] - 2026-06-30
|
|
13
|
+
|
|
14
|
+
### Added - yanstaller installs the byan-channel MCP entry by default (inert)
|
|
15
|
+
|
|
16
|
+
`npx create-byan-agent` now registers a second MCP server, `byan-channel`,
|
|
17
|
+
alongside `byan` in the project `.mcp.json`. It is a Claude Code RESEARCH PREVIEW
|
|
18
|
+
channel (v2.1.80+) and ships INERT: registering it enables nothing on its own --
|
|
19
|
+
it is only loaded when the user launches
|
|
20
|
+
`claude --dangerously-load-development-channels server:byan-channel`. No
|
|
21
|
+
`channelsEnabled`, no `allowedChannelPlugins`, no auto-activation flag is written.
|
|
22
|
+
Codex is not covered by this feature.
|
|
23
|
+
|
|
24
|
+
- **Port (read-only from byan_web)**: `channel-entry.js`, `lib/channel-server.js`,
|
|
25
|
+
`lib/channel-poll.js` brought into `_byan/mcp/byan-mcp-server/`. The entry
|
|
26
|
+
resolves its own config at boot via `resolve-config.js` (env ->
|
|
27
|
+
`~/.byan/credentials.json` -> defaults), so no secret is needed in `.mcp.json`.
|
|
28
|
+
- **Wiring -- one shape, every writer**: the byan + byan-channel entry shape has a
|
|
29
|
+
single source of truth, `mcpConfig.mergeByanEntry`, with no `.mcp.json` template
|
|
30
|
+
to drift out of sync. Both writers route through it -- `generateMcpConfig` (the
|
|
31
|
+
primary native-setup path, a pure delegation) and `installDirectMCP` -- so they
|
|
32
|
+
are byte-coherent. Each writes a project-relative path (not absolute, not
|
|
33
|
+
`{{PROJECT_ROOT}}`), preserves an existing custom `command` and non-byan env,
|
|
34
|
+
strips `BYAN_API_URL`/`BYAN_API_TOKEN`, and merges into an existing `.mcp.json`
|
|
35
|
+
without clobbering other servers. Additional default MCP servers are registered
|
|
36
|
+
via `addMcpEntry` (mcp-extensions), not a template.
|
|
37
|
+
- **Portable + secret-free**: relative paths survive a moved / npm-shipped repo;
|
|
38
|
+
the channel env is forced empty; no token shape can land in tracked `.mcp.json`.
|
|
39
|
+
- **Shipped**: the 3 runtime files + 2 tests are in `TARGET_ADDITIONS` and
|
|
40
|
+
mirrored to `install/templates`, parity enforced by `byan-sync-template --check`.
|
|
41
|
+
- **Honest post-install message**: states research-preview, version gate, inert
|
|
42
|
+
default, the activation flag, and that Codex is not covered.
|
|
43
|
+
|
|
44
|
+
Files: `install/packages/platform-config/lib/mcp-config.js` (mergeByanEntry /
|
|
45
|
+
mergeChannelEntry / mergeLeantimeRefs -- relative args, command preserved),
|
|
46
|
+
`install/lib/claude-native-setup.js` (generateMcpConfig is a pure delegation to
|
|
47
|
+
the shared merge), `install/lib/platforms/claude-code.js` (installDirectMCP),
|
|
48
|
+
`install/bin/create-byan-agent-v2.js` (message),
|
|
49
|
+
`_byan/mcp/byan-mcp-server/{channel-entry,lib/channel-server,lib/channel-poll}.js`,
|
|
50
|
+
`_byan/mcp/byan-mcp-server/lib/template-sync.js`,
|
|
51
|
+
`_byan/mcp/byan-mcp-server/test/{channel,channel-resolve}.test.js` (+ install
|
|
52
|
+
templates). Adversarial review (bmad-compliance) caught 3 message/coherence gaps,
|
|
53
|
+
all fixed before merge; a follow-up adversarial pass drove removal of the now-dead
|
|
54
|
+
`.mcp.json.tmpl` so the byan/byan-channel shape has a single source of truth.
|
|
55
|
+
jest root 2473/2473, MCP node --test 723/723.
|
|
56
|
+
|
|
57
|
+
## [2.37.1] - 2026-06-30
|
|
58
|
+
|
|
59
|
+
### Fixed - strict-stop-guard false positive on mentioned completion markers
|
|
60
|
+
|
|
61
|
+
`claimsCompletion` matched a completion marker ANYWHERE in the assistant message,
|
|
62
|
+
so a turn was blocked even when a marker was merely MENTIONED, not claimed:
|
|
63
|
+
`complete` inside `byan_strict_complete`, `done` inside the `BYAN-BENCH:done`
|
|
64
|
+
marker comment, or an accented marker embedded in another word (`fini` in
|
|
65
|
+
`indefini`, `termine` in `determine`). Hit repeatedly in one session. Hardened: a
|
|
66
|
+
working copy is denoised first (fenced + inline code, HTML comments, snake_case /
|
|
67
|
+
namespaced identifiers stripped), then markers match only as a standalone claim
|
|
68
|
+
with Unicode-aware boundaries and a permissive trailing inflection (`livre` ->
|
|
69
|
+
`livree` / `livres`). Bias toward fewer false blocks -- the pre-commit gate stays
|
|
70
|
+
the hard net for a real premature completion. Genuine claims (`done`,
|
|
71
|
+
`c'est termine`, `feature livree`, `the build is complete`) still fire. +4
|
|
72
|
+
regression tests.
|
|
73
|
+
|
|
74
|
+
Files: `.claude/hooks/strict-stop-guard.js` (+ install template),
|
|
75
|
+
`_byan/mcp/byan-mcp-server/test/strict-hooks.test.js`. MCP node --test 714/714,
|
|
76
|
+
root jest 2466/2466.
|
|
77
|
+
|
|
78
|
+
## [2.37.0] - 2026-06-30
|
|
79
|
+
|
|
80
|
+
### Added - Prod-grade + maximal scope as the mechanical default (anti-downgrade)
|
|
81
|
+
|
|
82
|
+
A 4-lens diagnosis workflow established WHY the agent kept drifting toward MVP /
|
|
83
|
+
half-work despite the whole anti-downgrade arsenal: it was OPT-IN (every guard a
|
|
84
|
+
no-op until a scope is locked), the strict loop was self-judged (agent writes the
|
|
85
|
+
contract, grades its own verdict), and the cost model was anchored on human-2010
|
|
86
|
+
time, generating the MVP-split reflex. This ships the mechanical, default-on fix.
|
|
87
|
+
|
|
88
|
+
- **F1 -- delivery-contract anchor (LIVE).** New `inject-delivery-default.js`
|
|
89
|
+
(UserPromptSubmit) + pure lib `delivery-contract.js` re-inject a contract every
|
|
90
|
+
turn: grade=PROD, scope=MAXIMAL (proposing an MVP / short-deliverable /
|
|
91
|
+
dont-block-the-heavy split is forbidden unless the user types an opt-out word
|
|
92
|
+
THIS message), cost yardstick=AI-2026 (estimate in agent-time x10, not
|
|
93
|
+
human-by-hand). Opt-out wordlist in `_byan/_config/delivery-default.json`. The
|
|
94
|
+
opt-out parser is biased toward PROD: a single opt-out word counts only as a
|
|
95
|
+
short directive or with a go-cheap cue, is dropped when negated ("pas de mvp"),
|
|
96
|
+
and a mere mention in a long meta message leaves the anchor armed. Preserved
|
|
97
|
+
across compaction (CLAUDE.md) and mirrored to AGENTS.md (Codex).
|
|
98
|
+
- **F2 -- non-agent completeness judge (built, DISARMED).** `completeness-evidence.js`
|
|
99
|
+
wired additively into strict `complete()` + the pre-commit gate: a "done" claim
|
|
100
|
+
is backed by a non-fabricable artifact (a real test-runner exit, a `git diff`
|
|
101
|
+
vs the locked paths, a file that exists), breaking the judge=defendant loop.
|
|
102
|
+
Ships behind `completenessGate.armed=false` (collect + ledger only) so it does
|
|
103
|
+
not change behavior or self-lock until the ledger validates arming.
|
|
104
|
+
- **F3 -- punt-guard (built, DISARMED).** Stop hook + pure `punt-detect.js`
|
|
105
|
+
flags handing the user a runnable command the agent could run itself, with a
|
|
106
|
+
creds carve-out (git push / npm publish). Ships behind `puntGuard.armed=false`
|
|
107
|
+
(observe + ledger).
|
|
108
|
+
|
|
109
|
+
Caught in build: F1's first live turn revealed a false positive (the anchor
|
|
110
|
+
self-disabled on any message that merely mentioned an opt-out word). Fixed in
|
|
111
|
+
place with the negation + directive-context hardening above + 3 regression tests.
|
|
112
|
+
|
|
113
|
+
Files: `.claude/hooks/inject-delivery-default.js`, `.claude/hooks/lib/delivery-contract.js`,
|
|
114
|
+
`.claude/hooks/punt-guard.js`, `.claude/hooks/lib/punt-detect.js`,
|
|
115
|
+
`_byan/mcp/byan-mcp-server/lib/completeness-evidence.js`, wired into `strict-mode.js`
|
|
116
|
+
+ `precommit-gate.js`, `_byan/_config/delivery-default.json`, `.claude/settings.json`,
|
|
117
|
+
CLAUDE.md + AGENTS.md (+ install templates) + tests. MCP node --test 710/710, root
|
|
118
|
+
jest 2466/2466. Strict scope 9f8c6048.
|
|
119
|
+
|
|
120
|
+
## [2.36.0] - 2026-06-29
|
|
121
|
+
|
|
122
|
+
### Added - Leantime auto-sync: complexity, priority and description on task creation
|
|
123
|
+
|
|
124
|
+
The FD->Leantime auto-sync (which already creates tasks and drives the
|
|
125
|
+
todo/doing/review/done lifecycle) now enriches each created task with effort,
|
|
126
|
+
priority and a traceable description -- no manual board work.
|
|
127
|
+
|
|
128
|
+
- **F1 -- pure resolvers + enriched intent** (`leantime-fd-core.js`). Two
|
|
129
|
+
exported pure functions: `priorityToLeantime` (P1/P2/P3 -> 3/2/1, omitted when
|
|
130
|
+
unknown) and `complexityToStorypoints` (a finite `item.complexity` bucketed on
|
|
131
|
+
the Fibonacci scale <=15->2 / 16-39->5 / 40-69->8 / >=70->13, else derived from
|
|
132
|
+
priority P1->8 / P2->5 / P3->3, default 3 -- returns a numeric estimate).
|
|
133
|
+
`decideActions` now emits `{ priority?, storypoints, description }` in the
|
|
134
|
+
`task_create` intent (`description` = `BYAN FD <id> -- <headline>` +
|
|
135
|
+
` [complexity:N]` when finite).
|
|
136
|
+
- **F2 -- carrier + passthrough** (`leantime-sync.js` + the `leantime-fd-sync`
|
|
137
|
+
hook, source + install template). `createTask` accepts and sends `storypoints`;
|
|
138
|
+
the hook passes `description` / `priority` / `storypoints` through to it. The
|
|
139
|
+
lifecycle sync is untouched.
|
|
140
|
+
|
|
141
|
+
Note: `storypoints` is the presumed Leantime effort field, `[UNVERIFIED]` against
|
|
142
|
+
a live instance (Leantime unreachable at build time). An unknown key is at worst
|
|
143
|
+
ignored by `addTicket` (no break), and the complexity is also carried in the
|
|
144
|
+
description as a fallback. Flagged for a live-verify when reachable.
|
|
145
|
+
|
|
146
|
+
Files: `_byan/mcp/byan-mcp-server/lib/leantime-fd-core.js`, `lib/leantime-sync.js`,
|
|
147
|
+
`.claude/hooks/leantime-fd-sync.js` (+ install template), `test/leantime-fd-core.test.js`
|
|
148
|
+
+ `test/leantime-sync.test.js` (+7 tests). MCP node --test 696/696, root jest
|
|
149
|
+
2441/2441. Strict scope 80405c59.
|
|
150
|
+
|
|
151
|
+
## [2.35.0] - 2026-06-26
|
|
152
|
+
|
|
153
|
+
### Added - Portable core / native projection doctrine + degradation litmus
|
|
154
|
+
|
|
155
|
+
BYAN's memory/identity is now governed by an explicit architecture doctrine: a
|
|
156
|
+
portable in-repo core, with native Claude features as opportunistic write-through
|
|
157
|
+
accelerators rather than dependencies.
|
|
158
|
+
|
|
159
|
+
- **F1 -- doctrine.** New `.claude/rules/portable-core.md` (+ install template)
|
|
160
|
+
states the boundary: source of truth lives under `_byan/` (+ byan_web); native
|
|
161
|
+
features (prompt caching, `@-import` memory files, hooks, subagent isolation)
|
|
162
|
+
are write-through accelerators; the native AutoMem
|
|
163
|
+
(`~/.claude/projects/<hash>/memory/`) is explicitly out-of-perimeter
|
|
164
|
+
(per-machine, not shippable, not a BYAN source). Carries a feature -> adapter
|
|
165
|
+
-> degraded-path table. Mirrored to `AGENTS.md` (Codex) and pointed to from
|
|
166
|
+
`.claude/CLAUDE.md` WITHOUT an `@-import` (token budget).
|
|
167
|
+
- **F2 -- degradation litmus.** New `.claude/__tests__/portable-core.test.js`
|
|
168
|
+
makes independence mechanical: identity (soul/tao/soul-memory) reconstructs from
|
|
169
|
+
portable `_byan/` artifacts alone, and no critical read path depends on the
|
|
170
|
+
native AutoMem (regression guard).
|
|
171
|
+
|
|
172
|
+
Origin: a memory-integration audit found BYAN runs a parallel memory stack that
|
|
173
|
+
does not touch the native AutoMem -- largely justified by npm portability, but
|
|
174
|
+
undocumented and drift-prone. This codifies the boundary instead of syncing two
|
|
175
|
+
stores (F3 anti-drift guard cut, YAGNI).
|
|
176
|
+
|
|
177
|
+
Files: `.claude/rules/portable-core.md` (+ template), `AGENTS.md`,
|
|
178
|
+
`.claude/CLAUDE.md` (+ template), `.claude/__tests__/portable-core.test.js`.
|
|
179
|
+
root jest 2441/2441, MCP node --test 689/689. Strict mode: scope 591e6e49.
|
|
180
|
+
|
|
181
|
+
## [2.34.0] - 2026-06-25
|
|
182
|
+
|
|
183
|
+
### Changed - Context engineering: do more with less (compaction + subagent isolation)
|
|
184
|
+
|
|
185
|
+
Two context-engineering moves from Anthropic's guidance, applied without touching
|
|
186
|
+
BYAN's persistent identity.
|
|
187
|
+
|
|
188
|
+
- **G2 -- compaction directive.** A `## Compact instructions` section in
|
|
189
|
+
`.claude/CLAUDE.md` tells the compaction what to preserve when a long session is
|
|
190
|
+
summarized: the active FD state (phase, backlog, verdicts -- `_byan-output/fd-state.json`),
|
|
191
|
+
the active Strict Mode session, BYAN's soul/tao voice, and recent commits. It
|
|
192
|
+
complements the `pre-compact-save` PreCompact hook (which writes a file snapshot):
|
|
193
|
+
one says what to keep in-context, the other persists a snapshot to disk.
|
|
194
|
+
- **G3 -- subagent isolation doctrine in hermes.** The dispatcher's worktree path
|
|
195
|
+
already capped the subagent's return; the `mcp-worker` path did not, and the
|
|
196
|
+
isolation principle was unnamed. Both spawn paths now cap the return to a
|
|
197
|
+
distilled summary (< 200 words / ~1-2k tokens) -- verbose tool output and
|
|
198
|
+
intermediate reasoning stay in the subagent's own context. A new "Subagent
|
|
199
|
+
isolation (token leverage)" section + a hard rule codify it (Anthropic: a
|
|
200
|
+
subagent may burn ~9k tokens internally yet return ~1-2k).
|
|
201
|
+
|
|
202
|
+
Files: `.claude/CLAUDE.md` (+ template), `.claude/skills/byan-hermes-dispatch/SKILL.md`
|
|
203
|
+
(+ template), skill-bundles manifest + ZIP rebuilt, `.claude/__tests__/claude-md-context-budget.test.js`.
|
|
204
|
+
root jest 2432/2432, MCP node --test 689/689. Source: Anthropic "Effective context engineering for AI agents".
|
|
205
|
+
|
|
206
|
+
## [2.33.0] - 2026-06-25
|
|
207
|
+
|
|
208
|
+
### Changed - Keep BYAN's voice alive on long sessions (tao persistence)
|
|
209
|
+
|
|
210
|
+
Hardens the 2.32.0 tao cache-alignment so BYAN's voice does not fade on a long
|
|
211
|
+
session, without re-introducing the per-turn cost.
|
|
212
|
+
|
|
213
|
+
- **F1 -- heart-survival pinned.** A test (`.claude/__tests__/soul-hooks.test.js`)
|
|
214
|
+
now fails if `inject-tao.js` stops being wired under SessionStart with an
|
|
215
|
+
all-sources matcher (so it keeps re-firing on `source: "compact"`) or stops
|
|
216
|
+
emitting the full tao. Claude Code re-fires SessionStart after each compaction
|
|
217
|
+
(per its docs), re-injecting the full tao then; this test guards that floor
|
|
218
|
+
against a silent refactor.
|
|
219
|
+
- **F2 -- periodic refresh.** `inject-voice-anchor.js` re-injects the FULL tao
|
|
220
|
+
every N turns (N via `BYAN_TAO_REFRESH_EVERY`, default 12); the other turns keep
|
|
221
|
+
the compact anchor. A per-turn counter under `_byan-output/` (gitignored), reset
|
|
222
|
+
at SessionStart by `inject-tao.js`, drives the cadence -- so the voice is
|
|
223
|
+
refreshed close to the live edge at least every N turns, between compactions.
|
|
224
|
+
Amortized cost stays well under the pre-2.32.0 per-turn tao.
|
|
225
|
+
- **Honest floor.** The periodic refresh is best-effort: it needs a writable
|
|
226
|
+
counter, and each turn is a separate process. If `_byan-output/` is not writable
|
|
227
|
+
the hook degrades to the anchor (exit 0, no crash) and the SessionStart /
|
|
228
|
+
compaction re-injection remains the floor. A test pins that degradation.
|
|
229
|
+
|
|
230
|
+
Built under BYAN Strict Mode; reviewed by bmad-compliance (one CHANGES round on the
|
|
231
|
+
FS-degradation honesty, then approve). root jest 2430/2430, MCP node --test 689/689.
|
|
232
|
+
|
|
233
|
+
## [2.32.0] - 2026-06-25
|
|
234
|
+
|
|
235
|
+
### Changed - Token cost reduction for BYAN's persistent identity (cache + dedup)
|
|
236
|
+
|
|
237
|
+
Cuts the per-turn token cost of BYAN's persistent identity payload without making
|
|
238
|
+
any of it conditional: tao, mantras, skeptic, ELO and fact-check stay applied each
|
|
239
|
+
turn. Two levers attack the transport/representation cost, not the presence.
|
|
240
|
+
|
|
241
|
+
- **Cache-align tao injection.** The full tao was re-injected each turn via a
|
|
242
|
+
UserPromptSubmit hook (~14.9 KB per turn, re-billed at the growing edge of the
|
|
243
|
+
conversation). It now loads once at SessionStart (`inject-tao.js` -> SessionStart,
|
|
244
|
+
the cacheable prefix), and a new `inject-voice-anchor.js` injects a compact
|
|
245
|
+
~95-token voice anchor each turn (register + signatures + tutoiement + zero-emoji
|
|
246
|
+
+ IA-16). Per-turn tao transport drops 14898 -> 383 chars (97.4% lower); the full
|
|
247
|
+
tao stays present, moved to the session prefix.
|
|
248
|
+
- **De-duplicate the persistent doctrine.** `strict-mode.md`, `benchmark.md` and
|
|
249
|
+
`fact-check.md` were `@`-imported by `CLAUDE.md`, force-loading the full files
|
|
250
|
+
into every turn (~5964 tokens). The `@`-imports become lean plain pointers. The
|
|
251
|
+
behavioral summary stays inline in `CLAUDE.md` and the enforcement lives in the
|
|
252
|
+
hooks (`strict-*-guard`, `autobench-stop-guard`, `fact-check-*`); the full rule
|
|
253
|
+
files stay reachable on demand via their skills. The benchmark pointer is
|
|
254
|
+
regenerated from the `sync-rules` renderer. `elo-trust` and `team-doctrine` keep
|
|
255
|
+
their `@`-import.
|
|
256
|
+
|
|
257
|
+
A third idea (output-side filtering) was closed as already covered by RTK + Claude
|
|
258
|
+
Code's native large-output truncation -- a documented redundancy, not a cut.
|
|
259
|
+
|
|
260
|
+
Files: `.claude/hooks/inject-tao.js` (now SessionStart), `.claude/hooks/inject-voice-anchor.js`
|
|
261
|
+
(new), `.claude/settings.json`, `.claude/CLAUDE.md`, `_byan/mcp/byan-mcp-server/lib/sync-rules.js`
|
|
262
|
+
(renderer), `_byan/mcp/byan-mcp-server/lib/template-sync.js` (ships the new hook), `AGENTS.md`
|
|
263
|
+
(regenerated), plus the template mirrors. Built under BYAN Strict Mode; reviewed by bmad-compliance
|
|
264
|
+
(approve, identity line held); root jest 2420/2420, MCP node --test 689/689, zero emoji. Token
|
|
265
|
+
figures are char/4 estimates; `/context` is the exact counter-test.
|
|
266
|
+
|
|
267
|
+
## [2.31.0] - 2026-06-24
|
|
268
|
+
|
|
269
|
+
### Added - Install-time service-account key setup for byan_publish
|
|
270
|
+
|
|
271
|
+
BYAN is open-source, so no Google key ships in the npm package: each user
|
|
272
|
+
provides their own service-account key, on their own machine. This release adds
|
|
273
|
+
the install-time setup that wires that key for `byan_publish` (the headless
|
|
274
|
+
Google Docs publisher from 2.30.0).
|
|
275
|
+
|
|
276
|
+
- `install/lib/gdoc-setup.js` (new) : `setupGdocPublish` guides the user to the
|
|
277
|
+
Google Cloud console, imports the downloaded SA JSON into
|
|
278
|
+
`~/.byan/google-sa.json` (mode `0600`, dir `0700`), validates it
|
|
279
|
+
(`client_email` + `private_key`), then persists the path via `writeCredentials`
|
|
280
|
+
(`GOOGLE_APPLICATION_CREDENTIALS` + optional `GDOC_TEMPLATE_ID` /
|
|
281
|
+
`GDOC_LOGO_PNG_URL`). Every side-effecting dep (prompt / fs / writeCredentials)
|
|
282
|
+
is injected; the function stays graceful (a missing, invalid, or unreadable key
|
|
283
|
+
degrades to `configured:false` rather than throwing). Only the key path is
|
|
284
|
+
persisted -- the secret stays on disk in `~/.byan/`, out of the repo.
|
|
285
|
+
- `install/setup-gdoc.js` (new) + `npm run setup-gdoc` : run the setup on demand,
|
|
286
|
+
outside the installer.
|
|
287
|
+
- `install/bin/create-byan-agent-v2.js` : opt-in block (prompt default no, mirrors
|
|
288
|
+
the RTK block; gated by `shouldOfferGdoc` -- TTY only, skipped on
|
|
289
|
+
`BYAN_SKIP_GDOC=1`).
|
|
290
|
+
- `@byan/platform-config` : `KNOWN_KEYS` extended with
|
|
291
|
+
`GOOGLE_APPLICATION_CREDENTIALS`, `GDOC_TEMPLATE_ID`, `GDOC_LOGO_PNG_URL` so
|
|
292
|
+
`writeCredentials` persists them (covered by test).
|
|
293
|
+
- Guide : `docs/google-docs-publish.md` documents the open-source per-user key
|
|
294
|
+
model and the `npm run setup-gdoc` path (mirrored to `install/templates/docs/`).
|
|
295
|
+
|
|
296
|
+
Built under BYAN Strict Mode (scope locked, self-verified) ; secrets and
|
|
297
|
+
never-throws self-reviewed PASS (independent compliance pass to re-run before
|
|
298
|
+
publish, transient API outage at review time). Root jest 2389/0.
|
|
299
|
+
|
|
300
|
+
## [2.30.0] - 2026-06-24
|
|
301
|
+
|
|
302
|
+
### Added - byan_publish : Google Docs brandés, headless (service account)
|
|
303
|
+
|
|
304
|
+
New MCP tool `byan_publish` : a byan-owned, headless Google Docs publisher. A
|
|
305
|
+
service-account JWT (durable, no OAuth, no browser, no 7-day refresh-token expiry)
|
|
306
|
+
creates a branded Google Doc from a content object and returns its URL, optionally
|
|
307
|
+
sharing it. Distinct from the gw OAuth connector.
|
|
308
|
+
|
|
309
|
+
- `lib/gdoc-content.js` (pure) : content -> Docs `batchUpdate` requests. Template
|
|
310
|
+
mode (`replaceAllText` over a branded template) or programmatic mode (insert +
|
|
311
|
+
the AcadéNice palette : marine `#0e2656`, teal `#24947a`, turquoise `#4cccb8`).
|
|
312
|
+
- `lib/gdoc-client.js` : service-account auth (google-auth-library JWT, scopes
|
|
313
|
+
`documents` + `drive.file`) + create-or-copy + `batchUpdate` +
|
|
314
|
+
`permissions.create`. googleapis is lazy-loaded so the server boots without it ;
|
|
315
|
+
every failure path returns `{ ok:false, reason }` (no-credentials /
|
|
316
|
+
bad-credentials / invalid-content / dep-missing / api-error) rather than
|
|
317
|
+
throwing. The SA key is read from a path (`GOOGLE_APPLICATION_CREDENTIALS`, via
|
|
318
|
+
resolve-config) and stays on disk -- not serialized into any output.
|
|
319
|
+
- `byan_publish` registered in server.js, kept OUT of `REMOTE_SAFE_TOOLS`
|
|
320
|
+
(network+auth, stdio-only). New deps : `googleapis` + `google-auth-library`.
|
|
321
|
+
- Guide : `docs/google-docs-publish.md` (SA key recipe + usage + branding/template
|
|
322
|
+
+ the standalone-vs-Workspace ownership model).
|
|
323
|
+
|
|
324
|
+
The single manual step is creating the SA key (Google Cloud IAM). RNCP/eval
|
|
325
|
+
content plugs in later as a thin adapter. Built under BYAN Strict Mode (scope
|
|
326
|
+
locked, self-verified) ; reviewed by bmad-compliance (security : secrets +
|
|
327
|
+
no-throw PASS, narrow scopes, fact-check floor L1). MCP suite 687/687, root jest
|
|
328
|
+
2378/0.
|
|
329
|
+
|
|
330
|
+
## [2.29.4] - 2026-06-24
|
|
331
|
+
|
|
332
|
+
### Changed - Google Workspace (gdrive) install: durable OAuth "Internal"
|
|
333
|
+
|
|
334
|
+
The installer's Google Workspace setup guide now points to an OAuth consent
|
|
335
|
+
screen in "Internal" mode instead of "External / Testing". "External + Testing"
|
|
336
|
+
expires the refresh token in ~7 days for scopes beyond openid/email/profile (all
|
|
337
|
+
of gw's Drive/Docs/... scopes qualify); "Internal" removes that expiry and skips
|
|
338
|
+
Google app verification (source: developers.google.com/identity/protocols/oauth2).
|
|
339
|
+
The result: ONE durable OAuth client is byan's single Google credential, and the
|
|
340
|
+
claude.ai Drive connector becomes redundant.
|
|
341
|
+
|
|
342
|
+
- `install/lib/mcp-extensions/gdrive.js`: `SETUP_LINKS` + `printSetupGuide` guide
|
|
343
|
+
to Internal, with the durability rationale, the org-Workspace prerequisite, and
|
|
344
|
+
the honest limit (one browser login at setup, org-only). A durability reminder
|
|
345
|
+
fires on the reuse path too.
|
|
346
|
+
- The package `google-workspace-mcp` does not support service accounts (its
|
|
347
|
+
README), so "Internal" is the durable path that keeps its 95+ tools. A
|
|
348
|
+
service-account route (for fully headless publishing) would be a separate,
|
|
349
|
+
byan-owned Google client — out of scope here.
|
|
350
|
+
- New guide: `docs/google-workspace-setup.md` (one-time Internal recipe + the
|
|
351
|
+
mutualization rationale).
|
|
352
|
+
|
|
353
|
+
Reviewed by bmad-compliance (auth domain, fact-check floor L1). 2378 tests green.
|
|
354
|
+
|
|
355
|
+
## [2.29.3] - 2026-06-24
|
|
356
|
+
|
|
357
|
+
### Fixed - RTK hook now actually installed (--auto-patch)
|
|
358
|
+
|
|
359
|
+
2.29.2 wired only the RTK instruction layer, not the transparent hook. `wireHook`
|
|
360
|
+
ran `rtk init -g` with stdio piped (no TTY), but bare `rtk init -g` PROMPTS before
|
|
361
|
+
patching `settings.json`, so the prompt was skipped and rtk wrote `RTK.md` + the
|
|
362
|
+
`@RTK.md` reference WITHOUT the PreToolUse hook — `rtk init --show` reported
|
|
363
|
+
"Hook: not found". `wireHook` now calls `rtk init -g --auto-patch`, which patches
|
|
364
|
+
`settings.json` non-interactively, so the command-rewriting hook is installed. An
|
|
365
|
+
older rtk lacking the flag degrades gracefully (reason `hook-failed`; the install
|
|
366
|
+
still succeeds). `doctor()` and the installer consent prompt were updated to match.
|
|
367
|
+
Verified live on a Debian/zsh host: `rtk init --show` reports "Hook: configured"
|
|
368
|
+
after the fix.
|
|
369
|
+
|
|
370
|
+
If you installed 2.29.x before this and RTK feels inactive, re-run
|
|
371
|
+
`rtk init -g --auto-patch`.
|
|
372
|
+
|
|
12
373
|
## [2.29.2] - 2026-06-23
|
|
13
374
|
|
|
14
375
|
### Fixed - RTK optional install: fail-proof, off-PATH, shell-aware
|
|
@@ -17,6 +17,7 @@ const { launchPhase2Chat, generateDefaultConfig } = require('../lib/phase2-chat'
|
|
|
17
17
|
const { setupByanWebIntegration, validateByanWebReachability } = require('../lib/byan-web-integration');
|
|
18
18
|
const { setupLeantimeIntegration, validateLeantimeReachability } = require('../lib/byan-leantime-integration');
|
|
19
19
|
const { setupRtkIntegration, shouldOfferRtk } = require('../lib/rtk-integration');
|
|
20
|
+
const { setupGdocPublish, shouldOfferGdoc } = require('../lib/gdoc-setup');
|
|
20
21
|
const { setupClaudeNative } = require('../lib/claude-native-setup');
|
|
21
22
|
const { setupCodexNative } = require('../lib/codex-native-setup');
|
|
22
23
|
const { setupMcpExtensions } = require('../lib/mcp-extensions');
|
|
@@ -1295,6 +1296,21 @@ async function install(options = {}) {
|
|
|
1295
1296
|
console.log(chalk.cyan('Claude Code native setup (hooks, skills, MCP server)'));
|
|
1296
1297
|
try {
|
|
1297
1298
|
await setupClaudeNative(projectRoot);
|
|
1299
|
+
// Honest disclosure about the byan-channel entry now in .mcp.json. It is a
|
|
1300
|
+
// Claude Code RESEARCH PREVIEW feature and ships INERT: registering it does
|
|
1301
|
+
// not enable it. We tell the user exactly what it is, what it requires, how
|
|
1302
|
+
// to turn it on, and that Codex is not covered — no overselling.
|
|
1303
|
+
console.log(
|
|
1304
|
+
chalk.gray(
|
|
1305
|
+
' - byan-channel = Claude Code RESEARCH PREVIEW channel (v2.1.80+), INERT by default.'
|
|
1306
|
+
)
|
|
1307
|
+
);
|
|
1308
|
+
console.log(
|
|
1309
|
+
chalk.gray(
|
|
1310
|
+
' To activate: claude --dangerously-load-development-channels server:byan-channel'
|
|
1311
|
+
)
|
|
1312
|
+
);
|
|
1313
|
+
console.log(chalk.gray(' Codex is not covered by this feature.'));
|
|
1298
1314
|
} catch (error) {
|
|
1299
1315
|
console.log(chalk.red(` ✘ Claude native setup failed: ${error.message}`));
|
|
1300
1316
|
console.log(
|
|
@@ -1378,7 +1394,7 @@ async function install(options = {}) {
|
|
|
1378
1394
|
{
|
|
1379
1395
|
type: 'confirm',
|
|
1380
1396
|
name: 'proceed',
|
|
1381
|
-
message: 'Install rtk now? Runs its official installer (brew/cargo, or a pinned curl|sh) and adds a GLOBAL Claude Code hook via `rtk init -g`.',
|
|
1397
|
+
message: 'Install rtk now? Runs its official installer (brew/cargo, or a pinned curl|sh) and adds a GLOBAL Claude Code hook via `rtk init -g --auto-patch`.',
|
|
1382
1398
|
default: false,
|
|
1383
1399
|
},
|
|
1384
1400
|
]);
|
|
@@ -1400,6 +1416,33 @@ async function install(options = {}) {
|
|
|
1400
1416
|
}
|
|
1401
1417
|
}
|
|
1402
1418
|
|
|
1419
|
+
if (needsClaude && shouldOfferGdoc()) {
|
|
1420
|
+
console.log();
|
|
1421
|
+
console.log(chalk.cyan('byan_publish — clé service account Google Docs (optionnel, headless)'));
|
|
1422
|
+
try {
|
|
1423
|
+
const { proceed } = await inquirer.prompt([
|
|
1424
|
+
{
|
|
1425
|
+
type: 'confirm',
|
|
1426
|
+
name: 'proceed',
|
|
1427
|
+
message: 'Configurer ta clé service account maintenant (chacun la sienne ; rien de secret ne ship) ?',
|
|
1428
|
+
default: false,
|
|
1429
|
+
},
|
|
1430
|
+
]);
|
|
1431
|
+
if (proceed) {
|
|
1432
|
+
const r = await setupGdocPublish({ log: (...a) => console.log(...a) });
|
|
1433
|
+
if (r.configured) {
|
|
1434
|
+
console.log(chalk.green(` ✓ byan_publish prêt (clé : ${r.path})`));
|
|
1435
|
+
} else {
|
|
1436
|
+
console.log(chalk.yellow(` ⚠ byan_publish non configuré (${r.skipReason}) — \`npm run setup-gdoc\` à tout moment`));
|
|
1437
|
+
}
|
|
1438
|
+
} else {
|
|
1439
|
+
console.log(chalk.gray(' byan_publish ignoré — `npm run setup-gdoc` à tout moment pour activer.'));
|
|
1440
|
+
}
|
|
1441
|
+
} catch (error) {
|
|
1442
|
+
console.log(chalk.yellow(` ⚠ byan_publish setup skipped: ${error.message}`));
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1403
1446
|
if (needsClaude) {
|
|
1404
1447
|
console.log();
|
|
1405
1448
|
console.log(chalk.cyan('Leantime board sync (optional — self-hosted)'));
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* - _byan/mcp/byan-mcp-server/** (no node_modules)
|
|
10
10
|
*
|
|
11
11
|
* Generates:
|
|
12
|
-
* - .mcp.json with the
|
|
12
|
+
* - .mcp.json with the RELATIVE path to the target project's MCP server
|
|
13
|
+
* (byan + inert byan-channel entries, via the shared pure merge)
|
|
13
14
|
*
|
|
14
15
|
* Runs:
|
|
15
16
|
* - npm install inside the copied MCP server dir (with fallback warning)
|
|
@@ -22,6 +23,7 @@ const chalk = require('chalk');
|
|
|
22
23
|
|
|
23
24
|
const TEMPLATE_ROOT = path.resolve(__dirname, '..', 'templates');
|
|
24
25
|
const { whitelistMcpServer } = require('./settings-local');
|
|
26
|
+
const { mcpConfig } = require('byan-platform-config');
|
|
25
27
|
|
|
26
28
|
async function copyClaudeHooks(projectRoot) {
|
|
27
29
|
const src = path.join(TEMPLATE_ROOT, '.claude', 'hooks');
|
|
@@ -78,30 +80,15 @@ async function copyMcpServer(projectRoot) {
|
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
async function generateMcpConfig(projectRoot, options = {}) {
|
|
81
|
-
const tmplPath = path.join(TEMPLATE_ROOT, '.mcp.json.tmpl');
|
|
82
83
|
const dstPath = path.join(projectRoot, '.mcp.json');
|
|
83
84
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
byan: {
|
|
92
|
-
command: 'node',
|
|
93
|
-
args: ['{{PROJECT_ROOT}}/_byan/mcp/byan-mcp-server/server.js'],
|
|
94
|
-
env: { BYAN_API_URL: options.apiUrl || 'http://localhost:3737' },
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
null,
|
|
99
|
-
2
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const rendered = template.replace(/\{\{PROJECT_ROOT\}\}/g, projectRoot);
|
|
104
|
-
|
|
85
|
+
// Read-merge-write through the single source of truth for the byan + inert
|
|
86
|
+
// byan-channel entry shape: mcpConfig.mergeByanEntry (relative args, secret-free,
|
|
87
|
+
// existing siblings + custom command + non-byan env preserved, channel added
|
|
88
|
+
// inert). This is byte-coherent with installDirectMCP, which routes through the
|
|
89
|
+
// same merge. Additional default MCP servers are registered via addMcpEntry
|
|
90
|
+
// (mcp-extensions), not here -- so there is no .mcp.json template to drift out
|
|
91
|
+
// of sync with the merge.
|
|
105
92
|
let existing = {};
|
|
106
93
|
if (await fs.pathExists(dstPath)) {
|
|
107
94
|
try {
|
|
@@ -111,20 +98,7 @@ async function generateMcpConfig(projectRoot, options = {}) {
|
|
|
111
98
|
}
|
|
112
99
|
}
|
|
113
100
|
|
|
114
|
-
const merged =
|
|
115
|
-
merged.mcpServers = { ...(existing.mcpServers || {}), ...merged.mcpServers };
|
|
116
|
-
|
|
117
|
-
// Security: BYAN_API_TOKEN is never written into .mcp.json (git-tracked); the
|
|
118
|
-
// token reaches the MCP server via .claude/settings.local.json env. Also honor
|
|
119
|
-
// the caller's apiUrl: the template URL is only a default.
|
|
120
|
-
const byanEntry = merged.mcpServers && merged.mcpServers.byan;
|
|
121
|
-
if (byanEntry && byanEntry.env) {
|
|
122
|
-
delete byanEntry.env.BYAN_API_TOKEN;
|
|
123
|
-
if (options.apiUrl) {
|
|
124
|
-
byanEntry.env.BYAN_API_URL = options.apiUrl;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
101
|
+
const merged = mcpConfig.mergeByanEntry(existing, { apiUrl: options.apiUrl });
|
|
128
102
|
await fs.writeJson(dstPath, merged, { spaces: 2 });
|
|
129
103
|
return { path: dstPath };
|
|
130
104
|
}
|
|
@@ -197,7 +171,7 @@ async function setupClaudeNative(projectRoot, options = {}) {
|
|
|
197
171
|
);
|
|
198
172
|
|
|
199
173
|
results.mcpConfig = await generateMcpConfig(projectRoot, options);
|
|
200
|
-
log(chalk.green(`
|
|
174
|
+
log(chalk.green(` byan + inert byan-channel entries in .mcp.json (relative paths)`));
|
|
201
175
|
|
|
202
176
|
// Whitelist the byan MCP server: a project .mcp.json entry is inert in Claude
|
|
203
177
|
// Code until its id is listed in .claude/settings.local.json.
|