@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
@@ -0,0 +1,305 @@
1
+ # MCP Tools — Integration Dependencies
2
+
3
+ This catalog lists every tool exposed by the Bridge API MCP server
4
+ (`@bridge_gpt/mcp-server`) and the external integrations each one depends on. It
5
+ answers a single operational question: *before I call this tool, what needs to be
6
+ connected, and what happens if it isn't?*
7
+
8
+ For the tool **reference** (parameters, endpoints, examples) see the
9
+ [package README](../../README.md). The dependency classes below are not editorial —
10
+ they mirror the enforced policy in the Bridge API backend
11
+ (`api/library/vcs/vcs_route_operations.py`, the single source of truth for
12
+ route → capability gating, and its probes in `api/library/vcs/vcs_preflight.py`).
13
+
14
+ ## Two dependency classes
15
+
16
+ - **BLOCK** — the tool refuses, or its output is untrustworthy enough that it should
17
+ not be used, without the integration. This covers both hard blockers (the backend
18
+ returns a refusal) and "no local alternative" tools. Codebase-grounded generators
19
+ are blocked on an unindexed repo on purpose: *"plan output on an unindexed repo is
20
+ worthless"* (`api/routes/jira_api.py`). In code, BLOCK ≈ `VCS_ROUTE_REQUIREMENTS`
21
+ (VCS-credential refusal) + `INDEX_REQUIRED_ROUTE_KEYS` (parse/index refusal).
22
+
23
+ - **DEGRADE** — the tool still runs and returns useful output, but quality is weaker
24
+ without the integration. In code, DEGRADE ≈ `VCS_ROUTE_WARNINGS` (Tier-4
25
+ "warn, never block"): the shared research helper `plan_researcher` returns *empty*
26
+ code research instead of erroring, so the tool falls back to ticket text alone and
27
+ attaches a non-blocking disclosure.
28
+
29
+ **Baseline (assumed for every tool, not repeated below):** every non-`LOCAL` tool
30
+ needs the Bridge API reachable plus a valid API key with repo access
31
+ (`verify_repo_access`); every AI tool needs an LLM provider (platform-managed).
32
+ `LOCAL` tools make no backend call at all. A tool with no integration dependency is
33
+ marked **— none**.
34
+
35
+ ## Integrations glossary
36
+
37
+ | Integration | What "connected" means | Where configured |
38
+ |---|---|---|
39
+ | **Ticket backend** | A ticket store in the repo's `ticket_backend_mode` — `jira` (Jira connection) or `local` (Postgres, no external service). Default is `jira`. | `config_projects.ticket_backend_mode`; Jira token in `config_projects_access` |
40
+ | **Jira (only)** | A live Jira connection specifically — for surfaces with no local-mode equivalent (comment threads, binary attachments). | `config_projects_access.jira_api_token` |
41
+ | **Version control (VCS)** | GitHub App or Bitbucket credentials for the repo. | `git_app_installation_id` / `git_app_owner` (GitHub) or `workspace` / `version_control_access_token` (Bitbucket) |
42
+ | **Code index** | A **succeeded** `parse_repository` run (Pinecone code embeddings). A repo can have valid VCS creds yet never have been parsed. | `config_projects_access.pinecone_index_name`; status in `repository_parse_runs` / `code_repositories` |
43
+ | **SFCC OCAPI** | Salesforce B2C sandbox OCAPI access: `dw.json` / AM token + `version` config field + OCAPI grants. | `dw.json`, `version` config field, OCAPI data-API grants |
44
+ | **SFCC WebDAV logs** | WebDAV log credentials (separate from OCAPI) plus the `sfcc_log_monitor_enabled` flag. | `sfcc_webdav_hostname/username/access_key`, `sfcc_log_monitor_enabled` |
45
+ | **Deep-research flag** | The `deep_research_enabled` config flag on the project (403 otherwise). Web research runs via Gemini/OpenAI. | `config_projects.deep_research_enabled` |
46
+ | **Image provider** | An image model provider (OpenAI DALL·E / Google Imagen). | platform provider config |
47
+ | **Conductor ledger** | The local conductor event ledger (`~/.config/bridge/events.db`) — a local file, not a remote service. | local file |
48
+
49
+ ## Profiles (a form of BLOCK)
50
+
51
+ The server registers **90 tools** total, gated by `BRIDGE_MCP_PROFILE`
52
+ (comma-separated group list, resolved once at startup by
53
+ `mcp_server/src/mcp-profile.ts`). A tool outside
54
+ the active profile is **not registered at all** — an absolute block until the group is
55
+ activated. `core` is always implicitly included.
56
+
57
+ | Profile | Tools | Registered when |
58
+ |---|---|---|
59
+ | `core` | **57** | always |
60
+ | `pipeline-authoring` | **+5** | `BRIDGE_MCP_PROFILE` includes `pipeline-authoring` or `full` |
61
+ | `conductor` | **+8** | includes `conductor` or `full` |
62
+ | `sfcc` | **+20** (2 diagnostics ship in `core`; 18 gated) | includes `sfcc` or `full` |
63
+
64
+ (57 core + 5 + 8 + 20 = 90. The 5 pipeline-authoring tools live in `index.ts` alongside
65
+ core, gated by `ACTIVE_GROUPS.has("pipeline-authoring")`, so `index.ts` holds 62
66
+ `registerTool` calls.)
67
+
68
+ ---
69
+
70
+ ## Core profile (57)
71
+
72
+ ### Connectivity, config & setup — no integration deps
73
+
74
+ These are never gated (`NEVER_GATED_ROUTE_KEYS`) or run entirely locally.
75
+
76
+ | Tool | Dependencies (class) |
77
+ |---|---|
78
+ | `ping` | — none |
79
+ | `get_project_standards` | — none |
80
+ | `get_my_role` | — none |
81
+ | `config_field` (get/update/list) | — none |
82
+ | `get_install_manifest` | — none |
83
+ | `apply_install_manifest` | — none |
84
+ | `persist_routing_credential` | — none (`LOCAL`) |
85
+ | `get_docs_dir` | — none (`LOCAL`) |
86
+ | `get_parse_status` | — none |
87
+ | `track_ticket` | — none (Bridge DB tracking record) |
88
+ | `update_ticket_state` | — none (Bridge DB) |
89
+ | `get_ticket_state` | — none (Bridge DB) |
90
+ | `get_ticket_model_tier` | — none (Bridge DB difficulty) |
91
+ | `get_pipeline_recipe` | — none (`LOCAL`, bundled recipes) |
92
+ | `generate_decision_page` | — none (`LOCAL` HTML) |
93
+ | `cleanup_fresh_base` | — none (`LOCAL`) |
94
+
95
+ ### Ticket CRUD — ticket backend
96
+
97
+ Backend-agnostic (work in `jira` **or** `local` mode; Jira-named for v1 compatibility).
98
+ BLOCK applies only in `jira` mode without a Jira connection — `local` mode needs no
99
+ external integration.
100
+
101
+ | Tool | Dependencies (class) |
102
+ |---|---|
103
+ | `create_ticket` | Ticket backend **[BLOCK in jira mode]** |
104
+ | `get_tickets` | Ticket backend **[BLOCK in jira mode]** |
105
+ | `get_ticket` | Ticket backend **[BLOCK in jira mode]** |
106
+ | `update_ticket_description` | Ticket backend **[BLOCK in jira mode]** |
107
+ | `update_jira_status` | Ticket backend **[BLOCK in jira mode]** (local sets a fixed status) |
108
+ | `get_jira_transitions` | Ticket backend **[BLOCK in jira mode]** (local returns fixed statuses) |
109
+
110
+ Jira-only — no local-mode equivalent (comment threads and binary attachments are out of
111
+ scope for local v1):
112
+
113
+ | Tool | Dependencies (class) |
114
+ |---|---|
115
+ | `get_comments` | Jira (only) **[BLOCK]** |
116
+ | `add_comment` | Jira (only) **[BLOCK]** |
117
+ | `attachment` (upload/download/list) | Jira (only) **[BLOCK]** |
118
+
119
+ ### AI ticket-artifact generators — ticket backend + VCS + code index
120
+
121
+ All read the ticket through the ticket-store seam (`_fetch_ticket_webhook_payload` →
122
+ `ticket_store_lib.get_ticket`, which the local store fully supports), so they run in
123
+ `local` mode too — they are **not** hard-Jira-blocked. Their VCS/index behavior splits
124
+ by tier.
125
+
126
+ **Tier-3 — codebase-grounded (refuse without VCS creds AND a succeeded parse):**
127
+
128
+ | Tool (request / retrieve) | Dependencies (class) |
129
+ |---|---|
130
+ | `request_plan_generation` / `get_plan` | Ticket backend [BLOCK in jira mode] · VCS **[BLOCK]** · Code index **[BLOCK]** |
131
+ | `request_architecture` / `get_architecture` | Ticket backend [BLOCK in jira mode] · VCS **[BLOCK]** · Code index **[BLOCK]** |
132
+ | `request_reimplement_context` / `get_reimplement_context` | Ticket backend [BLOCK in jira mode] · VCS **[BLOCK]** · Code index **[BLOCK]** |
133
+ | `create_doc` / `get_doc` — `doc_type` ∈ {tdd, architecture} | Ticket backend [BLOCK in jira mode] · VCS **[BLOCK]** · Code index **[BLOCK]** |
134
+
135
+ **Tier-4 — ticket-text (warn, never block; research empties without index):**
136
+
137
+ | Tool (request / retrieve) | Dependencies (class) |
138
+ |---|---|
139
+ | `request_clarifying_questions` / `get_clarifying_questions` | Ticket backend [BLOCK in jira mode] · VCS **[DEGRADE]** · Code index **[DEGRADE]** |
140
+ | `request_ticket_critique` / `get_ticket_critique` | Ticket backend [BLOCK in jira mode] · VCS **[DEGRADE]** · Code index **[DEGRADE]** |
141
+ | `request_ticket_review` | Ticket backend [BLOCK in jira mode] · VCS **[DEGRADE]** · Code index **[DEGRADE]** |
142
+ | `request_prd` / `get_prd` | Ticket backend [BLOCK in jira mode] · VCS **[DEGRADE]** · Code index **[DEGRADE]** |
143
+ | `create_doc` / `get_doc` — `doc_type` ∈ {prd, fsd} | Ticket backend [BLOCK in jira mode] · VCS **[DEGRADE]** · Code index **[DEGRADE]** |
144
+
145
+ **Estimation:**
146
+
147
+ | Tool | Dependencies (class) |
148
+ |---|---|
149
+ | `estimate_epic` | Jira **[BLOCK]** (resolves the repo from `jira_ticket_key`); no code-index dep |
150
+
151
+ ### Repository parse / index — VCS
152
+
153
+ | Tool | Dependencies (class) |
154
+ |---|---|
155
+ | `parse_repository` | VCS **[BLOCK]** (Tier-2; refuses without a VCS connection — it *produces* the index) |
156
+ | `regenerate_directory_map` | VCS **[BLOCK]** (Tier-2) |
157
+
158
+ ### LLM utilities & research
159
+
160
+ | Tool | Dependencies (class) |
161
+ |---|---|
162
+ | `second_opinion` | — none (pure LLM; repo access only) |
163
+ | `generate_image` | — none beyond an image provider |
164
+ | `visual_diff` | — none (`LOCAL` render + pixel diff; needs a reachable `target_url`) |
165
+ | `request_deep_research` / `get_deep_research` | Deep-research flag **[BLOCK]** (403 if `deep_research_enabled` off) |
166
+ | `request_brainstorm` / `get_brainstorm` | Code index **[BLOCK] for `technical`/`discovery` modes**; **— none for `design` mode** |
167
+
168
+ ### VCS & CI
169
+
170
+ | Tool | Dependencies (class) |
171
+ |---|---|
172
+ | `create_pull_request` | VCS **[BLOCK]** (Tier-1) |
173
+ | `resolve_ci_checks` | VCS **[BLOCK]** (Tier-1) |
174
+ | `poll_ci_checks` | VCS **[BLOCK]** (Tier-1); also **hidden until `ci_check_config` is resolved** (needs a prior `resolve_ci_checks`) |
175
+ | `materialize_fresh_base` | VCS / git base ref **[BLOCK]** (Tier-1; materializes a pinned base tree) |
176
+
177
+ ### Full-automation (composite)
178
+
179
+ These orchestrate an idea → ticket → review → start chain, so they inherit the
180
+ **strictest** dependency of every child step.
181
+
182
+ | Tool | Dependencies (class) |
183
+ |---|---|
184
+ | `run_full_automation` | Ticket backend [BLOCK in jira mode] · VCS **[BLOCK]** · Code index **[BLOCK]** (via child plan/review steps) |
185
+ | `resume_full_automation` | Same as `run_full_automation` |
186
+
187
+ ---
188
+
189
+ ## `pipeline-authoring` profile (5)
190
+
191
+ Profile-gated **[BLOCK]** to register at all. `run_pipeline` / `resume_pipeline`
192
+ additionally inherit the dependencies of whatever steps the invoked pipeline runs
193
+ (e.g. the `implement-ticket` pipeline pulls in ticket-backend + VCS + code-index deps).
194
+ Run state is persisted via the Bridge API.
195
+
196
+ | Tool | Dependencies (class) |
197
+ |---|---|
198
+ | `list_pipelines` | Profile-gated **[BLOCK]** |
199
+ | `run_pipeline` | Profile-gated **[BLOCK]** · inherits invoked pipeline's step deps |
200
+ | `resume_pipeline` | Profile-gated **[BLOCK]** · inherits invoked pipeline's step deps |
201
+ | `list_pipeline_runs` | Profile-gated **[BLOCK]** |
202
+ | `delete_pipeline_run` | Profile-gated **[BLOCK]** |
203
+
204
+ ---
205
+
206
+ ## `conductor` profile (8)
207
+
208
+ Profile-gated **[BLOCK]** to register. Most operate on the **local** conductor ledger
209
+ (`~/.config/bridge/events.db`), so beyond the profile gate they have no remote
210
+ integration dependency.
211
+
212
+ | Tool | Dependencies (class) |
213
+ |---|---|
214
+ | `emit_event` | Profile-gated **[BLOCK]**; else `LOCAL` ledger |
215
+ | `poll_events` | Profile-gated **[BLOCK]**; else `LOCAL` ledger |
216
+ | `wait_for_event` | Profile-gated **[BLOCK]**; else `LOCAL` ledger |
217
+ | `get_supervisor_snapshot` | Profile-gated **[BLOCK]**; else `LOCAL` ledger |
218
+ | `send_message` | Profile-gated **[BLOCK]**; else `LOCAL` relay |
219
+ | `check_messages` | Profile-gated **[BLOCK]**; else `LOCAL` relay |
220
+ | `get_epic_snapshot` | Profile-gated **[BLOCK]** · Bridge API epic snapshot (Jira epic keys) |
221
+ | `wait_for_done_gate` | Profile-gated **[BLOCK]** · VCS **[BLOCK]** (resolves PR number + head SHA) |
222
+
223
+ ---
224
+
225
+ ## `sfcc` group (20)
226
+
227
+ ### Always-on diagnostics (ship in `core`)
228
+
229
+ | Tool | Dependencies (class) |
230
+ |---|---|
231
+ | `sfcc_setup_status` | — none (its purpose is to report which SFCC prerequisites are missing) |
232
+ | `check_permissions` | SFCC OCAPI **[BLOCK]** (probes OCAPI; reports not-OK without access / version config) |
233
+
234
+ ### Gated behind the `sfcc` group (18)
235
+
236
+ All are profile-gated **[BLOCK]** to register, and all require SFCC OCAPI creds +
237
+ `version` config + a reachable sandbox → SFCC OCAPI **[BLOCK]**. Writes are
238
+ sandbox-only and destructive.
239
+
240
+ **Reads (8):**
241
+
242
+ | Tool | Dependencies (class) |
243
+ |---|---|
244
+ | `system_object_list` | Profile-gated **[BLOCK]** · SFCC OCAPI **[BLOCK]** |
245
+ | `system_object_get` | Profile-gated **[BLOCK]** · SFCC OCAPI **[BLOCK]** |
246
+ | `system_object_attribute_search` | Profile-gated **[BLOCK]** · SFCC OCAPI **[BLOCK]** |
247
+ | `custom_object_definition_attributes_get` | Profile-gated **[BLOCK]** · SFCC OCAPI **[BLOCK]** |
248
+ | `custom_object_definition_attribute_search` | Profile-gated **[BLOCK]** · SFCC OCAPI **[BLOCK]** |
249
+ | `site_preference_group_list` | Profile-gated **[BLOCK]** · SFCC OCAPI **[BLOCK]** |
250
+ | `site_preference_get` | Profile-gated **[BLOCK]** · SFCC OCAPI **[BLOCK]** |
251
+ | `site_preference_search` | Profile-gated **[BLOCK]** · SFCC OCAPI **[BLOCK]** |
252
+
253
+ **Writes (9, sandbox-only):**
254
+
255
+ | Tool | Dependencies (class) |
256
+ |---|---|
257
+ | `system_object_attribute_definition_create` | Profile-gated **[BLOCK]** · SFCC OCAPI write **[BLOCK]** |
258
+ | `system_object_attribute_definition_update` | Profile-gated **[BLOCK]** · SFCC OCAPI write **[BLOCK]** |
259
+ | `system_object_attribute_group_create` | Profile-gated **[BLOCK]** · SFCC OCAPI write **[BLOCK]** |
260
+ | `system_object_attribute_group_update` | Profile-gated **[BLOCK]** · SFCC OCAPI write **[BLOCK]** |
261
+ | `system_object_attribute_assign_to_group` | Profile-gated **[BLOCK]** · SFCC OCAPI write **[BLOCK]** |
262
+ | `custom_preference_definition_create` | Profile-gated **[BLOCK]** · SFCC OCAPI write **[BLOCK]** |
263
+ | `custom_object_definition_attribute_create` | Profile-gated **[BLOCK]** · SFCC OCAPI write **[BLOCK]** |
264
+ | `custom_object_definition_attribute_update` | Profile-gated **[BLOCK]** · SFCC OCAPI write **[BLOCK]** |
265
+ | `site_preference_values_set` | Profile-gated **[BLOCK]** · SFCC OCAPI write **[BLOCK]** |
266
+
267
+ **Logs (1):**
268
+
269
+ | Tool | Dependencies (class) |
270
+ |---|---|
271
+ | `sfcc_log_query` | Profile-gated **[BLOCK]** · SFCC WebDAV creds **[BLOCK]** · `sfcc_log_monitor_enabled` **[BLOCK]** · required `environment` scope |
272
+
273
+ ---
274
+
275
+ ## Quick matrix: integration → dependent tools
276
+
277
+ | Integration | BLOCK without it | DEGRADE without it |
278
+ |---|---|---|
279
+ | **Ticket backend** (jira mode) | `create_ticket`, `get_ticket(s)`, `update_ticket_description`, `update_jira_status`, `get_jira_transitions`, and every AI generator (they read the ticket) | — |
280
+ | **Jira (only)** | `get_comments`, `add_comment`, `attachment`, `estimate_epic` | — |
281
+ | **Version control (VCS)** | `create_pull_request`, `resolve_ci_checks`, `poll_ci_checks`, `materialize_fresh_base`, `parse_repository`, `regenerate_directory_map`, `wait_for_done_gate`; **Tier-3** `request_plan_generation`/`get_plan`, `request_architecture`/`get_architecture`, `request_reimplement_context`/`get_reimplement_context`, `create_doc`(tdd/architecture) | **Tier-4** `request_clarifying_questions`, `request_ticket_critique`, `request_ticket_review`, `request_prd`, `create_doc`(prd/fsd) |
282
+ | **Code index** (succeeded parse) | Tier-3 plan/architecture/reimplement/`create_doc`(tdd/architecture); `request_brainstorm` in `technical`/`discovery` modes | Tier-4 clarifying-questions/critique/review/prd/fsd |
283
+ | **SFCC OCAPI** | `check_permissions` + all 16 SFCC read/write tools | — |
284
+ | **SFCC WebDAV logs** | `sfcc_log_query` | — |
285
+ | **Deep-research flag** | `request_deep_research`, `get_deep_research` | — |
286
+ | **Profile gating** | all `pipeline-authoring` (5), `conductor` (8), gated `sfcc` (18) tools | — |
287
+
288
+ ## Notes & caveats
289
+
290
+ - **Refusals are graceful.** VCS/index BLOCKs are enforced by
291
+ `build_vcs_preflight_refusal_response`; they return a refusal in the route's normal
292
+ success-class status (e.g. 202 for job-submit routes) rather than a new 4xx/5xx, so a
293
+ capability gap never looks like a server error.
294
+ - **DEGRADE is deliberately non-fatal.** Tier-4 tools attach a disclosure via
295
+ `build_vcs_preflight_warning_disclosure`; `plan_researcher` returns empty research on
296
+ an unindexed repo instead of raising — the same fallback the Tier-3 routes rely on.
297
+ - **Index check fails open.** A transient DB error during the index probe collapses to
298
+ "available" (blocking an indexed repo on a flaky read is worse than a rare ungrounded
299
+ generation). Legacy repos parsed before `repository_parse_runs` existed fall back to a
300
+ `code_repositories` existence check and are not falsely refused.
301
+ - **Ticket-backend default is `jira`.** The seam is fail-safe: any config/DAL problem
302
+ resolves to `jira`, so a misconfigured repo behaves as jira-mode (and thus BLOCKs
303
+ without a Jira connection) rather than silently using local.
304
+ - **Baseline is assumed.** A reachable Bridge API + valid API key (and, for AI tools, an
305
+ LLM provider) underlies everything above and is not listed per tool.
@@ -0,0 +1,140 @@
1
+ # Installing the SFCC Integration (OCAPI)
2
+
3
+ Bridge's Salesforce B2C Commerce (SFCC) tools give an AI coding agent read access to
4
+ a sandbox's object model, custom object definitions, and site preferences — plus a
5
+ small set of sandbox-only writes — through the **OCAPI Data API**. This guide covers
6
+ setting up the OCAPI client that those tools authenticate against.
7
+
8
+ > **Sandbox / local development only.** This integration is intended for a **developer
9
+ > sandbox**. The tools reject non-sandbox instances, and the permissions grant below is
10
+ > deliberately broad (all methods, all resources) — appropriate for a throwaway dev
11
+ > sandbox, **never** for staging or production. Do not configure this grant on any
12
+ > instance that holds real data. Credentials stay local (in `dw.json` or `SFCC_*` env
13
+ > vars) and are never sent to Bridge.
14
+
15
+ For the full per-tool list and what each SFCC tool depends on, see
16
+ [MCP Tool Integration Dependencies](./mcp-tool-integrations.md). For the tool reference
17
+ and the `BRIDGE_MCP_PROFILE` gating, see the SFCC section of the
18
+ [package README](../../README.md).
19
+
20
+ ## Prerequisites
21
+
22
+ - A running SFCC **developer sandbox** and its hostname
23
+ (e.g. `zzzz-001.sandbox.us01.dx.commercecloud.salesforce.com`).
24
+ - An **Account Manager API client** — a `client-id` and `client-secret`. This is the
25
+ OCAPI client the tools use to obtain an OAuth token. Create one in Account Manager
26
+ (**API Client** → *Add API Client*) if you don't already have it, and note its
27
+ `client_id`.
28
+ - Business Manager access to the sandbox with permission to edit **Open Commerce API
29
+ Settings**.
30
+
31
+ ## 1. Grant the OCAPI client access in Business Manager
32
+
33
+ In Business Manager for the sandbox:
34
+
35
+ **Administration → Site Development → Open Commerce API Settings → Data API** tab.
36
+
37
+ Add the following client entry to the `clients` array of the Data API settings, then
38
+ **Save**. This grants the client full read/write access to every Data API resource —
39
+ acceptable only on a developer sandbox:
40
+
41
+ ```json
42
+ {
43
+ "client_id": "<your-client-id-here>",
44
+ "resources": [
45
+ {
46
+ "methods": ["get", "post", "put", "patch", "delete"],
47
+ "read_attributes": "(**)",
48
+ "write_attributes": "(**)",
49
+ "resource_id": "/**"
50
+ }
51
+ ]
52
+ }
53
+ ```
54
+
55
+ Notes:
56
+
57
+ - The `client_id` **must match** the Account Manager API client whose credentials you
58
+ put in `dw.json` / `SFCC_*` below. Replace the value above with your own client id if
59
+ it differs.
60
+ - If the Data API settings are empty, wrap the entry in the standard settings envelope:
61
+
62
+ ```json
63
+ {
64
+ "_v": "23.2",
65
+ "clients": [
66
+ {
67
+ "client_id": "<your-client-id-here>",
68
+ "resources": [
69
+ {
70
+ "methods": ["get", "post", "put", "patch", "delete"],
71
+ "read_attributes": "(**)",
72
+ "write_attributes": "(**)",
73
+ "resource_id": "/**"
74
+ }
75
+ ]
76
+ }
77
+ ]
78
+ }
79
+ ```
80
+
81
+ - `check_permissions` (below) prints a ready-to-paste grant JSON on a 401/403, so you can
82
+ also let the tool tell you exactly what to add.
83
+
84
+ ## 2. Provide credentials locally
85
+
86
+ Create a `dw.json` in your project root (auto-added to git exclude — never commit it):
87
+
88
+ ```json
89
+ {
90
+ "hostname": "zzzz-001.sandbox.us01.dx.commercecloud.salesforce.com",
91
+ "client-id": "<your-client-id-here>",
92
+ "client-secret": "<account-manager-client-secret>"
93
+ }
94
+ ```
95
+
96
+ Accepted key spellings: `hostname`/`host`, `client-id`/`clientId`/`client_id`,
97
+ `client-secret`/`clientSecret`/`client_secret`. Prefer a single config — a multi-entry
98
+ `configs[]` array forces an explicit `instance` on every call. Alternatively, export
99
+ `SFCC_HOSTNAME` / `SFCC_CLIENT_ID` / `SFCC_CLIENT_SECRET` in the MCP server environment.
100
+
101
+ ## 3. Set the repo `version` config field
102
+
103
+ Set the repo's `version` config to your SFCC project type — one of
104
+ `sfra | pwakit | sitegenesis | storefrontnext | hybrid`. The call-time gate reads this;
105
+ a non-SFCC value blocks every SFCC tool except `sfcc_setup_status`. Set it via your
106
+ normal config path, the `config_field` MCP tool (operation `update`, field `version`),
107
+ or the `/teach-bridge` skill.
108
+
109
+ ## 4. Enable the SFCC tools
110
+
111
+ The two diagnostic tools (`sfcc_setup_status`, `check_permissions`) are always
112
+ registered. The read tools, write tools, and `sfcc_log_query` are gated behind the
113
+ `sfcc` profile. Add `sfcc` to `BRIDGE_MCP_PROFILE` in the MCP server `env` block (it is
114
+ comma-separated; `full` also works), then **restart the MCP client**:
115
+
116
+ ```json
117
+ "env": { "BRIDGE_MCP_PROFILE": "sfcc" }
118
+ ```
119
+
120
+ ## 5. Verify
121
+
122
+ Ask your agent to run:
123
+
124
+ 1. `sfcc_setup_status` — expect all prerequisite checks ✓ (Bridge API key, repo name,
125
+ `version` config, `dw.json` presence/uniqueness, AM/OCAPI token acquisition).
126
+ 2. `check_permissions` — probes OCAPI via `GET /system_object_definitions`. A 200 (with
127
+ the OCAPI version) confirms the grant. On 401/403 it prints the exact grant JSON to
128
+ paste back in step 1.
129
+
130
+ Restart the MCP client after any credential, grant, or env change — a running session
131
+ does not pick them up.
132
+
133
+ ## Notes
134
+
135
+ - **WebDAV logs are separate.** `sfcc_log_query` authenticates with a Business Manager
136
+ username + a 40-character **WebDAV access key** over HTTP Basic auth — *not* the OCAPI
137
+ OAuth token configured here. `sfcc_setup_status` reports OCAPI (step 5) and WebDAV
138
+ (step 6) independently; one can be green while the other is not.
139
+ - **Writes are sandbox-only.** The write tools (attribute/preference create/update) target
140
+ a developer sandbox and echo a paste-ready grant JSON on a 403.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bridge_gpt/mcp-server",
3
- "version": "0.2.21",
3
+ "version": "0.2.24",
4
4
  "description": "Bridge API MCP server — exposes Jira endpoints as MCP tools for Claude Code agents",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,16 +19,16 @@
19
19
  "design-assets/",
20
20
  "public/",
21
21
  "README.md",
22
- "CONDUCTOR.md",
22
+ "docs/",
23
23
  "LICENSE"
24
24
  ],
25
25
  "scripts": {
26
- "build": "node scripts/bundle-version.js && node scripts/bundle-readme.js && node scripts/bundle-pipelines.js && node scripts/bundle-commands.js && node scripts/bundle-agents.js && tsc && node scripts/bundle-esbuild.js",
26
+ "build": "node scripts/bundle-version.js && node scripts/bundle-readme.js && node scripts/bundle-pipelines.js && node scripts/bundle-commands.js && node scripts/bundle-agents.js && node scripts/bundle-docs.js && tsc && node scripts/bundle-esbuild.js",
27
27
  "check:version-generated": "node scripts/bundle-version.js && node scripts/check-version-generated.js",
28
28
  "postbuild": "node scripts/prepend-shebang.cjs",
29
29
  "start": "node build/index.js",
30
- "test": "node --test --test-force-exit build/pipeline-utils.test.js build/backend-warnings.test.js build/update-check.test.js build/cli-upgrade.test.js build/decision-page-schema.test.js build/decision-page-template.test.js build/bundle-pipelines.test.js build/instructions-contract.test.js build/pipeline-orchestrator-persistence.test.js build/pipeline-orchestrator-execution.test.js build/pipeline-orchestrator-integration.test.js build/index-static.test.js build/config-fields.static.test.js build/index-resolvers.test.js build/index-project-root.test.js build/index-pipelines.test.js build/index.test.js build/bridge-config.test.js build/credential-store.test.js build/agent-config-credential-migration.test.js build/mcp-invoke.test.js build/mcp-provisioning.test.js build/mcp-server-invocation.test.js build/third-party-mcp-targets.test.js build/git-ignore-utils.test.js build/credential-materialization.test.js build/mcp-registration-doctor.test.js build/secret-safety.test.js build/start-tickets.test.js build/review-tickets.test.js build/start-tickets-base-branch.test.js build/agent-registry.test.js build/agent-registry.model-routing.test.js build/start-tickets.shell-model-routing.test.js build/start-tickets.bridge-api-model-routing.test.js build/start-tickets.tier-fetch-model-routing.test.js build/start-tickets.resolve-model-routing.test.js build/start-tickets.orchestrate-model-routing.test.js build/start-tickets.routing-diagnostics.test.js build/start-tickets-repo.test.js build/start-tickets-credential-invariants.static.test.js build/credentials-cli.test.js build/start-tickets-prereqs.test.js build/regression-check.test.js build/doctor.test.js build/install-doctor.test.js build/install-bridge.test.js build/init.test.js build/resolveUploadAttachment.test.js build/package-static.test.js build/chain-utils.test.js build/chain-orchestrator.test.js build/scheduler-backends/types.test.js build/scheduler-backends/escaping.test.js build/scheduler-backends/launchd.test.js build/scheduler-backends/task-scheduler.test.js build/scheduler-backends/systemd-user.test.js build/scheduler-backends/at-fallback.test.js build/scheduler-backends/index.test.js build/command-catalog.test.js build/scheduled-prompt.test.js build/agent-launchers/claude.test.js build/agent-launchers/cursor.test.js build/agent-launchers/index.test.js build/schedule-store.test.js build/schedule-run.test.js build/agent-capabilities/cli.test.js build/agent-capabilities/runner.test.js build/agent-capabilities/probes.test.js build/agent-capabilities/probe-context.test.js build/agent-capabilities/reporter.test.js build/conductor/taxonomy-and-errors.test.js build/conductor/github-mergeability.test.js build/conductor/merge-conflict-routing.test.js build/conductor/redaction-normalization.test.js build/conductor/claude-hook.test.js build/conductor/git-ci-types.test.js build/conductor/done-gate.test.js build/conductor/git-ci-taxonomy-payload.test.js build/conductor/bridge-api-client.test.js build/conductor/plan.test.js build/conductor/producer-ledger.test.js build/conductor/spec-review-producer.test.js build/conductor/git-producer.test.js build/conductor/git-hooks.test.js build/conductor/store-migration.test.js build/conductor/pr-discovery.test.js build/conductor/pr-ci-producer.test.js build/conductor/pr-review-producer.test.js build/conductor/doctor.test.js build/conductor/deny-enforcement-preflight.test.js build/conductor/errors.test.js build/conductor/store.test.js build/conductor/index-poll-ci-producer.test.js build/start-tickets-conductor.test.js build/start-tickets-conductor.spawn.test.js build/start-tickets-conductor-node-propagation.test.js build/start-tickets.non-mutating-base.test.js build/start-tickets-live-source-guard.test.js build/conductor/worker-ledger-cli.test.js build/conductor/supervisor-config.test.js build/conductor/supervisor-ledger.test.js build/conductor/supervisor-state-reducer.test.js build/conductor/supervisor-housekeeping-projection.test.js build/conductor/supervisor-escalation.test.js build/conductor/supervisor-retired-judgment.static.test.js build/conductor/supervisor-runtime.test.js build/conductor/supervisor-store-projection.test.js build/conductor/supervisor-cli.test.js build/conductor/supervisor-start-tickets.test.js build/conductor/supervisor-message-relay.test.js build/conductor/supervisor-state-message-events.test.js build/conductor/store-message-relay.test.js build/start-tickets-message-relay.test.js build/conductor/event-accessors.test.js build/conductor/merge-ledger.test.js build/conductor/deterministic-completion.static.test.js build/conductor/deterministic-completion.integration.test.js build/conductor/local-merge.test.js build/conductor/local-merge.static.test.js build/conductor/supervisor-merge.test.js build/conductor/bridge-api-merge-client.test.js build/conductor/bridge-api-epic-client.test.js build/conductor/supervisor-merge-runtime-state.test.js build/conductor/epic-state.test.js build/executor/claude-settings.test.js build/executor/cli.test.js build/executor/credentials.test.js build/executor/echo-acceptance.test.js build/executor/env.test.js build/executor/heartbeat.test.js build/executor/http-client.test.js build/executor/job-runner.test.js build/executor/job-runner.payload-timeout.test.js build/executor/worker-finalization.test.js build/executor/job-runner.static.test.js build/executor/prompt-spec.test.js build/executor/job-types.test.js build/executor/recovery-job.static.test.js build/executor/observation.test.js build/executor/permissions.test.js build/executor/preflight.test.js build/executor/process.test.js build/executor/results.test.js build/executor/runner.test.js build/executor/terminal-mutation.test.js build/executor/worker-command.test.js build/executor/worktree-core.test.js build/executor/worktree.test.js build/executor/job-errors.test.js build/executor/worktree-inspection.test.js build/executor/resume-pre-spawn.test.js build/executor/verdict-artifact.test.js build/executor/worker-log.test.js build/executor/job-log-registry.test.js build/executor/viewer-tabs.test.js build/executor/watch-cli.test.js build/executor/merge-job.test.js build/executor/job-runner.merge.test.js build/executor/worktree-gc.test.js build/executor/runner.job-behaviors.test.js build/conductor/cli-freeze.test.js build/conductor/epic-reconcile.test.js build/conductor/epic-runtime.test.js build/conductor/epic-tick-sequence.test.js build/conductor/epic-runtime-post-action.test.js build/conductor/file-scope-guard.test.js build/conductor/file-scope-guard.integration.test.js build/mcp-profile.test.js build/mcp-profile-registration.test.js build/tools-budget.test.js build/visual-diff-worker.test.js build/visual-diff.test.js build/estimate-epic.test.js build/integration/measure-tools.test.js build/sfcc/config.test.js build/sfcc/ocapi-shape.test.js build/sfcc/output.test.js build/sfcc/credentials.test.js build/sfcc/ocapi-write-faults.test.js build/sfcc/write-guard.test.js build/sfcc/write-grants.test.js build/sfcc/write-result.test.js build/sfcc/writes.test.js build/sfcc/writes-system-object-payloads.test.js build/sfcc/writes-payloads.test.js && node --experimental-test-module-mocks --test --test-force-exit build/index-heavy-read-truncation.test.js build/index-artifacts.test.js build/index.review-rounds.test.js build/index-brainstorm-filenames.test.js build/index-output-path.test.js build/index-generate-decision-page.test.js build/index-generate-decision-page.integration.test.js build/visual-diff.registration.test.js build/visual-diff.attachment-adapter.test.js build/attachment-download.test.js build/attachment-upload.test.js build/conductor/paths.test.js build/conductor/store-lifecycle.test.js build/conductor/store-queries.test.js build/conductor/tools.test.js build/conductor/cli.test.js build/conductor/security-regressions.test.js build/conductor/git-inspection.test.js build/conductor/tools-done-gate.test.js build/conductor/pr-ci-producer-emit-seam.test.js build/conductor/cli-git-hooks.test.js build/sfcc/client.test.js build/sfcc/tool-wrapper.test.js build/sfcc/setup-status.test.js build/sfcc/permissions.test.js build/sfcc/register.test.js build/sfcc/reads-system-object.test.js build/sfcc/reads-custom-object-def.test.js build/sfcc/reads-site-preference.test.js build/sfcc/writes-system-object.test.js build/sfcc/writes-custom-object-def.test.js build/sfcc/writes-site-preference.test.js",
31
- "test:integration": "node --test build/integration/refresh-main.integration.test.js build/integration/start-tickets.integration.test.js build/integration/doctor.integration.test.js build/integration/agent-capabilities.integration.test.js build/integration/conductor-producer.integration.test.js build/integration/conductor-message-relay.integration.test.js build/integration/executor-http-runner.integration.test.js build/integration/executor-job-behaviors.integration.test.js build/integration/executor-recovery-jobs.integration.test.js build/integration/executor-spec-review-prompt.integration.test.js build/integration/resume-pre-spawn.git.integration.test.js build/integration/worker-finalization-origin.integration.test.js build/integration/post-remediation-merge-ci-wait.integration.test.js build/integration/executor-merge-supervision.integration.test.js build/integration/attachment-binary-roundtrip.integration.test.js",
30
+ "test": "node --test --test-force-exit build/pipeline-utils.test.js build/backend-warnings.test.js build/update-check.test.js build/cli-upgrade.test.js build/decision-page-schema.test.js build/decision-page-template.test.js build/bundle-pipelines.test.js build/instructions-contract.test.js build/pipeline-orchestrator-persistence.test.js build/pipeline-orchestrator-execution.test.js build/pipeline-orchestrator-integration.test.js build/index-static.test.js build/config-fields.static.test.js build/execute-plan-instructions.static.test.js build/index-resolvers.test.js build/index-project-root.test.js build/index-pipelines.test.js build/index.test.js build/bridge-config.test.js build/credential-store.test.js build/agent-config-credential-migration.test.js build/mcp-invoke.test.js build/mcp-provisioning.test.js build/mcp-server-invocation.test.js build/third-party-mcp-targets.test.js build/git-ignore-utils.test.js build/credential-materialization.test.js build/mcp-registration-doctor.test.js build/secret-safety.test.js build/base-ref.test.js build/pr-base-contract.test.js build/start-tickets.test.js build/review-tickets.test.js build/start-tickets-base-branch.test.js build/agent-registry.test.js build/agent-registry.model-routing.test.js build/start-tickets.shell-model-routing.test.js build/start-tickets.bridge-api-model-routing.test.js build/start-tickets.tier-fetch-model-routing.test.js build/start-tickets.resolve-model-routing.test.js build/start-tickets.orchestrate-model-routing.test.js build/start-tickets.routing-diagnostics.test.js build/start-tickets-repo.test.js build/start-tickets-credential-invariants.static.test.js build/credentials-cli.test.js build/start-tickets-prereqs.test.js build/regression-check.test.js build/doctor.test.js build/install-doctor.test.js build/install-bridge.test.js build/install-bridge-invite.test.js build/install-bridge-prompt.test.js build/init.test.js build/resolveUploadAttachment.test.js build/package-static.test.js build/chain-utils.test.js build/chain-orchestrator.test.js build/scheduler-backends/types.test.js build/scheduler-backends/escaping.test.js build/scheduler-backends/launchd.test.js build/scheduler-backends/task-scheduler.test.js build/scheduler-backends/systemd-user.test.js build/scheduler-backends/at-fallback.test.js build/scheduler-backends/index.test.js build/command-catalog.test.js build/scheduled-prompt.test.js build/agent-launchers/claude.test.js build/agent-launchers/cursor.test.js build/agent-launchers/index.test.js build/schedule-store.test.js build/schedule-run.test.js build/setup-epic.test.js build/agent-capabilities/cli.test.js build/agent-capabilities/runner.test.js build/agent-capabilities/probes.test.js build/agent-capabilities/probe-context.test.js build/agent-capabilities/reporter.test.js build/conductor/taxonomy-and-errors.test.js build/conductor/github-mergeability.test.js build/conductor/merge-conflict-routing.test.js build/conductor/redaction-normalization.test.js build/conductor/claude-hook.test.js build/conductor/git-ci-types.test.js build/conductor/done-gate.test.js build/conductor/git-ci-taxonomy-payload.test.js build/conductor/bridge-api-client.test.js build/conductor/plan.test.js build/conductor/producer-ledger.test.js build/conductor/spec-review-producer.test.js build/conductor/git-producer.test.js build/conductor/git-hooks.test.js build/conductor/store-migration.test.js build/conductor/pr-discovery.test.js build/conductor/pr-ci-producer.test.js build/conductor/pr-review-producer.test.js build/conductor/doctor.test.js build/conductor/deny-enforcement-preflight.test.js build/conductor/errors.test.js build/conductor/store.test.js build/conductor/index-poll-ci-producer.test.js build/start-tickets-conductor.test.js build/start-tickets-conductor.spawn.test.js build/start-tickets-conductor-node-propagation.test.js build/start-tickets.non-mutating-base.test.js build/start-tickets-live-source-guard.test.js build/conductor/worker-ledger-cli.test.js build/conductor/supervisor-config.test.js build/conductor/supervisor-ledger.test.js build/conductor/supervisor-state-reducer.test.js build/conductor/supervisor-housekeeping-projection.test.js build/conductor/supervisor-escalation.test.js build/conductor/supervisor-retired-judgment.static.test.js build/conductor/supervisor-runtime.test.js build/conductor/supervisor-store-projection.test.js build/conductor/supervisor-cli.test.js build/conductor/supervisor-start-tickets.test.js build/conductor/supervisor-message-relay.test.js build/conductor/supervisor-state-message-events.test.js build/conductor/store-message-relay.test.js build/start-tickets-message-relay.test.js build/conductor/event-accessors.test.js build/conductor/merge-ledger.test.js build/conductor/deterministic-completion.static.test.js build/conductor/deterministic-completion.integration.test.js build/conductor/local-merge.test.js build/conductor/local-merge.static.test.js build/conductor/supervisor-merge.test.js build/conductor/bridge-api-merge-client.test.js build/conductor/bridge-api-epic-client.test.js build/conductor/supervisor-merge-runtime-state.test.js build/conductor/epic-state.test.js build/executor/claude-settings.test.js build/executor/cli.test.js build/executor/credentials.test.js build/executor/echo-acceptance.test.js build/executor/env.test.js build/executor/base-branch.test.js build/executor/heartbeat.test.js build/executor/http-client.test.js build/executor/job-runner.test.js build/executor/job-runner.payload-timeout.test.js build/executor/worker-finalization.test.js build/executor/job-runner.static.test.js build/executor/prompt-spec.test.js build/executor/job-types.test.js build/executor/recovery-job.static.test.js build/executor/observation.test.js build/executor/permissions.test.js build/executor/preflight.test.js build/executor/process.test.js build/executor/results.test.js build/executor/runner.test.js build/executor/terminal-mutation.test.js build/executor/worker-command.test.js build/executor/worktree-core.test.js build/executor/worktree.test.js build/executor/job-errors.test.js build/executor/worktree-inspection.test.js build/executor/resume-pre-spawn.test.js build/executor/verdict-artifact.test.js build/executor/worker-log.test.js build/executor/job-log-registry.test.js build/executor/viewer-tabs.test.js build/executor/watch-cli.test.js build/executor/merge-job.test.js build/executor/job-runner.merge.test.js build/executor/worktree-gc.test.js build/executor/runner.job-behaviors.test.js build/conductor/cli-freeze.test.js build/conductor/epic-reconcile.test.js build/conductor/epic-runtime.test.js build/conductor/epic-tick-sequence.test.js build/conductor/epic-runtime-post-action.test.js build/conductor/file-scope-guard.test.js build/conductor/file-scope-guard.integration.test.js build/mcp-profile.test.js build/mcp-profile-registration.test.js build/tools-budget.test.js build/visual-diff-worker.test.js build/visual-diff.test.js build/estimate-epic.test.js build/integration/measure-tools.test.js build/sfcc/config.test.js build/sfcc/ocapi-shape.test.js build/sfcc/output.test.js build/sfcc/credentials.test.js build/sfcc/ocapi-write-faults.test.js build/sfcc/write-guard.test.js build/sfcc/write-grants.test.js build/sfcc/write-result.test.js build/sfcc/writes.test.js build/sfcc/writes-system-object-payloads.test.js build/sfcc/writes-payloads.test.js build/sfcc/log-gate.test.js build/sfcc/log-query.test.js && node --experimental-test-module-mocks --test --test-force-exit build/index-heavy-read-truncation.test.js build/index-artifacts.test.js build/index.review-rounds.test.js build/index-brainstorm-filenames.test.js build/index-output-path.test.js build/index-generate-decision-page.test.js build/index-generate-decision-page.integration.test.js build/visual-diff.registration.test.js build/visual-diff.attachment-adapter.test.js build/attachment-download.test.js build/attachment-upload.test.js build/conductor/paths.test.js build/conductor/store-lifecycle.test.js build/conductor/store-queries.test.js build/conductor/tools.test.js build/conductor/cli.test.js build/conductor/security-regressions.test.js build/conductor/git-inspection.test.js build/conductor/tools-done-gate.test.js build/conductor/pr-ci-producer-emit-seam.test.js build/conductor/cli-git-hooks.test.js build/sfcc/client.test.js build/sfcc/tool-wrapper.test.js build/sfcc/setup-status.test.js build/sfcc/permissions.test.js build/sfcc/register.test.js build/sfcc/reads-system-object.test.js build/sfcc/reads-custom-object-def.test.js build/sfcc/reads-site-preference.test.js build/sfcc/writes-system-object.test.js build/sfcc/writes-custom-object-def.test.js build/sfcc/writes-site-preference.test.js",
31
+ "test:integration": "node --test build/integration/refresh-main.integration.test.js build/integration/start-tickets.integration.test.js build/integration/doctor.integration.test.js build/integration/agent-capabilities.integration.test.js build/integration/conductor-producer.integration.test.js build/integration/conductor-message-relay.integration.test.js build/integration/executor-http-runner.integration.test.js build/integration/executor-job-behaviors.integration.test.js build/integration/executor-recovery-jobs.integration.test.js build/integration/executor-spec-review-prompt.integration.test.js build/integration/resume-pre-spawn.git.integration.test.js build/integration/worker-finalization-origin.integration.test.js build/integration/post-remediation-merge-ci-wait.integration.test.js build/integration/executor-merge-supervision.integration.test.js build/integration/attachment-binary-roundtrip.integration.test.js build/integration/dependent-ticket-fresh-base.integration.test.js build/integration/execute-plan-instructions.integration.test.js build/integration/install-bridge-repo-resolution.integration.test.js",
32
32
  "test:smoke": "node --test build/integration/packaged-cli-smoke.test.js",
33
33
  "prepublishOnly": "node scripts/bundle-assets.js && npm run build && node scripts/verify-shebang.cjs"
34
34
  },
@@ -3496,7 +3496,9 @@ __webpack_require__.r(__webpack_exports__);
3496
3496
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
3497
3497
  /* harmony export */ hideModal: () => (/* binding */ hideModal),
3498
3498
  /* harmony export */ initModal: () => (/* binding */ initModal),
3499
- /* harmony export */ showModal: () => (/* binding */ showModal)
3499
+ /* harmony export */ replaceModalBody: () => (/* binding */ replaceModalBody),
3500
+ /* harmony export */ showModal: () => (/* binding */ showModal),
3501
+ /* harmony export */ showModalNode: () => (/* binding */ showModalNode)
3500
3502
  /* harmony export */ });
3501
3503
  // src/js/modal.js
3502
3504
 
@@ -3550,6 +3552,49 @@ function showModal(title, message, onConfirm = null, showCancel = false, onClose
3550
3552
  }
3551
3553
  }
3552
3554
 
3555
+ /**
3556
+ * Show the modal with a caller-built DOM node as its body.
3557
+ *
3558
+ * Additive companion to {@link showModal} for rich, structured content (e.g. the
3559
+ * SFCC ticket preview). The node is appended directly — never serialized through
3560
+ * innerHTML — so untrusted values built with textContent stay safe. The caller
3561
+ * supplies its own action controls inside `contentEl`, so the shared
3562
+ * confirm/cancel actions are hidden. `onClose` runs when the modal is dismissed,
3563
+ * letting the caller restore focus to the invoking element.
3564
+ *
3565
+ * @param {string} title - Modal header text.
3566
+ * @param {HTMLElement} contentEl - Caller-created body node.
3567
+ * @param {Function|null} onClose - Optional callback fired on dismiss.
3568
+ */
3569
+ function showModalNode(title, contentEl, onClose = null) {
3570
+ if (pageModalTitle) pageModalTitle.textContent = title;
3571
+ replaceModalBody(contentEl);
3572
+
3573
+ currentConfirmCallback = null;
3574
+ currentCloseCallback = onClose;
3575
+
3576
+ if (pageModalActions) pageModalActions.classList.add('hidden');
3577
+ if (pageModal) {
3578
+ pageModal.style.display = 'block';
3579
+ } else {
3580
+ console.error('Modal element not found.');
3581
+ }
3582
+ }
3583
+
3584
+ /**
3585
+ * Replace the modal body with a caller-built DOM node without re-showing it.
3586
+ *
3587
+ * Used to transition the same open modal between states (processing → preview →
3588
+ * success/error). Clears the previous content with textContent then appends the
3589
+ * node — never innerHTML.
3590
+ * @param {HTMLElement} contentEl
3591
+ */
3592
+ function replaceModalBody(contentEl) {
3593
+ if (!pageModalBody) return;
3594
+ pageModalBody.textContent = '';
3595
+ if (contentEl) pageModalBody.appendChild(contentEl);
3596
+ }
3597
+
3553
3598
  /**
3554
3599
  * Hides the modal dialog.
3555
3600
  */
@@ -5321,12 +5366,12 @@ function populateCiFollowupConfig(rawValue) {
5321
5366
  // ladder below are kept byte-identical to the backend
5322
5367
  // (api/library/review_ticket_policy.py) so a stored override round-trips exactly.
5323
5368
  const REVIEW_POLICY_BUCKETS = Object.freeze([
5324
- { name: 'Very Easy', slug: 'very-easy', range: '1' },
5325
- { name: 'Easy', slug: 'easy', range: '2' },
5326
- { name: 'Easy-Moderate', slug: 'easy-moderate', range: '3-4' },
5327
- { name: 'Moderate', slug: 'moderate', range: '5' },
5328
- { name: 'Moderate-Hard', slug: 'moderate-hard', range: '6' },
5329
- { name: 'Hard', slug: 'hard', range: '7-10' },
5369
+ { name: 'Very Easy', slug: 'very-easy', range: '1-2' },
5370
+ { name: 'Easy', slug: 'easy', range: '3-4' },
5371
+ { name: 'Easy-Moderate', slug: 'easy-moderate', range: '5' },
5372
+ { name: 'Moderate', slug: 'moderate', range: '6' },
5373
+ { name: 'Moderate-Hard', slug: 'moderate-hard', range: '7' },
5374
+ { name: 'Hard', slug: 'hard', range: '8-10' },
5330
5375
  ]);
5331
5376
 
5332
5377
  // The two per-bucket automations and their coarse per-round tiers. `clarify` must
@@ -5345,9 +5390,9 @@ const REVIEW_POLICY_DEFAULT_NEW_TIER = 'basic';
5345
5390
  const DEFAULT_REVIEW_POLICY_LADDER = Object.freeze({
5346
5391
  'Very Easy': { clarify: ['basic'], critique: [] },
5347
5392
  'Easy': { clarify: ['basic', 'basic'], critique: [] },
5348
- 'Easy-Moderate': { clarify: ['premium', 'basic'], critique: [] },
5349
- 'Moderate': { clarify: ['premium', 'premium'], critique: ['basic'] },
5350
- 'Moderate-Hard': { clarify: ['premium'], critique: ['premium'] },
5393
+ 'Easy-Moderate': { clarify: ['basic', 'basic'], critique: ['basic'] },
5394
+ 'Moderate': { clarify: ['premium', 'basic'], critique: ['premium'] },
5395
+ 'Moderate-Hard': { clarify: ['premium', 'basic'], critique: ['premium', 'basic'] },
5351
5396
  'Hard': { clarify: ['premium', 'premium'], critique: ['premium', 'premium'] },
5352
5397
  });
5353
5398