@bridge_gpt/mcp-server 0.2.12 → 0.2.14
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/CONDUCTOR.md +131 -0
- package/README.md +125 -103
- package/build/conductor/doctor.js +78 -1
- package/build/conductor/epic-runtime.js +126 -54
- package/build/conductor/epic-state.js +20 -5
- package/build/conductor/local-merge.js +212 -0
- package/build/conductor/pr-ci-producer.js +12 -2
- package/build/conductor/store.js +7 -4
- package/build/conductor/taxonomy.js +4 -0
- package/build/conductor-bin.js +476 -137
- package/build/doctor.js +3 -0
- package/build/index.js +1818 -441
- package/build/init.js +57 -0
- package/build/mcp-profile.js +33 -30
- package/build/readme.generated.js +1 -1
- package/build/sfcc/client.js +151 -0
- package/build/sfcc/config.js +39 -0
- package/build/sfcc/credentials.js +136 -0
- package/build/sfcc/ocapi-shape.js +77 -0
- package/build/sfcc/output.js +39 -0
- package/build/sfcc/permissions.js +136 -0
- package/build/sfcc/reads-custom-object-def.js +119 -0
- package/build/sfcc/reads-site-preference.js +158 -0
- package/build/sfcc/reads-system-object.js +162 -0
- package/build/sfcc/register.js +73 -0
- package/build/sfcc/setup-status.js +114 -0
- package/build/sfcc/tool-wrapper.js +70 -0
- package/build/start-tickets-conductor.js +9 -1
- package/build/start-tickets.js +47 -4
- package/build/version.generated.js +1 -1
- package/package.json +3 -2
package/CONDUCTOR.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Conductor — epic & multi-agent orchestration
|
|
2
|
+
|
|
3
|
+
Conductor is the **opt-in, off-by-default** coordination layer for running many
|
|
4
|
+
agent sessions together (epic supervision, inter-agent messaging, done-gate
|
|
5
|
+
evaluation, and conditional auto-merge). A normal `start-tickets` run does **not**
|
|
6
|
+
involve Conductor — you opt in per run with `--conductor`, and epic-tick dispatch
|
|
7
|
+
enables it internally.
|
|
8
|
+
|
|
9
|
+
This document is the reference for Conductor's observability stream, local git
|
|
10
|
+
hooks, and the per-repo done-gate / auto-merge config. For the everyday
|
|
11
|
+
`start-tickets` flags and cross-platform behavior, see
|
|
12
|
+
[README → CLI Subcommands](./README.md#cli-subcommands).
|
|
13
|
+
|
|
14
|
+
## Conductor observability (opt-in via `--conductor`, BAPI-394)
|
|
15
|
+
|
|
16
|
+
Conductor is **off by default** — without `--conductor` no `BAPI_CONDUCTOR_*` env,
|
|
17
|
+
supervisor tab, or message-relay prompt is produced. With `--conductor`, a run mints
|
|
18
|
+
a single conductor `run_id` and emits one canonical `run.started` event into the
|
|
19
|
+
local conductor ledger (`~/.config/bridge/events.db`), attributing each worker by
|
|
20
|
+
`worker_id`, ticket key, and worktree path, and opens a supervisor peer tab. When
|
|
21
|
+
the selected agent is **Claude Code**, the CLI also injects a conductor lifecycle
|
|
22
|
+
hook into each created worktree's `.claude/settings.local.json` (preserving any
|
|
23
|
+
existing hooks) so the spawned session streams local `run.started` / `run.stopped` /
|
|
24
|
+
`agent.notification` (and, with `BAPI_CONDUCTOR_ENABLE_PRE_TOOL_USE=1`,
|
|
25
|
+
`tool.intent`) events. Per-worker conductor identity is passed only via secret-free
|
|
26
|
+
environment scoped to that one terminal/tab/session — no credentials are ever placed
|
|
27
|
+
in the env, hook command, or run metadata. Override the gate/supervisor labels with
|
|
28
|
+
`BAPI_CONDUCTOR_GATE_NAME` / `BAPI_CONDUCTOR_SUPERVISOR_MODE`. Inspect the stream
|
|
29
|
+
with `conductor doctor`. Observability is best-effort: a conductor failure never
|
|
30
|
+
blocks or aborts a spawn, and `--dry-run` performs no conductor side effects.
|
|
31
|
+
(Epic-tick dispatch always enables conductor internally, independent of this flag.)
|
|
32
|
+
|
|
33
|
+
When `--conductor` is set, the spawn boundary also injects
|
|
34
|
+
`BRIDGE_MCP_PROFILE=conductor` so each worker registers the 8 conductor/event/
|
|
35
|
+
supervisor MCP tools (a plain `start-tickets` run stays on the default `core`
|
|
36
|
+
profile). See [README → Environment Variables](./README.md#environment-variables).
|
|
37
|
+
|
|
38
|
+
## `conductor install-git-hooks` (BAPI-395)
|
|
39
|
+
|
|
40
|
+
Installs local git hooks that opportunistically emit conductor git/PR/CI events into
|
|
41
|
+
the local ledger:
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
conductor install-git-hooks [--json]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The installed hooks are **local, unversioned, opportunistic, and bypassable**: they
|
|
48
|
+
live in the worktree's git hooks directory (resolved via
|
|
49
|
+
`git rev-parse --git-common-dir`), insert only a clearly-delimited managed block
|
|
50
|
+
(preserving any existing user hook content), launch the producer **detached in the
|
|
51
|
+
background** so a commit or ref update is never blocked, and tolerate every failure
|
|
52
|
+
(`|| true`). A directory that is not a git worktree, or an existing hook that looks
|
|
53
|
+
binary/unsafe, is left untouched and reported as a **degraded optional capability** —
|
|
54
|
+
never a fatal error. The hooks installed are `post-commit` (emits
|
|
55
|
+
`git.commit_created`) and `reference-transaction` (emits `worktree.changed` for
|
|
56
|
+
committed ref updates).
|
|
57
|
+
|
|
58
|
+
Missing hooks do **not** prevent PR/CI gate evaluation — `conductor doctor` reads
|
|
59
|
+
hook presence and managed-snippet status **read-only** (a new `git hooks` section /
|
|
60
|
+
`git_hooks` JSON object alongside the ledger report), and the `wait_for_done_gate`
|
|
61
|
+
MCP tool drives CI polling and gate evaluation regardless of whether hooks are
|
|
62
|
+
installed.
|
|
63
|
+
|
|
64
|
+
## `conductor_done_gate` config
|
|
65
|
+
|
|
66
|
+
The per-repo `conductor_done_gate` config field (read through the existing
|
|
67
|
+
config-field route) defines the v1 done gate. It supports exactly one condition,
|
|
68
|
+
`required_ci_checks_green`:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"enabled": true,
|
|
73
|
+
"conditions": [
|
|
74
|
+
{ "type": "required_ci_checks_green", "required_checks": ["build", "test"] }
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`gate.met` is emitted (exactly once per `repo + pr_number + head_sha + effective
|
|
80
|
+
config`) only when every listed required check is present, complete, and green for
|
|
81
|
+
the bound PR head SHA. The gate **fails closed**: an unset, disabled (`enabled` not
|
|
82
|
+
strictly `true`), malformed, empty, or unsupported config emits no `gate.met`.
|
|
83
|
+
|
|
84
|
+
## `conductor_auto_merge_enabled` config (C6 conditional auto-merge)
|
|
85
|
+
|
|
86
|
+
When a worker's PR meets the done gate (`gate.met`), the supervisor can autonomously
|
|
87
|
+
merge it — but **only** when the repo has explicitly opted in. The per-repo
|
|
88
|
+
`conductor_auto_merge_enabled` config field (read through the same config-field route
|
|
89
|
+
as `conductor_done_gate`) is the opt-in switch:
|
|
90
|
+
|
|
91
|
+
```json
|
|
92
|
+
{ "enabled": true }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
A bare JSON boolean (`true`) is also accepted. **Auto-merge is disabled by default.**
|
|
96
|
+
Behavior:
|
|
97
|
+
|
|
98
|
+
- **Disabled / unset / malformed → dry-run.** Anything other than `true` or
|
|
99
|
+
`{"enabled": true}` — including unset, `false`, `{"enabled": false}`, or any
|
|
100
|
+
malformed value — fails **closed**: the supervisor records a `merge.dry_run` event
|
|
101
|
+
and **no PR is ever merged**.
|
|
102
|
+
- **Enabled → autonomous merge** when the gate is met and the deterministic guards
|
|
103
|
+
pass.
|
|
104
|
+
- **Kill-switch.** Set `conductor_auto_merge_enabled` to `false` or remove the field
|
|
105
|
+
to immediately stop autonomous merges. The protected merge endpoint
|
|
106
|
+
**independently re-enforces** the flag, so even a conductor that calls it cannot
|
|
107
|
+
merge while the flag is off.
|
|
108
|
+
|
|
109
|
+
Merge authority is **deterministic code, never an LLM**. The deterministic guards,
|
|
110
|
+
all bound to **PR number + expected head SHA (never a branch name)**:
|
|
111
|
+
|
|
112
|
+
- the per-repo enablement flag (off → dry-run),
|
|
113
|
+
- the PR is still open,
|
|
114
|
+
- the merge is bound to the PR number plus the expected head SHA — **head-SHA drift
|
|
115
|
+
between gate evaluation and merge aborts the merge**,
|
|
116
|
+
- required CI checks are **revalidated green immediately before merge**.
|
|
117
|
+
|
|
118
|
+
Idempotency is crash-safe and race-safe: a TTL lease keyed by the deterministic
|
|
119
|
+
action key `merge:{repo}:{pr}:{head_sha}:{gate}` is claimed before acting, and an
|
|
120
|
+
existing `merge.succeeded` for that key is terminal — the supervisor never
|
|
121
|
+
double-merges across a crash/restart or two racing instances. The conductor never
|
|
122
|
+
holds VCS write credentials: it calls the protected Bridge API endpoint
|
|
123
|
+
`POST /vcs/pull-requests/{pr_number}/merge`, which owns the privileged merge, and
|
|
124
|
+
records the returned `merge.dry_run` / `merge.attempted` / `merge.succeeded` /
|
|
125
|
+
`merge.failed` / `merge.pending_approval` events into the local ledger.
|
|
126
|
+
`merge.failed` is **retryable** (a drifted head SHA produces a new action key);
|
|
127
|
+
`merge.pending_approval` is **nonterminal** — the worker remains active until a human
|
|
128
|
+
redeems the approval token and the server returns `merge.succeeded`.
|
|
129
|
+
**`merge.succeeded` is the only terminal merge event.** The local SQLite conductor
|
|
130
|
+
store uses schema version 5 (BAPI-413) to accommodate the `merge.pending_approval`
|
|
131
|
+
type in the `events.type` CHECK constraint.
|
package/README.md
CHANGED
|
@@ -1,19 +1,58 @@
|
|
|
1
1
|
# @bridge_gpt/mcp-server
|
|
2
2
|
|
|
3
|
-
MCP
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
The Bridge MCP is an end-to-end accelerator for shipping code within SFCC, powered by [Bridge API](https://bridgegpt-api.com). Works with Claude Code, Github Copilot, Cursor, Windsurf, and OpenAI Codex.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- [Getting Started](#getting-started)
|
|
8
|
+
- [Usage Documentation](#usage-documentation)
|
|
9
|
+
- [Tier 1 — Regularly useful](#tier-1--regularly-useful)
|
|
10
|
+
- [Tier 2 — Occasionally useful](#tier-2--occasionally-useful)
|
|
11
|
+
- [Tier 3 — Now and then](#tier-3--now-and-then)
|
|
12
|
+
- [Operational commands](#operational-commands)
|
|
13
|
+
- [Extra Capabilities](#extra-capabilities)
|
|
14
|
+
- [Salesforce B2C Commerce (SFCC) Tools](#salesforce-b2c-commerce-sfcc-tools)
|
|
15
|
+
- [CLI Subcommands](#cli-subcommands)
|
|
16
|
+
- [Custom Pipelines](#custom-pipelines)
|
|
17
|
+
- [Environment Variables](#environment-variables)
|
|
18
|
+
- [Worktree credentials and the `mcp-invoke` shim](#worktree-credentials-and-the-mcp-invoke-shim)
|
|
19
|
+
- [Reference](#reference)
|
|
20
|
+
|
|
21
|
+
For advanced epic/multi-agent orchestration, see [CONDUCTOR.md](./CONDUCTOR.md).
|
|
6
22
|
|
|
7
23
|
## Getting Started
|
|
8
24
|
|
|
9
|
-
### Quick start
|
|
25
|
+
### Quick start
|
|
10
26
|
|
|
11
|
-
From your **project root**,
|
|
27
|
+
From your **project root**, install and connect in one command:
|
|
12
28
|
|
|
13
29
|
```bash
|
|
14
30
|
npx -y @bridge_gpt/mcp-server@latest install-bridge
|
|
15
31
|
```
|
|
16
32
|
|
|
33
|
+
`install-bridge` scaffolds the project, writes your editor's MCP config with real
|
|
34
|
+
values, verifies connectivity, persists your API key to the user-scoped credential
|
|
35
|
+
store, and opens a fresh agent session to finish setup (`/install-bridge` then
|
|
36
|
+
`/learn-repository`). The only inputs are an **API key** (generate one on the Bridge
|
|
37
|
+
API web UI **Security** page) and a **repo name** — everything else is derived. Add
|
|
38
|
+
`--dry-run` to preview every step without writing, pinging, or spawning anything.
|
|
39
|
+
|
|
40
|
+
To upgrade later, run:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx -y @bridge_gpt/mcp-server upgrade
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`upgrade` re-execs from `@latest`, refreshes all scaffolded artifacts (slash
|
|
47
|
+
commands, agents, pipelines), rewrites the version pin, and reconnects — also
|
|
48
|
+
available as the `/upgrade-bridge` slash command. (The legacy `--upgrade` flag still
|
|
49
|
+
works as a fallback.)
|
|
50
|
+
|
|
51
|
+
<details>
|
|
52
|
+
<summary><strong>Installation Instructions</strong></summary>
|
|
53
|
+
|
|
54
|
+
#### What `install-bridge` does
|
|
55
|
+
|
|
17
56
|
`install-bridge` collapses the whole setup into a single command. It:
|
|
18
57
|
|
|
19
58
|
1. **Scaffolds** the project (the same artifacts `--init` writes: slash commands,
|
|
@@ -55,9 +94,9 @@ That's it — once `install-bridge` finishes you're connected. If you prefer to
|
|
|
55
94
|
it by hand (or just want to understand each step), the manual flow below does the
|
|
56
95
|
same thing.
|
|
57
96
|
|
|
58
|
-
|
|
97
|
+
#### Manual Setup (Alternative)
|
|
59
98
|
|
|
60
|
-
|
|
99
|
+
##### 1. Install the Package
|
|
61
100
|
|
|
62
101
|
From your **project root**, install the MCP server and scaffold slash commands:
|
|
63
102
|
|
|
@@ -74,7 +113,7 @@ npx -y @bridge_gpt/mcp-server --init
|
|
|
74
113
|
|
|
75
114
|
Re-run `--init` after upgrading the package to get updated commands.
|
|
76
115
|
|
|
77
|
-
|
|
116
|
+
##### 2. Generate an API Key
|
|
78
117
|
|
|
79
118
|
1. Log in to [Bridge API](https://bridgegpt-api.com) and navigate to your project's **Security** page
|
|
80
119
|
2. Click **Create New Key**
|
|
@@ -82,7 +121,7 @@ Re-run `--init` after upgrading the package to get updated commands.
|
|
|
82
121
|
4. Click **Create Key**
|
|
83
122
|
5. **Copy the key immediately** — it will not be shown again
|
|
84
123
|
|
|
85
|
-
|
|
124
|
+
##### 3. Configure the MCP Server
|
|
86
125
|
|
|
87
126
|
Add the following to your editor's MCP configuration file, pasting in the API key from step 2:
|
|
88
127
|
|
|
@@ -196,28 +235,30 @@ BAPI_DOCS_DIR = "docs/tmp"
|
|
|
196
235
|
|
|
197
236
|
After saving the config, restart your editor or reload the MCP server connection. Verify connectivity by asking your AI assistant to call the `ping` tool.
|
|
198
237
|
|
|
199
|
-
|
|
238
|
+
##### 4. First-Time Setup: Teach Bridge Your Codebase
|
|
200
239
|
|
|
201
240
|
If you're the first person to install Bridge API on your project, run the `/learn-repository` slash command after completing setup. This analyzes your codebase's architecture, testing patterns, code review standards, and documentation conventions, then uploads the findings to Bridge API. This gives Bridge the context it needs to generate implementation plans, ticket critiques, and code reviews that are consistent with your project's actual architecture and conventions.
|
|
202
241
|
|
|
203
242
|
You only need to do this once per project — the learned standards persist for all team members.
|
|
204
243
|
|
|
205
|
-
|
|
244
|
+
##### Upgrading (details)
|
|
206
245
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
This runs `npm i @bridge_gpt/mcp-server@latest`, prints a before/after version summary, then re-runs the full `--init` scaffolding flow to update your slash commands, agents, and pipeline definitions.
|
|
246
|
+
The one-command `npx -y @bridge_gpt/mcp-server upgrade` (shown above) is the
|
|
247
|
+
recommended path. The legacy flag `npx -y @bridge_gpt/mcp-server --upgrade` still
|
|
248
|
+
works: it runs `npm i @bridge_gpt/mcp-server@latest`, prints a before/after version
|
|
249
|
+
summary, then re-runs the full `--init` scaffolding flow to update your slash
|
|
250
|
+
commands, agents, and pipeline definitions.
|
|
214
251
|
|
|
215
252
|
The MCP server also checks for updates automatically on startup. If a newer version is available, you'll see a notice in your editor's MCP output logs with the upgrade command to run. This check is cached for 24 hours and never blocks server startup.
|
|
216
253
|
|
|
254
|
+
</details>
|
|
255
|
+
|
|
217
256
|
## Usage Documentation
|
|
218
257
|
|
|
219
258
|
This is the Bridge API tooling worth knowing about as a software engineer — the things you'd ask an agent to do — grouped by how often you would use them. Each entry covers **what it does**, **when it's useful** and **how to use it**. The behind-the-scenes plumbing is summarized at the end under [Extra Capabilities](#extra-capabilities), and a full enumeration lives in [Reference](#reference).
|
|
220
259
|
|
|
260
|
+
Working in a Salesforce B2C Commerce codebase? Bridge also ships read-only SFCC platform-introspection tools — see [Salesforce B2C Commerce (SFCC) Tools](#salesforce-b2c-commerce-sfcc-tools).
|
|
261
|
+
|
|
221
262
|
For invocation, prefer the slash command — it's deterministic. A free-text example is shown only where natural-language phrasing reliably maps to the right automation; high-consequence or easily-misread automations show only the slash command on purpose.
|
|
222
263
|
|
|
223
264
|
### Tier 1 — Regularly useful
|
|
@@ -401,6 +442,66 @@ Behind-the-scenes capabilities an agent gains from the MCP tools — mostly invo
|
|
|
401
442
|
- **Retrieve any generated artifact** (`get_*` for plans, critiques, questions, brainstorms, research, architecture) without regenerating it.
|
|
402
443
|
- **Tiered-section execution telemetry** recording (internal measurement).
|
|
403
444
|
|
|
445
|
+
## Salesforce B2C Commerce (SFCC) Tools
|
|
446
|
+
|
|
447
|
+
Salesforce's official MCP server, `@salesforce/b2c-dx-mcp`, covers developer-experience tasks — cartridge deploy, step debugging, docs search, logs/MRT, and SCAPI Custom API scaffolding. As of its current toolset it has no way to *read* the platform's object model, custom objects, or site configuration — exactly the context an AI coding agent needs to write correct Commerce code and to inspect a sandbox before touching it. Bridge's SFCC tools install side-by-side with `b2c-dx-mcp` (they don't duplicate its surface) and close that gap with **read-only OCAPI Data API introspection** of system objects, custom object definitions, and site preferences.
|
|
448
|
+
|
|
449
|
+
**v1 is read-only and developer-sandbox-only** — no writes, and non-sandbox instances are rejected. Credentials stay local (in `dw.json` or `SFCC_*` env vars) and are never sent to Bridge.
|
|
450
|
+
|
|
451
|
+
<details>
|
|
452
|
+
<summary><strong>Setup</strong></summary>
|
|
453
|
+
|
|
454
|
+
The two diagnostic tools (`sfcc_setup_status`, `check_permissions`) are always available. The seven read tools must be enabled with a profile (step 3).
|
|
455
|
+
|
|
456
|
+
**Prerequisites:** a running SFCC **sandbox** and its hostname, plus an Account Manager API client (`client-id` + `client-secret`).
|
|
457
|
+
|
|
458
|
+
**1. Set the repo `version` config field** to your SFCC project type — one of `sfra | pwakit | sitegenesis | storefrontnext | hybrid`. The call-time gate reads this; a non-SFCC value blocks every SFCC tool except `sfcc_setup_status`. Set it via your normal config path, the `config_field` MCP tool (operation `update`, field `version`), or the `/teach-bridge` skill.
|
|
459
|
+
|
|
460
|
+
**2. Provide SFCC credentials.** Create a `dw.json` in your project root:
|
|
461
|
+
|
|
462
|
+
```json
|
|
463
|
+
{
|
|
464
|
+
"hostname": "zzzz-001.sandbox.us01.dx.commercecloud.salesforce.com",
|
|
465
|
+
"client-id": "<account-manager-client-id>",
|
|
466
|
+
"client-secret": "<account-manager-client-secret>"
|
|
467
|
+
}
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
Accepted key spellings: `hostname`/`host`, `client-id`/`clientId`/`client_id`, `client-secret`/`clientSecret`/`client_secret`. Prefer a single config — a multi-entry `configs[]` array forces you to pass an explicit `instance` on every call. `dw.json` is auto-added to git exclude and must never be committed. Alternatively, export `SFCC_HOSTNAME` / `SFCC_CLIENT_ID` / `SFCC_CLIENT_SECRET` in the MCP server environment.
|
|
471
|
+
|
|
472
|
+
**3. Enable the read tools.** Add `sfcc` to `BRIDGE_MCP_PROFILE` in the MCP server `env` block (it is comma-separated; `full` also works), then **restart the MCP client**:
|
|
473
|
+
|
|
474
|
+
```json
|
|
475
|
+
"env": { "BRIDGE_MCP_PROFILE": "sfcc" }
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Without this, only the diagnostic tools are registered.
|
|
479
|
+
|
|
480
|
+
**4. Verify and grant OCAPI access.** Ask your agent to run `sfcc_setup_status` (expect all checks ✓), then `check_permissions`. If it reports HTTP 401/403, it prints the exact OCAPI Settings JSON to paste in Business Manager (**Administration → Site Development → Open Commerce API Settings → Data API** tab); save it there and re-run. Restart the MCP client after any credential or env change — a running session does not pick them up.
|
|
481
|
+
|
|
482
|
+
</details>
|
|
483
|
+
|
|
484
|
+
### Tools
|
|
485
|
+
|
|
486
|
+
All SFCC tools are read-only and target a developer sandbox. Oversized responses are automatically saved to `BAPI_DOCS_DIR/sfcc/` and previewed inline.
|
|
487
|
+
|
|
488
|
+
**Diagnostics** (always available, no profile needed)
|
|
489
|
+
- `sfcc_setup_status` — report on every prerequisite: Bridge API key, repo name, `version` config, `dw.json` presence/uniqueness, and AM token acquisition.
|
|
490
|
+
- `check_permissions` — probe OCAPI access via `GET /system_object_definitions`; on 401/403, print the exact OCAPI Settings JSON to paste in Business Manager (split read-only vs. write/import grants).
|
|
491
|
+
|
|
492
|
+
**System object model** (needs the `sfcc` profile)
|
|
493
|
+
- `system_object_list` — list system object types (Product, Order, Customer, …).
|
|
494
|
+
- `system_object_get` — fetch one type's definition, optionally with its full attribute definitions (`expand_attribute_definitions`).
|
|
495
|
+
- `system_object_attribute_search` — search a type's attribute definitions; prefer this over a full dump when hunting a specific `c_` custom attribute.
|
|
496
|
+
|
|
497
|
+
**Custom object definitions** (needs the `sfcc` profile)
|
|
498
|
+
- `custom_object_definition_list` — list custom object type definitions.
|
|
499
|
+
- `custom_object_definition_get` — fetch an existing custom type with its key definition and attribute definitions/groups. Read-only — creating a custom object *type* isn't possible via OCAPI; that's a future v2 metadata-import capability.
|
|
500
|
+
|
|
501
|
+
**Site preferences** (needs the `sfcc` profile; sandbox only)
|
|
502
|
+
- `site_preference_get` — read a preference group's effective preferences.
|
|
503
|
+
- `site_preference_search` — search/filter preferences within a group.
|
|
504
|
+
|
|
404
505
|
## CLI Subcommands
|
|
405
506
|
|
|
406
507
|
Beyond `--init` / `--upgrade`, the package ships operational subcommands of the **single `bridge-api-mcp-server` bin** (not separate binaries) — so they travel with the package to every consumer. See [Usage Documentation → Start Tickets](#tier-1--regularly-useful) for *when* to use `start-tickets`; this section is the full CLI reference.
|
|
@@ -433,7 +534,7 @@ npx -y @bridge_gpt/mcp-server start-tickets --agent cursor-agent BAPI-248
|
|
|
433
534
|
|
|
434
535
|
**Difficulty-based model routing.** Before launching each agent, the CLI selects an implementation **model tier** from the ticket's `difficulty` (1-2 → cheap, 3-5 → basic, 6+ → premium) and injects it as a `--model` flag at the spawn boundary. The Python backend returns only the coarse tier (`GET /jira/tickets/{KEY}/model-tier`, computing + caching difficulty on demand); this CLI alone maps a tier to the agent-specific alias (`claude`: `haiku`/`sonnet`/`opus`; `cursor-agent`: version-suffixed strings validated against `cursor-agent --list-models`). It is gated per repo by `difficulty_model_routing_enabled` (default **ON**) with an optional `difficulty_model_tier_overrides` JSON map (tier → alias). Routing is **fail-open**: missing credentials, an evaluation failure/timeout, a backend `fallback`, an invalid/unavailable alias, an unadvertised Cursor model, or an agent without `--model` support all omit `--model` (the agent uses its default) and surface a per-ticket warning rather than failing the spawn. `--dry-run` does **not** fetch tiers or inject `--model`.
|
|
435
536
|
|
|
436
|
-
**Conductor observability (opt-in via `--conductor`, BAPI-394).** Conductor is **off by default
|
|
537
|
+
**Conductor observability (opt-in via `--conductor`, BAPI-394).** Conductor is **off by default**. With `--conductor`, a run mints a conductor `run_id`, emits events into the local ledger (`~/.config/bridge/events.db`), opens a supervisor peer tab, and (for Claude Code) injects a secret-free lifecycle hook into each worktree; it also sets `BRIDGE_MCP_PROFILE=conductor` so workers get the conductor MCP tools. Observability is best-effort — a conductor failure never blocks a spawn, and `--dry-run` performs no conductor side effects. (Epic-tick dispatch always enables conductor internally.) See **[CONDUCTOR.md](./CONDUCTOR.md)** for the full observability, git-hook, done-gate, and auto-merge reference.
|
|
437
538
|
|
|
438
539
|
**Cross-platform spawning.** The CLI routes spawning per platform; `--dry-run` previews the platform-correct command form on any OS. An unsupported `process.platform` (not `darwin`/`win32`/`linux`) fails fast with a clear "unsupported platform" message.
|
|
439
540
|
|
|
@@ -453,55 +554,9 @@ npx -y @bridge_gpt/mcp-server doctor [--agent <name>]
|
|
|
453
554
|
|
|
454
555
|
It is **read-only**: it never installs anything, modifies your system, adds an npm `postinstall`, spawns a terminal, or starts the MCP server, and there is no `--fix`. For each prerequisite it prints found/missing and, when missing, the exact per-OS install command **as a manual instruction you run yourself**. The checked set is the `start-tickets` preflight prerequisites **plus `uv`** **plus the selected agent's command** (`claude` by default, or `cursor-agent` with `--agent cursor-agent`). The Worktrunk binary is probed via the resolved name (honoring `BAPI_WORKTRUNK_BIN`), not a hard-coded one. **Exit code:** `0` when all required prerequisites are present, non-zero when any is missing or the platform is unsupported. A failing `start-tickets` preflight now hints you to run `doctor` for an actionable diagnostics report.
|
|
455
556
|
|
|
456
|
-
###
|
|
457
|
-
|
|
458
|
-
Installs local git hooks that opportunistically emit conductor git/PR/CI events into the local ledger:
|
|
459
|
-
|
|
460
|
-
```
|
|
461
|
-
conductor install-git-hooks [--json]
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
The installed hooks are **local, unversioned, opportunistic, and bypassable**: they live in the worktree's git hooks directory (resolved via `git rev-parse --git-common-dir`), insert only a clearly-delimited managed block (preserving any existing user hook content), launch the producer **detached in the background** so a commit or ref update is never blocked, and tolerate every failure (`|| true`). A directory that is not a git worktree, or an existing hook that looks binary/unsafe, is left untouched and reported as a **degraded optional capability** — never a fatal error. The hooks installed are `post-commit` (emits `git.commit_created`) and `reference-transaction` (emits `worktree.changed` for committed ref updates).
|
|
465
|
-
|
|
466
|
-
Missing hooks do **not** prevent PR/CI gate evaluation — `conductor doctor` reads hook presence and managed-snippet status **read-only** (a new `git hooks` section / `git_hooks` JSON object alongside the ledger report), and the `wait_for_done_gate` MCP tool drives CI polling and gate evaluation regardless of whether hooks are installed.
|
|
467
|
-
|
|
468
|
-
#### `conductor_done_gate` config
|
|
469
|
-
|
|
470
|
-
The per-repo `conductor_done_gate` config field (read through the existing config-field route) defines the v1 done gate. It supports exactly one condition, `required_ci_checks_green`:
|
|
471
|
-
|
|
472
|
-
```json
|
|
473
|
-
{
|
|
474
|
-
"enabled": true,
|
|
475
|
-
"conditions": [
|
|
476
|
-
{ "type": "required_ci_checks_green", "required_checks": ["build", "test"] }
|
|
477
|
-
]
|
|
478
|
-
}
|
|
479
|
-
```
|
|
557
|
+
### Conductor (epic & multi-agent orchestration)
|
|
480
558
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
#### `conductor_auto_merge_enabled` config (C6 conditional auto-merge)
|
|
484
|
-
|
|
485
|
-
When a worker's PR meets the done gate (`gate.met`), the supervisor can autonomously merge it — but **only** when the repo has explicitly opted in. The per-repo `conductor_auto_merge_enabled` config field (read through the same config-field route as `conductor_done_gate`) is the opt-in switch:
|
|
486
|
-
|
|
487
|
-
```json
|
|
488
|
-
{ "enabled": true }
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
A bare JSON boolean (`true`) is also accepted. **Auto-merge is disabled by default.** Behavior:
|
|
492
|
-
|
|
493
|
-
- **Disabled / unset / malformed → dry-run.** Anything other than `true` or `{"enabled": true}` — including unset, `false`, `{"enabled": false}`, or any malformed value — fails **closed**: the supervisor records a `merge.dry_run` event and **no PR is ever merged**.
|
|
494
|
-
- **Enabled → autonomous merge** when the gate is met and the deterministic guards pass.
|
|
495
|
-
- **Kill-switch.** Set `conductor_auto_merge_enabled` to `false` or remove the field to immediately stop autonomous merges. The protected merge endpoint **independently re-enforces** the flag, so even a conductor that calls it cannot merge while the flag is off.
|
|
496
|
-
|
|
497
|
-
Merge authority is **deterministic code, never an LLM**. The deterministic guards, all bound to **PR number + expected head SHA (never a branch name)**:
|
|
498
|
-
|
|
499
|
-
- the per-repo enablement flag (off → dry-run),
|
|
500
|
-
- the PR is still open,
|
|
501
|
-
- the merge is bound to the PR number plus the expected head SHA — **head-SHA drift between gate evaluation and merge aborts the merge**,
|
|
502
|
-
- required CI checks are **revalidated green immediately before merge**.
|
|
503
|
-
|
|
504
|
-
Idempotency is crash-safe and race-safe: a TTL lease keyed by the deterministic action key `merge:{repo}:{pr}:{head_sha}:{gate}` is claimed before acting, and an existing `merge.succeeded` for that key is terminal — the supervisor never double-merges across a crash/restart or two racing instances. The conductor never holds VCS write credentials: it calls the protected Bridge API endpoint `POST /vcs/pull-requests/{pr_number}/merge`, which owns the privileged merge, and records the returned `merge.dry_run` / `merge.attempted` / `merge.succeeded` / `merge.failed` / `merge.pending_approval` events into the local ledger. `merge.failed` is **retryable** (a drifted head SHA produces a new action key); `merge.pending_approval` is **nonterminal** — the worker remains active until a human redeems the approval token and the server returns `merge.succeeded`. **`merge.succeeded` is the only terminal merge event.** The local SQLite conductor store uses schema version 5 (BAPI-413) to accommodate the `merge.pending_approval` type in the `events.type` CHECK constraint.
|
|
559
|
+
Conductor is an **opt-in, off-by-default** layer for epic supervision, inter-agent messaging, done-gate evaluation, local git-hook event producers, and conditional auto-merge. Its full reference — `conductor install-git-hooks`, the `conductor_done_gate` and `conductor_auto_merge_enabled` config fields, and the observability stream — lives in **[CONDUCTOR.md](./CONDUCTOR.md)**.
|
|
505
560
|
|
|
506
561
|
## Custom Pipelines
|
|
507
562
|
|
|
@@ -544,40 +599,6 @@ See `.bridge/pipelines/README.md` for the full schema reference.
|
|
|
544
599
|
|
|
545
600
|
If a custom pipeline has the same key as a built-in pipeline, the custom version takes precedence (a warning is logged at startup).
|
|
546
601
|
|
|
547
|
-
## Smoke testing
|
|
548
|
-
|
|
549
|
-
The package ships a canonical, **opt-in** in-host smoke-test runbook at
|
|
550
|
-
`smoke-test/SMOKE-TEST.md`. An AI agent running inside your host (Claude Code,
|
|
551
|
-
Cursor, Codex, Windsurf, or VS Code/Copilot) executes it to verify that the MCP
|
|
552
|
-
server actually works end-to-end *inside that host* — it calls the real tools and
|
|
553
|
-
records a PASS/FAIL verdict for each one in a markdown report.
|
|
554
|
-
|
|
555
|
-
- `smoke-test/SMOKE-TEST.md` **ships with the npm package** and is the
|
|
556
|
-
**canonical** source of truth for the smoke test.
|
|
557
|
-
- The smoke test **adds no MCP tool** and **does not change the registered
|
|
558
|
-
tool surface** (the server still registers its existing 62 tools).
|
|
559
|
-
- It is **opt-in**: default `--init` **does not scaffold `/smoke-test-mcp`**, so
|
|
560
|
-
consumer command palettes are not polluted.
|
|
561
|
-
|
|
562
|
-
### Running it
|
|
563
|
-
|
|
564
|
-
You have two options:
|
|
565
|
-
|
|
566
|
-
1. **Copy the opt-in command manually.** Copy the packaged command stub into your
|
|
567
|
-
host's command directory, then invoke `/smoke-test-mcp`:
|
|
568
|
-
|
|
569
|
-
```bash
|
|
570
|
-
# Claude Code
|
|
571
|
-
cp node_modules/@bridge_gpt/mcp-server/smoke-test/smoke-test-mcp.md .claude/commands/smoke-test-mcp.md
|
|
572
|
-
# Cursor
|
|
573
|
-
cp node_modules/@bridge_gpt/mcp-server/smoke-test/smoke-test-mcp.md .cursor/commands/smoke-test-mcp.md
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
2. **Open the runbook directly.** Alternatively, open
|
|
577
|
-
`smoke-test/SMOKE-TEST.md` and ask the host agent to execute it.
|
|
578
|
-
|
|
579
|
-
Reports are written to `<BAPI_DOCS_DIR>/smoke-test/REPORT-<host>-<timestamp>.md`.
|
|
580
|
-
|
|
581
602
|
## Environment Variables
|
|
582
603
|
|
|
583
604
|
| Variable | Required | Default | Description |
|
|
@@ -591,7 +612,8 @@ Reports are written to `<BAPI_DOCS_DIR>/smoke-test/REPORT-<host>-<timestamp>.md`
|
|
|
591
612
|
| `BAPI_WORKTRUNK_BIN` | No | `wt` (`git-wt` on Windows) | Override the Worktrunk executable name/path used by `start-tickets` for nonstandard installs |
|
|
592
613
|
| `BAPI_TMUX_SESSION` | No | `bridge-start-tickets` | Override the tmux session-name prefix used by `start-tickets` on Linux |
|
|
593
614
|
| `BAPI_MCP_UPGRADE_ADVICE_ENABLED` | No | _(enabled)_ | MCP-local opt-out for proactively surfacing upgrade advice in pipeline recipe preambles. Set to `false`/`0`/`no`/`off`/`disabled` to suppress. Disabling it does **not** change the `/jira/ping` response or server-side upgrade computation — it only gates the recipe-preamble convention |
|
|
594
|
-
| `
|
|
615
|
+
| `CURSOR_API_KEY` | No | _(none)_ | API key used to authenticate `cursor-agent` when launching `start-tickets`/scheduled runs with `--agent cursor-agent`. Not needed for the default Claude Code agent |
|
|
616
|
+
| `BRIDGE_MCP_PROFILE` | No | `core` | Startup-time tool registration profile — a **comma-separated** list of groups controlling which tool groups are registered when the server starts. `core` is always implicitly included. Valid groups: `core` (default — normal coding tools only), `conductor` (+ 8 conductor/event/supervisor tools), `pipeline-authoring` (+ 5 pipeline run/admin tools — `get_pipeline_recipe` is NOT gated; it stays in `core` because the recipe-driven slash commands depend on it), `sfcc` (+ the 7 heavy SFCC read tools — see [Salesforce B2C Commerce (SFCC) Tools](#salesforce-b2c-commerce-sfcc-tools); the `sfcc_setup_status`/`check_permissions` diagnostics are always registered regardless), and `full` (shortcut that expands to every group). Example: `sfcc,conductor`. Unknown, blank, or malformed tokens are dropped (falling back to `core`). Dynamic mid-session switching via `tools/list_changed` is unsupported — groups are resolved once at process startup. Conductor/epic sessions launched via `start-tickets --conductor` automatically inject `BRIDGE_MCP_PROFILE=conductor` at the spawn boundary; a normal `start-tickets` run stays on `core`. |
|
|
595
617
|
|
|
596
618
|
## Worktree credentials and the `mcp-invoke` shim
|
|
597
619
|
|
|
@@ -666,7 +688,7 @@ The full surface, for when you need the complete enumeration. Day-to-day, use [U
|
|
|
666
688
|
|
|
667
689
|
### MCP tools
|
|
668
690
|
|
|
669
|
-
The server
|
|
691
|
+
The server exposes **58 documented tools** (enumerated below). What's actually registered in a session depends on `BRIDGE_MCP_PROFILE`: the default `core` profile loads a trimmed subset, and the conductor/pipeline-authoring/SFCC tools are added only under their respective profiles (see [Environment Variables](#environment-variables)). Async AI tools follow a request/get pattern: call the `request_*` tool to kick off generation, then the matching `get_*` tool to retrieve the result (or pass `wait_for_result: true` to poll automatically).
|
|
670
692
|
|
|
671
693
|
- **Connectivity & identity** — `ping`, `get_my_role`, `get_docs_dir`
|
|
672
694
|
- **Jira tickets** — `get_tickets`, `get_ticket`, `create_ticket`, `update_ticket_description`, `add_comment`, `get_comments`
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* failure. This module performs NO writes: no hook installation, no schema
|
|
8
8
|
* migration, no event emission, and no scheduler unit creation.
|
|
9
9
|
*/
|
|
10
|
+
import { spawnSync } from "node:child_process";
|
|
10
11
|
import { doctorConductorLedger } from "./store.js";
|
|
11
12
|
import { inspectConductorGitHooks } from "./git-hooks.js";
|
|
12
13
|
/**
|
|
@@ -105,6 +106,65 @@ export function inspectMcpProfile(env, epicTick) {
|
|
|
105
106
|
}
|
|
106
107
|
return { resolved_profile, conductor_context_detected, degraded, warnings };
|
|
107
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Read-only probe of the local-merge (F4) capability. Runs `gh --version` and
|
|
111
|
+
* `gh auth status` (no writes, no merge) and reports whether the host could merge
|
|
112
|
+
* a PR locally if `policy_json.local_merge.enabled` were set. Never throws.
|
|
113
|
+
*/
|
|
114
|
+
export function inspectLocalMerge(runCommand) {
|
|
115
|
+
const run = runCommand ??
|
|
116
|
+
((cmd, args) => {
|
|
117
|
+
try {
|
|
118
|
+
// Static ESM import (this package is "type": "module"): a lazy
|
|
119
|
+
// require("child_process") throws ReferenceError under ESM, which the
|
|
120
|
+
// catch swallowed — making `gh` always look unavailable (false negative).
|
|
121
|
+
//
|
|
122
|
+
// `gh auth status` hits api.github.com; with no timeout a network stall
|
|
123
|
+
// (expired token, DNS hiccup, partition) blocks the doctor process until
|
|
124
|
+
// the OS TCP timeout fires (30s–2min). Bound it to 10s — a hung health
|
|
125
|
+
// check then simply reports `gh` unavailable. GH_PROMPT_DISABLED keeps an
|
|
126
|
+
// interactive prompt from holding the process past the timeout.
|
|
127
|
+
const r = spawnSync(cmd, args, {
|
|
128
|
+
encoding: "utf8",
|
|
129
|
+
timeout: 10_000,
|
|
130
|
+
env: { ...process.env, GH_PROMPT_DISABLED: "1" },
|
|
131
|
+
});
|
|
132
|
+
return { status: r.status };
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
return { status: null };
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
let gh_available = false;
|
|
139
|
+
let gh_authed = false;
|
|
140
|
+
try {
|
|
141
|
+
gh_available = run("gh", ["--version"]).status === 0;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
gh_available = false;
|
|
145
|
+
}
|
|
146
|
+
if (gh_available) {
|
|
147
|
+
try {
|
|
148
|
+
gh_authed = run("gh", ["auth", "status"]).status === 0;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
gh_authed = false;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const warnings = [];
|
|
155
|
+
if (!gh_available) {
|
|
156
|
+
warnings.push("`gh` is not installed or not on PATH. Local merge (policy_json.local_merge.enabled) " +
|
|
157
|
+
"cannot run; install the GitHub CLI to enable conductor-driven merges.");
|
|
158
|
+
}
|
|
159
|
+
else if (!gh_authed) {
|
|
160
|
+
warnings.push("`gh` is installed but not authenticated (`gh auth status` failed). Run `gh auth login` " +
|
|
161
|
+
"to grant the conductor merge permission; otherwise local merge will emit merge.failed/skip.");
|
|
162
|
+
}
|
|
163
|
+
// Capability gap only — local merge is opt-in, so an unauthed host is not a hard
|
|
164
|
+
// failure unless the operator enabled it. Reported as degraded for visibility.
|
|
165
|
+
const degraded = !gh_available || !gh_authed;
|
|
166
|
+
return { gh_available, gh_authed, degraded, warnings };
|
|
167
|
+
}
|
|
108
168
|
/**
|
|
109
169
|
* Build the combined read-only doctor report. Composes the existing ledger
|
|
110
170
|
* doctor, git hook inspection, and the epic-tick schedule enablement check.
|
|
@@ -120,6 +180,7 @@ export async function buildConductorDoctorReport(deps = {}) {
|
|
|
120
180
|
git_hooks: inspectHooks(deps.hooksDeps),
|
|
121
181
|
epic_tick: epicTick,
|
|
122
182
|
mcp_profile,
|
|
183
|
+
local_merge: inspectLocalMerge(deps.runCommand),
|
|
123
184
|
};
|
|
124
185
|
}
|
|
125
186
|
/**
|
|
@@ -128,7 +189,7 @@ export async function buildConductorDoctorReport(deps = {}) {
|
|
|
128
189
|
* status tags consistent with the git hooks section's visual hierarchy.
|
|
129
190
|
*/
|
|
130
191
|
export function formatConductorDoctorReport(report) {
|
|
131
|
-
const { ledger, git_hooks, epic_tick, mcp_profile } = report;
|
|
192
|
+
const { ledger, git_hooks, epic_tick, mcp_profile, local_merge } = report;
|
|
132
193
|
const lines = [
|
|
133
194
|
"Conductor ledger doctor",
|
|
134
195
|
"───────────────────────",
|
|
@@ -193,5 +254,21 @@ export function formatConductorDoctorReport(report) {
|
|
|
193
254
|
for (const w of mcp_profile.warnings)
|
|
194
255
|
lines.push(` - ${w}`);
|
|
195
256
|
}
|
|
257
|
+
lines.push("");
|
|
258
|
+
lines.push("Local merge capability (optional, opt-in)");
|
|
259
|
+
lines.push("─────────────────────────────────────────");
|
|
260
|
+
const ghTag = local_merge.gh_available
|
|
261
|
+
? local_merge.gh_authed
|
|
262
|
+
? "[OK]"
|
|
263
|
+
: "[WARNING] not authenticated"
|
|
264
|
+
: "[WARNING] not installed";
|
|
265
|
+
lines.push(`gh available: ${local_merge.gh_available} ${ghTag}`);
|
|
266
|
+
lines.push(`gh authenticated: ${local_merge.gh_authed}`);
|
|
267
|
+
lines.push(`degraded: ${local_merge.degraded}`);
|
|
268
|
+
if (local_merge.warnings.length > 0) {
|
|
269
|
+
lines.push("local merge warnings:");
|
|
270
|
+
for (const w of local_merge.warnings)
|
|
271
|
+
lines.push(` - ${w}`);
|
|
272
|
+
}
|
|
196
273
|
return lines.join("\n");
|
|
197
274
|
}
|