@bridge_gpt/mcp-server 0.2.46 → 0.2.48
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 +101 -85
- package/build/agent-capabilities/default-deps.js +2 -2
- package/build/agent-launchers/claude.js +10 -19
- package/build/agent-launchers/cursor.js +4 -12
- package/build/agent-launchers/prompt.js +117 -0
- package/build/commands.generated.js +16 -22
- package/build/conduct-epic/bridge-client.js +73 -0
- package/build/conduct-epic/cli.js +152 -6
- package/build/conductor/cli.js +6 -7
- package/build/conductor/doctor.js +13 -116
- package/build/conductor/tools.js +18 -349
- package/build/conductor-bin.js +6 -30
- package/build/docs.generated.js +1 -1
- package/build/executor/deps.js +1 -0
- package/build/executor/service-lifecycle.js +6 -6
- package/build/executor/service-unit.js +13 -16
- package/build/index.js +214 -755
- package/build/init.js +15 -17
- package/build/install-doctor.js +1 -1
- package/build/learn-tool-gating.js +283 -0
- package/build/mcp-profile.js +13 -3
- package/build/mcp-server-invocation.js +14 -0
- package/build/pipelines.generated.js +19 -139
- package/build/platform-escaping.js +72 -0
- package/build/readme.generated.js +1 -1
- package/build/review-tickets.js +1 -1
- package/build/run-unit-tests-launcher.js +0 -1
- package/build/sfcc/register.js +41 -31
- package/build/sfcc/registration-inventory.js +44 -20
- package/build/start-tickets-conductor.js +2 -2
- package/build/start-tickets.js +8 -38
- package/build/version.generated.js +2 -2
- package/docs/CONDUCTOR.md +10 -12
- package/docs/install/mcp-tool-integrations.md +9 -55
- package/package.json +1 -1
- package/pipelines/idea-to-ticket.json +2 -2
- package/pipelines/review-ticket.json +9 -8
- package/pipelines/check-ci-ticket.json +0 -36
- package/pipelines/pr-ticket.json +0 -24
package/README.md
CHANGED
|
@@ -351,7 +351,7 @@ later boot.
|
|
|
351
351
|
"mcpServers": {
|
|
352
352
|
"bridge": {
|
|
353
353
|
"command": "npx",
|
|
354
|
-
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.
|
|
354
|
+
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.47", "serve"],
|
|
355
355
|
"env": {
|
|
356
356
|
"BAPI_BASE_URL": "https://bridgegpt-api.com",
|
|
357
357
|
"BAPI_REPO_NAME": "your-repo",
|
|
@@ -373,7 +373,7 @@ later boot.
|
|
|
373
373
|
"bridge": {
|
|
374
374
|
"type": "stdio",
|
|
375
375
|
"command": "npx",
|
|
376
|
-
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.
|
|
376
|
+
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.47", "serve"],
|
|
377
377
|
"env": {
|
|
378
378
|
"BAPI_BASE_URL": "https://bridgegpt-api.com",
|
|
379
379
|
"BAPI_REPO_NAME": "your-repo",
|
|
@@ -395,7 +395,7 @@ later boot.
|
|
|
395
395
|
"bridge": {
|
|
396
396
|
"type": "stdio",
|
|
397
397
|
"command": "npx",
|
|
398
|
-
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.
|
|
398
|
+
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.47", "serve"],
|
|
399
399
|
"env": {
|
|
400
400
|
"BAPI_BASE_URL": "https://bridgegpt-api.com",
|
|
401
401
|
"BAPI_REPO_NAME": "your-repo",
|
|
@@ -420,7 +420,7 @@ you select `copilot-cli`; the shape below is what it produces.
|
|
|
420
420
|
"bridge": {
|
|
421
421
|
"type": "local",
|
|
422
422
|
"command": "npx",
|
|
423
|
-
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.
|
|
423
|
+
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.47", "serve"],
|
|
424
424
|
"tools": ["*"],
|
|
425
425
|
"env": {
|
|
426
426
|
"BAPI_BASE_URL": "https://bridgegpt-api.com",
|
|
@@ -444,7 +444,7 @@ Windsurf only supports global MCP configuration.
|
|
|
444
444
|
"mcpServers": {
|
|
445
445
|
"bridge": {
|
|
446
446
|
"command": "npx",
|
|
447
|
-
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.
|
|
447
|
+
"args": ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.47", "serve"],
|
|
448
448
|
"env": {
|
|
449
449
|
"BAPI_BASE_URL": "https://bridgegpt-api.com",
|
|
450
450
|
"BAPI_REPO_NAME": "your-repo",
|
|
@@ -463,7 +463,7 @@ Windsurf only supports global MCP configuration.
|
|
|
463
463
|
```toml
|
|
464
464
|
[mcp_servers.bridge]
|
|
465
465
|
command = "npx"
|
|
466
|
-
args = ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.
|
|
466
|
+
args = ["-y", "--prefer-offline", "@bridge_gpt/mcp-server@0.2.47", "serve"]
|
|
467
467
|
|
|
468
468
|
[mcp_servers.bridge.env]
|
|
469
469
|
BAPI_BASE_URL = "https://bridgegpt-api.com"
|
|
@@ -617,54 +617,24 @@ Good to know, but not needed every day.
|
|
|
617
617
|
- **How to use it:** `/plan-ticket BAPI-123`
|
|
618
618
|
- **Flags:** `--provider <name>` choose the model provider · `--second-opinion <provider>` cross-check the plan with a second provider.
|
|
619
619
|
|
|
620
|
-
**3.
|
|
621
|
-
- **What it does:** Generates clarifying questions for a ticket, or debugging guidance when the ticket is a bug.
|
|
622
|
-
- **When it's useful:** (Refinement) When a ticket feels under-specified and you want the open questions made explicit.
|
|
623
|
-
- **How to use it:** `/clarify-ticket BAPI-123`
|
|
624
|
-
- **Flags:** `--provider <name>` choose the model provider · `--second-opinion <provider>` cross-check with a second provider.
|
|
625
|
-
|
|
626
|
-
**4. Critique Ticket**
|
|
627
|
-
- **What it does:** Critiques a ticket against your project's standards and lists the deviations and improvements it found.
|
|
628
|
-
- **When it's useful:** (Refinement) When you want a quality gate on a ticket before anyone works it.
|
|
629
|
-
- **How to use it:** `/critique-ticket BAPI-123`
|
|
630
|
-
- **Flags:** `--provider <name>` choose the model provider · `--second-opinion <provider>` cross-check with a second provider.
|
|
631
|
-
|
|
632
|
-
**5. Create Doc**
|
|
620
|
+
**3. Create Doc**
|
|
633
621
|
- **What it does:** Generates a design document for a ticket — a technical design document, a functional spec, or a product requirements document.
|
|
634
622
|
- **When it's useful:** (Architecture | Refinement) When a ticket needs a fuller design write-up before planning or implementation, in the shape that fits your audience.
|
|
635
623
|
- **How to use it:** `/create-doc BAPI-123 --doc-type tdd` (or `fsd` / `prd`)
|
|
636
624
|
- **Flags:** `--doc-type tdd|fsd|prd` which document to generate (required) · `--provider <name>` choose the model provider · `--second-opinion <provider>` cross-check with a second provider.
|
|
637
625
|
|
|
638
|
-
**
|
|
626
|
+
**4. Second Opinion**
|
|
639
627
|
- **What it does:** Gets an immediate critique of any text from a different model family, without saving an artifact.
|
|
640
628
|
- **When it's useful:** (Architecture | Refinement | Implementation) Any time you want a quick sanity check on a plan, draft, or decision from a fresh perspective.
|
|
641
629
|
- **How to use it:** Ask your agent — "Get a second opinion from Gemini on whether the BAPI-123 plan's migration step is safe to run against production."
|
|
642
630
|
- **Flags:** Pick the provider (anthropic / openai / gemini) and the tier (cheap / basic / premium).
|
|
643
631
|
|
|
644
|
-
**
|
|
632
|
+
**5. Generate Image**
|
|
645
633
|
- **What it does:** Generates an image from a text prompt using a provider image model, spending provider credits on every call.
|
|
646
634
|
- **When it's useful:** (Architecture | Refinement) When you want a quick visual — a UI mockup, diagram, or illustration — to anchor a design discussion or attach to a ticket.
|
|
647
635
|
- **How to use it:** Ask your agent — "Generate an image of a dashboard showing SOC2 evidence freshness as a traffic-light grid."
|
|
648
636
|
- **Flags:** `provider` openai (`gpt-image-2`) / gemini (Imagen, which adds an invisible SynthID watermark) · `quality` low (default, cheapest) / medium / high · `size` 1024x1024 / 1024x1536 / 1536x1024. The image is saved to `BAPI_DOCS_DIR/images/` and also returned inline.
|
|
649
637
|
|
|
650
|
-
**8. Request PRD**
|
|
651
|
-
- **What it does:** Generates a product requirements document for a ticket covering the problem, the goals, and the success metrics.
|
|
652
|
-
- **When it's useful:** (Architecture | Refinement) When a piece of work needs its problem, goals, and success metrics written down before anyone designs a solution.
|
|
653
|
-
- **How to use it:** `/create-doc BAPI-123 --doc-type prd`
|
|
654
|
-
- **Flags:** `--provider <name>` choose the model provider · `--second-opinion <provider>` cross-check with a second provider.
|
|
655
|
-
|
|
656
|
-
**9. Full Automation**
|
|
657
|
-
- **What it does:** Drives the whole chain from a raw idea through tickets and reviews to implementation sessions.
|
|
658
|
-
- **When it's useful:** (Automation) When you want to go from a raw idea to in-progress implementation with minimal hands-on steps.
|
|
659
|
-
- **How to use it:** `/full-automation <idea>` (command only — it creates tickets, spawns worktrees, and carries scheduling flags free text cannot).
|
|
660
|
-
- **Flags:** `--require-approval` re-enable the approval gates; the chain runs end to end by default · `--max-children <n>` cap how many child tickets an epic decomposes into.
|
|
661
|
-
|
|
662
|
-
**10. Update Ticket Description**
|
|
663
|
-
- **What it does:** Rewrites a ticket's description with AI, using the ticket's own content and its reference material. A rewrite that changes more than 60% of the description is held for review instead of applied.
|
|
664
|
-
- **When it's useful:** (Refinement) When a ticket has accumulated comments, attachments, or links and its description no longer reflects them.
|
|
665
|
-
- **How to use it:** Ask your agent — "Update the description for BAPI-123."
|
|
666
|
-
- **Flags:** None. Poll the ticket's state for the outcome; if the update was held for review, read the proposal instead of applying it blind.
|
|
667
|
-
|
|
668
638
|
### Now and then
|
|
669
639
|
|
|
670
640
|
Useful once in a while.
|
|
@@ -682,10 +652,10 @@ Useful once in a while.
|
|
|
682
652
|
- **Flags:** None.
|
|
683
653
|
|
|
684
654
|
**3. Get Ticket**
|
|
685
|
-
- **What it does:** Retrieves the full details of a ticket, including its summary, status, and description.
|
|
655
|
+
- **What it does:** Retrieves the full details of a ticket, including its summary, status, and description, and optionally the model tier its difficulty routes to.
|
|
686
656
|
- **When it's useful:** (Refinement | Implementation) Any time you want the agent to read a ticket before acting on it.
|
|
687
657
|
- **How to use it:** Ask your agent — "Pull up BAPI-123 and show me its description, status, and acceptance criteria."
|
|
688
|
-
- **Flags:**
|
|
658
|
+
- **Flags:** `include_model_tier` adds the model tier the ticket's difficulty routes to; leave it off for an ordinary read.
|
|
689
659
|
|
|
690
660
|
**4. Search Tickets**
|
|
691
661
|
- **What it does:** Searches across the tickets in your project.
|
|
@@ -711,13 +681,7 @@ Useful once in a while.
|
|
|
711
681
|
- **How to use it:** Ask your agent — "Download the design mockups attached to BAPI-123 into my docs folder," or "Attach build-log.txt to BAPI-123."
|
|
712
682
|
- **Flags:** Choose the direction (download from the ticket, or upload to it) and, for a download, where the files should land.
|
|
713
683
|
|
|
714
|
-
**8. Estimate
|
|
715
|
-
- **What it does:** Estimates the development effort for one ticket. Use Estimate Epic instead for a whole epic or a named group of tickets.
|
|
716
|
-
- **When it's useful:** (Refinement) When you need a size for a single ticket before committing to it.
|
|
717
|
-
- **How to use it:** Ask your agent — "Estimate BAPI-123."
|
|
718
|
-
- **Flags:** Ask for a fresh estimate to regenerate rather than reuse a stored one.
|
|
719
|
-
|
|
720
|
-
**9. Estimate Epic**
|
|
684
|
+
**8. Estimate Epic**
|
|
721
685
|
- **What it does:** Estimates an epic, or an explicit group of tickets you name.
|
|
722
686
|
- **When it's useful:** (Architecture | Refinement) When you need a sizing pass across an epic, or across a set of tickets you name explicitly.
|
|
723
687
|
- **How to use it:** `/estimate-epic BAPI-123`
|
|
@@ -799,14 +763,10 @@ step and no server call; the full rationale and the closed exception list ship a
|
|
|
799
763
|
|
|
800
764
|
### Operational commands
|
|
801
765
|
|
|
802
|
-
|
|
766
|
+
Repository and ticket housekeeping commands, beyond the tiers above. Implementation, commit/push, PR creation, and CI monitoring are steps of the `implement-ticket` recipe rather than standalone commands:
|
|
803
767
|
|
|
804
768
|
| Command | What it does |
|
|
805
769
|
|---|---|
|
|
806
|
-
| `/code-ticket PROJ-123` | Download the implementation plan and questions, then execute the plan inline |
|
|
807
|
-
| `/commit-ticket PROJ-123` | Stage, commit, and push changes; transition Jira status; post a smoke-test comment |
|
|
808
|
-
| `/create-pr PROJ-123` | Resolve the base branch and open a pull request for the ticket's branch (run after `/commit-ticket`) |
|
|
809
|
-
| `/check-ci PROJ-123` | Monitor CI checks for the current branch, triage failures, apply fixes, and report results |
|
|
810
770
|
| `/parse-repository` | Queue a background job to index the repository for Bridge AI agents |
|
|
811
771
|
| `/check-parse-status` | Check whether a background repository parse job is still running |
|
|
812
772
|
| `/scan-tickets` | Sync recently-updated Jira tickets and backfill workflow timestamps |
|
|
@@ -817,15 +777,15 @@ Workflow commands you'll reach for during implementation and CI, beyond the tier
|
|
|
817
777
|
|
|
818
778
|
Behind-the-scenes capabilities an agent gains from the MCP tools — mostly invoked automatically by the commands above, rarely requested by name:
|
|
819
779
|
|
|
820
|
-
- **Ship a PR end-to-end:** commit & push, open a pull request, transition the Jira status, and discover/poll CI checks
|
|
821
|
-
- **
|
|
822
|
-
- **Index the codebase** so Bridge's agents can reason about it: queue/parse the repo
|
|
780
|
+
- **Ship a PR end-to-end:** commit & push, open a pull request, transition the Jira status, and discover/poll CI checks — the commit-and-push, PR-creation, and CI-monitoring steps of the `implement-ticket` recipe, driven by its bundled instruction assets.
|
|
781
|
+
- **Design documents** for a ticket (TDD / FSD / PRD, generated and retrieved through `create_doc` / `get_doc`).
|
|
782
|
+
- **Index the codebase** so Bridge's agents can reason about it: queue/parse the repo and check parse status (`parse_repository`), regenerate the directory map.
|
|
823
783
|
- **Read & tune project config/standards:** list/read/update config fields, fetch project standards, and the per-topic `learn-*` commands that populate them.
|
|
824
784
|
- **Ticket lifecycle bookkeeping:** track tickets and backfill workflow-state timestamps (`scan-tickets`), search across tickets, read comments, list attachments.
|
|
825
|
-
- **Pipeline machinery:**
|
|
785
|
+
- **Pipeline machinery:** fetch a resolved pipeline recipe (the step list behind the orchestration commands) and execute its steps agent-side.
|
|
826
786
|
- **Decision page** generation for capturing human review decisions as structured data.
|
|
827
|
-
- **Connectivity
|
|
828
|
-
- **Retrieve any generated artifact** (`get_*` for plans, critiques, questions, councils, research,
|
|
787
|
+
- **Connectivity check:** ping Bridge to confirm the API key and repository resolve.
|
|
788
|
+
- **Retrieve any generated artifact** (`get_*` for plans, critiques, questions, councils, research, design docs) without regenerating it.
|
|
829
789
|
- **Tiered-section execution telemetry** recording (internal measurement).
|
|
830
790
|
|
|
831
791
|
## Salesforce B2C Commerce (SFCC) Tools
|
|
@@ -841,7 +801,7 @@ For a step-by-step OCAPI client setup guide (including the Business Manager perm
|
|
|
841
801
|
<details>
|
|
842
802
|
<summary><strong>Setup</strong></summary>
|
|
843
803
|
|
|
844
|
-
|
|
804
|
+
Every SFCC tool must be enabled with a profile (step 3) — including the two diagnostics, `sfcc_setup_status` and `check_permissions`, which belong to the `sfcc` profile. A session on the default `core` profile registers no SFCC tool at all. Changing `BRIDGE_MCP_PROFILE` requires an MCP client restart.
|
|
845
805
|
|
|
846
806
|
**Prerequisites:** a running SFCC **sandbox** and its hostname, plus an Account Manager API client (`client-id` + `client-secret`).
|
|
847
807
|
|
|
@@ -877,7 +837,7 @@ Because tier 2 outranks tier 3, a stale `SFCC_HOSTNAME` left in the environment
|
|
|
877
837
|
|
|
878
838
|
`sfcc` gives the eight read tools plus `sfcc_log_query`. For the nine destructive write tools as well, use `"sfcc,sfcc-write"`; `full` expands to every group and is therefore write-capable. Without any of these, only the diagnostic tools are registered.
|
|
879
839
|
|
|
880
|
-
**4. Verify and grant OCAPI access.**
|
|
840
|
+
**4. Verify and grant OCAPI access.** With `sfcc` selected in step 3 (both diagnostics live in that profile), ask your agent to run `sfcc_setup_status` (expect all checks ✓), then `check_permissions`. If it reports HTTP 401/403, it prints the exact OCAPI Settings JSON to paste in Business Manager (**Administration → Site Development → Open Commerce API Settings → Data API** tab); save it there and re-run. Restart the MCP client after any credential or env change — a running session does not pick them up.
|
|
881
841
|
|
|
882
842
|
Read what it prints before pasting it. The output is **two labelled blocks**, and they are not equivalent:
|
|
883
843
|
|
|
@@ -926,11 +886,24 @@ domain with no suffix that separates them.
|
|
|
926
886
|
|
|
927
887
|
| `BRIDGE_MCP_PROFILE` | SFCC tools registered |
|
|
928
888
|
|---|---|
|
|
929
|
-
| unset / `core` |
|
|
930
|
-
| `
|
|
931
|
-
| `sfcc
|
|
889
|
+
| unset / `core` | none |
|
|
890
|
+
| `estimation` | none — this group adds only `estimate_epic`, which is not an SFCC tool |
|
|
891
|
+
| `sfcc` | `sfcc_setup_status`, `check_permissions`, the 8 OCAPI read tools, and `sfcc_log_query` |
|
|
892
|
+
| `sfcc-write` | the 9 destructive write tools **only** — it does not imply `sfcc`, so neither diagnostic and no read tool is registered |
|
|
932
893
|
| `sfcc,sfcc-write` | all 20 |
|
|
933
|
-
| `full` | all 20 — `full` includes `sfcc-write` and is therefore write-capable |
|
|
894
|
+
| `full` | all 20 — `full` includes `sfcc-write` and is therefore write-capable, and it also includes `estimation` |
|
|
895
|
+
|
|
896
|
+
**`check_permissions` needs `sfcc`, even when you are diagnosing writes.** It is
|
|
897
|
+
the tool that prints the mutation-grant OCAPI Settings JSON on a 401/403, but it
|
|
898
|
+
is registered by the `sfcc` group, not `sfcc-write`. An `sfcc-write`-only session
|
|
899
|
+
therefore cannot run it. Use `BRIDGE_MCP_PROFILE=sfcc,sfcc-write` whenever you
|
|
900
|
+
need to diagnose write grants.
|
|
901
|
+
|
|
902
|
+
**Diagnostics moved into `sfcc`.** `sfcc_setup_status` and `check_permissions`
|
|
903
|
+
used to register unconditionally, on every session including non-SFCC ones. They
|
|
904
|
+
no longer do. The accepted consequence is that a session without `sfcc` can no
|
|
905
|
+
longer ask the server why SFCC tools are missing — run `npx -y @bridge_gpt/mcp-server doctor`
|
|
906
|
+
for that instead, which reports the resolved profile without needing any tool.
|
|
934
907
|
|
|
935
908
|
**Migration.** Enabling `sfcc` used to register the nine write tools as well. It
|
|
936
909
|
no longer does. If you were relying on SFCC writes through
|
|
@@ -939,13 +912,13 @@ Users of `BRIDGE_MCP_PROFILE=full` keep write access and need no change.
|
|
|
939
912
|
|
|
940
913
|
### Tools
|
|
941
914
|
|
|
942
|
-
Twenty tools in total
|
|
915
|
+
Twenty tools in total, none of them registered unconditionally: the `sfcc` profile's **read-only** surface (the two diagnostics, eight OCAPI reads, and `sfcc_log_query`), plus the nine destructive writes that only the separate `sfcc-write` profile registers — see [Read and write profiles](#read-and-write-profiles). Every one of them is bounded to a developer sandbox by the same invocation-time check. All twenty are enumerated below.
|
|
943
916
|
|
|
944
917
|
An oversized response is saved in full to `BAPI_DOCS_DIR/sfcc/` and replaced by a parseable JSON descriptor — `truncated: true`, the `saved_path` it was written to, and the `page` metadata (`returned`, `total` when OCAPI supplied one, `has_more`) — so the collection metadata survives even though the data itself is on disk. If that save fails, the complete payload is returned inline instead, still as parseable JSON.
|
|
945
918
|
|
|
946
919
|
Attribute-definition reads and writes can return an attribute's `default_value` at `projection: "full"`, and Bridge withholds it — every key is preserved except that one, whose value becomes `[REDACTED_BY_BRIDGE]` — from the inline response, the saved file, and a successful write echo alike. Attribute defaults are intentionally unavailable through this MCP surface; Business Manager is the supported path to read one.
|
|
947
920
|
|
|
948
|
-
**Diagnostics** (
|
|
921
|
+
**Diagnostics** (registered by the `sfcc` profile)
|
|
949
922
|
- `sfcc_setup_status` — report on every prerequisite: Bridge API key, repo name, `version` config, `dw.json` presence/uniqueness, AM (OCAPI) token acquisition, and the independent **SFCC Log Query (WebDAV)** capability that gates `sfcc_log_query`.
|
|
950
923
|
- `check_permissions` — probe OCAPI access via `GET /system_object_definitions`; on 401/403, print the exact OCAPI Settings JSON to paste in Business Manager (read/search grants for the `sfcc` tools, mutation grants for the `sfcc-write` tools). An explicit `instance` hostname is still subject to the sandbox check below.
|
|
951
924
|
|
|
@@ -1008,7 +981,7 @@ npx -y @bridge_gpt/mcp-server start-tickets [flags] KEY [KEY ...]
|
|
|
1008
981
|
| `--base-branch <BRANCH>` | `main` | Cut new worktrees from `<BRANCH>` and refresh `origin/<BRANCH>` instead of `main` |
|
|
1009
982
|
| `--no-refresh-main` | off (the configured base branch is refreshed) | Skip refresh of the configured base branch (default `main`). Historical flag name preserved for backward compatibility — despite the name, it now skips refresh of whatever `--base-branch` resolves to. |
|
|
1010
983
|
| `--max-parallel N` | `3` | Max worktrees created concurrently |
|
|
1011
|
-
| `--conductor` | off | Opt into the Conductor system (per-worker `BAPI_CONDUCTOR_*` env + Claude hook injection,
|
|
984
|
+
| `--conductor` | off | Opt into the Conductor system (per-worker `BAPI_CONDUCTOR_*` env + Claude hook injection, lifecycle ledger events, and a supervisor peer tab). **Default off** — a plain run spawns `cd <worktree> && <agent> '/implement-ticket <KEY>'`. |
|
|
1012
985
|
| `-h`, `--help` | — | Show usage |
|
|
1013
986
|
|
|
1014
987
|
Each `KEY` must match `[A-Z]+-[0-9]+` (e.g., `BAPI-248`). The CLI creates/switches each worktree up front (throttled by `--max-parallel`), then opens one tab/session per successful worktree running the selected agent's `'/implement-ticket <KEY>'` — `claude '/implement-ticket <KEY>'` by default, or `cursor-agent '/implement-ticket <KEY>'` with `--agent cursor-agent`. The `/implement-ticket <KEY>` prompt is unchanged for both agents. To launch Cursor Agent instead of Claude Code:
|
|
@@ -1234,12 +1207,58 @@ If a custom pipeline has the same key as a built-in pipeline, the custom version
|
|
|
1234
1207
|
| `BAPI_MCP_TOOL_SURFACE_POLL_ENABLED` | No | _(disabled)_ | Opt IN to the recurring tool-surface **poll**. Default-**off**: a session gates once via the startup probe and never re-probes. Set to `true`/`1`/`yes`/`on`/`enabled` to restore the jittered 12–18 s heartbeat that pushes `notifications/tools/list_changed` on mid-session capability changes. No effect when gating itself is disabled |
|
|
1235
1208
|
| `BAPI_MCP_UPDATE_CHECK_ENABLED` | No | _(enabled)_ | MCP-local kill switch for the cached update check run at startup. Default-on; set to `false`/`0`/`no`/`off`/`disabled` to skip it entirely — no npm registry request, no update-cache read/write, no stderr advice, and no `tools/list` advisory decoration. Any other value is treated as enabled. Useful behind a firewall/registry-restricted network, and used by the payload-measurement harness so a stale local cache can never perturb a capture |
|
|
1236
1209
|
| `CURSOR_API_KEY` | No | _(none)_ | API key used to authenticate `cursor-agent` when launching `start-tickets`/scheduled runs with `--agent cursor-agent`. Not needed for the default Claude Code agent |
|
|
1237
|
-
| `BRIDGE_MCP_PROFILE` | No | `core` | Startup-time tool registration profile — a **comma-separated** list of groups controlling which tool groups are registered when the server starts. `core` is always implicitly included. Valid groups: `core` (default — normal coding tools only), `conductor` (+ 8 conductor/event/supervisor tools), `pipeline-authoring` (+ 5 pipeline run/admin tools — `get_pipeline_recipe` is NOT gated; it stays in `core` because the recipe-driven slash commands depend on it), `sfcc` (+ the 8 heavy SFCC read tools and `
|
|
1210
|
+
| `BRIDGE_MCP_PROFILE` | No | `core` | Startup-time tool registration profile — a **comma-separated** list of groups controlling which tool groups are registered when the server starts. `core` is always implicitly included. Valid groups: `core` (default — normal coding tools only), `conductor` (+ 8 conductor/event/supervisor tools), `pipeline-authoring` (+ 5 pipeline run/admin tools — `get_pipeline_recipe` is NOT gated; it stays in `core` because the recipe-driven slash commands depend on it), `estimation` (+ `estimate_epic`, which is **hidden by default** — `/estimate-epic` needs this group), `sfcc` (+ the 8 heavy SFCC read tools, `sfcc_log_query`, and the `sfcc_setup_status`/`check_permissions` diagnostics — read-only, see [Salesforce B2C Commerce (SFCC) Tools](#salesforce-b2c-commerce-sfcc-tools)), `sfcc-write` (+ the 9 destructive SFCC write tools — independent of `sfcc`, which does not enable them; see [Read and write profiles](#read-and-write-profiles)), and `full` (shortcut that expands to every group, **including `estimation` and `sfcc-write`**). Example: `sfcc,conductor`; use `sfcc,sfcc-write` for reads plus writes. Unknown, blank, or malformed tokens are dropped (falling back to `core`). Dynamic mid-session switching via `tools/list_changed` is unsupported — groups are resolved once at process startup, so **changing this variable requires restarting the MCP server**. That is separate from the learn/onboarding tools, which are gated per session and can appear mid-session without a restart (see [Learn/onboarding tool availability](#learnonboarding-tool-availability)). Conductor/epic sessions launched via `start-tickets --conductor` **merge** `conductor` into the parent process's already-resolved groups at the spawn boundary rather than replacing them — a project running on `sfcc` spawns workers on `core,sfcc,conductor`. A normal `start-tickets` run stays on `core`. |
|
|
1238
1211
|
|
|
1239
1212
|
Environment values are **trimmed**, and only a non-empty result wins. A
|
|
1240
1213
|
whitespace-only `BAPI_API_KEY` therefore does not override anything: it falls
|
|
1241
1214
|
through to credential-store resolution exactly as an unset variable would.
|
|
1242
1215
|
|
|
1216
|
+
## Learn/onboarding tool availability
|
|
1217
|
+
|
|
1218
|
+
Three tools are **gated per session** rather than by profile:
|
|
1219
|
+
|
|
1220
|
+
- `apply_install_manifest`
|
|
1221
|
+
- `invite_member`
|
|
1222
|
+
- `regenerate_directory_map`
|
|
1223
|
+
|
|
1224
|
+
They are registered in the `core` profile like any other core tool, but the
|
|
1225
|
+
server starts them **disabled**, so a client that honors mid-session tool-list
|
|
1226
|
+
changes does not see them in its first `tools/list`. They are revealed — all
|
|
1227
|
+
three together, once per session — by either of two successful requests:
|
|
1228
|
+
|
|
1229
|
+
1. a successful **`get_install_manifest`** call, or
|
|
1230
|
+
2. a **`get_pipeline_recipe`** request for the **`learn-repository`** pipeline.
|
|
1231
|
+
|
|
1232
|
+
On reveal the server emits `notifications/tools/list_changed`, so a client that
|
|
1233
|
+
honors it picks the three tools up **without a restart**.
|
|
1234
|
+
|
|
1235
|
+
`get_install_manifest` and `persist_routing_credential` stay ungated in `core` at
|
|
1236
|
+
all times, so the install and `start-tickets` flows always have their entry
|
|
1237
|
+
points. Only the first of those two is a trigger — `persist_routing_credential`
|
|
1238
|
+
never reveals anything; it is listed here because `/start-tickets` calls it and
|
|
1239
|
+
it therefore must never be gated.
|
|
1240
|
+
|
|
1241
|
+
**Unrecognized clients get all three at startup.** The hide-then-reveal behavior
|
|
1242
|
+
applies only to clients verified to honor mid-session `tools/list_changed`. Any
|
|
1243
|
+
other client — including one that sends no name, a blank name, or a name the
|
|
1244
|
+
server does not recognize — is enabled at session initialization instead and
|
|
1245
|
+
therefore sees all three tools in its **first** `tools/list`. This is deliberate:
|
|
1246
|
+
the failure mode of guessing wrong should be an extra tool, never a permanently
|
|
1247
|
+
missing one.
|
|
1248
|
+
|
|
1249
|
+
**A failed request changes nothing.** Only a genuinely successful manifest
|
|
1250
|
+
reveals the tools — the response must parse as JSON and carry a nonblank
|
|
1251
|
+
`snapshot_token`. An error response, a non-JSON body, or a manifest without a
|
|
1252
|
+
token leaves the three tools hidden, and the response you receive is unchanged by
|
|
1253
|
+
the check either way. Likewise, only the exact `learn-repository` pipeline is a
|
|
1254
|
+
trigger; other recipes and failed lookups reveal nothing.
|
|
1255
|
+
|
|
1256
|
+
**Capability filtering still applies independently.** Revealing these tools does
|
|
1257
|
+
not override the backend capability gate described below. The effective surface
|
|
1258
|
+
is the *intersection* of the two, so a tool can be enabled for the session and
|
|
1259
|
+
still be absent from `tools/list` because this repository lacks the integration
|
|
1260
|
+
it needs. That is expected behavior, not a bug — check the integration first.
|
|
1261
|
+
|
|
1243
1262
|
## Dynamic tool-surface gating (capability availability)
|
|
1244
1263
|
|
|
1245
1264
|
The **effective advertised tool surface** is the intersection of three things:
|
|
@@ -1405,18 +1424,18 @@ The full surface, for when you need the complete enumeration. Day-to-day, use [U
|
|
|
1405
1424
|
|
|
1406
1425
|
### MCP tools
|
|
1407
1426
|
|
|
1408
|
-
The authoritative tool catalog covers **
|
|
1427
|
+
The authoritative tool catalog covers **69 tools** (enumerated below). What's actually registered in a session depends on `BRIDGE_MCP_PROFILE`: the default `core` profile loads a trimmed subset, and the conductor/pipeline-authoring/SFCC tools are added only under their respective profiles (see [Environment Variables](#environment-variables)). Async AI tools follow a request/get pattern: call the `request_*` tool to kick off generation, then the matching `get_*` tool to retrieve the result (or pass `wait_for_result: true` to poll automatically).
|
|
1409
1428
|
|
|
1410
|
-
- **Connectivity & identity** — `ping`, `
|
|
1429
|
+
- **Connectivity & identity** — `ping` (its JSON also carries `docs_dir`, `role`, and `customer_type`)
|
|
1411
1430
|
- **Team & access** — `invite_member` (admin-only; mints a scoped access key for a teammate on an already-configured project — the plaintext key is shown exactly once)
|
|
1412
1431
|
- **Jira tickets** — `get_tickets`, `get_ticket`, `create_ticket`, `update_ticket_description`, `add_comment`, `get_comments`
|
|
1413
1432
|
- **Attachments** — `attachment` (operations: `upload`, `download`, `list`)
|
|
1414
|
-
- **AI generation (request/get)** — `request_plan_generation`/`get_plan`, `
|
|
1433
|
+
- **AI generation (request/get)** — `request_plan_generation`/`get_plan`, `create_doc`/`get_doc` (design docs by `doc_type`: tdd/architecture/fsd/prd, where `architecture` is an alias of `tdd`), `request_ticket_review` (writes both `get_clarifying_questions` and `get_ticket_critique`), `request_reimplement_context`/`get_reimplement_context`, `request_council`/`get_council`, `request_deep_research`/`get_deep_research`
|
|
1415
1434
|
- **Other AI** — `second_opinion`, `generate_image`, `generate_decision_page`, `visual_diff` (deterministic pixel diff of a rendered URL vs a design comp)
|
|
1416
1435
|
- **Ticket lifecycle** — `track_ticket`, `update_ticket_state`, `get_ticket_state`, `get_ticket_state_tree` (live repo-wide lifecycle + dependency tree; read-only, no mutation parameter)
|
|
1417
|
-
- **Jira status** — `
|
|
1418
|
-
- **Repository & CI** — `parse_repository
|
|
1419
|
-
- **Pipelines & automation** — `
|
|
1436
|
+
- **Jira status** — `update_jira_status` (pass `status: "auto"` to resolve the configured post-PR status server-side)
|
|
1437
|
+
- **Repository & CI** — `parse_repository` (`action`: `start`, `status`), `regenerate_directory_map`, `create_pull_request`, `merge_pull_request`, `resolve_ci_checks`, `poll_ci_checks`
|
|
1438
|
+
- **Pipelines & automation** — `get_pipeline_recipe` (returns a fully resolved recipe the agent executes step-by-step)
|
|
1420
1439
|
- **Config** — `get_project_standards`, `config_field` (operations: `get`, `update`, `list`)
|
|
1421
1440
|
|
|
1422
1441
|
### Bundled pipelines
|
|
@@ -1429,17 +1448,14 @@ Pipelines are declarative, multi-step workflows your AI agent executes step-by-s
|
|
|
1429
1448
|
| `review-ticket` | Full ticket quality review: clarifying questions + critique plus an automatic second-opinion pass, then evaluation and decision capture. The backend owns round orchestration; pass `--rounds=1` for a single-pass review or `--rounds=2` to force the full second-opinion review, or omit `--rounds` to let the backend decide adaptively. | `/review-ticket PROJ-123` |
|
|
1430
1449
|
| `idea-to-ticket` | Turn an idea into a Jira Task/Spike (or Epic + children) with research, dedup, and critique | `/idea-to-ticket "<idea>"` |
|
|
1431
1450
|
| `plan-epic` | Decompose an epic into sub-tasks with a structured exploration doc for each | `/plan-epic "<epic>"` |
|
|
1432
|
-
| `full-automation` |
|
|
1433
|
-
| `pr-ticket` | Commit changes and open a pull request | `/create-pr PROJ-123` |
|
|
1434
|
-
| `check-ci-ticket` | Commit, open a PR, then monitor CI checks until they pass or fail | `/check-ci PROJ-123` |
|
|
1451
|
+
| `full-automation` | Client-side wrapper: runs the `idea-to-ticket` recipe, then hands the created keys to `/review-and-start --auto` | `/full-automation "<idea>"` |
|
|
1435
1452
|
| `learn-repository` | Analyze codebase architecture, testing, review, and documentation standards, then upload to Bridge | `/learn-repository` |
|
|
1436
1453
|
|
|
1437
1454
|
### Pipeline response envelope
|
|
1438
1455
|
|
|
1439
|
-
`
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
Paused runs auto-expire after an idle TTL (default 24 hours; override with `ttl_seconds`). The TTL is reset on every state transition. List output is metadata-only — it never includes resolved recipes, params, instructions, results, or agent outputs.
|
|
1456
|
+
`get_pipeline_recipe` returns a fully resolved recipe: an ordered `steps` array
|
|
1457
|
+
plus `total_steps`, `auto_approve`, and `execution_mode`. Each step is either an
|
|
1458
|
+
`mcp_call` (a tool name with resolved params) or an `agent_task` (instruction
|
|
1459
|
+
text). `execution_mode` is `inline` — the calling agent executes every step
|
|
1460
|
+
itself and keeps its own durable record through `record_phase_result` /
|
|
1461
|
+
`record_checkpoint`. There is no server-side orchestrator and no run to resume.
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* timeout guard in `probe-context.ts` can actually kill a hung agent (the
|
|
6
6
|
* version-sensitive `cursor-agent -p` non-exit bug) instead of leaking it.
|
|
7
7
|
*
|
|
8
|
-
* Mirrors
|
|
9
|
-
*
|
|
8
|
+
* Mirrors the executor's own default deps, adding the temp-dir filesystem ops
|
|
9
|
+
* and a unique-suffix source the probes need.
|
|
10
10
|
*/
|
|
11
11
|
import { execFile } from "node:child_process";
|
|
12
12
|
import { mkdtemp, rm, writeFile, mkdir } from "node:fs/promises";
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The `claude` agent launcher (BAPI-327, generalized in BAPI-351).
|
|
3
3
|
*
|
|
4
|
-
* Resolves the `claude` binary against the *
|
|
5
|
-
* ambient process default) and builds the
|
|
4
|
+
* Resolves the `claude` binary against the *explicitly supplied PATH* (not the
|
|
5
|
+
* ambient process default) and builds the launched-run invocation by delegating
|
|
6
6
|
* to the shared `renderScheduledPrompt` renderer (no hard-coded `/full-automation`
|
|
7
7
|
* prompt). It emits `{ exe, args: ["-p", prompt] }`. Claude Code has no
|
|
8
|
-
* working-directory flag, so the cwd is always set by the
|
|
8
|
+
* working-directory flag, so the cwd is always set by the launching unit — this
|
|
9
9
|
* adapter must never add a working-directory argument to the invocation.
|
|
10
10
|
*/
|
|
11
|
-
import { pathApiForPlatform } from "../
|
|
12
|
-
import { posixShellQuote, windowsCmdQuote } from "../
|
|
13
|
-
import { renderScheduledPrompt } from "
|
|
14
|
-
import { quotePromptToken } from "../scheduled-prompt.js";
|
|
11
|
+
import { pathApiForPlatform } from "../worktree-core.js";
|
|
12
|
+
import { posixShellQuote, windowsCmdQuote } from "../platform-escaping.js";
|
|
13
|
+
import { renderScheduledPrompt, quotePromptToken } from "./prompt.js";
|
|
15
14
|
/**
|
|
16
15
|
* Resolve a bare command to an absolute path using the platform PATH-probe,
|
|
17
|
-
* forcing the
|
|
18
|
-
*
|
|
16
|
+
* forcing the supplied PATH so the launch resolves the same binary the caller
|
|
17
|
+
* captured. On Windows both `PATH` and `Path` are overridden (Node and
|
|
19
18
|
* `where.exe` disagree on casing). Returns the first non-empty *absolute* path
|
|
20
19
|
* from stdout, or `null` when the probe fails or yields only relative paths.
|
|
21
20
|
*/
|
|
@@ -57,15 +56,7 @@ export { quotePromptToken };
|
|
|
57
56
|
* shared renderer. Exposed for focused unit testing of the launcher wiring.
|
|
58
57
|
*/
|
|
59
58
|
export function buildClaudePrompt(input) {
|
|
60
|
-
return renderScheduledPrompt(
|
|
61
|
-
scheduleId: input.scheduleId,
|
|
62
|
-
scheduledAt: input.runAtIso,
|
|
63
|
-
autoApprove: input.autoApprove,
|
|
64
|
-
commandName: input.commandName,
|
|
65
|
-
args: input.args,
|
|
66
|
-
commandBody: input.commandBody,
|
|
67
|
-
schema: input.schema,
|
|
68
|
-
});
|
|
59
|
+
return renderScheduledPrompt(input);
|
|
69
60
|
}
|
|
70
61
|
const CLAUDE_CAPABILITY = {
|
|
71
62
|
name: "claude",
|
|
@@ -82,7 +73,7 @@ export function createClaudeLauncher() {
|
|
|
82
73
|
},
|
|
83
74
|
buildInvocation(exe, input) {
|
|
84
75
|
const prompt = buildClaudePrompt(input);
|
|
85
|
-
// No working-directory flag: cwd is owned by the
|
|
76
|
+
// No working-directory flag: cwd is owned by the launching unit.
|
|
86
77
|
return { exe, args: [CLAUDE_CAPABILITY.promptFlag, prompt], prompt };
|
|
87
78
|
},
|
|
88
79
|
formatInvocationLine(invocation, platform) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The `cursor-agent` agent launcher (BAPI-351).
|
|
3
3
|
*
|
|
4
4
|
* A near-mirror of the Claude launcher: it resolves the `cursor-agent` binary
|
|
5
|
-
* against the
|
|
5
|
+
* against the explicitly supplied PATH and builds the launched-run prompt via
|
|
6
6
|
* the shared `renderScheduledPrompt` renderer (so the drift gate and command body
|
|
7
7
|
* are identical across agents). A local spike confirmed cursor-agent resolves the
|
|
8
8
|
* same `.claude/commands` catalog and exits cleanly in headless mode.
|
|
@@ -14,20 +14,12 @@
|
|
|
14
14
|
* - headless auth is via the `CURSOR_API_KEY` environment variable. This adapter
|
|
15
15
|
* never reads or prints that value — auth readiness is a prerequisite check.
|
|
16
16
|
*/
|
|
17
|
-
import { posixShellQuote, windowsCmdQuote } from "../
|
|
18
|
-
import { renderScheduledPrompt } from "
|
|
17
|
+
import { posixShellQuote, windowsCmdQuote } from "../platform-escaping.js";
|
|
18
|
+
import { renderScheduledPrompt } from "./prompt.js";
|
|
19
19
|
import { resolveCommandOnPath } from "./claude.js";
|
|
20
20
|
/** Build the scheduled-run prompt for the Cursor launcher via the shared renderer. */
|
|
21
21
|
export function buildCursorPrompt(input) {
|
|
22
|
-
return renderScheduledPrompt(
|
|
23
|
-
scheduleId: input.scheduleId,
|
|
24
|
-
scheduledAt: input.runAtIso,
|
|
25
|
-
autoApprove: input.autoApprove,
|
|
26
|
-
commandName: input.commandName,
|
|
27
|
-
args: input.args,
|
|
28
|
-
commandBody: input.commandBody,
|
|
29
|
-
schema: input.schema,
|
|
30
|
-
});
|
|
22
|
+
return renderScheduledPrompt(input);
|
|
31
23
|
}
|
|
32
24
|
const CURSOR_CAPABILITY = {
|
|
33
25
|
name: "cursor-agent",
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/** The fixed late-fire threshold, in seconds, shared by every launched run. */
|
|
2
|
+
export const LATE_FIRE_THRESHOLD_SECONDS = 60;
|
|
3
|
+
/**
|
|
4
|
+
* Quote a single argument token for safe inclusion in the rendered prompt while
|
|
5
|
+
* preserving its boundary. Simple tokens (alphanumerics plus a small set of
|
|
6
|
+
* path/flag-safe punctuation) are left bare; anything containing whitespace or
|
|
7
|
+
* prompt/markup-sensitive characters is wrapped in double quotes with embedded
|
|
8
|
+
* double quotes escaped. This is prompt-token quoting, NOT shell quoting — no
|
|
9
|
+
* shell ever sees these strings.
|
|
10
|
+
*/
|
|
11
|
+
export function quotePromptToken(token) {
|
|
12
|
+
if (token === "")
|
|
13
|
+
return '""';
|
|
14
|
+
// Safe: letters, digits, and characters that never need quoting in a prompt
|
|
15
|
+
// (path separators, ISO-timestamp punctuation, flag dashes, etc.).
|
|
16
|
+
if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(token))
|
|
17
|
+
return token;
|
|
18
|
+
return `"${token.replace(/"/g, '\\"')}"`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* True when a command's declared argument schema can parse a boolean `--auto`
|
|
22
|
+
* flag. Private to this module: the launchers only need the rendering decision,
|
|
23
|
+
* not a general command-schema query API.
|
|
24
|
+
*/
|
|
25
|
+
function schemaSupportsAutoFlag(schema) {
|
|
26
|
+
if (!schema)
|
|
27
|
+
return false;
|
|
28
|
+
return schema.flags.some((f) => f.flag === "--auto" && f.type === "boolean");
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Compute the augmented argv tokens the launched run delegates to the command:
|
|
32
|
+
* the normalized `input.args`, plus (only where the command can parse them)
|
|
33
|
+
* `--scheduled-at <ISO>` and `--auto`.
|
|
34
|
+
*
|
|
35
|
+
* `--scheduled-at` is appended for `full-automation` (legacy) and `epic-tick`
|
|
36
|
+
* (BAPI-418), both of whose parsers accept it as a first-class argument. Every
|
|
37
|
+
* other command rejects unrecognized flags and halts (e.g. `start-tickets` stops
|
|
38
|
+
* on any unsupported flag), and the shared late-fire gate already embeds the
|
|
39
|
+
* scheduled time — so injecting `--scheduled-at` into their argv would break an
|
|
40
|
+
* otherwise launchable command for no benefit.
|
|
41
|
+
*
|
|
42
|
+
* `--auto` is appended when auto-approve is set AND the command supports it (its
|
|
43
|
+
* schema declares a boolean `--auto` flag, or it is `full-automation` / `epic-tick`).
|
|
44
|
+
* It is never duplicated if already present in `input.args`.
|
|
45
|
+
*
|
|
46
|
+
* This is the SINGLE source of the delegated argv: both the rendered target
|
|
47
|
+
* command line and the `$ARGUMENTS` body substitution derive from it, so the body
|
|
48
|
+
* parse and the command line never disagree (e.g. `review-ticket`, which reads
|
|
49
|
+
* `--auto` out of `$ARGUMENTS`, sees the same `--auto` the command line shows).
|
|
50
|
+
*/
|
|
51
|
+
function buildAugmentedArgs(input) {
|
|
52
|
+
const args = [...input.args];
|
|
53
|
+
// Commands whose parsers accept --scheduled-at as a first-class argument.
|
|
54
|
+
// epic-tick already accepts --scheduled-at (parseEpicTickArgs, cli.ts) so it
|
|
55
|
+
// receives the scheduled time as a structured arg for the late-fire decision,
|
|
56
|
+
// not just via the embedded gate text.
|
|
57
|
+
if (input.commandName === "full-automation" || input.commandName === "epic-tick") {
|
|
58
|
+
args.push("--scheduled-at", input.runAtIso);
|
|
59
|
+
}
|
|
60
|
+
const supportsAuto = schemaSupportsAutoFlag(input.schema) ||
|
|
61
|
+
input.commandName === "full-automation" ||
|
|
62
|
+
input.commandName === "epic-tick";
|
|
63
|
+
const alreadyHasAuto = input.args.includes("--auto");
|
|
64
|
+
if (input.autoApprove && supportsAuto && !alreadyHasAuto) {
|
|
65
|
+
args.push("--auto");
|
|
66
|
+
}
|
|
67
|
+
return args;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Render the delegated target command line as
|
|
71
|
+
* `/<commandName> <augmented args...>` (see {@link buildAugmentedArgs}).
|
|
72
|
+
*/
|
|
73
|
+
function buildTargetCommandLine(input) {
|
|
74
|
+
const parts = [`/${input.commandName}`];
|
|
75
|
+
for (const arg of buildAugmentedArgs(input))
|
|
76
|
+
parts.push(quotePromptToken(arg));
|
|
77
|
+
return parts.join(" ");
|
|
78
|
+
}
|
|
79
|
+
/** Render only the fixed late-fire gate text. */
|
|
80
|
+
function renderLateFireGate(scheduleId, scheduledAt, autoApprove) {
|
|
81
|
+
const lateAction = autoApprove
|
|
82
|
+
? "explain that the run is firing late and then PROCEED with the command below (this schedule was created with auto-approve)."
|
|
83
|
+
: "explain that the run is firing late and then HALT WITHOUT EXECUTING the command below (this schedule was created without auto-approve, and a headless run must not proceed unconfirmed).";
|
|
84
|
+
return [
|
|
85
|
+
"## Scheduled-run drift gate",
|
|
86
|
+
"",
|
|
87
|
+
`This is an automated, headless scheduled run (schedule id: ${scheduleId}).`,
|
|
88
|
+
`It was scheduled to fire at ${scheduledAt}.`,
|
|
89
|
+
"",
|
|
90
|
+
`Before doing anything else, check how late this run is firing. If it is more than ${LATE_FIRE_THRESHOLD_SECONDS} seconds later than the scheduled time above, ${lateAction}`,
|
|
91
|
+
`If it is within ${LATE_FIRE_THRESHOLD_SECONDS} seconds of the scheduled time, proceed silently.`,
|
|
92
|
+
"",
|
|
93
|
+
"Then run the following command exactly as written:",
|
|
94
|
+
].join("\n");
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Replace `$ARGUMENTS` in a command body with the safely-quoted, normalized
|
|
98
|
+
* argument string. Every occurrence is replaced (commands often repeat the
|
|
99
|
+
* placeholder in a title and a body line).
|
|
100
|
+
*/
|
|
101
|
+
function replaceArgumentsPlaceholder(body, argString) {
|
|
102
|
+
return body.split("$ARGUMENTS").join(argString);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Render the full launched-run prompt: gate + delegated command line + command
|
|
106
|
+
* body (with `$ARGUMENTS` substituted). Deterministic for identical inputs.
|
|
107
|
+
*/
|
|
108
|
+
export function renderScheduledPrompt(input) {
|
|
109
|
+
const gate = renderLateFireGate(input.scheduleId, input.runAtIso, input.autoApprove);
|
|
110
|
+
const targetCommandLine = buildTargetCommandLine(input);
|
|
111
|
+
// `$ARGUMENTS` must match what the command line shows — including the appended
|
|
112
|
+
// `--scheduled-at` / `--auto` — so a body that re-parses `$ARGUMENTS` (e.g.
|
|
113
|
+
// review-ticket reading `--auto`) agrees with the rendered command line.
|
|
114
|
+
const argString = buildAugmentedArgs(input).map(quotePromptToken).join(" ");
|
|
115
|
+
const body = replaceArgumentsPlaceholder(input.commandBody, argString);
|
|
116
|
+
return [gate, "", targetCommandLine, "", body].join("\n");
|
|
117
|
+
}
|