@bridge_gpt/mcp-server 0.2.66 → 0.2.67
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/README.md +252 -77
- package/build/agent-capabilities/probes.js +15 -5
- package/build/agent-launchers/claude-executor-adapter.js +43 -16
- package/build/agent-launchers/executor-adapter.js +7 -4
- package/build/agents.generated.js +1 -1
- package/build/bounded-wait.js +67 -10
- package/build/commands.generated.js +11 -11
- package/build/conductor/bridge-api-client.js +143 -1
- package/build/conductor/bring-up-facts.js +1 -1
- package/build/conductor/doctor.js +3 -3
- package/build/conductor/epic-implementer-cli.js +22 -6
- package/build/conductor/errors.js +4 -3
- package/build/conductor/guided-repair.js +6 -2
- package/build/conductor/hook-runtime-qualification.js +1 -1
- package/build/conductor/merge-execution-contract.js +27 -8
- package/build/conductor/merge-execution-eligibility.js +3 -2
- package/build/conductor/pr-ci-producer.js +1 -1
- package/build/conductor/readiness-cli.js +18 -2
- package/build/conductor/readiness-sections.js +41 -6
- package/build/conductor/readiness.js +181 -29
- package/build/conductor/recovery-cli.js +200 -8
- package/build/conductor/recovery-operations.js +69 -3
- package/build/conductor/repair-contract.js +54 -3
- package/build/conductor/repository-workflow-remedy.js +125 -0
- package/build/conductor/tools.js +2 -2
- package/build/conductor-bundle-artifacts.js +8 -0
- package/build/docs.generated.js +8 -3
- package/build/drive-epic-key.js +6 -5
- package/build/drive-epic.js +85 -54
- package/build/epic-coherence-input.js +2 -1
- package/build/epic-implementer-bin.js +22 -20
- package/build/epic-implementer-bundle-cli.js +2 -2
- package/build/executor/cli.js +3 -2
- package/build/executor/completion-contract.js +48 -5
- package/build/executor/completion-supervision.js +4 -0
- package/build/executor/env.js +19 -0
- package/build/executor/heartbeat.js +1 -1
- package/build/executor/http-client.js +20 -0
- package/build/executor/job-errors.js +25 -0
- package/build/executor/job-runner.js +225 -41
- package/build/executor/observation.js +6 -1
- package/build/executor/preflight.js +51 -14
- package/build/executor/required-work-ledger.js +6 -1
- package/build/executor/resume-pre-spawn.js +2 -0
- package/build/executor/runner.js +8 -2
- package/build/executor/service-unit.js +7 -1
- package/build/executor/worker-finalization.js +82 -29
- package/build/executor/worker-guard-hook.js +137 -33
- package/build/executor/worktree.js +82 -1
- package/build/index.js +403 -429
- package/build/install-bridge-conductor.js +8 -6
- package/build/install-bridge.js +3 -3
- package/build/phase-context-git-probe.js +68 -0
- package/build/phase-result-artifacts.js +173 -5
- package/build/pipelines.generated.js +18 -24
- package/build/plane/alembic-head.js +12 -3
- package/build/plane/base-worktree-guard.js +147 -0
- package/build/plane/cli.js +217 -17
- package/build/plane/code-snapshot.js +468 -0
- package/build/plane/defaults.js +48 -3
- package/build/plane/endpoint.js +41 -0
- package/build/plane/manifest.js +120 -1
- package/build/plane/member-roster.js +94 -19
- package/build/plane/preflight.js +30 -2
- package/build/plane/process-cwd.js +67 -0
- package/build/plane/restart.js +542 -0
- package/build/plane/shutdown.js +31 -0
- package/build/plane/status.js +143 -8
- package/build/plane/supervisor.js +586 -179
- package/build/plane/types.js +54 -2
- package/build/printed-remedy-commands.js +37 -0
- package/build/readiness-check.js +1 -1
- package/build/readme.generated.js +1 -1
- package/build/review-generation.js +22 -0
- package/build/setup-epic.js +44 -19
- package/build/sfcc/config.js +9 -0
- package/build/sfcc/credentials.js +100 -38
- package/build/sfcc/hostname.js +67 -0
- package/build/sfcc/permissions.js +17 -13
- package/build/sfcc/register.js +1 -1
- package/build/sfcc/tool-wrapper.js +39 -43
- package/build/sfcc/write-grants.js +17 -11
- package/build/sfcc/write-result.js +4 -3
- package/build/sfcc/writes-site-preference.js +20 -8
- package/build/start-tickets.js +179 -31
- package/build/tool-error-envelope.js +61 -0
- package/build/version.generated.js +3 -3
- package/build/visual-diff.js +22 -1
- package/build/worker-guard-hook-bin.js +3 -6
- package/build/worker-guard-hook-main.js +47 -0
- package/build/worktree-core.js +130 -4
- package/docs/EPIC-IMPLEMENTER-INSTALL.md +849 -0
- package/docs/EPIC-IMPLEMENTER.md +662 -0
- package/docs/install/mcp-tool-integrations.md +24 -15
- package/docs/install/sfcc-integration.md +12 -4
- package/package.json +1 -1
- package/pipelines/plan-epic.json +0 -5
- package/pipelines/review-ticket.json +1 -1
- package/docs/CONDUCTOR.md +0 -605
- package/pipelines/idea-to-pr.json +0 -49
|
@@ -0,0 +1,849 @@
|
|
|
1
|
+
# Epic Implementer install guide (for agents)
|
|
2
|
+
|
|
3
|
+
This guide is for a coding agent (Claude Code, Cursor, or similar) working in a
|
|
4
|
+
customer repository. Your human said "set up the Epic Implementer" and does not
|
|
5
|
+
know how. Follow the steps below in order. Each step says why it matters, the
|
|
6
|
+
exact command, how to check it worked, what to do if it fails, and whether you
|
|
7
|
+
must ask the human first.
|
|
8
|
+
|
|
9
|
+
Bridge copies this file into every installed project at
|
|
10
|
+
`docs/install/epic-implementer-install.md`. The same text ships in the npm
|
|
11
|
+
package as `docs/EPIC-IMPLEMENTER-INSTALL.md`. For the full reference, read
|
|
12
|
+
`docs/EPIC-IMPLEMENTER.md` inside the `@bridge_gpt/mcp-server` package.
|
|
13
|
+
|
|
14
|
+
In this guide, `<launcher>` means `npx -y @bridge_gpt/mcp-server`. Always keep
|
|
15
|
+
the `-y`. Without it, `npx` stops to ask whether to install the package.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 0. Rules for you, the agent
|
|
20
|
+
|
|
21
|
+
1. **Read first, write later.** Run every read-only check in a step before any
|
|
22
|
+
step that writes.
|
|
23
|
+
2. **Ask before any write or push.** Ask the human before you install a GitHub
|
|
24
|
+
App, open a pull request, create a secret, change an admin setting, or push a
|
|
25
|
+
branch. Say what will change and why.
|
|
26
|
+
3. **Replace every placeholder before you run a printed remedy.** The tools now
|
|
27
|
+
print complete commands, with the `npx -y @bridge_gpt/mcp-server` prefix and
|
|
28
|
+
every required flag. Some carry a placeholder that only a real value can fill:
|
|
29
|
+
`<@org/team|@user>` (the one reviewer of the workflow file; Bridge cannot infer
|
|
30
|
+
it) and `<check-name>` (the exact name of a CI check this repository requires;
|
|
31
|
+
repeat `--required-check` for more than one). Older tool versions printed
|
|
32
|
+
shorthand; the table in [§12](#12-troubleshooting-and-known-wrong-remedies)
|
|
33
|
+
maps it to the full command.
|
|
34
|
+
4. **Stop at human-only access.** Some steps need a browser, a GitHub admin, or
|
|
35
|
+
the Bridge admin panel. Stop, say exactly what the human must do, and wait.
|
|
36
|
+
5. **Interactive commands go to the human.** `install`, `connect-github`, and
|
|
37
|
+
both `install conductor` forms ask questions on a terminal. A shell you run
|
|
38
|
+
has no terminal (no TTY), so the answer is always "no":
|
|
39
|
+
- `install conductor` prints `Aborted` and **exits `0`**. The exit code does
|
|
40
|
+
not tell you it failed.
|
|
41
|
+
- `install conductor --merge-workflow` prints `consent_declined` and exits `1`.
|
|
42
|
+
|
|
43
|
+
Ask the human to run these commands in their own terminal, from the
|
|
44
|
+
repository root. Then read what they paste back.
|
|
45
|
+
6. **Never write a secret into the repository.** No token, API key, or merge
|
|
46
|
+
credential goes into a tracked file, a command argument you print, or a
|
|
47
|
+
commit.
|
|
48
|
+
7. **Keep notes.** Record which step you finished. Step 5 asks the human to
|
|
49
|
+
restart the MCP client, which may end this session.
|
|
50
|
+
|
|
51
|
+
## 1. What you are setting up
|
|
52
|
+
|
|
53
|
+
The Epic Implementer drives a multi-ticket epic from an approved plan to merged
|
|
54
|
+
pull requests. It cuts an `epic/<EPIC-KEY>` branch, hands each child ticket to
|
|
55
|
+
an agent on this machine, waits for CI and code review on each child PR, and
|
|
56
|
+
merges each child PR into the epic branch. A person merges the final
|
|
57
|
+
integration PR into the default branch.
|
|
58
|
+
|
|
59
|
+
By default a run with two or more tickets is **unattended**: it merges child
|
|
60
|
+
PRs on its own. `--attended` is the opt-out: the run then has no permission to
|
|
61
|
+
merge by itself.
|
|
62
|
+
|
|
63
|
+
Both kinds of run still need CI and code review to actually run on child PRs
|
|
64
|
+
into `epic/<EPIC-KEY>`, or every ticket waits forever. Unattended runs also need
|
|
65
|
+
the server to confirm the setup (steps 6 to 9). Attended runs skip that
|
|
66
|
+
confirmation, but have their own launch path ([§11c](#11c-attended-runs)).
|
|
67
|
+
|
|
68
|
+
## 2. Preflight checklist (read-only)
|
|
69
|
+
|
|
70
|
+
**Why:** the executor that runs the jobs lives on this machine. It refuses to
|
|
71
|
+
start without certain tools, and several later steps need `gh` and push rights.
|
|
72
|
+
|
|
73
|
+
**Ask first?** No. Everything here only reads.
|
|
74
|
+
|
|
75
|
+
| Check | Command | Pass when |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| Node.js 18 or newer | `node --version` | `v18` or later. The optional git hooks want an even LTS line, `v20` or later. |
|
|
78
|
+
| Operating system | `uname -s` | `Darwin` or `Linux`. The executor does not run on Windows. |
|
|
79
|
+
| git | `git --version` | Prints a version. |
|
|
80
|
+
| GitHub CLI, logged in | `gh auth status` | Logged in to github.com. |
|
|
81
|
+
| Claude Code CLI | `claude --version` | Prints a version. The human must also be logged in to `claude`. |
|
|
82
|
+
| Worktrunk | `wt --version` | Prints a version. The executor refuses to start without it. |
|
|
83
|
+
| Push rights | `gh repo view --json viewerPermission -q .viewerPermission` | `WRITE`, `MAINTAIN`, or `ADMIN`. Setup pushes an `epic/<EPIC-KEY>` branch with the human's own git. |
|
|
84
|
+
| No retired variables | The command below | Prints nothing. |
|
|
85
|
+
|
|
86
|
+
Retired-variable check (prints names only, never values):
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
env | grep -E '^(BAPI_CONDUCTOR_|CONDUCTOR_(NODE_PATH|DEAD_MAN_ONLY|DEADMAN_CHANNEL_TYPE|DEADMAN_DESTINATION_REF)=)' | cut -d= -f1
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
These are old Epic Implementer variable names. If any is set, every
|
|
93
|
+
`<launcher>` command exits `1` and lists each old name with its new one. Show
|
|
94
|
+
the names to the human and ask them to rename or remove them in their shell
|
|
95
|
+
profile, then open a fresh shell.
|
|
96
|
+
|
|
97
|
+
If a tool is missing, stop and tell the human which one. Do not install tools
|
|
98
|
+
yourself without asking.
|
|
99
|
+
|
|
100
|
+
Then run the three Bridge diagnostics. All three only read:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npx -y @bridge_gpt/mcp-server doctor
|
|
104
|
+
npx -y @bridge_gpt/mcp-server epic-implementer doctor
|
|
105
|
+
npx -y @bridge_gpt/mcp-server epic-implementer readiness --json
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
- `doctor` checks the base install: repository identity, credentials, server
|
|
109
|
+
connection, and whether the repository is indexed.
|
|
110
|
+
- `epic-implementer doctor` checks this machine: the local ledger, git hooks,
|
|
111
|
+
and the merge credential. It briefly starts a headless `claude` probe to check
|
|
112
|
+
that permission denials are enforced.
|
|
113
|
+
- `epic-implementer readiness --json` combines all of these with the server's
|
|
114
|
+
view. It is the one report you will re-run after every step. It always exits
|
|
115
|
+
`0`, even when things fail, so read the JSON.
|
|
116
|
+
|
|
117
|
+
**How to read `readiness --json`:** look at the `checks` array. Each entry has an
|
|
118
|
+
`id` (for example `server.github-credentials`), a `status`, a `label`, and
|
|
119
|
+
sometimes a `detail` and a `remediation`.
|
|
120
|
+
|
|
121
|
+
- `pass` — fine.
|
|
122
|
+
- `warn` — works but degraded. Note it.
|
|
123
|
+
- `fail` — not met, **or could not be checked**. Read the `detail` to tell which.
|
|
124
|
+
- `skip` — does not apply here.
|
|
125
|
+
|
|
126
|
+
Rows whose `id` starts with `plane.` only matter when the human runs their own
|
|
127
|
+
Bridge API server. Against the hosted service you can ignore them. The
|
|
128
|
+
`server.executor-readiness` row may fail before the first run. That is fine:
|
|
129
|
+
`drive-epic` starts an executor for each run by itself.
|
|
130
|
+
|
|
131
|
+
Map each failing row to a step below. Do not run the `remediation` text as a
|
|
132
|
+
command; see rule 3.
|
|
133
|
+
|
|
134
|
+
## 3. Base install (only if Bridge is not installed yet)
|
|
135
|
+
|
|
136
|
+
**Why:** every Epic Implementer command needs the repository's Bridge identity
|
|
137
|
+
and API key.
|
|
138
|
+
|
|
139
|
+
**Check first:** if `.bridge/config` exists and `doctor` reports the credential
|
|
140
|
+
and server connection as fine, skip this step.
|
|
141
|
+
|
|
142
|
+
**Ask first?** Yes. It is interactive and writes files.
|
|
143
|
+
|
|
144
|
+
Ask the human to run this in their own terminal, from the repository root:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
npx -y @bridge_gpt/mcp-server install
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
It asks for an email (new account) or a key or invite (existing account). It
|
|
151
|
+
writes `.bridge/config`, the editor's MCP config, and the slash commands. It
|
|
152
|
+
stores the API key outside the repository.
|
|
153
|
+
|
|
154
|
+
**How credentials are found.** Every command looks for the API key in this
|
|
155
|
+
order: the `BAPI_API_KEY` environment variable, then the file
|
|
156
|
+
`~/.config/bridge/credentials.json` under the key `bapi:<repo_name>`. A key
|
|
157
|
+
that lives only in the editor's MCP config is **not** visible to a shell you
|
|
158
|
+
start, so rely on the credentials file.
|
|
159
|
+
|
|
160
|
+
**The `repo_name` rule.** `repo_name` must match byte for byte everywhere:
|
|
161
|
+
`.bridge/config`, the `BAPI_REPO_NAME` in the MCP config, the `bapi:<repo_name>`
|
|
162
|
+
key, and any `--repo` flag. Never derive it from the folder or GitHub name. A
|
|
163
|
+
hyphen where Bridge has an underscore gives a **403** that looks like a
|
|
164
|
+
permissions problem. Read it:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
grep '^repo_name' .bridge/config
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Check it worked:** re-run `npx -y @bridge_gpt/mcp-server doctor`. The identity,
|
|
171
|
+
credential, and connectivity rows should pass.
|
|
172
|
+
|
|
173
|
+
**If it fails:** a 403 almost always means a `repo_name` mismatch. A 401 means
|
|
174
|
+
the key was rejected or rotated. Ask the human for a fresh key.
|
|
175
|
+
|
|
176
|
+
## 4. Connect GitHub
|
|
177
|
+
|
|
178
|
+
**Why:** the server watches CI and review through the Bridge GitHub App. Without
|
|
179
|
+
App credentials, `drive-epic` refuses to start any run (`github_credentials`).
|
|
180
|
+
|
|
181
|
+
**Check first:** in `readiness --json`, find `server.github-credentials`. If it
|
|
182
|
+
passes, skip to the permission check below.
|
|
183
|
+
|
|
184
|
+
**Ask first?** Yes. It opens a browser and installs a GitHub App.
|
|
185
|
+
|
|
186
|
+
Ask the human to run, in their own terminal:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
npx -y @bridge_gpt/mcp-server connect-github --repo <repo_name>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
It opens the GitHub App install page. The human installs the App there, comes
|
|
193
|
+
back to the terminal, and confirms the repository. No GitHub token is ever
|
|
194
|
+
typed. If someone else administers the GitHub organization, use
|
|
195
|
+
`connect-github --handoff --repo <repo_name>` instead. It prints a link to send
|
|
196
|
+
to that admin. After they finish, run `connect-github --resume --repo <repo_name>`.
|
|
197
|
+
|
|
198
|
+
**Permission check.** Find `server.github-actions-permission` in
|
|
199
|
+
`readiness --json`. It should read `actions: write`. Without it, the Epic
|
|
200
|
+
Implementer cannot re-run a flaky workflow (the rerun fails with a 403). This is
|
|
201
|
+
a warning, not a blocker. If it shows a lower level, ask the human to check the
|
|
202
|
+
Bridge GitHub App's installation in their GitHub settings and accept any
|
|
203
|
+
pending permission request. If `detail` says the permission could not be
|
|
204
|
+
checked, re-run readiness after credentials resolve.
|
|
205
|
+
|
|
206
|
+
**Check it worked:** `server.github-credentials` passes.
|
|
207
|
+
|
|
208
|
+
## 5. Bootstrap the repository: `install conductor`
|
|
209
|
+
|
|
210
|
+
**Why:** this writes the repository's default Epic Implementer settings on the
|
|
211
|
+
server: the required CI check each ticket must pass, merge approval, and the
|
|
212
|
+
review policy. `drive-epic` refuses a repository without them
|
|
213
|
+
(`supervisor_setup`, `supervisor_config`). With extra flags it also writes the
|
|
214
|
+
`claude-review` workflow that step 6 needs, and it adds the Epic Implementer MCP
|
|
215
|
+
tools to your editor config.
|
|
216
|
+
|
|
217
|
+
The subcommand is still named `install conductor` (the Epic Implementer's old
|
|
218
|
+
name). `install-bridge conductor` is the same command.
|
|
219
|
+
|
|
220
|
+
**Ask first?** Yes. It asks several yes/no questions and writes to the server
|
|
221
|
+
and to local files. It needs a real terminal.
|
|
222
|
+
|
|
223
|
+
### 5a. Choose the required check
|
|
224
|
+
|
|
225
|
+
`--required-check` is **required**. It must be the exact name of a CI check run
|
|
226
|
+
that GitHub reports on child PRs into `epic/<EPIC-KEY>`. A name that never
|
|
227
|
+
reports leaves every ticket waiting forever.
|
|
228
|
+
|
|
229
|
+
- **Unattended runs (the default):** the name must be a job `name:` written
|
|
230
|
+
literally in `.github/workflows/epic-implementer-ci.yml` or
|
|
231
|
+
`.github/workflows/claude-review.yml` on the default branch. At approval the
|
|
232
|
+
server checks each required check against those two files. Any other name,
|
|
233
|
+
including a real check from another workflow, is refused as
|
|
234
|
+
`admission_evidence_unverifiable`. Use **`epic-implementer-ci / gate`**, the
|
|
235
|
+
gate job in the step 6 template.
|
|
236
|
+
- **Attended runs only:** any real check name works, as long as that check runs
|
|
237
|
+
on pull requests into `epic/**`. List the names on a recent pull request:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
gh pr view <pr-number> --json statusCheckRollup \
|
|
241
|
+
| jq -r '.statusCheckRollup[] | .name // .context'
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
**Never use `claude-review` as a required check.** It is the review signal, not
|
|
245
|
+
a test run. The review gate reads it separately.
|
|
246
|
+
|
|
247
|
+
### 5b. Choose the review workflow values
|
|
248
|
+
|
|
249
|
+
`.github/workflows/claude-review.yml` produces the review verdict the review
|
|
250
|
+
gate waits for. For unattended runs it must also emit two markers (`run-id:`
|
|
251
|
+
and `Reviewed-SHA:`). This command writes a correct file when you pass **all
|
|
252
|
+
three** of these flags. If one is missing, phase 3 prints a `skipped — …` line
|
|
253
|
+
and writes nothing.
|
|
254
|
+
|
|
255
|
+
| Flag | Value |
|
|
256
|
+
|---|---|
|
|
257
|
+
| `--allowed-bot` | The GitHub App bot whose PRs get reviewed. Child PRs are opened by the Bridge GitHub App. For hosted Bridge, use `bridge-gpt-ai-tools-for-sfcc[bot]`. A self-hosted Bridge uses its own App's `<app-slug>[bot]`. |
|
|
258
|
+
| `--secret-name` | The **name** (not the value) of a GitHub Actions secret that holds a Claude Code OAuth token, for example `CLAUDE_CODE_OAUTH_TOKEN`. Upper-case letters, digits, and underscores only. |
|
|
259
|
+
| `--branches` | The pull-request base branches to review: the default branch plus `epic/**`, for example `main,epic/**`. Child PRs target `epic/<EPIC-KEY>`, so without `epic/**` they are never reviewed. |
|
|
260
|
+
|
|
261
|
+
The review policy defaults to `verdict_protocol`, which is the one that uses
|
|
262
|
+
this workflow. You do not need to pass `--review-policy`. Passing it explicitly
|
|
263
|
+
also stores it as the repository default.
|
|
264
|
+
|
|
265
|
+
If the repository already has a `claude-review.yml`, the command asks before
|
|
266
|
+
overwriting it. An older or hand-written file may lack the markers. Readiness
|
|
267
|
+
tells you which marker is missing.
|
|
268
|
+
|
|
269
|
+
### 5c. Run it
|
|
270
|
+
|
|
271
|
+
Find the default branch:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
gh repo view --json defaultBranchRef -q .defaultBranchRef.name
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
First ask the human to preview with `--dry-run`. The preview still asks one
|
|
278
|
+
question (whether to use the shown Bridge API URL) because it reads from the
|
|
279
|
+
server. It writes nothing:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
npx -y @bridge_gpt/mcp-server install conductor \
|
|
283
|
+
--required-check "epic-implementer-ci / gate" \
|
|
284
|
+
--allowed-bot "bridge-gpt-ai-tools-for-sfcc[bot]" \
|
|
285
|
+
--secret-name CLAUDE_CODE_OAUTH_TOKEN \
|
|
286
|
+
--branches "main,epic/**" \
|
|
287
|
+
--dry-run
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Replace `main` with the real default branch and adjust the other values. Then
|
|
291
|
+
ask the human to run the same command **without** `--dry-run`, in their own
|
|
292
|
+
terminal, from the repository root. It runs eight phases:
|
|
293
|
+
|
|
294
|
+
1. A read-only doctor. It stops before any write if something fatal is missing.
|
|
295
|
+
2. A preview of the server settings, then "Write the safe project-default
|
|
296
|
+
supervisor posture now?". If the change would remove an existing
|
|
297
|
+
requirement, it asks a second, separate question.
|
|
298
|
+
3. The `claude-review` workflow (only with the three flags from 5b).
|
|
299
|
+
4. **Tool visibility:** adds `epic_implementer` to `BRIDGE_MCP_PROFILE` in the
|
|
300
|
+
Bridge entry of `.mcp.json`, `.vscode/mcp.json`, and `.cursor/mcp.json`. It
|
|
301
|
+
only edits files that already have a Bridge entry. It never creates a file
|
|
302
|
+
and never touches Codex or Copilot config.
|
|
303
|
+
5. Local observability: the optional local git hooks. Safe to decline.
|
|
304
|
+
6. A plan check, only with `--epic-key` and `--plan-file`. Skip it for now.
|
|
305
|
+
7. An executor service, only with `--executor-id`. Skip it: `drive-epic` starts
|
|
306
|
+
one for each run.
|
|
307
|
+
8. A capability report and a final doctor.
|
|
308
|
+
|
|
309
|
+
The last line is `complete` or `complete-with-manual-steps`. Before the first
|
|
310
|
+
run, `complete-with-manual-steps` is normal, because no executor has been seen
|
|
311
|
+
yet. Read the "Manual actions" list it prints.
|
|
312
|
+
|
|
313
|
+
**After it finishes:**
|
|
314
|
+
|
|
315
|
+
- The workflow file (phase 3) was only written locally. It lands in step 6.
|
|
316
|
+
- **Restart the MCP client** (the editor or `claude` session). The server reads
|
|
317
|
+
its tool groups at startup, so `get_epic_snapshot` and `explain_run` appear
|
|
318
|
+
only after a restart. Save your notes first. After the restart, confirm those
|
|
319
|
+
two tools are listed. If they are not, check that the Bridge entry's
|
|
320
|
+
`BRIDGE_MCP_PROFILE` contains `epic_implementer`, for example
|
|
321
|
+
`core,epic_implementer`.
|
|
322
|
+
|
|
323
|
+
**Check it worked:** in `readiness --json`, `server.supervisor-setup`,
|
|
324
|
+
`server.supervisor-config`, and `server.supervisor-required-checks` pass.
|
|
325
|
+
|
|
326
|
+
**If it fails:** if the output says `Aborted` right after the URL question, it
|
|
327
|
+
had no terminal or the human answered no. Ask them to run it again in their own
|
|
328
|
+
terminal. If phase 1 lists a fatal row, fix that row first (usually step 3 or 4).
|
|
329
|
+
|
|
330
|
+
## 6. The two workflows, on the default branch
|
|
331
|
+
|
|
332
|
+
**Why:** child PRs need CI and review that really run. For unattended runs, the
|
|
333
|
+
server also reads two files from the **default branch**, at fixed paths, before
|
|
334
|
+
it creates or approves a run. If either is wrong, it refuses with
|
|
335
|
+
`repository_readiness_unconfirmed`. **No install command fixes this.** The files
|
|
336
|
+
must be merged into the default branch.
|
|
337
|
+
|
|
338
|
+
| File | Requirement |
|
|
339
|
+
|---|---|
|
|
340
|
+
| `.github/workflows/claude-review.yml` | Must emit the `run-id:` and `Reviewed-SHA:` markers. Written by step 5 with the three flags from 5b. |
|
|
341
|
+
| `.github/workflows/epic-implementer-ci.yml` | Must exist and parse as a workflow. Nothing in the package writes it. Use the template below. |
|
|
342
|
+
|
|
343
|
+
A different file name does not count, even if it runs the same tests.
|
|
344
|
+
|
|
345
|
+
**Ask first?** Yes. You will create a branch and open a pull request.
|
|
346
|
+
|
|
347
|
+
### 6a. The `epic-implementer-ci.yml` template
|
|
348
|
+
|
|
349
|
+
This is a minimal, generic starting point. It runs the repository's tests on the
|
|
350
|
+
Epic Implementer's pull requests and reports one check,
|
|
351
|
+
`epic-implementer-ci / gate`. That name is the required check from step 5.
|
|
352
|
+
`gh pr view --json statusCheckRollup` shows it as `epic-implementer-ci / gate`.
|
|
353
|
+
The GitHub web page may show it as `epic-implementer-ci / epic-implementer-ci / gate`
|
|
354
|
+
(workflow name, then job name). The required check is still
|
|
355
|
+
`epic-implementer-ci / gate`.
|
|
356
|
+
|
|
357
|
+
The Epic Implementer names each child branch `feature/<TICKET-KEY>` and the
|
|
358
|
+
epic branch `epic/<EPIC-KEY>`. Child PRs go from `feature/…` into `epic/…`. The
|
|
359
|
+
final integration PR goes from `epic/…` into the default branch. The template
|
|
360
|
+
tests every same-repository PR from a `feature/` or `epic/` branch. To test only
|
|
361
|
+
the Epic Implementer's tickets, you may narrow `feature/` to
|
|
362
|
+
`feature/<PREFIX>-`, where `<PREFIX>` is the ticket prefix of the **child**
|
|
363
|
+
tickets. Get that wrong and every child PR counts as out of scope, so the gate
|
|
364
|
+
passes **without running any tests**.
|
|
365
|
+
|
|
366
|
+
```yaml
|
|
367
|
+
name: epic-implementer-ci
|
|
368
|
+
|
|
369
|
+
on:
|
|
370
|
+
pull_request:
|
|
371
|
+
# The default branch (change main if yours differs) and the epic branches
|
|
372
|
+
# that child pull requests target.
|
|
373
|
+
branches: [main, "epic/**"]
|
|
374
|
+
|
|
375
|
+
permissions:
|
|
376
|
+
contents: read
|
|
377
|
+
|
|
378
|
+
# A new push cancels the run for the older head of the same pull request.
|
|
379
|
+
concurrency:
|
|
380
|
+
group: epic-implementer-ci-${{ github.event.pull_request.number }}
|
|
381
|
+
cancel-in-progress: true
|
|
382
|
+
|
|
383
|
+
jobs:
|
|
384
|
+
tests:
|
|
385
|
+
name: tests
|
|
386
|
+
# Same-repository feature/ and epic/ branches only.
|
|
387
|
+
if: >-
|
|
388
|
+
${{ github.event.pull_request.head.repo.full_name == github.repository &&
|
|
389
|
+
(startsWith(github.event.pull_request.head.ref, 'feature/') ||
|
|
390
|
+
startsWith(github.event.pull_request.head.ref, 'epic/')) }}
|
|
391
|
+
runs-on: ubuntu-latest
|
|
392
|
+
steps:
|
|
393
|
+
- uses: actions/checkout@v4
|
|
394
|
+
with:
|
|
395
|
+
# Test the exact head commit of the pull request.
|
|
396
|
+
ref: ${{ github.event.pull_request.head.sha }}
|
|
397
|
+
persist-credentials: false
|
|
398
|
+
# Add the repository's real setup steps here (language runtime,
|
|
399
|
+
# dependency install), then its real test command.
|
|
400
|
+
- name: Run tests
|
|
401
|
+
run: |
|
|
402
|
+
echo "Replace this step with the repository's test command."
|
|
403
|
+
exit 1
|
|
404
|
+
|
|
405
|
+
gate:
|
|
406
|
+
# This name IS the check-run name the done gate waits for. Keep it literal.
|
|
407
|
+
name: epic-implementer-ci / gate
|
|
408
|
+
needs: [tests]
|
|
409
|
+
if: ${{ always() }}
|
|
410
|
+
runs-on: ubuntu-latest
|
|
411
|
+
steps:
|
|
412
|
+
- name: Aggregate the result
|
|
413
|
+
env:
|
|
414
|
+
# Keep this identical to the tests job's condition.
|
|
415
|
+
IN_SCOPE: ${{ github.event.pull_request.head.repo.full_name == github.repository && (startsWith(github.event.pull_request.head.ref, 'feature/') || startsWith(github.event.pull_request.head.ref, 'epic/')) }}
|
|
416
|
+
TESTS_RESULT: ${{ needs.tests.result }}
|
|
417
|
+
run: |
|
|
418
|
+
if [ "$IN_SCOPE" != "true" ]; then
|
|
419
|
+
echo "Out-of-scope pull request: the gate passes without running tests."
|
|
420
|
+
exit 0
|
|
421
|
+
fi
|
|
422
|
+
if [ "$TESTS_RESULT" = "success" ]; then
|
|
423
|
+
echo "Tests passed."
|
|
424
|
+
exit 0
|
|
425
|
+
fi
|
|
426
|
+
echo "Tests concluded '$TESTS_RESULT', so the gate fails."
|
|
427
|
+
exit 1
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
Fill in the `tests` job with the repository's real test command. Find it in the
|
|
431
|
+
existing CI workflows, `package.json` scripts, a `Makefile`, or the README. Ask
|
|
432
|
+
the human if it is unclear. Do not leave the placeholder step: it fails on
|
|
433
|
+
purpose.
|
|
434
|
+
|
|
435
|
+
**Things to keep**, in this file and in `claude-review.yml`:
|
|
436
|
+
|
|
437
|
+
- `if: ${{ always() }}` on the gate. Without it, a failed or skipped test job
|
|
438
|
+
would leave the gate check missing instead of red.
|
|
439
|
+
- The gate is green only when the tests job concluded `success`. A skipped or
|
|
440
|
+
cancelled test job is never treated as a pass.
|
|
441
|
+
- `persist-credentials: false` and the checkout of the pull request's head SHA.
|
|
442
|
+
- **Static job names.** For unattended runs the server must read every job's
|
|
443
|
+
check name straight from both files. If either file has any of the following,
|
|
444
|
+
the server cannot read the names, and approval refuses every required check:
|
|
445
|
+
- a `strategy.matrix` on any job;
|
|
446
|
+
- a job-level `uses:` (a reusable workflow call). A `uses:` inside a step is
|
|
447
|
+
fine;
|
|
448
|
+
- a `${{ … }}` expression in any job id or job `name:`.
|
|
449
|
+
|
|
450
|
+
Put matrix or reusable-workflow jobs in a different workflow file if you need
|
|
451
|
+
them.
|
|
452
|
+
|
|
453
|
+
### 6b. The `migration-guard` job (only for Alembic repositories)
|
|
454
|
+
|
|
455
|
+
Check whether the repository has `alembic.ini` at its **root** on the default
|
|
456
|
+
branch:
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
git fetch origin
|
|
460
|
+
git ls-tree --name-only origin/<default-branch> alembic.ini
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
If that prints nothing, skip this part. If it prints `alembic.ini`, the server
|
|
464
|
+
also requires a job whose id is exactly `migration-guard`, with a step that runs
|
|
465
|
+
exactly `python scripts/check_alembic_migration_graph.py`. The repository must
|
|
466
|
+
contain that script. It should fail when the Alembic revision graph has more
|
|
467
|
+
than one head, a duplicate revision id, a missing parent, or a cycle. Add the
|
|
468
|
+
job to `needs:` in the gate and fail the gate unless it concluded `success`. If
|
|
469
|
+
the human does not want this, they can run attended instead.
|
|
470
|
+
|
|
471
|
+
### 6c. Land both files
|
|
472
|
+
|
|
473
|
+
1. Ask the human before you branch and push.
|
|
474
|
+
2. Create a branch, for example `chore/epic-implementer-workflows`.
|
|
475
|
+
3. Commit `.github/workflows/epic-implementer-ci.yml` and the
|
|
476
|
+
`.github/workflows/claude-review.yml` that step 5 wrote.
|
|
477
|
+
4. Open a pull request into the default branch with `gh pr create`.
|
|
478
|
+
5. Ask the human to review and merge it. Do not merge it yourself.
|
|
479
|
+
|
|
480
|
+
**Secret the human must add** (repository Settings, then Secrets and variables,
|
|
481
|
+
then Actions): a secret with the exact name you passed to `--secret-name`,
|
|
482
|
+
holding a Claude Code OAuth token. The human can create one with
|
|
483
|
+
`claude setup-token`. Never ask them to paste the token to you.
|
|
484
|
+
|
|
485
|
+
**Check it worked:** after the merge, re-run `readiness --json`.
|
|
486
|
+
`server.review-workflow`, `server.conductor-ci-workflow`, and
|
|
487
|
+
`server.repository-workflow-readiness` should pass.
|
|
488
|
+
|
|
489
|
+
**If it fails:** readiness names the missing item, for example "does not emit
|
|
490
|
+
the Reviewed-SHA: marker". A detail saying Bridge "could not read" a file means
|
|
491
|
+
the read failed, not that the file is wrong. Re-run readiness. If it keeps
|
|
492
|
+
failing, contact Bridge support.
|
|
493
|
+
|
|
494
|
+
## 7. Index the repository, after the workflows merge
|
|
495
|
+
|
|
496
|
+
**Why:** `setup-epic` cuts `epic/<EPIC-KEY>` at the exact commit the code index
|
|
497
|
+
was built from, not at the tip of the default branch. If that commit is older
|
|
498
|
+
than the merge from step 6, the epic branch has no workflows. Then child PRs into
|
|
499
|
+
it get no CI and no review, and every ticket waits forever. Each child ticket's
|
|
500
|
+
plan also uses the index to find code.
|
|
501
|
+
|
|
502
|
+
**Ask first?** No. Indexing runs on the server and changes nothing in the
|
|
503
|
+
repository. It can take a while on a large repository.
|
|
504
|
+
|
|
505
|
+
After the step 6 pull request has merged, run the `/parse-repository` slash
|
|
506
|
+
command, even if the repository was indexed before. Then poll the
|
|
507
|
+
`parse_repository` MCP tool with `action: "status"` until it reports completed.
|
|
508
|
+
`doctor` also shows the indexing state.
|
|
509
|
+
|
|
510
|
+
You will confirm the cut commit in [§11a](#11a-plan-the-epic), once a plan
|
|
511
|
+
exists.
|
|
512
|
+
|
|
513
|
+
**If it fails:** report the status message to the human. Do not start a real
|
|
514
|
+
run until indexing has completed after the merge.
|
|
515
|
+
|
|
516
|
+
## 8. Unattended prerequisites
|
|
517
|
+
|
|
518
|
+
**Why:** an unattended run merges on its own, so three things are checked
|
|
519
|
+
before a run is created. `--attended` skips them. `setup-epic` (which `/plan-epic`
|
|
520
|
+
runs) and the `drive-epic` preview name each one differently.
|
|
521
|
+
|
|
522
|
+
**Repository consent**
|
|
523
|
+
- `setup-epic` refusal: `target_not_allowed`. `drive-epic` preview:
|
|
524
|
+
`unattended_consent`. Readiness row: `server.unattended-consent`.
|
|
525
|
+
- It is **on by default**. The repository owner switches "Allow unattended Epic
|
|
526
|
+
Implementer runs" on the repository's Setup page in the Bridge admin panel.
|
|
527
|
+
Only a human can change it. If it is already on, contact Bridge support.
|
|
528
|
+
|
|
529
|
+
**An escalation channel** (where alerts go when the run needs a person)
|
|
530
|
+
- `setup-epic` refusal: `webhook_unverified`. `drive-epic` preview:
|
|
531
|
+
`unattended_notify_default`. Readiness row: `server.unattended-notify-default`.
|
|
532
|
+
- The simplest channel is the email address on the Bridge account. It needs no
|
|
533
|
+
extra step when the account has one.
|
|
534
|
+
- A webhook also works, but only through a `--policy-file` that sets
|
|
535
|
+
`notify.webhook_url`. `/plan-epic` and `/drive-epic-run` never pass a policy
|
|
536
|
+
file, so the webhook route needs the shell `drive-epic` ([§11c](#11c-attended-runs)
|
|
537
|
+
shows the command form). `notify.local_sink` does not count.
|
|
538
|
+
|
|
539
|
+
```json
|
|
540
|
+
{ "notify": { "webhook_url": "https://example.com/your-webhook" } }
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
A policy file is the **complete** run policy, so keep it minimal. The server
|
|
544
|
+
tests the webhook when the run activates, so it must be reachable from the
|
|
545
|
+
internet.
|
|
546
|
+
|
|
547
|
+
**The two workflows**
|
|
548
|
+
- `setup-epic` refusal: `repository_readiness_unconfirmed`. `drive-epic`
|
|
549
|
+
preview: `repository_readiness`. Readiness row:
|
|
550
|
+
`server.repository-workflow-readiness`.
|
|
551
|
+
- Finish step 6. The message names the missing file, marker, or job.
|
|
552
|
+
|
|
553
|
+
**Readiness could not be read**
|
|
554
|
+
- `setup-epic` refusal: `readiness_unreadable`.
|
|
555
|
+
- The server did not report these facts. Retry. If it persists, contact Bridge
|
|
556
|
+
support.
|
|
557
|
+
|
|
558
|
+
**Ask first?** Yes for anything that changes an account or admin setting. Only
|
|
559
|
+
the human can change these.
|
|
560
|
+
|
|
561
|
+
## 9. Merge credential and merge modes
|
|
562
|
+
|
|
563
|
+
**Why:** in an unattended run, the executor on this machine merges each child PR
|
|
564
|
+
into the epic branch with `gh pr merge`. In the default local mode it uses
|
|
565
|
+
**only** the token in `BAPI_LOCAL_MERGE_TOKEN`. (A run in machine-user mode uses
|
|
566
|
+
only `BAPI_MACHINE_MERGE_TOKEN` instead.) It never falls back to the human's `gh`
|
|
567
|
+
login, `GH_TOKEN`, or `GITHUB_TOKEN`. Without the token, merges are refused. The
|
|
568
|
+
diagnostics show this only as a warning (`conductor.merge-credential`), so it is
|
|
569
|
+
easy to miss.
|
|
570
|
+
|
|
571
|
+
**Ask first?** Yes. This concerns the human's GitHub credential.
|
|
572
|
+
|
|
573
|
+
The executor inherits its environment from the process that runs `drive-epic`.
|
|
574
|
+
So the variable must be set in the shell that launches `drive-epic`. If you use
|
|
575
|
+
`/drive-epic-run`, that is **your own session's** environment, so the human must
|
|
576
|
+
set it before starting the editor or `claude`.
|
|
577
|
+
|
|
578
|
+
The simplest source is the human's own GitHub CLI token:
|
|
579
|
+
|
|
580
|
+
```bash
|
|
581
|
+
export BAPI_LOCAL_MERGE_TOKEN="$(gh auth token)"
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
To make it last, suggest the human add that exact line (the command, not the
|
|
585
|
+
token value) to their shell profile, for example `~/.zshrc`, then open a new
|
|
586
|
+
terminal and restart the editor. Never write the token value into any file, and
|
|
587
|
+
never add it to the repository.
|
|
588
|
+
|
|
589
|
+
If an executor is already running for a run, it will not see a newly exported
|
|
590
|
+
value. It must be restarted from a shell that has it.
|
|
591
|
+
|
|
592
|
+
**Check it worked:** `npx -y @bridge_gpt/mcp-server epic-implementer doctor`
|
|
593
|
+
no longer warns about the merge credential. Run it from the same shell.
|
|
594
|
+
|
|
595
|
+
### Optional: GitHub Actions merge mode
|
|
596
|
+
|
|
597
|
+
Use this only if the human wants merges done by a GitHub Actions workflow
|
|
598
|
+
instead of this machine. It applies only to a run whose policy file declares
|
|
599
|
+
`"merge_execution_mode": "github_actions"`. Otherwise skip it.
|
|
600
|
+
|
|
601
|
+
Ask the human to run, in their own terminal (it asks before writing):
|
|
602
|
+
|
|
603
|
+
```bash
|
|
604
|
+
npx -y @bridge_gpt/mcp-server install conductor --merge-workflow --codeowner <@org/team|@user>
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
`--codeowner` is required: the one GitHub user or team who must review changes
|
|
608
|
+
to the merge workflow. Add `--dry-run` first to preview. The command writes
|
|
609
|
+
`.github/workflows/epic-implementer-merge.yml` and two helper files, pushes a
|
|
610
|
+
branch with the human's own git, and opens a pull request with their own `gh`.
|
|
611
|
+
It never merges it.
|
|
612
|
+
|
|
613
|
+
After the human merges that pull request, three manual steps remain. The human
|
|
614
|
+
does all three:
|
|
615
|
+
|
|
616
|
+
1. Create a repository Actions secret named `BAPI_API_KEY` holding the
|
|
617
|
+
repository's Bridge API key.
|
|
618
|
+
2. Merge the rule from `.bridge/merge-workflow/CODEOWNERS.fragment` into the
|
|
619
|
+
active CODEOWNERS file. The fragment does nothing on its own.
|
|
620
|
+
3. Add a default-branch rule that requires a pull request and code-owner review.
|
|
621
|
+
Until it exists, the workflow file is not protected.
|
|
622
|
+
|
|
623
|
+
## 10. Verify
|
|
624
|
+
|
|
625
|
+
**Before a plan exists**, use readiness only:
|
|
626
|
+
|
|
627
|
+
```bash
|
|
628
|
+
npx -y @bridge_gpt/mcp-server epic-implementer readiness --json
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
The `drive-epic` preview is not useful yet. Without a plan it only says
|
|
632
|
+
`decision: stop`, with no reason, or a generic "not ready" refusal.
|
|
633
|
+
|
|
634
|
+
**Done means:**
|
|
635
|
+
|
|
636
|
+
- These rows pass: `server.supervisor-setup`, `server.supervisor-config`,
|
|
637
|
+
`server.supervisor-required-checks`, and `server.github-credentials`.
|
|
638
|
+
- For unattended runs, these pass too: `server.unattended-consent`,
|
|
639
|
+
`server.unattended-notify-default`, and `server.repository-workflow-readiness`.
|
|
640
|
+
If a `server.admission-required-checks` row is present, it passes too.
|
|
641
|
+
- `server.worker-present` and `server.single-transition-authority` pass. These
|
|
642
|
+
are the server's own health. If they fail, contact Bridge support.
|
|
643
|
+
- `conductor.merge-credential` passes in the shell that will launch runs.
|
|
644
|
+
- The `get_epic_snapshot` and `explain_run` tools are available.
|
|
645
|
+
- Every other `fail` is explained, and the human accepted it.
|
|
646
|
+
|
|
647
|
+
**After `/plan-epic` has written a plan**, preview the launch:
|
|
648
|
+
|
|
649
|
+
```bash
|
|
650
|
+
npx -y @bridge_gpt/mcp-server drive-epic <EPIC> --plan-file <path to epic-plan.dag.json> --dry-run --json
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
It changes nothing. Its `decision` is `create`, `attach`, `refuse`, or `stop`. A
|
|
654
|
+
`refuse` carries `refusal.reason_id` and `refusal.remedy`. Map the `reason_id`:
|
|
655
|
+
|
|
656
|
+
- `supervisor_setup`, `supervisor_config` — step 5.
|
|
657
|
+
- `github_credentials` — step 4.
|
|
658
|
+
- `unattended_consent`, `unattended_notify_default`, `repository_readiness` — step 8.
|
|
659
|
+
- `remote-reconciler-not-live` — the Bridge server side. Contact Bridge support.
|
|
660
|
+
- Anything else — read its `remedy`, then check the table in step 12 before you
|
|
661
|
+
run anything.
|
|
662
|
+
|
|
663
|
+
Report to the human what passed, what failed, and what they still need to do.
|
|
664
|
+
|
|
665
|
+
## 11. First run
|
|
666
|
+
|
|
667
|
+
### 11a. Plan the epic
|
|
668
|
+
|
|
669
|
+
`/plan-epic` needs an **existing epic ticket**. Run `/plan-epic <EPIC>` with its
|
|
670
|
+
key, for example `SHOP-100`. Free text instead of a key gives no epic key, and
|
|
671
|
+
no run can be created from it.
|
|
672
|
+
|
|
673
|
+
It explores the code, splits the epic into child tickets, and asks the human to
|
|
674
|
+
approve the split. It writes its files to `<docs_dir>/epic-plans/<slug>/`, where
|
|
675
|
+
`<docs_dir>` is the docs folder the `ping` MCP tool reports (often `docs/tmp`).
|
|
676
|
+
The plan file is `epic-plan.dag.json`.
|
|
677
|
+
|
|
678
|
+
**Before the plan is approved, check every `ticket_key` in
|
|
679
|
+
`epic-plan.dag.json`.** Each one must be a real ticket key. A placeholder such as
|
|
680
|
+
`TBD-1` must not reach approval. If you see one, stop and create or link the
|
|
681
|
+
real tickets first.
|
|
682
|
+
|
|
683
|
+
**The last step of `/plan-epic` creates and approves an unattended run** (it
|
|
684
|
+
runs `setup-epic` without `--attended`). For an attended run, see §11c before
|
|
685
|
+
you reach that step.
|
|
686
|
+
|
|
687
|
+
Before that step runs `setup-epic` for real, run its dry run and check the cut
|
|
688
|
+
commit (plain output, not `--json`):
|
|
689
|
+
|
|
690
|
+
```bash
|
|
691
|
+
npx -y @bridge_gpt/mcp-server setup-epic --epic-key <EPIC> \
|
|
692
|
+
--plan-file <path to epic-plan.dag.json> --dry-run
|
|
693
|
+
git fetch origin
|
|
694
|
+
git ls-tree --name-only <sha from the "Cut:" line> .github/workflows/
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
The listing must include `claude-review.yml` and `epic-implementer-ci.yml`. If
|
|
698
|
+
it does not, the index is older than the step 6 merge. Go back to step 7 and
|
|
699
|
+
re-index first.
|
|
700
|
+
|
|
701
|
+
**If `setup-epic` fails, what happened depends on where it failed:**
|
|
702
|
+
|
|
703
|
+
- **`setup-epic REFUSED (<reason>)`** — a check before creation failed.
|
|
704
|
+
`target_not_allowed`, `webhook_unverified`, `repository_readiness_unconfirmed`,
|
|
705
|
+
and `readiness_unreadable` are all this kind. **Nothing was created.** Fix the
|
|
706
|
+
named item (step 8) and run it again.
|
|
707
|
+
- **`The plan was NOT approved: …`** — the server refused at approval. By then
|
|
708
|
+
the run **was** created, the epic branch **was** cut, and the plan **was**
|
|
709
|
+
stored. The run waits in `planning`. The message always talks about unattended
|
|
710
|
+
consent, whatever the real cause. Ignore that wording and read the `Detail:`
|
|
711
|
+
line for `predicate` and `reason_code`:
|
|
712
|
+
- `admission_evidence_unverifiable` or `admission_evidence_denied` with
|
|
713
|
+
predicate `required_checks` — the required check is not a static job name in
|
|
714
|
+
the two workflow files (step 5a, and "Things to keep" in 6a).
|
|
715
|
+
- predicate `repository_readiness` — step 6.
|
|
716
|
+
- predicate `webhook` or `notify_webhook` — step 8, escalation channel.
|
|
717
|
+
- predicate `target_allowed` or `unattended_consent` — step 8, consent.
|
|
718
|
+
- any other predicate — report the `predicate` and `reason_code` to the human.
|
|
719
|
+
|
|
720
|
+
Fix the cause, then run the same `setup-epic` command again. It reuses the
|
|
721
|
+
existing run instead of creating a second one.
|
|
722
|
+
|
|
723
|
+
### 11b. Drive an unattended run
|
|
724
|
+
|
|
725
|
+
In Claude Code or Cursor:
|
|
726
|
+
|
|
727
|
+
```text
|
|
728
|
+
/drive-epic-run <EPIC> <path to epic-plan.dag.json>
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
It previews the launch, asks the human once, creates the run (or attaches to the
|
|
732
|
+
one `/plan-epic` created), starts an executor, and watches the run to the end. It
|
|
733
|
+
accepts no flags, so it cannot pass `--attended` or `--policy-file`. When it
|
|
734
|
+
creates a run, the run must be unattended.
|
|
735
|
+
|
|
736
|
+
From a shell, the same launch is:
|
|
737
|
+
|
|
738
|
+
```bash
|
|
739
|
+
npx -y @bridge_gpt/mcp-server drive-epic <EPIC> --plan-file <path to epic-plan.dag.json>
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
Add `--policy-file <policy.json>` for a webhook (step 8). Run it from the
|
|
743
|
+
repository root, in a shell that has `BAPI_LOCAL_MERGE_TOKEN`. Always pass
|
|
744
|
+
`--plan-file`. Without it, `drive-epic` searches only `docs/tmp/epic-plans/` (or
|
|
745
|
+
`BAPI_DOCS_DIR`), which may not be where `/plan-epic` wrote. `drive-epic` starts
|
|
746
|
+
a run-scoped executor in the background. Its log is
|
|
747
|
+
`.bridge/executors/<run>.log`. The executor exits by itself when the run is done
|
|
748
|
+
or abandoned.
|
|
749
|
+
|
|
750
|
+
### 11c. Attended runs
|
|
751
|
+
|
|
752
|
+
An attended run never merges by itself. It still needs a required check that
|
|
753
|
+
really runs on child PRs into `epic/<EPIC-KEY>` (step 5a, attended branch), and a
|
|
754
|
+
review verdict on those PRs (step 5b, `--branches` including `epic/**`).
|
|
755
|
+
|
|
756
|
+
1. Plan with `/plan-epic <EPIC>`, but **do not let its last step run
|
|
757
|
+
`setup-epic`**. That step would create an unattended run whenever the
|
|
758
|
+
unattended prerequisites hold. Tell the human, and skip that step with their
|
|
759
|
+
agreement. If it has already run and refused with `setup-epic REFUSED`,
|
|
760
|
+
nothing was created and you can continue.
|
|
761
|
+
2. Check every `ticket_key` in `epic-plan.dag.json`, as in §11a.
|
|
762
|
+
3. Launch from a shell, from the repository root:
|
|
763
|
+
|
|
764
|
+
```bash
|
|
765
|
+
npx -y @bridge_gpt/mcp-server drive-epic <EPIC> \
|
|
766
|
+
--plan-file <path to epic-plan.dag.json> --attended
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
`/drive-epic-run` cannot create an attended run.
|
|
770
|
+
|
|
771
|
+
### 11d. Monitor
|
|
772
|
+
|
|
773
|
+
- MCP tools: `get_epic_snapshot` (the full run state) and `explain_run` (why a
|
|
774
|
+
run or ticket is stuck). Both need the `epic_implementer` profile from step 5.
|
|
775
|
+
- Notifications: `npx -y @bridge_gpt/mcp-server notifications --repo <repo_name> --run <EPIC> --follow`.
|
|
776
|
+
- Quick health: `npx -y @bridge_gpt/mcp-server epic-implementer epic-status --epic-key <EPIC>`.
|
|
777
|
+
|
|
778
|
+
### 11e. Stop and recover
|
|
779
|
+
|
|
780
|
+
Always diagnose with the `explain_run` MCP tool first. Then apply one verb. Ask
|
|
781
|
+
the human before any of them. Each runs as:
|
|
782
|
+
|
|
783
|
+
```bash
|
|
784
|
+
npx -y @bridge_gpt/mcp-server epic-implementer <verb> --epic-run-id <EPIC>
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
`--epic-run-id` takes the run id, or the epic key when the epic has exactly one
|
|
788
|
+
active run.
|
|
789
|
+
|
|
790
|
+
The two you will use most:
|
|
791
|
+
|
|
792
|
+
| Verb | Use it to |
|
|
793
|
+
|---|---|
|
|
794
|
+
| `unpark --ticket-key <key>` | Send a parked (`needs_human`) ticket back into its gates once the cause is fixed. |
|
|
795
|
+
| `stop-run` | Stop the run now: no new work, queued work cancelled. The record stays. |
|
|
796
|
+
|
|
797
|
+
Advanced verbs. Use them only when `explain_run` points at them:
|
|
798
|
+
|
|
799
|
+
| Verb | Use it to |
|
|
800
|
+
|---|---|
|
|
801
|
+
| `abandon-run` | End the run for good. **Terminal and irreversible.** |
|
|
802
|
+
| `resume-run [--clear-quarantine]` | Resume a paused run. |
|
|
803
|
+
| `adopt-current-head-and-unpark --ticket-key <key>` | Recover a ticket parked because someone pushed to its PR. |
|
|
804
|
+
| `continue-child --ticket-key <key>` | Let a parked child carry on without resetting its attempt. |
|
|
805
|
+
| `continuation-receipt --ticket-key <key>` | Check whether a `continue-child` request took effect (read-only). |
|
|
806
|
+
| `resume-ci --ticket-key <key>` | Resume a child parked on a CI stop once CI is green. |
|
|
807
|
+
| `dispatch-remediation --ticket-key <key> --context-file <path>` | Queue a repair job with your notes. |
|
|
808
|
+
| `merge-child --pr <number>` | Merge the run's child PR through the shared merge service. |
|
|
809
|
+
| `scope-reparse --scope-id <scope>` | Re-index the run's own index scope. |
|
|
810
|
+
| `scope-catch-up --scope-id <scope>` | Replay merges the run's scope missed. |
|
|
811
|
+
| `patch-policy --patch-file <path>` | Change part of the run's policy. |
|
|
812
|
+
|
|
813
|
+
In Claude Code or Cursor, `/drive-epic-run` applies these for you within limits,
|
|
814
|
+
and asks when it must.
|
|
815
|
+
|
|
816
|
+
## 12. Troubleshooting and known-wrong remedies
|
|
817
|
+
|
|
818
|
+
Current tools print complete commands. Replace any placeholder in them with a
|
|
819
|
+
real value before you run them. Older tool versions printed the shorthand in the
|
|
820
|
+
left-hand column below, which does not work as typed. Use the right-hand column
|
|
821
|
+
instead.
|
|
822
|
+
|
|
823
|
+
| Printed remedy | Problem | Run this instead |
|
|
824
|
+
|---|---|---|
|
|
825
|
+
| `install-bridge connect-github` | `install` accepts no such argument, and there is no `npx` prefix. | `npx -y @bridge_gpt/mcp-server connect-github --repo <repo_name>` (step 4) |
|
|
826
|
+
| `install-bridge conductor` or `install conductor` with no flags | Missing the `npx` prefix and the required `--required-check`. | The full command in step 5c |
|
|
827
|
+
| `install-bridge conductor --merge-workflow` (older tools) | Missing the `npx` prefix and the required `--codeowner`. | `npx -y @bridge_gpt/mcp-server install conductor --merge-workflow --codeowner <@org/team\|@user>`; replace the placeholder with the one reviewer (step 9) |
|
|
828
|
+
| `npx @bridge_gpt/mcp-server install` | Missing `-y`, so `npx` stops to ask. | `npx -y @bridge_gpt/mcp-server install` (step 3) |
|
|
829
|
+
| Any remedy for `repository_readiness_unconfirmed` that names an install command | No install command creates the workflows. | Step 6, then step 7 |
|
|
830
|
+
| `The plan was NOT approved: this repository is no longer authorized for unattended runs` | Printed for every approval refusal, whatever the cause. | Read `Detail:` (§11a) |
|
|
831
|
+
| `install conductor --executor-id <id> --repo-wide` for executor readiness | Not needed to launch. | Nothing. `drive-epic` starts an executor per run. |
|
|
832
|
+
|
|
833
|
+
Other common problems:
|
|
834
|
+
|
|
835
|
+
| Symptom | Cause | Fix |
|
|
836
|
+
|---|---|---|
|
|
837
|
+
| Every `<launcher>` command exits `1` with a list of variable names | Old Epic Implementer variable names are set. | Step 2, retired-variable check. |
|
|
838
|
+
| `install conductor` prints `Aborted` and exits `0` | No terminal, or the human answered no. | Rule 5: the human runs it in their own terminal. |
|
|
839
|
+
| `--merge-workflow` prints `consent_declined` | No terminal, or the human answered no. | Rule 5. |
|
|
840
|
+
| 403 on any command | `repo_name` does not match byte for byte. | Step 3. |
|
|
841
|
+
| `get_epic_snapshot` is not available | The MCP client was not restarted, or the profile lacks `epic_implementer`. | Step 5, "After it finishes". |
|
|
842
|
+
| Child PRs get no CI or no review at all | The epic branch was cut before the workflows merged, or `--branches` / the CI trigger lacks `epic/**`. | Steps 5b, 6a, and 7. |
|
|
843
|
+
| Tickets wait forever at CI | The required check name does not match a check that runs on child PRs. | Step 5a. Compare with `gh pr view <n> --json statusCheckRollup`. |
|
|
844
|
+
| Tickets pass CI but no tests ran | A narrowed `feature/<PREFIX>-` does not match the child branches. | Step 6a. |
|
|
845
|
+
| Approval refused: `admission_evidence_unverifiable` on `required_checks` | The required check is not a static job name in the two workflow files. | Steps 5a and 6a. |
|
|
846
|
+
| Child PRs are never merged | `BAPI_LOCAL_MERGE_TOKEN` was not set for the executor. | Step 9. |
|
|
847
|
+
| `merge_execution_ineligible` | The policy declares `github_actions` merge mode, but the merge workflow is missing or not ready. | Step 9, optional part. Or remove that line from the policy. |
|
|
848
|
+
| `drive-epic` cannot find the plan | It searched `docs/tmp/epic-plans/` only. | Pass `--plan-file`. |
|
|
849
|
+
| The reconciler or worker rows fail | The Bridge server side is not healthy. | Nothing to fix locally. Contact Bridge support. |
|