@bridge_gpt/mcp-server 0.2.21 → 0.2.24

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.
Files changed (41) hide show
  1. package/README.md +144 -18
  2. package/build/base-ref.js +151 -0
  3. package/build/commands.generated.js +6 -4
  4. package/build/conductor/bridge-api-client.js +44 -3
  5. package/build/conductor/doctor.js +33 -22
  6. package/build/conductor/epic-runtime.js +101 -5
  7. package/build/conductor/pr-ci-producer.js +21 -2
  8. package/build/conductor/pr-discovery.js +12 -2
  9. package/build/conductor-bin.js +50 -20
  10. package/build/credential-store.js +564 -64
  11. package/build/decision-page-template.js +9 -4
  12. package/build/docs.generated.js +5 -0
  13. package/build/executor/base-branch.js +50 -0
  14. package/build/executor/env.js +12 -1
  15. package/build/executor/job-errors.js +1 -0
  16. package/build/executor/job-runner.js +38 -7
  17. package/build/executor/test-clock.js +6 -1
  18. package/build/executor/worker-finalization.js +88 -1
  19. package/build/executor/worktree.js +21 -1
  20. package/build/index.js +2741 -702
  21. package/build/init.js +29 -0
  22. package/build/install-bridge.js +1076 -114
  23. package/build/pipelines.generated.js +2 -2
  24. package/build/pr-base-contract.js +36 -0
  25. package/build/readme.generated.js +1 -1
  26. package/build/setup-epic.js +483 -0
  27. package/build/sfcc/log-gate.js +85 -0
  28. package/build/sfcc/log-query.js +170 -0
  29. package/build/sfcc/register.js +10 -0
  30. package/build/sfcc/setup-status.js +33 -3
  31. package/build/start-tickets.js +164 -75
  32. package/build/version.generated.js +1 -1
  33. package/build/worktree-core.js +62 -10
  34. package/{CONDUCTOR.md → docs/CONDUCTOR.md} +88 -29
  35. package/docs/install/github-app.md +189 -0
  36. package/docs/install/mcp-tool-integrations.md +305 -0
  37. package/docs/install/sfcc-integration.md +140 -0
  38. package/package.json +5 -5
  39. package/public/js/main.min.js +55 -10
  40. package/public/js/main.min.js.map +1 -1
  41. package/smoke-test/SMOKE-TEST.md +3 -2
@@ -145,6 +145,44 @@ export async function isExistingBranchSafeToReuse(deps, branch, baseStartPoint)
145
145
  * job-type logic lives here — the caller decides the start point, the stale
146
146
  * guard, and the freshen behavior.
147
147
  */
148
+ /**
149
+ * Hard-reset the branch checked out in `worktreePath` onto `ref`. Returns null on
150
+ * success or a bounded, secret-free `create-failed` error string on failure.
151
+ * Shared by the recovery freshen path and the BAPI-586 fresh-dispatch alignment.
152
+ */
153
+ async function hardResetWorktree(deps, worktreePath, ref) {
154
+ const resetArgs = ["reset", "--hard", ref];
155
+ const reset = await deps.runCommand("git", resetArgs, { cwd: worktreePath });
156
+ if (!commandSucceeded(reset)) {
157
+ const reason = (reset.stderr || reset.stdout || "").trim();
158
+ return `git ${resetArgs.join(" ")} failed${reason ? `: ${reason}` : ""}`;
159
+ }
160
+ return null;
161
+ }
162
+ /**
163
+ * BAPI-586: resolve the worktree's `HEAD^{commit}` and the `expected` ref/commit
164
+ * and confirm they are equal. Returns null when they match, or a bounded,
165
+ * secret-free `create-failed` error string otherwise. Short-SHA fragments in the
166
+ * message are safe (they are public commit identifiers, not secrets).
167
+ */
168
+ async function verifyWorktreeHead(deps, worktreePath, expected) {
169
+ const headRes = await deps.runCommand("git", ["rev-parse", "--verify", "HEAD^{commit}"], { cwd: worktreePath });
170
+ if (!commandSucceeded(headRes)) {
171
+ return "failed to resolve worktree HEAD after creation (git rev-parse HEAD^{commit} failed).";
172
+ }
173
+ const expectedRes = await deps.runCommand("git", ["rev-parse", "--verify", `${expected}^{commit}`], { cwd: worktreePath });
174
+ if (!commandSucceeded(expectedRes)) {
175
+ return "failed to resolve the expected base commit after creation (git rev-parse --verify failed).";
176
+ }
177
+ const head = headRes.stdout.trim();
178
+ const want = expectedRes.stdout.trim();
179
+ if (head !== want) {
180
+ return (`worktree head ${head.slice(0, 12)} does not match the pinned base ${want.slice(0, 12)}; ` +
181
+ `Worktrunk seeded the worktree from an unexpected start point. Refusing to hand a mis-seeded ` +
182
+ `worktree to a worker.`);
183
+ }
184
+ return null;
185
+ }
148
186
  export async function createWorktreeForTicket(deps, key, branchOverrides, worktrunkBinary, baseStartPoint = "main", guardStaleWorktree = false, behavior = {}) {
149
187
  const branch = resolveBranchForTicket(key, branchOverrides);
150
188
  try {
@@ -181,16 +219,30 @@ export async function createWorktreeForTicket(deps, key, branchOverrides, worktr
181
219
  // `origin/<branch>`), so this only applies when the local branch pre-existed.
182
220
  // Run inside the switched worktree (the branch is checked out there).
183
221
  if (exists && behavior.freshenFromOrigin) {
184
- const resetArgs = ["reset", "--hard", behavior.freshenFromOrigin];
185
- const reset = await deps.runCommand("git", resetArgs, { cwd: worktreePath });
186
- if (!commandSucceeded(reset)) {
187
- const reason = (reset.stderr || reset.stdout || "").trim();
188
- return {
189
- key,
190
- branch,
191
- status: "create-failed",
192
- error: `git ${resetArgs.join(" ")} failed${reason ? `: ${reason}` : ""}`,
193
- };
222
+ const resetError = await hardResetWorktree(deps, worktreePath, behavior.freshenFromOrigin);
223
+ if (resetError) {
224
+ return { key, branch, status: "create-failed", error: resetError };
225
+ }
226
+ }
227
+ // BAPI-586 (fresh dispatch): a guard-approved pre-existing branch is an
228
+ // ancestor of base but may sit at an OLDER tip. Align it EXACTLY to the
229
+ // pinned base SHA so a fresh implementation starts at base, not at a stale
230
+ // ancestor. The stale-branch guard above already ran (and refused unsafe
231
+ // branches) before this destructive reset. Absent branches were created
232
+ // straight from `baseStartPoint`, so no alignment is needed there.
233
+ if (exists && behavior.alignExistingBranchTo) {
234
+ const resetError = await hardResetWorktree(deps, worktreePath, behavior.alignExistingBranchTo);
235
+ if (resetError) {
236
+ return { key, branch, status: "create-failed", error: resetError };
237
+ }
238
+ }
239
+ // BAPI-586 (fresh dispatch): verify the worktree actually starts at the
240
+ // pinned base. If Worktrunk seeded from an unexpected sibling despite
241
+ // `-b <sha>`, fail CLOSED before the worktree is handed to a worker.
242
+ if (behavior.verifyHeadMatches) {
243
+ const verifyError = await verifyWorktreeHead(deps, worktreePath, behavior.verifyHeadMatches);
244
+ if (verifyError) {
245
+ return { key, branch, status: "create-failed", error: verifyError };
194
246
  }
195
247
  }
196
248
  return { key, branch, status: "created", path: worktreePath };
@@ -3,13 +3,61 @@
3
3
  Conductor is the **opt-in, off-by-default** coordination layer for running many
4
4
  agent sessions together (epic supervision, inter-agent messaging, done-gate
5
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.
6
+ involve Conductor — you opt in per run with `--conductor`.
8
7
 
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).
8
+ This document is the reference for Conductor's architecture, epic setup,
9
+ observability stream, local git hooks, and the per-repo done-gate / auto-merge
10
+ config. For the everyday `start-tickets` flags and cross-platform behavior, see
11
+ [README → CLI Subcommands](../README.md#cli-subcommands).
12
+
13
+ ## Epic Conductor v2 — how an epic is actually driven
14
+
15
+ **The v1 `conductor epic-tick` command is frozen.** It throws
16
+ `EPIC_TICK_V1_FROZEN` on every invocation and advances nothing. There is nothing
17
+ to schedule locally. If you have an epic-tick schedule registered from an earlier
18
+ release, cancel it (`schedule-run cancel --id <id>`) — it is a dead timer.
19
+ `conductor doctor` flags one if it finds it.
20
+
21
+ v2 splits the old local tick into two halves:
22
+
23
+ | Half | Where it runs | What it does |
24
+ | --- | --- | --- |
25
+ | **Reconciler** | **Server-side**, on the Bridge API worker dyno, every 30s | Selects every epic run whose status is `active`, evaluates gates, and enqueues executor jobs. Nothing to install or schedule. |
26
+ | **Executor** | **Locally**, on your machine | Polls for jobs, claims them, spawns worker agents, heartbeats. This is the only piece you run. |
27
+
28
+ ```
29
+ npx -y @bridge_gpt/mcp-server executor --repo <name>
30
+ ```
31
+
32
+ The reconciler drives a run purely off `epic_runs.status = 'active'` — there is no
33
+ local schedule, and no per-repo "enable the tick" flag. (An `epic_tick_enabled`
34
+ config field existed briefly and was inert; it has been removed.)
35
+
36
+ ## Setting up an epic
37
+
38
+ One command creates the run, stores the plan, and approves it:
39
+
40
+ ```
41
+ npx -y @bridge_gpt/mcp-server setup-epic --epic-key BAPI-405 \
42
+ --plan-file docs/tmp/epic-plans/<slug>/epic-plan.dag.json
43
+ ```
44
+
45
+ The plan sidecar (`epic-plan.dag.json`) is produced by the `decompose-epic`
46
+ pipeline step. `setup-epic` validates it locally (unique ticket keys, resolvable
47
+ `depends_on`/edge references, acyclicity) before sending anything, so a malformed
48
+ plan fails legibly instead of as a bare HTTP 400.
49
+
50
+ It is **idempotent**: re-running it on an epic that already has a live run reuses
51
+ that run rather than minting a second one. Use `--dry-run` to validate a plan and
52
+ preview the calls without mutating anything.
53
+
54
+ Once the plan is approved the run becomes `active`, the server-side reconciler
55
+ picks it up within ~30s, and your local `executor` starts claiming jobs.
56
+
57
+ > **A caveat worth knowing before you plan an epic.** Conductor has no
58
+ > merge-conflict handling, and plan-time file-overlap serialization is currently
59
+ > dark (the planner does not yet emit the `touched_files` metadata it needs). If
60
+ > two sibling tickets touch the same files, do not let them dispatch in parallel.
13
61
 
14
62
  ## Conductor observability (opt-in via `--conductor`, BAPI-394)
15
63
 
@@ -28,12 +76,12 @@ in the env, hook command, or run metadata. Override the gate/supervisor labels w
28
76
  `BAPI_CONDUCTOR_GATE_NAME` / `BAPI_CONDUCTOR_SUPERVISOR_MODE`. Inspect the stream
29
77
  with `conductor doctor`. Observability is best-effort: a conductor failure never
30
78
  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.)
79
+ (Epic dispatch always enables conductor internally, independent of this flag.)
32
80
 
33
81
  When `--conductor` is set, the spawn boundary also injects
34
82
  `BRIDGE_MCP_PROFILE=conductor` so each worker registers the 8 conductor/event/
35
83
  supervisor MCP tools (a plain `start-tickets` run stays on the default `core`
36
- profile). See [README → Environment Variables](./README.md#environment-variables).
84
+ profile). See [README → Environment Variables](../README.md#environment-variables).
37
85
 
38
86
  ## `conductor install-git-hooks` (BAPI-395)
39
87
 
@@ -61,10 +109,28 @@ hook presence and managed-snippet status **read-only** (a new `git hooks` sectio
61
109
  MCP tool drives CI polling and gate evaluation regardless of whether hooks are
62
110
  installed.
63
111
 
64
- ## `conductor_done_gate` config
112
+ ## Supervisor config — where the done gate and auto-merge live
113
+
114
+ > **These are not config fields.** They used to be `conductor_done_gate` and
115
+ > `conductor_auto_merge_enabled` on the generic config-field route; BAPI-438 moved
116
+ > them onto dedicated supervisor endpoints. Setting them via
117
+ > `PUT /jira/config-field/...` returns **HTTP 400 "Invalid config field"** — that
118
+ > rejection is correct, not a bug. Use the endpoints below.
119
+
120
+ Two scopes exist for each: a per-repo **project default**, and a per-epic override.
65
121
 
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,
122
+ | Setting | Endpoint (project default) |
123
+ | --- | --- |
124
+ | `done_gate_config` | `PUT /jira/epic-runs/supervisor-setup/defaults/?repo_name=<repo>` |
125
+ | `auto_merge_enabled`, `merge_approval_required` | `PUT /jira/epic-runs/supervisor-config/defaults/?repo_name=<repo>` |
126
+
127
+ Swap `…/defaults/` for `…/runs/{epic_key}/…` to scope a setting to one epic. The
128
+ matching `GET` on each returns the effective value, with a `source` of `epic`,
129
+ `project_default`, or `none` (nothing configured — fails closed).
130
+
131
+ ### `done_gate_config`
132
+
133
+ Defines the done gate. It supports exactly one condition,
68
134
  `required_ci_checks_green`:
69
135
 
70
136
  ```json
@@ -81,30 +147,23 @@ config`) only when every listed required check is present, complete, and green f
81
147
  the bound PR head SHA. The gate **fails closed**: an unset, disabled (`enabled` not
82
148
  strictly `true`), malformed, empty, or unsupported config emits no `gate.met`.
83
149
 
84
- ## `conductor_auto_merge_enabled` config (C6 conditional auto-merge)
150
+ ### `auto_merge_enabled` (C6 conditional auto-merge)
85
151
 
86
152
  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
- ```
153
+ merge it — but **only** when the repo has explicitly opted in.
154
+ `auto_merge_enabled` on the supervisor-config endpoint is the opt-in switch.
94
155
 
95
- A bare JSON boolean (`true`) is also accepted. **Auto-merge is disabled by default.**
96
- Behavior:
156
+ **Auto-merge is disabled by default.** Behavior:
97
157
 
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**.
158
+ - **Disabled / unset / unconfigured → dry-run.** Anything other than an explicit
159
+ `true` — including a repo with no supervisor config at all (`source: "none"`)
160
+ fails **closed**: the supervisor records a `merge.dry_run` event and **no PR is
161
+ ever merged**.
102
162
  - **Enabled → autonomous merge** when the gate is met and the deterministic guards
103
163
  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.
164
+ - **Kill-switch.** Set `auto_merge_enabled` to `false` to immediately stop
165
+ autonomous merges. The protected merge endpoint **independently re-enforces** the
166
+ flag, so even a conductor that calls it cannot merge while the flag is off.
108
167
 
109
168
  Merge authority is **deterministic code, never an LLM**. The deterministic guards,
110
169
  all bound to **PR number + expected head SHA (never a branch name)**:
@@ -0,0 +1,189 @@
1
+ # Installing the Bridge GitHub App
2
+
3
+ Bridge connects to GitHub through a **GitHub App**, not a personal access token. Once
4
+ the app is installed on your repository and linked to your Bridge project, Bridge can
5
+ open pull requests, run automated code review, read CI check status, and (when enabled)
6
+ auto-merge — all using short-lived, per-call installation tokens. Your code and
7
+ credentials stay on GitHub; Bridge mints a fresh token for each operation and stores no
8
+ long-lived GitHub token.
9
+
10
+ ## The app
11
+
12
+ | | |
13
+ |---|---|
14
+ | **Name** | Bridge GPT - AI Tools for SFCC |
15
+ | **Owner** | [@Bridge-GPT](https://github.com/Bridge-GPT) |
16
+ | **Public install page** | <https://github.com/apps/bridge-gpt-ai-tools-for-sfcc> |
17
+ | **App ID** | `954077` |
18
+ | **Client ID** | `Iv23liBEyDUeD25W06ix` |
19
+
20
+ > The App ID and Client ID are **public** identifiers (GitHub shows them on the app's
21
+ > settings page). They are not secrets. Only the app's **private key** and webhook
22
+ > secret are sensitive, and those are held by whoever operates the Bridge deployment —
23
+ > see [Self-hosting / operator setup](#self-hosting--operator-setup) at the end. As an
24
+ > end user you never handle them.
25
+
26
+ ## Prerequisites
27
+
28
+ - A GitHub repository you want Bridge to work on.
29
+ - Permission to install a GitHub App on the account that owns it:
30
+ - **Personal repo:** you can install it yourself.
31
+ - **Organization repo:** you must be an **organization owner**, or a member who can
32
+ *request* the install for an owner to approve. (GitHub decides which button you see —
33
+ **Install**, **Install & request**, or **Request** — based on your role.)
34
+ - Your Bridge project already registered (you have a Bridge API key and repo name).
35
+
36
+ ---
37
+
38
+ ## Option A — Connect GitHub button (recommended)
39
+
40
+ This is the normal path. Bridge captures the installation automatically — you never copy
41
+ an ID by hand.
42
+
43
+ 1. Open your project's **Get Started** page in the Bridge web UI.
44
+ 2. Click **Connect GitHub**. Bridge mints a short-lived, single-use link scoped to your
45
+ project and sends you to GitHub's app-install screen.
46
+ 3. On GitHub, choose the **account or organization** that owns the repository.
47
+ 4. Under **Repository access**, choose **Only select repositories** and pick the repo(s)
48
+ you want Bridge to cover (or **All repositories**). See
49
+ [Choosing repositories](#choosing-repositories) below.
50
+ 5. Review the requested permissions and click **Install** (or **Install & request** /
51
+ **Request** if an org owner must approve).
52
+ 6. GitHub redirects you back to Bridge. Bridge verifies the installation directly with
53
+ GitHub, links it to your project, and stores the installation automatically. If the
54
+ installation covers exactly one repo — or one repo clearly matches your project —
55
+ Bridge binds it for you; otherwise it shows a short **repository picker** so you can
56
+ confirm which repo maps to this project.
57
+
58
+ That's it — no manual ID entry. If the automatic link fails for any reason, Bridge tells
59
+ you and points you to Option B.
60
+
61
+ ---
62
+
63
+ ## Option B — Manual install + Installation ID (fallback)
64
+
65
+ Use this if the Connect GitHub button isn't available to you, or automatic linking
66
+ failed.
67
+
68
+ ### 1. Install the app
69
+
70
+ Go to the public install page and install it on the owning account/organization,
71
+ selecting the repository/repositories you want Bridge to access:
72
+
73
+ <https://github.com/apps/bridge-gpt-ai-tools-for-sfcc/installations/new>
74
+
75
+ (Same repository-selection and permissions-review screen as Option A, steps 3–5.)
76
+
77
+ ### 2. Find the Installation ID
78
+
79
+ The Installation ID is the trailing number in the app's **Configure** URL:
80
+
81
+ - **Personal account:** open **Settings → Applications → Installed GitHub Apps**, click
82
+ **Configure** next to *Bridge GPT - AI Tools for SFCC*. The URL is
83
+ `https://github.com/settings/installations/<INSTALLATION_ID>`.
84
+ - **Organization:** open **Organization Settings → Third-party Access → GitHub Apps**,
85
+ click **Configure** next to the app. The URL is
86
+ `https://github.com/organizations/<ORG>/settings/installations/<INSTALLATION_ID>`.
87
+
88
+ For example, `https://github.com/organizations/Bridge-GPT/settings/installations/61661616`
89
+ has Installation ID **`61661616`**.
90
+
91
+ ### 3. Enter it in Bridge
92
+
93
+ On your project's **Setup** page, in the GitHub section, paste the **Installation ID**
94
+ into the field provided and save. Make sure the project's **version control system** is
95
+ set to `github`. Bridge fills in the account owner and repository from your project
96
+ settings.
97
+
98
+ ---
99
+
100
+ ## Choosing repositories
101
+
102
+ When installing (either option), GitHub asks which repositories the app may access:
103
+
104
+ - **All repositories** — the app can access every current and future repo on the account.
105
+ - **Only select repositories** — pick specific repos from the **Select repositories**
106
+ dropdown. Recommended: grant only the repo(s) you actually want Bridge to work on.
107
+
108
+ You can change this later at any time: **Configure** the installation (paths above),
109
+ adjust **Repository access**, and click **Save**. If the app creates a repository, it is
110
+ automatically granted access to that repo.
111
+
112
+ ## What the app can access
113
+
114
+ At install time GitHub shows the **authoritative** list of permissions the app requests —
115
+ review it there. Functionally, the Bridge integration exercises these GitHub permissions:
116
+
117
+ | Permission | Why |
118
+ |---|---|
119
+ | **Contents** (read & write) | Read repo files for parsing/review; manage branch refs when opening/cleaning up PRs |
120
+ | **Pull requests** (read & write) | List/read PRs and diffs; post review comments and reviews; merge when auto-merge is enabled |
121
+ | **Checks / Commit statuses** (read) | Poll CI check-run and status results for a commit |
122
+ | **Administration** (read) | Read branch-protection required-status-checks to resolve which checks must pass |
123
+ | **Metadata** (read) | Baseline repo metadata; verify the installation's repository list |
124
+ | **Webhook events** | Receive `pull_request`, `installation`, and review/merge events that drive automated review and merge |
125
+
126
+ > These are inferred from the GitHub REST endpoints the integration calls. The exact set
127
+ > the app is *registered* with is shown by GitHub on the install screen; treat that
128
+ > screen as the source of truth.
129
+
130
+ ## Verifying the connection
131
+
132
+ After linking, confirm Bridge can act on the repo:
133
+
134
+ - The Bridge **Setup / integration status** should show version control as connected.
135
+ - A Bridge operation that needs GitHub — e.g. `create_pull_request`, `resolve_ci_checks`,
136
+ or `poll_ci_checks` from the MCP — should succeed rather than return a
137
+ "no VCS connection" refusal. (See
138
+ [MCP Tool Integration Dependencies](./mcp-tool-integrations.md) for which tools require
139
+ a VCS connection.)
140
+
141
+ If a GitHub-dependent tool refuses, the installation isn't linked to that project yet —
142
+ re-run Option A, or set the Installation ID via Option B.
143
+
144
+ ## Managing or removing the app
145
+
146
+ - **Change repo access / review permissions:** **Configure** the installation (URLs
147
+ above) → adjust **Repository access** → **Save**.
148
+ - **Uninstall:** on the same Configure page, scroll to **Danger zone → Uninstall**.
149
+ Uninstalling revokes Bridge's access immediately; existing stored installation IDs stop
150
+ working.
151
+
152
+ ---
153
+
154
+ ## Self-hosting / operator setup
155
+
156
+ *Skip this section if you are an end user connecting to a hosted Bridge deployment — it is
157
+ for whoever runs the Bridge API server.*
158
+
159
+ The GitHub App identity is configured **once per deployment** via environment variables.
160
+ Bridge uses the App private key to mint short-lived installation tokens on demand; it
161
+ persists no long-lived GitHub token.
162
+
163
+ | Env var | Value / purpose |
164
+ |---|---|
165
+ | `GIT_APP_ID` | The app's numeric App ID — `954077` for *Bridge GPT - AI Tools for SFCC*. |
166
+ | `GIT_PRIVATE_KEY` | **base64-encoded PEM** private key generated for the app (GitHub → app settings → *Generate a private key*). This is the one true secret. |
167
+ | `GITHUB_APP_INSTALL_URL` | The public install URL the **Connect GitHub** button sends users to: `https://github.com/apps/bridge-gpt-ai-tools-for-sfcc/installations/new`. |
168
+ | `GITHUB_WEBHOOK_SECRET` | App-level shared secret validating signed `installation` / merge webhooks. If unset, those webhooks are disabled (the redirect-callback path still works). |
169
+ | `BGPT_ENCRYPTION_KEY` | Fernet key used to encrypt per-repo credentials at rest. |
170
+
171
+ The app's **Setup URL** (in GitHub app settings) must point at the deployment's
172
+ `GET /setup/github/callback` endpoint so the post-install redirect can auto-link the
173
+ installation. Webhook endpoints used by the integration include the code-review hook
174
+ (e.g. `https://<deployment-host>/github/code-review`); configure these on the app to match
175
+ your deployment host.
176
+
177
+ > **Note:** an older placeholder app slug (`bridge-gpt-code-reviewer`) still appears as a
178
+ > stale default string in the codebase. The runtime install URL and App ID always come
179
+ > from `GITHUB_APP_INSTALL_URL` / `GIT_APP_ID`, so set those to the `954077` /
180
+ > `bridge-gpt-ai-tools-for-sfcc` values above rather than relying on the code default.
181
+
182
+ ## See also
183
+
184
+ - [MCP Tool Integration Dependencies](./mcp-tool-integrations.md) — which MCP tools need a
185
+ VCS connection (BLOCK) vs merely degrade without one.
186
+ - [Installing the SFCC Integration (OCAPI)](./sfcc-integration.md) — the separate
187
+ Salesforce B2C sandbox integration.
188
+ - GitHub docs: [Installing a GitHub App from a third party](https://docs.github.com/en/apps/using-github-apps/installing-a-github-app-from-a-third-party),
189
+ [Reviewing and modifying installed GitHub Apps](https://docs.github.com/en/apps/using-github-apps/reviewing-and-modifying-installed-github-apps).