@bridge_gpt/mcp-server 0.2.26 → 0.2.27

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 (57) hide show
  1. package/build/commands.generated.js +1 -1
  2. package/build/conductor-bin.js +68 -9267
  3. package/build/conductor-claude-hook-bin.js +2 -172
  4. package/build/decision-page-template.js +2 -31
  5. package/build/index.js +4652 -37042
  6. package/build/init.js +80 -56
  7. package/build/install-bridge.js +36 -20
  8. package/build/version.generated.js +1 -1
  9. package/package.json +1 -3
  10. package/design-assets/favicon/android-chrome-192x192.png +0 -0
  11. package/design-assets/favicon/android-chrome-512x512.png +0 -0
  12. package/design-assets/favicon/apple-touch-icon.png +0 -0
  13. package/design-assets/favicon/favicon-16x16.png +0 -0
  14. package/design-assets/favicon/favicon.ico +0 -0
  15. package/design-assets/favicon/site.webmanifest +0 -1
  16. package/public/css/main.min.css +0 -4971
  17. package/public/css/main.min.css.map +0 -1
  18. package/public/fonts/OFL.txt +0 -93
  19. package/public/fonts/SourceSansPro-Black.ttf +0 -0
  20. package/public/fonts/SourceSansPro-BlackItalic.ttf +0 -0
  21. package/public/fonts/SourceSansPro-Bold.ttf +0 -0
  22. package/public/fonts/SourceSansPro-BoldItalic.ttf +0 -0
  23. package/public/fonts/SourceSansPro-ExtraLight.ttf +0 -0
  24. package/public/fonts/SourceSansPro-ExtraLightItalic.ttf +0 -0
  25. package/public/fonts/SourceSansPro-Italic.ttf +0 -0
  26. package/public/fonts/SourceSansPro-Light.ttf +0 -0
  27. package/public/fonts/SourceSansPro-LightItalic.ttf +0 -0
  28. package/public/fonts/SourceSansPro-Regular.ttf +0 -0
  29. package/public/fonts/SourceSansPro-SemiBold.ttf +0 -0
  30. package/public/fonts/SourceSansPro-SemiBoldItalic.ttf +0 -0
  31. package/public/img/bridge-logo-160x51.webp +0 -0
  32. package/public/img/bridge-logo-300x92.webp +0 -0
  33. package/public/img/favicon/android-chrome-192x192.png +0 -0
  34. package/public/img/favicon/android-chrome-512x512.png +0 -0
  35. package/public/img/favicon/apple-touch-icon.png +0 -0
  36. package/public/img/favicon/favicon-16x16.png +0 -0
  37. package/public/img/favicon/favicon-32x32.png +0 -0
  38. package/public/img/favicon/favicon.ico +0 -0
  39. package/public/img/favicon/site.webmanifest +0 -1
  40. package/public/img/installation/bitbucket/app-password-1.png +0 -0
  41. package/public/img/installation/bitbucket/app-password-2.png +0 -0
  42. package/public/img/installation/bitbucket/create-token-1.png +0 -0
  43. package/public/img/installation/bitbucket/create-token-2.png +0 -0
  44. package/public/img/installation/bitbucket/webhook-1.png +0 -0
  45. package/public/img/installation/github/github-review-webhook.png +0 -0
  46. package/public/img/installation/jira/credentials/api-key.png +0 -0
  47. package/public/img/installation/jira/webhook/create-rule.png +0 -0
  48. package/public/img/installation/jira/webhook/project-settings.png +0 -0
  49. package/public/img/installation/jira/webhook/rule-create-1.png +0 -0
  50. package/public/img/installation/jira/webhook/rule-create-2.png +0 -0
  51. package/public/img/installation/jira/webhook/rule-create-3.png +0 -0
  52. package/public/img/installation/pinecone/pinecone-api-key.png +0 -0
  53. package/public/img/installation/pinecone/pinecone-index.png +0 -0
  54. package/public/js/main.min.js +0 -10409
  55. package/public/js/main.min.js.map +0 -1
  56. package/smoke-test/SMOKE-TEST.md +0 -560
  57. package/smoke-test/smoke-test-mcp.md +0 -23
@@ -14,7 +14,7 @@ export const COMMANDS = {
14
14
  "full-automation.md": "---\nschedulable: true\narguments: {\"positionals\":[],\"flags\":[{\"name\":\"ideaFile\",\"flag\":\"--idea-file\",\"type\":\"string\",\"required\":true},{\"name\":\"auto\",\"flag\":\"--auto\",\"type\":\"boolean\"}]}\n---\n\nRun the end-to-end full-automation chain (idea-to-ticket → review-ticket → start-tickets) via the server-side chain orchestrator.\n\n$ARGUMENTS\n\n---\n\n# Instructions\n\nThis command drives Phase A's server-side full-automation chain. The only orchestration tools you may drive are `run_full_automation` and `resume_full_automation`; any other Bridge API MCP call you make must be one a server `agent_task` instruction explicitly directs. The server owns all orchestration — ticket creation, review fan-out, and the start-tickets handoff. Do NOT enrich, re-implement, or second-guess any of that work on the client side.\n\n## Stage 0 — Parse arguments\n\n1. Tokenize `$ARGUMENTS` on whitespace. Recognize the following position-independent flags. Each flag supports both the space form (`--flag value`) and the equals form (`--flag=value`) where a value is taken:\n - `--idea <text>` / `--idea=<text>`\n - `--idea-file <path>` / `--idea-file=<path>`\n - `--auto`\n - `--require-approval`\n - `--scheduled-at <ISO-8601>` / `--scheduled-at=<ISO-8601>`\n - `--chain-run-id <UUID>` / `--chain-run-id=<UUID>`\n - `--max-children N` / `--max-children=N`\n - `--allow-duplicate`\n\n2. Value-consumption rules:\n - `--idea` (space form) consumes every subsequent token until the next recognized flag — the idea may contain spaces.\n - `--idea-file`, `--scheduled-at`, `--chain-run-id`, and `--max-children` each consume exactly one value token (the immediately following token, or the text after `=`).\n - `--auto`, `--require-approval`, and `--allow-duplicate` are boolean toggles and consume no value.\n\n3. Free-form idea: all non-flag tokens become the free-form `idea` text **only when both `--idea` and `--idea-file` are absent**. Join those tokens back together preserving order and trim surrounding whitespace. When `--idea` or `--idea-file` is present, there must be no leftover non-flag tokens: reject any stray non-flag token (for example, text following `--idea=<text>` or following the `--idea-file <path>` value) before any MCP tool call rather than silently dropping it.\n\n4. Reject **unknown flags** (any token beginning with `--` that is not one of the recognized flags above) before making any MCP tool call. Stop and report the offending flag.\n\n5. Reject **combined `--idea` and `--idea-file`** before making any MCP tool call:\n ```text\n Provide exactly one of --idea or --idea-file; do not pass both.\n ```\n\n6. Missing-input rule: unless `--chain-run-id` is present, an idea is required. If `--chain-run-id` is absent **and** no idea was supplied (no `--idea`, no `--idea-file`, and no free-form idea tokens), stop immediately and display exactly:\n ```text\n Usage: /full-automation (--idea \"<text>\" | --idea-file <path> | <free-form idea>) [--require-approval] [--scheduled-at <ISO-8601>] [--chain-run-id <UUID>] [--max-children N] [--allow-duplicate]\n ```\n\n7. `--chain-run-id` is the resume path and does **not** require any idea content — when it is present, skip the missing-input check above and proceed to resume.\n\n8. `--idea-file` is forwarded as a path. The skill must **not** read the file contents locally; the server resolves the file.\n\n9. Resolve the derived values:\n - `auto_approve` defaults to `true` (full automation is hands-off by default). It is `false` **only** when `--require-approval` is present. `--auto` is accepted but redundant (a no-op that restates the default), and `--scheduled-at` likewise runs hands-off. When `--require-approval` is present, the chain pauses at external-mutation and review-decision gates for confirmation.\n - `max_children` is the parsed positive integer when `--max-children` is present; otherwise omit it entirely so the server default applies.\n - `allow_duplicate` is `true` only when `--allow-duplicate` is present; otherwise omit it.\n\n## Stage 1 — Drift-check gate\n\nThis gate runs immediately after parsing and **before any MCP tool call**.\n\n1. If `--scheduled-at` is absent, skip this entire stage.\n2. Compute `delta_seconds = now_utc - scheduled_at` (both in UTC).\n3. If `delta_seconds <= 60`, proceed silently to Stage 2.\n4. If `delta_seconds > 60`, present this prompt verbatim (substituting the bracketed values):\n ```text\n Scheduled at <T-iso> UTC; running now at <now-iso> UTC (<Δ human-readable> late). The laptop was likely asleep or unavailable at the scheduled time. Confirm to proceed with the chain, or cancel.\n ```\n Offer the user the choices: `[Confirm] / [Cancel]`.\n5. On `Confirm`, proceed to Stage 2.\n6. On `Cancel`, print this message verbatim and stop:\n ```text\n Chain cancelled by user (drift confirmation declined). No Jira tickets created.\n ```\n When the user cancels, `run_full_automation` must **not** be called.\n7. The 60-second threshold is fixed and must not be made configurable.\n\n## Stage 2 — Run or resume the chain\n\nThe chain is driven entirely by the server-side orchestrator. Announce progress using each envelope's `preamble`, preserving its `Stage N of M — <title>` shape.\n\n### Stage 2a — Start (when `--chain-run-id` is absent)\n\nCall **only** `run_full_automation`. Build the payload, **omitting** any optional value that was not provided (never send `null` or empty strings):\n```json\n{\n \"idea\": \"<resolved inline/free-form idea, when provided>\",\n \"idea_file\": \"<idea-file path, when provided>\",\n \"auto_approve\": \"<resolved boolean>\",\n \"scheduled_at\": \"<scheduled-at value, when provided>\",\n \"max_children\": \"<parsed integer, when provided>\",\n \"allow_duplicate\": \"<true, when provided>\"\n}\n```\n\n### Stage 2b — Resume (when `--chain-run-id` is present)\n\nCall **only** `resume_full_automation` first, with:\n```json\n{\n \"chain_run_id\": \"<UUID>\",\n \"agent_result\": \"Manual resume requested from /full-automation --chain-run-id.\"\n}\n```\n\n### Stage 2c — Envelope loop\n\nFor each envelope returned by `run_full_automation` / `resume_full_automation`, dispatch on `status` / `next_action.kind`:\n\n- `status: \"failed\"` → stop chain progression and render the final report (Stage 3) with the failure status. Do **not** advance to any later stage.\n- `status: \"completed\"` or `next_action.kind: \"complete\"` → render the final report (Stage 3).\n- `status: \"needs_agent_task\"` with `next_action.kind: \"agent_task\"` → display the envelope `preamble`, perform the agent task exactly as the `next_action.instruction` directs, then call `resume_full_automation` with `chain_run_id` set to the envelope's `chain_run_id` and `agent_result` set to the resulting text. Loop back and process the next envelope.\n\nSpecial case — the stage-3 handoff: when the agent-task instruction names a `/start-tickets ...` command, invoke that slash command in **this same session**, summarize the outcome in one line, and pass that one-line summary as `agent_result` to `resume_full_automation`.\n\nConstraints:\n- On your own initiative, the skill must **not** call any Bridge API MCP tool other than `run_full_automation` / `resume_full_automation` — in particular, never independently drive orchestration (`run_pipeline`, `resume_pipeline`, `get_pipeline_recipe`) or enrich tickets (`get_ticket`, `update_ticket_description`, etc.). **However, when a `needs_agent_task` instruction returned by the server explicitly directs you to call a specific Bridge API MCP tool** (for example an orchestrator-directed `get_tickets`, `create_ticket`, `attachment`, or `track_ticket`), **you must invoke that tool exactly as instructed** — performing an orchestrator-directed agent task is not re-orchestrating.\n- If a v1 envelope unexpectedly returns `next_action.kind: \"mcp_call\"`, stop with a clear protocol error instead of bypassing the server-side orchestrator:\n ```text\n Protocol error: chain returned next_action.kind \"mcp_call\", which is out of scope for /full-automation v1. Stopping.\n ```\n\n## Stage 3 — Final report\n\nWhen the chain completes or fails, render this skeleton verbatim:\n\n```markdown\n## Full Automation Complete\n\nChain run: <chain_run_id>\nIdea: <first 80 chars of idea>...\nStages:\n 1. idea-to-ticket: <stages[0].summary>\n 2. review-ticket: <stages[1].summary>\n 3. start-tickets: <stages[2].summary>\n\nTotal Jira tickets created: N\nTotal worktrees spawned: M\nStatus: Success / Failed at stage N — <reason>\n```\n\n- Stage summaries come from the chain envelope or manifest when present.\n- When the completed envelope does not include full stage objects, use the summaries already surfaced in the prior `preamble` text rather than calling additional tools.\n- A stage-1 `too_vague_to_ticket` failure must render the upstream halt reason and set `Status: Failed at stage 1 — <reason>`.\n- Failed chains must not advance to later stages after a failed envelope is received.\n",
15
15
  "idea-to-ticket.md": "Convert a short human idea into a Jira ticket (or Epic plus child tickets) via the server-side idea-to-ticket pipeline.\n\n$ARGUMENTS\n\n---\n\n# Instructions\n\nThis command is recipe-driven. Do not call MCP tools directly other than `get_pipeline_recipe` — the recipe determines which tools to call and with what parameters.\n\n## Stage 0 — Parse arguments\n\n1. Tokenize `$ARGUMENTS` on whitespace. Recognize the following position-independent flags (any other tokens are part of the idea):\n - `--allow-duplicate`\n - `--max-children=N` where `N` is a positive integer\n - `--auto`\n\n Flags are optional. Treat absence of a flag as the default; never pass empty-string or null as a placeholder.\n\n2. Everything that is not a recognized flag is the free-form `idea` text. Join those tokens back together preserving order. Trim surrounding whitespace.\n\n3. If the resulting `idea` is empty, stop immediately and display:\n ```\n Usage: /idea-to-ticket <idea> [--allow-duplicate] [--max-children=N] [--auto]\n ```\n\n## Stage 1 — Derive pipeline variables\n\n4. Derive `slug` from the first 6-8 meaningful words of the idea: lowercase, kebab-case, strip non-alphanumeric characters except hyphens, and truncate to roughly 60 characters. Skip stop-words such as \"the\", \"a\", \"an\" when picking the 6-8 meaningful words.\n\n5. Derive `run_id` as `<YYYYMMDD-HHMMSS>-<short-uuid>` using the current UTC time and a short UUID suffix (8 hex chars is enough). The combination of `slug` and `run_id` uniquely identifies this run's artifact directory.\n\n6. Derive the boolean-as-string variables:\n - `allow_duplicate` is `\"true\"` if `--allow-duplicate` was present, otherwise `\"false\"`.\n - `auto_approve_external` is `\"true\"` if `--auto` was present, otherwise `\"false\"`.\n - `max_children` is the integer following `--max-children=` as a string, or `\"10\"` when the flag is absent.\n\n## Stage 2 — Call the recipe\n\n7. Call the `get_pipeline_recipe` MCP tool with:\n - `pipeline`: `\"idea-to-ticket\"`\n - `variables`: `{ \"idea\": \"<idea>\", \"slug\": \"<slug>\", \"run_id\": \"<run_id>\", \"allow_duplicate\": \"<allow_duplicate>\", \"auto_approve_external\": \"<auto_approve_external>\", \"max_children\": \"<max_children>\" }`\n\n Do NOT pass `docs_dir` or `idea_hash` in variables — both are auto-injected by the pipeline system (`docs_dir` from `BAPI_DOCS_DIR`; `idea_hash` is a stable hash derived from the `idea`).\n\n If the tool returns an error, stop and report the failure.\n\n8. Read and strictly obey the `agent_instructions` field in the response. Execute each step in order, announcing each as **Step N of M: <description>**.\n\n The recipe drives the ordered stages for you — do not invoke them directly. In order they are: preflight-and-readiness → research-decision → execute-research → duplicate-and-context-scan → screen-and-resolve → frame-goals-and-nfrs → **comp-analysis** (a gated, backend-safe perception step that maps any attached/referenced design comp to existing components, templates, SCSS/CSS tokens, and routes before drafting; it short-circuits for backend-only or no-comp work) → draft-and-critique → upload-and-track.\n\n## Stage 3 — Final summary\n\n9. After all steps complete, display a summary:\n ```\n ## Pipeline Complete\n\n **Idea**: <first 80 characters of idea>...\n **Slug**: <slug>\n **Run directory**: <docs_dir>/idea-to-ticket/<slug>-<run_id>/\n **Steps executed**: N of M\n **Status**: Success / Failed at step N\n ```\n",
16
16
  "implement-ticket.md": "# Implement Ticket\n\n$ARGUMENTS\n\n---\n\n# Instructions\n\nThis command is recipe-driven. Do not call MCP tools directly -- the recipe determines which tools to call and with what parameters.\n\n## CONDUCTOR_MESSAGE_RELAY ##\n\nIf you were launched under the Conductor (your environment carries a conductor run/worker identity), cooperatively poll for supervisor guidance while you work: at natural checkpoints — after reading context, before major code changes, after major implementation chunks, while polling CI checks during the post-PR correction loop, and before your final response — call the `check_messages` MCP tool. The tool reads and acknowledges any messages addressed to you, and acknowledged messages are not redelivered, so a later call returns only new guidance. This is cooperative polling only — it is not prompt injection and never mutates a live session. If the tool or conductor identity is unavailable, continue the task without derailing.\n\n1. Parse `$ARGUMENTS` to extract:\n - A required `ticket_key` matching the Jira key pattern (`[A-Z][A-Z0-9]+-\\d+`).\n - An optional position-independent `--auto` flag.\n\n Tokenize `$ARGUMENTS` on whitespace. The first token matching the Jira key pattern is the `ticket_key`; ignore any additional ticket-key tokens. The presence of a `--auto` token (anywhere in `$ARGUMENTS`) sets `auto_approve` to `true`.\n\n If `$ARGUMENTS` is empty or contains no token matching the Jira key pattern, stop immediately and display:\n ```\n Invalid ticket key format. Expected: PROJ-123 [--auto]\n Usage: /implement-ticket <ticket_key> [--auto]\n ```\n\n2. Call the `get_pipeline_recipe` MCP tool with:\n - `pipeline`: `\"implement-ticket\"`\n - `variables`: `{ \"ticket_key\": \"<ticket_key>\" }`\n - `auto_approve`: `true` — only when `--auto` was passed; otherwise omit this field entirely.\n\n If the tool returns an error, stop and report the failure.\n\n3. Read and strictly obey the `agent_instructions` field in the response. Execute each step in order, announcing each as **Step N of M: <description>**.\n\n4. After all steps complete, display a summary:\n ```\n ## Pipeline Complete\n\n **Ticket**: <ticket_key>\n **Steps executed**: N of M\n **Status**: Success / Failed at step N\n ```\n\n---\n\n# Worker scope discipline and clean exit (Conductor auto mode)\n\nThese rules apply only when you were launched under the Conductor in auto mode (`--auto`); a normal interactive `/implement-ticket` run is unaffected.\n\n## Declared file-scope discipline (N-2)\n\nIf your environment carries `BAPI_CONDUCTOR_DECLARED_TOUCHED_FILES_JSON` (a JSON array of the ticket's declared touched files), stay within that declared file boundary: do **not** create, modify, or delete files outside the declared set. Those out-of-scope files typically belong to a sibling ticket, and editing them risks a merge conflict or a silent clobber of the sibling's merged work. The pre-PR file-scope guard (run at the PR-creation step) will warn about any out-of-scope diff — treat that warning as a signal to re-check your scope, not as a blocker. When the variable is absent, empty, or invalid there is no declared boundary and this rule does not apply.\n\n## Clean session exit (D2)\n\nAfter the final pipeline step completes, cleanly end your worker session (for example by issuing the `/exit` command) so the worktree is released and no idle process lingers — but **only when no follow-up remains that you still own**. Do **not** exit while any of the following is true:\n\n- there are unresolved CI failures you are still correcting (the post-PR CI-correction loop in the CI-monitoring step still owns work),\n- review changes were requested and you have not yet addressed them,\n- there is a merge conflict on your PR that you still own,\n- you have unpushed local commits.\n\nExit only after your final branch state is pushed, the done-gate / CI-monitoring workflow required by the recipe has completed, and no CI/review follow-up remains. A clean `SessionEnd` is both the correct terminal lifecycle signal and the point at which the worker should exit.\n",
17
- "install-bridge.md": "Bootstrap Bridge API project configuration from the local codebase via the easy-install manifest.\n\n$ARGUMENTS\n\n---\n\n# Instructions\n\nThis command takes no arguments; any `$ARGUMENTS` text is ignored.\n\nCommand contract version: **3**. The install manifest returns a `command_contract_version`; Stage 2\ncompares it to this number to detect a stale scaffolded copy of this command.\n\nThis command performs a one-time \"easy install\" of Bridge API project configuration. It reads the\nserver-owned install manifest once, derives values for the **unset** bootstrap fields from the local\ncodebase, asks for human approval of the project description, applies everything in a single atomic\ncall, and then presents a **capability report** derived from a fresh read-after-write manifest read.\nThe server owns all skip-if-set, conflict, and confirmation semantics — this command never makes its\nown skip-if-set decisions — and the server owns the complete tool catalog, its grouping and ordering,\nand every gate and dependency relationship; this command formats the server's contract and never\nrecomputes it from prose.\n\nThis command is portable across Claude Code, Cursor, and Copilot: it only drives the Bridge API MCP\ntools (`get_my_role`, `get_install_manifest`, `apply_install_manifest`).\n\nIf any stage fails, stop immediately and report which stage failed and why.\n\n**Install-spawn context.** When the spawning instruction explicitly says this `/install-bridge` run is\nin the \"install-spawn context\" (it was launched by the `install-bridge` CLI's fresh agent session),\nStage 8 and Stage 9 are SKIPPED and the single closing interaction is the index-consent question the\nspawn prompt owns. When you invoke `/install-bridge` directly (manual invocation), Stages 8 and 9\nrun normally.\n\n## Stage 1 — Admin preflight\n\n1. Call the `get_my_role` MCP tool (no parameters). Inspect the response:\n - If `source` is `\"legacy\"`: proceed (legacy keys are permitted).\n - Else if `role` is `\"admin\"`: proceed.\n - Otherwise (a non-admin `user_access` key): stop immediately and display:\n ```\n Admin role required to apply install configuration. Ask a project admin to run /install-bridge,\n or use an admin API key.\n ```\n\n## Stage 2 — Read the manifest (once, pre-apply)\n\n1. Call the `get_install_manifest` MCP tool exactly once here.\n2. Keep the returned `snapshot_token` verbatim — you must pass the SAME token to the apply call in\n Stage 5. Do not call `get_install_manifest` again before applying; a fresh read would invalidate\n the token you are about to use. (Stage 7 performs a SEPARATE, later read-after-write manifest read\n for the current capability status — that is deliberate and does not reuse this token.)\n3. The manifest contains ordered `groups` of bootstrap fields (each with `field_name`, `is_set`,\n `current_value`, `guidance`, `examples`, `validation_summary`, `requires_confirmation`), a list of\n `deferred_fields`, a `next_step`, `done_criteria`, a `command_contract_version`, and the\n `snapshot_token`. It also carries the additive capability fields (`integrations`, `configured`,\n `learned`, `indexed`, `tool_capabilities`, `locked_tools`, `unlocked_tools`) — but ignore those\n here; the accurate capability status is the post-apply read in Stage 7. `tool_capabilities` is the\n COMPLETE catalog-backed report field (one entry per registered MCP tool, grouped and ordered by the\n server); `locked_tools` / `unlocked_tools` are LEGACY compatibility data covering only the VCS/index\n policy cases and are NOT the tool inventory.\n4. Compare the manifest's `command_contract_version` to this command's contract version (3, stated at\n the top of this file). If the manifest's version is HIGHER, this scaffolded command copy is stale:\n warn the user to refresh it by running `npx -y @bridge_gpt/mcp-server --init` in the project root,\n then proceed conservatively — wherever the manifest's `guidance`, `next_step`, or `done_criteria`\n differ from these instructions, follow the manifest.\n\n## Stage 3 — Derive values for UNSET bootstrap fields only\n\n1. Consider ONLY fields whose `is_set` is `false`. Never re-derive or overwrite a field that is\n already set — the server will also skip already-set fields, but you should not even propose them.\n2. For each unset field, derive a value from the local codebase following that field's `guidance`\n (e.g. infer `working_in` from frameworks/manifests, `version_control_system` from the git remote,\n testing stacks from test config and dependencies, directory fields from the repo layout).\n3. Omit any field you are uncertain about or that does not apply — leaving it unset is always\n acceptable. Do NOT guess.\n4. Specifically, do NOT invent a `version` when the platform has no meaningful version concept; leave\n it unset.\n5. Before deriving `version_control_system` or `base_branch`, confirm the git repository root is THIS\n project's root: `git rev-parse --show-toplevel` must resolve to the project directory itself. If\n the git root is an ancestor directory (the project is nested inside another repository), OMIT both\n fields and note why in the final report — deriving them would describe the parent repository, not\n this project.\n6. If you find real evidence for TWO OR MORE plausible values for a field (e.g. configs for multiple\n test frameworks, multiple frameworks in a monorepo), treat the value as ambiguous and omit it\n rather than picking one.\n7. Do NOT derive `selected_mcp_slugs`, even though it appears as an unset bootstrap-eligible field in\n the manifest. MCP validation manual selection is deferred to `/learn-repository`, which derives and\n confirms it with the codebase already researched. Install neither proposes nor applies this field.\n\n## Stage 4 — Human approval for confirmation-requiring fields\n\n`project_description` is the ONLY confirmation-requiring field install proposes. It carries\n`requires_confirmation: true` in the manifest, so it is never applied on derivation alone — it needs\nexplicit human approval. (`selected_mcp_slugs` also requires confirmation, but install does not\nderive it at all; `/learn-repository` asks for it. See Stage 3 step 7.)\n\n1. If `project_description` is unset and you can draft a concise description from the codebase,\n present the proposed `project_description` text to the human and ask for explicit approval before\n including it.\n2. Include `project_description` in the apply payload ONLY as\n `{ \"value\": <approved value>, \"confirmed\": true }`, and only after the human approves it. If the\n human does not approve it, omit the field entirely.\n3. If no human response can be obtained (e.g. a non-interactive / headless session), do NOT stall and\n do NOT abandon the install: proceed to Stage 5 with `project_description` omitted, and report it\n as \"pending human input\" in the final summary. The other derived fields must still be applied — an\n unapproved description never blocks them.\n\n## Stage 5 — Apply (one call)\n\n1. Make exactly ONE call to the `apply_install_manifest` MCP tool, passing:\n - `snapshot_token`: the exact token from Stage 2.\n - `fields`: a map of the derived fields. Scalar fields may be passed directly\n (e.g. `\"base_branch\": \"main\"`); an approved `project_description` must use the\n `{ \"value\": ..., \"confirmed\": true }` object form from Stage 4. Never include\n `selected_mcp_slugs` in this payload — install does not derive or apply it (Stage 3 step 7).\n2. Do not implement any client-side skip-if-set, conflict, or confirmation logic — the server owns\n all of that and returns the outcome buckets.\n3. The apply is partial-tolerant: fields that fail server-side validation are returned in the\n `rejected` bucket while the valid fields still commit. A rejected field is therefore reported,\n not fatal — do NOT retry the whole apply just because one field was rejected.\n\n## Stage 6 — Persist the routing credential\n\nThe Bash-spawned `start-tickets` CLI runs in a DIFFERENT runtime surface than this MCP server, so a\nkey that lives only in `.mcp.json` / `.cursor/mcp.json` is invisible to it and difficulty→model\nrouting silently degrades. This final stage persists the already-validated key into the user-scoped\ncredential store (`~/.config/bridge/credentials.json`) so shell-spawned CLI commands can resolve it.\n\n1. Call the `persist_routing_credential` MCP tool with `repo_name` set to the repository name for\n this install (the configured `BAPI_REPO_NAME`). Pass `repo_name` ONLY — this tool resolves the\n API key inside the MCP server process. NEVER pass or display `BAPI_API_KEY` (nor `api_key`,\n `apiKey`, `secret`, or `token`); the key value must not appear in the tool call or in any output.\n2. On success, tell the user the credential was stored, echoing the returned `target` and `path`,\n e.g. `Stored routing credential for bapi:<repo_name> at <path>`.\n3. On failure, do NOT block the install — show the rest of the install summary anyway, then tell the\n user the routing credential could not be stored. They can rerun `/install-bridge` after setting\n `BAPI_API_KEY` in the environment, or run\n `npx -y @bridge_gpt/mcp-server credentials migrate-agent-config --write-credentials` to migrate an\n existing key. Until then, `start-tickets` model routing fails open (assumes a hard ticket and\n defaults to premium/Opus when available) — this is the MOST EXPENSIVE model tier, so unexplained\n cost is the symptom of leaving this unfixed. Recommend verifying credential resolution afterwards\n with `npx -y @bridge_gpt/mcp-server doctor`.\n\n## Stage 7 — Summarize the outcome, then present the capability report\n\nFirst, begin with an explicit applied count: \"Applied N of M derivable fields\" (M = the unset\nbootstrap fields you derived values for). An install that applied 0 fields must say so loudly — the\ninstall is NOT complete until the apply call reports applied fields.\n\nThen summarize the six buckets from the apply response for the user:\n- `applied` — fields written this run.\n- `skipped` — fields already set (left untouched).\n- `conflict` — fields that changed since the manifest was read (re-run /install-bridge to retry).\n- `needs_confirmation` — fields awaiting explicit confirmation (e.g. project_description).\n- `rejected` — fields that failed validation or were not bootstrap-eligible (the other fields still\n applied; fix or drop the rejected values before any retry).\n- `deferred` — fields intentionally not auto-written by install (owned by /learn-repository or set\n deliberately). `selected_mcp_slugs` belongs here: report it as deferred to `/learn-repository`,\n never as approved, declined, or pending an install-time decision.\n\n### Read-after-write: fetch current capability status\n\nAfter the bucket summary, call the `get_install_manifest` MCP tool ONCE MORE. This post-apply read\nreflects the configuration you just wrote, so its capability fields are current (the Stage-2 read was\npre-apply and is stale for this purpose). This read does not need the snapshot token. Use ONLY this\npost-write response for the capability report below.\n\nThe response carries:\n\n- the `integrations` checklist — each item has `label`, `is_configured`, `required_for`,\n `configure_in`, and MAY have `optional_components` (a list of optional, non-gating add-ons nested\n under that integration, each with `id`, `label`, `is_configured`, `required_for`, `configure_in`,\n and `gating: false`);\n- the separate `configured` / `learned` / `indexed` readiness values;\n- `tool_capabilities` — the COMPLETE catalog-backed collection. It is an ordered array of groups, each\n `{id, name, description, tools}`. Each tool is `{tool, display_name, description, group, profile,\n availability, availability_text, effect, missing, semantics, variants}`, one entry per registered MCP\n tool, keyed by physical tool id;\n- `locked_tools` / `unlocked_tools` — LEGACY compatibility arrays covering only the VCS/index policy\n cases, keyed by policy-case id. They are NOT the tool inventory and you do not render them.\n\nServer authority: the server owns catalog membership, grouping, ordering, gates, and dependency\nrelationships. Never recompute any of them, and never derive them from `docs/mcp-tool-integrations.md`\nor any other documentation — cite that file only for a human explanation of a gate's \"why\".\n\nIf the post-write response has no capability fields at all (no `integrations` / `tool_capabilities`\nkeys, e.g. the additive enrichment was omitted), print exactly:\n`No capability status is available yet; configuration can still continue.` and skip the five sections.\n\nOtherwise, open with a short plain-language framing before the first section: explain that Bridge\nconnects the user's systems (their tracker, their code host, their platform) to their local code\neditor, and that connecting more of those systems unlocks richer capabilities. Then render exactly\nthese five sections, in this order, with these exact headings:\n\n**Connected ✓**\n\n- List each configured integration's `label` from the post-write `integrations` checklist, with a\n restrained `✓` marker. (Do not let the `✓` markers dominate the report.)\n- If a listed integration has `optional_components`, list each component beneath its parent as a\n sub-item, and describe it as optional and not required for the parent to work. A component with\n `gating: false` NEVER blocks anything: it is not a separate integration, it does not belong in the\n top-level list, and its state must not change how you describe its parent.\n\n**Not yet connected ✗**\n\n- List each unconfigured integration: its `label`, its `required_for` items, and the exact\n `configure_in` pointer. Do NOT include `setup_instructions` content — the pointer is the only\n configuration direction you emit. Apply the same `optional_components` rule as above.\n- The pointer is per-integration and is NOT always the setup UI. Emit whatever the server sent,\n VERBATIM: `github_app` points at the terminal command `npx -y @bridge_gpt/mcp-server@latest\n connect-github --repo <repo_name>`; `sfcc` points at the guide `docs/install/sfcc-integration.md`;\n Jira and `vcs_access_token` point at the setup UI. Never rewrite a command pointer into \"the setup\n UI\", and never replace GitHub's command with a guide.\n- STRICT INVARIANT: you DIRECT the human to that pointer; you never ask for, accept, echo, or\n transport an integration credential (Jira, GitHub, VCS, webhook, or SFCC — API token, access token,\n access key, webhook secret) in any form. This is unchanged for GitHub: the connect-github command\n authenticates the human to GitHub in their own browser, and no GitHub credential ever reaches Bridge\n or an agent. The SFCC pointer is a guide the human follows themselves — it is never an invitation to\n hand you credentials.\n\n**Tools you can use now**\n\n- Render from `tool_capabilities`, using the server's group order and, within each group, the server's\n tool order. Show each group's `name`, then each tool's `display_name`, its one-sentence\n `description`, and its `availability_text` exactly as provided.\n- Include here every tool whose `availability` is `available_now`, `available_with_less_context`,\n `profile_required`, or `varies_by_variant`.\n- Describe an `available_with_less_context` tool as available now with less codebase context — never\n as failed or unavailable.\n- For a `profile_required` tool, emit the server's neutral profile wording as given. Do NOT claim the\n profile is or is not registered locally: the server cannot observe that, so neither can you.\n- A `varies_by_variant` tool belongs here because at least one of its options is usable now. Render\n its variants beneath it and rely on each variant's own `availability_text` for accuracy — do NOT\n describe the whole tool as blocked, and do NOT describe it as fully available. (This is a common\n state, not a corner case: `create_doc` reports it whenever VCS is connected but the repository is\n not yet indexed, since `tdd` needs the index while `fsd`/`prd` do not.)\n- If a tool has a non-empty `variants` array, render the variants as sub-items BENEATH that one tool,\n each with its `label` and its own `availability_text`. Variants are options of a single tool\n (`create_doc`'s tdd/fsd/prd, `request_council`'s modes) — never present them as separately\n registered tools, and never invent an id like `create_doc:tdd`.\n- NEVER emit `BLOCK` or `DEGRADE`. The `effect` field is internal metadata that remains in the\n payload for compatibility; it is not for display. `availability_text` is what a human reads.\n\n**Tools you'll unlock**\n\n- Render every tool whose `availability` is `available_after_dependencies`, in the same server-provided\n grouping and order, each with its `display_name`, `description`, and `availability_text`. Where a\n tool's `variants` differ, show the variants beneath it so the user can see which options are already\n usable.\n- The `availability_text` already names the connection needed in plain language, including \"or\"\n relationships (an unknown VCS provider yields \"the GitHub App or a VCS access token\") and the\n separately-required repository index. Emit it as given rather than re-deriving it from `missing` or\n `semantics`.\n- Cite `docs/mcp-tool-integrations.md` briefly for a gate's human \"why\" — but never recompute\n membership from it.\n\n**Recommended next step + why**\n\n- Make this section visually strongest through ordering and concise wording. Choose the single most\n valuable next action using this deterministic priority based only on the server output. Jira or SFCC\n never displaces this order unless the server itself reports it as a dependency:\n 1. If any tool's `missing` includes a VCS integration (`github_app` / `vcs_access_token`), recommend\n connecting VCS first, using that integration's own `configure_in` pointer verbatim (for\n `github_app` that is the `connect-github` terminal command, not the setup UI).\n 2. Else if any tool's `missing` includes `code_index`, recommend running repository indexing\n (`/parse-repository`) next.\n 3. Else if `learned` is false, recommend running `/learn-repository` to populate the deeper\n instruction-tier configuration.\n- If `indexed` is `null` (unknown), include this exact warning:\n `Index status could not be confirmed—check again before relying on codebase-grounded tools.`\n\n## Stage 8 — Offer the next steps\n\n**Skip this entire stage in the install-spawn context** (the spawning instruction identifies it); the\nspawn prompt owns the single closing index-consent question there. On direct manual `/install-bridge`\ninvocation, run it normally:\n\n1. Offer to continue with `/learn-repository` to populate the deeper instruction-tier configuration\n (architecture, review, testing, and correctness standards), matching the manifest's `next_step`.\n Mention that it also derives and confirms the applicable MCP validation manuals\n (`selected_mcp_slugs`) — it researches the codebase first, so it can propose them with evidence\n and explain what they do, which is why install leaves that field alone.\n2. After `/learn-repository` completes (or if the human declines it), offer to start **repository\n indexing**: ask ONE consent question (\"Start repository indexing now? It runs as a background job\n and makes the codebase searchable for Bridge API's agents.\"). On yes, call the `parse_repository`\n MCP tool once. Report that the job was QUEUED and that progress can be checked with\n `get_parse_status` (or `/check-parse-status`) — do NOT poll it to completion in this session.\n Indexing is deliberately last so the applied `exclude_directories` / `custom_directories` values\n scope it correctly. If no human response can be obtained (non-interactive session), skip indexing\n and list it as a pending next step in the final report — never start it without consent.\n\n## Stage 9 — Offer CI follow-up configuration (only when CI is detected)\n\n**Skip this entire stage in the install-spawn context** (the spawning instruction identifies it), so\nthe index-consent question the spawn prompt owns remains the sole closing interaction. On direct\nmanual `/install-bridge` invocation, run it normally.\n\nThis stage is separate from the single apply call: it writes at most ONE field via the\n`config_field` MCP tool. `ci_followup_config` is REPLACE-NOT-AUGMENT — leaving it NULL already means\nsafe poll-only defaults, so \"skip\" is always a correct answer.\n\n1. Gate: only offer this when Stage 3 found real CI evidence (e.g. `.github/workflows/*.yml`,\n `bitbucket-pipelines.yml`). With no CI detected, skip this stage and note \"no CI detected — CI\n follow-up not offered\" in the final report.\n2. Ask ONE question, referencing the discovered CI by name, with exactly these preset profiles\n (default: skip):\n - **observe** — poll CI results only, never attempt fixes:\n `{\"strategy\": \"poll_only\", \"max_iterations\": 1, \"max_minutes\": 10, \"instructions\": \"\"}`\n - **self-heal** — bounded fix-and-iterate loop on the automation's own PRs:\n `{\"strategy\": \"fix_and_iterate\", \"max_iterations\": 3, \"max_minutes\": 45, \"instructions\": \"\"}`\n - **skip** (default) — leave `ci_followup_config` unset (NULL = baseline poll-only behavior).\n3. Do NOT offer or compose a `custom` strategy during install — free-form CI follow-up instructions\n are a deliberate later act (setup UI or a direct `config_field` update).\n4. When the human picks a profile, call the `config_field` MCP tool once (operation `\"update\"`,\n `field_name: \"ci_followup_config\"`, `value`: the profile's JSON object). If the server rejects the\n value, retry ONCE with a corrected payload; if it is rejected again, stop, show the proposed JSON\n to the human, and leave the field unset.\n5. Never select a profile in a non-interactive session — skip and list it as a pending next step. An\n unattended install must never enable fix-and-iterate behavior.\n\n## Return\n\nReport the admin check result, the \"Applied N of M\" count, the\napplied/skipped/conflict/needs_confirmation/rejected field names, any fields omitted for\nnested-repository or ambiguity reasons, the approval outcome for `project_description` — install's\nonly confirmation-requiring field — (approved / declined / pending human input), the fact that\n`selected_mcp_slugs` is deferred to `/learn-repository` rather than decided here, whether a\nstale-command warning was raised (manifest\n`command_contract_version` higher than this command's), whether the routing credential was persisted\n(the returned `target` and `path`, or the non-blocking failure remediation), the five-section\ncapability report (Connected ✓ / Not yet connected ✗ / Tools you can use now / Tools you'll unlock /\nRecommended next step + why) from the post-apply read-after-write manifest read, the CI follow-up\noutcome (profile written / skipped / no CI detected / pending / skipped in install-spawn context), and\nthe recommended next step.\n",
17
+ "install-bridge.md": "Bootstrap Bridge API project configuration from the local codebase via the easy-install manifest.\n\n$ARGUMENTS\n\n---\n\n# Instructions\n\nThis command takes no arguments; any `$ARGUMENTS` text is ignored.\n\nCommand contract version: **4**. The install manifest returns a `command_contract_version`; Stage 2\ncompares it to this number to detect a stale scaffolded copy of this command.\n\nThis command performs a one-time \"easy install\" of Bridge API project configuration. It reads the\nserver-owned install manifest once, derives values for the **unset** bootstrap fields from the local\ncodebase, asks for human approval of the project description, applies everything in a single atomic\ncall, and then presents a **capability report** derived from a fresh read-after-write manifest read.\nThe server owns all skip-if-set, conflict, and confirmation semantics — this command never makes its\nown skip-if-set decisions — and the server owns the complete tool catalog, its grouping and ordering,\nand every gate and dependency relationship; this command formats the server's contract and never\nrecomputes it from prose.\n\nThis command is portable across Claude Code, Cursor, and Copilot: it only drives the Bridge API MCP\ntools (`get_my_role`, `get_install_manifest`, `apply_install_manifest`).\n\nIf any stage fails, stop immediately and report which stage failed and why.\n\n**Install-spawn context.** When the spawning instruction explicitly says this `/install-bridge` run is\nin the \"install-spawn context\" (it was launched by the `install-bridge` CLI's fresh agent session),\nStage 8, Stage 9, and Stage 10 are SKIPPED and the single closing interaction is the index-consent\nquestion the spawn prompt owns. When you invoke `/install-bridge` directly (manual invocation),\nStages 8, 9, and 10 run normally.\n\n## Stage 1 — Admin preflight\n\n1. Call the `get_my_role` MCP tool (no parameters). Inspect the response:\n - If `source` is `\"legacy\"`: proceed (legacy keys are permitted).\n - Else if `role` is `\"admin\"`: proceed.\n - Otherwise (a non-admin `user_access` key): stop immediately and display:\n ```\n Admin role required to apply install configuration. Ask a project admin to run /install-bridge,\n or use an admin API key.\n ```\n\n## Stage 2 — Read the manifest (once, pre-apply)\n\n1. Call the `get_install_manifest` MCP tool exactly once here.\n2. Keep the returned `snapshot_token` verbatim — you must pass the SAME token to the apply call in\n Stage 5. Do not call `get_install_manifest` again before applying; a fresh read would invalidate\n the token you are about to use. (Stage 7 performs a SEPARATE, later read-after-write manifest read\n for the current capability status — that is deliberate and does not reuse this token.)\n3. The manifest contains ordered `groups` of bootstrap fields (each with `field_name`, `is_set`,\n `current_value`, `guidance`, `examples`, `validation_summary`, `requires_confirmation`), a list of\n `deferred_fields`, a `next_step`, `done_criteria`, a `command_contract_version`, and the\n `snapshot_token`. It also carries the additive capability fields (`integrations`, `configured`,\n `learned`, `indexed`, `tool_capabilities`, `locked_tools`, `unlocked_tools`) — but ignore those\n here; the accurate capability status is the post-apply read in Stage 7. `tool_capabilities` is the\n COMPLETE catalog-backed report field (one entry per registered MCP tool, grouped and ordered by the\n server); `locked_tools` / `unlocked_tools` are LEGACY compatibility data covering only the VCS/index\n policy cases and are NOT the tool inventory.\n4. Compare the manifest's `command_contract_version` to this command's contract version (4, stated at\n the top of this file). If the manifest's version is HIGHER, this scaffolded command copy is stale:\n warn the user to refresh it by running `npx -y @bridge_gpt/mcp-server --init` in the project root,\n then proceed conservatively — wherever the manifest's `guidance`, `next_step`, or `done_criteria`\n differ from these instructions, follow the manifest.\n\n## Stage 3 — Derive values for UNSET bootstrap fields only\n\n1. Consider ONLY fields whose `is_set` is `false`. Never re-derive or overwrite a field that is\n already set — the server will also skip already-set fields, but you should not even propose them.\n2. For each unset field, derive a value from the local codebase following that field's `guidance`\n (e.g. infer `working_in` from frameworks/manifests, `version_control_system` from the git remote,\n testing stacks from test config and dependencies, directory fields from the repo layout).\n3. Omit any field you are uncertain about or that does not apply — leaving it unset is always\n acceptable. Do NOT guess.\n4. Specifically, do NOT invent a `version` when the platform has no meaningful version concept; leave\n it unset.\n5. Before deriving `version_control_system` or `base_branch`, confirm the git repository root is THIS\n project's root: `git rev-parse --show-toplevel` must resolve to the project directory itself. If\n the git root is an ancestor directory (the project is nested inside another repository), OMIT both\n fields and note why in the final report — deriving them would describe the parent repository, not\n this project.\n6. If you find real evidence for TWO OR MORE plausible values for a field (e.g. configs for multiple\n test frameworks, multiple frameworks in a monorepo), treat the value as ambiguous and omit it\n rather than picking one.\n7. Do NOT derive `selected_mcp_slugs`, even though it appears as an unset bootstrap-eligible field in\n the manifest. MCP validation manual selection is deferred to `/learn-repository`, which derives and\n confirms it with the codebase already researched. Install neither proposes nor applies this field.\n\n## Stage 4 — Human approval for confirmation-requiring fields\n\n`project_description` is the ONLY confirmation-requiring field install proposes. It carries\n`requires_confirmation: true` in the manifest, so it is never applied on derivation alone — it needs\nexplicit human approval. (`selected_mcp_slugs` also requires confirmation, but install does not\nderive it at all; `/learn-repository` asks for it. See Stage 3 step 7.)\n\n1. If `project_description` is unset and you can draft a concise description from the codebase,\n present the proposed `project_description` text to the human and ask for explicit approval before\n including it.\n2. Include `project_description` in the apply payload ONLY as\n `{ \"value\": <approved value>, \"confirmed\": true }`, and only after the human approves it. If the\n human does not approve it, omit the field entirely.\n3. If no human response can be obtained (e.g. a non-interactive / headless session), do NOT stall and\n do NOT abandon the install: proceed to Stage 5 with `project_description` omitted, and report it\n as \"pending human input\" in the final summary. The other derived fields must still be applied — an\n unapproved description never blocks them.\n\n## Stage 5 — Apply (one call)\n\n1. Make exactly ONE call to the `apply_install_manifest` MCP tool, passing:\n - `snapshot_token`: the exact token from Stage 2.\n - `fields`: a map of the derived fields. Scalar fields may be passed directly\n (e.g. `\"base_branch\": \"main\"`); an approved `project_description` must use the\n `{ \"value\": ..., \"confirmed\": true }` object form from Stage 4. Never include\n `selected_mcp_slugs` in this payload — install does not derive or apply it (Stage 3 step 7).\n2. Do not implement any client-side skip-if-set, conflict, or confirmation logic — the server owns\n all of that and returns the outcome buckets.\n3. The apply is partial-tolerant: fields that fail server-side validation are returned in the\n `rejected` bucket while the valid fields still commit. A rejected field is therefore reported,\n not fatal — do NOT retry the whole apply just because one field was rejected.\n\n## Stage 6 — Persist the routing credential\n\nThe Bash-spawned `start-tickets` CLI runs in a DIFFERENT runtime surface than this MCP server, so a\nkey that lives only in `.mcp.json` / `.cursor/mcp.json` is invisible to it and difficulty→model\nrouting silently degrades. This final stage persists the already-validated key into the user-scoped\ncredential store (`~/.config/bridge/credentials.json`) so shell-spawned CLI commands can resolve it.\n\n1. Call the `persist_routing_credential` MCP tool with `repo_name` set to the repository name for\n this install (the configured `BAPI_REPO_NAME`). Pass `repo_name` ONLY — this tool resolves the\n API key inside the MCP server process. NEVER pass or display `BAPI_API_KEY` (nor `api_key`,\n `apiKey`, `secret`, or `token`); the key value must not appear in the tool call or in any output.\n2. On success, tell the user the credential was stored, echoing the returned `target` and `path`,\n e.g. `Stored routing credential for bapi:<repo_name> at <path>`.\n3. On failure, do NOT block the install — show the rest of the install summary anyway, then tell the\n user the routing credential could not be stored. They can rerun `/install-bridge` after setting\n `BAPI_API_KEY` in the environment, or run\n `npx -y @bridge_gpt/mcp-server credentials migrate-agent-config --write-credentials` to migrate an\n existing key. Until then, `start-tickets` model routing fails open (assumes a hard ticket and\n defaults to premium/Opus when available) — this is the MOST EXPENSIVE model tier, so unexplained\n cost is the symptom of leaving this unfixed. Recommend verifying credential resolution afterwards\n with `npx -y @bridge_gpt/mcp-server doctor`.\n\n## Stage 7 — Summarize the outcome, then present the capability report\n\nFirst, begin with an explicit applied count: \"Applied N of M derivable fields\" (M = the unset\nbootstrap fields you derived values for). An install that applied 0 fields must say so loudly — the\ninstall is NOT complete until the apply call reports applied fields.\n\nThen summarize the six buckets from the apply response for the user:\n- `applied` — fields written this run.\n- `skipped` — fields already set (left untouched).\n- `conflict` — fields that changed since the manifest was read (re-run /install-bridge to retry).\n- `needs_confirmation` — fields awaiting explicit confirmation (e.g. project_description).\n- `rejected` — fields that failed validation or were not bootstrap-eligible (the other fields still\n applied; fix or drop the rejected values before any retry).\n- `deferred` — fields intentionally not auto-written by install (owned by /learn-repository or set\n deliberately). `selected_mcp_slugs` belongs here: report it as deferred to `/learn-repository`,\n never as approved, declined, or pending an install-time decision.\n\n### Read-after-write: fetch current capability status\n\nAfter the bucket summary, call the `get_install_manifest` MCP tool ONCE MORE. This post-apply read\nreflects the configuration you just wrote, so its capability fields are current (the Stage-2 read was\npre-apply and is stale for this purpose). This read does not need the snapshot token. Use ONLY this\npost-write response for the capability report below.\n\nThe response carries:\n\n- the `integrations` checklist — each item has `label`, `is_configured`, `required_for`,\n `configure_in`, and MAY have `optional_components` (a list of optional, non-gating add-ons nested\n under that integration, each with `id`, `label`, `is_configured`, `required_for`, `configure_in`,\n and `gating: false`);\n- the separate `configured` / `learned` / `indexed` readiness values;\n- `tool_capabilities` — the COMPLETE catalog-backed collection. It is an ordered array of groups, each\n `{id, name, description, tools}`. Each tool is `{tool, display_name, description, group, profile,\n availability, availability_text, effect, missing, semantics, variants}`, one entry per registered MCP\n tool, keyed by physical tool id;\n- `locked_tools` / `unlocked_tools` — LEGACY compatibility arrays covering only the VCS/index policy\n cases, keyed by policy-case id. They are NOT the tool inventory and you do not render them.\n\nServer authority: the server owns catalog membership, grouping, ordering, gates, and dependency\nrelationships. Never recompute any of them, and never derive them from `docs/mcp-tool-integrations.md`\nor any other documentation — cite that file only for a human explanation of a gate's \"why\".\n\nIf the post-write response has no capability fields at all (no `integrations` / `tool_capabilities`\nkeys, e.g. the additive enrichment was omitted), print exactly:\n`No capability status is available yet; configuration can still continue.` and skip the five sections.\n\nOtherwise, open with a short plain-language framing before the first section: explain that Bridge\nconnects the user's systems (their tracker, their code host, their platform) to their local code\neditor, and that connecting more of those systems unlocks richer capabilities. Then render exactly\nthese five sections, in this order, with these exact headings:\n\n**Connected ✓**\n\n- List each configured integration's `label` from the post-write `integrations` checklist, with a\n restrained `✓` marker. (Do not let the `✓` markers dominate the report.)\n- If a listed integration has `optional_components`, list each component beneath its parent as a\n sub-item, and describe it as optional and not required for the parent to work. A component with\n `gating: false` NEVER blocks anything: it is not a separate integration, it does not belong in the\n top-level list, and its state must not change how you describe its parent.\n\n**Not yet connected ✗**\n\n- List each unconfigured integration: its `label`, its `required_for` items, and the exact\n `configure_in` pointer. Do NOT include `setup_instructions` content — the pointer is the only\n configuration direction you emit. Apply the same `optional_components` rule as above.\n- The pointer is per-integration and is NOT always the setup UI. Emit whatever the server sent,\n VERBATIM: `github_app` points at the terminal command `npx -y @bridge_gpt/mcp-server@latest\n connect-github --repo <repo_name>`; `sfcc` points at the guide `docs/install/sfcc-integration.md`;\n Jira and `vcs_access_token` point at the setup UI. Never rewrite a command pointer into \"the setup\n UI\", and never replace GitHub's command with a guide.\n- STRICT INVARIANT: you DIRECT the human to that pointer; you never ask for, accept, echo, or\n transport an integration credential (Jira, GitHub, VCS, webhook, or SFCC — API token, access token,\n access key, webhook secret) in any form. This is unchanged for GitHub: the connect-github command\n authenticates the human to GitHub in their own browser, and no GitHub credential ever reaches Bridge\n or an agent. The SFCC pointer is a guide the human follows themselves — it is never an invitation to\n hand you credentials.\n\n**Tools you can use now**\n\n- Render from `tool_capabilities`, using the server's group order and, within each group, the server's\n tool order. Show each group's `name`, then each tool's `display_name`, its one-sentence\n `description`, and its `availability_text` exactly as provided.\n- Include here every tool whose `availability` is `available_now`, `available_with_less_context`,\n `profile_required`, or `varies_by_variant`.\n- Describe an `available_with_less_context` tool as available now with less codebase context — never\n as failed or unavailable.\n- For a `profile_required` tool, emit the server's neutral profile wording as given. Do NOT claim the\n profile is or is not registered locally: the server cannot observe that, so neither can you.\n- A `varies_by_variant` tool belongs here because at least one of its options is usable now. Render\n its variants beneath it and rely on each variant's own `availability_text` for accuracy — do NOT\n describe the whole tool as blocked, and do NOT describe it as fully available. (This is a common\n state, not a corner case: `create_doc` reports it whenever VCS is connected but the repository is\n not yet indexed, since `tdd` needs the index while `fsd`/`prd` do not.)\n- If a tool has a non-empty `variants` array, render the variants as sub-items BENEATH that one tool,\n each with its `label` and its own `availability_text`. Variants are options of a single tool\n (`create_doc`'s tdd/fsd/prd, `request_council`'s modes) — never present them as separately\n registered tools, and never invent an id like `create_doc:tdd`.\n- NEVER emit `BLOCK` or `DEGRADE`. The `effect` field is internal metadata that remains in the\n payload for compatibility; it is not for display. `availability_text` is what a human reads.\n\n**Tools you'll unlock**\n\n- Render every tool whose `availability` is `available_after_dependencies`, in the same server-provided\n grouping and order, each with its `display_name`, `description`, and `availability_text`. Where a\n tool's `variants` differ, show the variants beneath it so the user can see which options are already\n usable.\n- The `availability_text` already names the connection needed in plain language, including \"or\"\n relationships (an unknown VCS provider yields \"the GitHub App or a VCS access token\") and the\n separately-required repository index. Emit it as given rather than re-deriving it from `missing` or\n `semantics`.\n- Cite `docs/mcp-tool-integrations.md` briefly for a gate's human \"why\" — but never recompute\n membership from it.\n\n**Recommended next step + why**\n\n- Make this section visually strongest through ordering and concise wording. Choose the single most\n valuable next action using this deterministic priority based only on the server output. Jira or SFCC\n never displaces this order unless the server itself reports it as a dependency:\n 1. If any tool's `missing` includes a VCS integration (`github_app` / `vcs_access_token`), recommend\n connecting VCS first, using that integration's own `configure_in` pointer verbatim (for\n `github_app` that is the `connect-github` terminal command, not the setup UI).\n 2. Else if any tool's `missing` includes `code_index`, recommend running repository indexing\n (`/parse-repository`) next.\n 3. Else if `learned` is false, recommend running `/learn-repository` to populate the deeper\n instruction-tier configuration.\n- If `indexed` is `null` (unknown), include this exact warning:\n `Index status could not be confirmed—check again before relying on codebase-grounded tools.`\n\n## Stage 8 — Offer the next steps\n\n**Skip this entire stage in the install-spawn context** (the spawning instruction identifies it); the\nspawn prompt owns the single closing index-consent question there. On direct manual `/install-bridge`\ninvocation, run it normally:\n\n1. Offer to continue with `/learn-repository` to populate the deeper instruction-tier configuration\n (architecture, review, testing, and correctness standards), matching the manifest's `next_step`.\n Mention that it also derives and confirms the applicable MCP validation manuals\n (`selected_mcp_slugs`) — it researches the codebase first, so it can propose them with evidence\n and explain what they do, which is why install leaves that field alone.\n2. After `/learn-repository` completes (or if the human declines it), offer to start **repository\n indexing**: ask ONE consent question (\"Start repository indexing now? It runs as a background job\n and makes the codebase searchable for Bridge API's agents.\"). On yes, call the `parse_repository`\n MCP tool once. Report that the job was QUEUED and that progress can be checked with\n `get_parse_status` (or `/check-parse-status`) — do NOT poll it to completion in this session.\n Indexing is deliberately last so the applied `exclude_directories` / `custom_directories` values\n scope it correctly. If no human response can be obtained (non-interactive session), skip indexing\n and list it as a pending next step in the final report — never start it without consent.\n\n## Stage 9 — Offer CI follow-up configuration (only when CI is detected)\n\n**Skip this entire stage in the install-spawn context** (the spawning instruction identifies it), so\nthe index-consent question the spawn prompt owns remains the sole closing interaction. On direct\nmanual `/install-bridge` invocation, run it normally.\n\nThis stage is separate from the single apply call: it writes at most ONE field via the\n`config_field` MCP tool. `ci_followup_config` is REPLACE-NOT-AUGMENT — leaving it NULL already means\nsafe poll-only defaults, so \"skip\" is always a correct answer.\n\n1. Gate: only offer this when Stage 3 found real CI evidence (e.g. `.github/workflows/*.yml`,\n `bitbucket-pipelines.yml`). With no CI detected, skip this stage and note \"no CI detected — CI\n follow-up not offered\" in the final report.\n2. Ask ONE question, referencing the discovered CI by name, with exactly these preset profiles\n (default: skip):\n - **observe** — poll CI results only, never attempt fixes:\n `{\"strategy\": \"poll_only\", \"max_iterations\": 1, \"max_minutes\": 10, \"instructions\": \"\"}`\n - **self-heal** — bounded fix-and-iterate loop on the automation's own PRs:\n `{\"strategy\": \"fix_and_iterate\", \"max_iterations\": 3, \"max_minutes\": 45, \"instructions\": \"\"}`\n - **skip** (default) — leave `ci_followup_config` unset (NULL = baseline poll-only behavior).\n3. Do NOT offer or compose a `custom` strategy during install — free-form CI follow-up instructions\n are a deliberate later act (setup UI or a direct `config_field` update).\n4. When the human picks a profile, call the `config_field` MCP tool once (operation `\"update\"`,\n `field_name: \"ci_followup_config\"`, `value`: the profile's JSON object). If the server rejects the\n value, retry ONCE with a corrected payload; if it is rejected again, stop, show the proposed JSON\n to the human, and leave the field unset.\n5. Never select a profile in a non-interactive session — skip and list it as a pending next step. An\n unattended install must never enable fix-and-iterate behavior.\n\n## Stage 10 — Offer the speed-vs-quality repository preference\n\n**Skip this entire stage in the install-spawn context** (the spawning instruction identifies it), so\nthe index-consent question the spawn prompt owns remains the sole closing interaction. On direct\nmanual `/install-bridge` invocation, run it normally.\n\nThis stage is separate from the single apply call: it writes at most ONE field via the `config_field`\nMCP tool, `field_name: \"speed_vs_quality\"`. The column defaults to `5` (max quality) for every\nrepository, so \"skip\" always leaves a safe, valid value in place.\n\n1. Never ask this question in a non-interactive session — skip and list it as a pending next step. An\n unattended install must never block on or silently answer this preference.\n2. Read the current value first via the `config_field` MCP tool (operation `\"get\"`,\n `field_name: \"speed_vs_quality\"`) so a reinstall can show the stored value — not always `5` — as\n the displayed default rather than silently re-asking from scratch.\n3. Ask ONE question with exactly these five numbered presets (default: the value from step 2, or `5`\n if this is the first install):\n - **1** — Max speed\n - **2** — Prefer speed\n - **3** — Balanced\n - **4** — Prefer quality\n - **5** — Max quality (default)\n4. Persist ONLY on an explicit answer — including an explicitly accepted default — by calling the\n `config_field` MCP tool once (operation `\"update\"`, `field_name: \"speed_vs_quality\"`,\n `value`: the selected integer 1-5). Do not overwrite an existing value when the human gives no\n answer at all (e.g. the session cannot obtain one) — leave the stored/default value untouched in\n that case, distinct from an explicit accepted-default selection of `5`.\n5. After a successful persist, emit one additive structured log line (mirroring the codebase's\n `logging.info(msg, extra={...})` convention for non-response-body observability signals) with\n fields: `event=\"install.speed_vs_quality\"`, `repo_name`, `field_name=\"speed_vs_quality\"`,\n `selected_preset` (the persisted integer), `outcome=\"persisted\"`. Never log this event before the\n `config_field` tool call has confirmed the write.\n6. When skipped, emit the corresponding structured event with `outcome` set to one of\n `\"skipped_non_interactive\"` (non-interactive session) or `\"skipped_no_answer\"` (interactive session,\n no explicit answer obtained) — omit `selected_preset` and any prompt text from this event.\n7. If the `config_field` call is rejected, retry ONCE with a corrected payload; if it is rejected\n again, stop, show the proposed value to the human, and leave the field at its current stored value.\n Do not log a persistence-success event for a rejected or failed write.\n\n## Return\n\nReport the admin check result, the \"Applied N of M\" count, the\napplied/skipped/conflict/needs_confirmation/rejected field names, any fields omitted for\nnested-repository or ambiguity reasons, the approval outcome for `project_description` — install's\nonly confirmation-requiring field — (approved / declined / pending human input), the fact that\n`selected_mcp_slugs` is deferred to `/learn-repository` rather than decided here, whether a\nstale-command warning was raised (manifest\n`command_contract_version` higher than this command's), whether the routing credential was persisted\n(the returned `target` and `path`, or the non-blocking failure remediation), the five-section\ncapability report (Connected ✓ / Not yet connected ✗ / Tools you can use now / Tools you'll unlock /\nRecommended next step + why) from the post-apply read-after-write manifest read, the CI follow-up\noutcome (profile written / skipped / no CI detected / pending / skipped in install-spawn context), the\nspeed-vs-quality preference outcome (persisted with its preset / skipped_non_interactive /\nskipped_no_answer / pending / skipped in install-spawn context), and the recommended next step.\n",
18
18
  "learn-repository.md": "Learn and document all configuration fields for the repository by running parallel research agents.\n\n$ARGUMENTS\n\n---\n\n# Instructions\n\nThis command is recipe-driven. Do not call MCP tools directly -- the recipe determines which tools to call and with what parameters.\n\n1. This command takes no arguments.\n\n2. **Before executing any recipe step**, tell the user what they are about to sit through and why it\n is worth it:\n\n ```\n Learning this repository. This takes a while — the research agents read the actual codebase, and\n all the unlearned fields are researched in parallel, so the wait is roughly the slowest single\n field rather than the sum of all of them. Fields that are already populated are skipped entirely.\n\n What this buys you: these fields are what ground Bridge's agents in THIS codebase. Planning,\n reviewing, and code generation all read them, so they follow your repository's actual\n architecture, testing, documentation, and correctness conventions instead of generic defaults.\n\n It runs unattended — there are no approval prompts during the run. You may be asked one batched\n question at the very end.\n ```\n\n Do not invent a specific number of minutes; the honest statement is the parallel-wait shape above.\n\n3. Call the `get_pipeline_recipe` MCP tool with:\n - `pipeline`: `\"learn-repository\"`\n\n If the tool returns an error, stop and report the failure.\n\n4. Read and strictly obey the `agent_instructions` field in the response. Execute each step in order, announcing each as **Step N of M: <description>**.\n\n Retain, for the closing summary: the consolidated research task's structured result (its per-field\n `status`, `character_count`, `condensed`, and `condensation_reason`), each upload step's result,\n and the final confirmation task's structured result. You will need all three — do not discard them\n as you go.\n\n5. After all steps complete, display a summary built from the results you retained:\n\n ```\n ## Learn Complete\n\n **Status**: Success / Completed with gaps / Failed at step N\n\n **Learned and applied**: <fields drafted this run and written to config>\n **Already populated (skipped)**: <fields skipped because they already had a value>\n **Condensed to fit the field limit**: <field — reason it was condensed, per field>\n **Gaps**: <fields whose research or upload failed, each named with its reason>\n **Confirmation**: <approved / applied / declined / pending human input / not applicable, per field>\n\n Review or edit any of these on the **Project Configuration** page, under **Code Writer Settings**\n for the learned instructions and **MCP Validation Manuals** for the manual selection. Bridge's\n agents read whatever is stored there, so correcting a wrong conclusion there changes their\n behavior.\n ```\n\n Rules for the summary:\n\n - A run where some fields failed but others applied is **`Completed with gaps`**, not `Failed`.\n Name every gap explicitly — an unnamed gap is worse than a failed run, because the user believes\n the field was learned.\n - Report confirmation candidates that could not be presented in a headless session with the exact\n phrase `pending human input`.\n - Every field that was condensed must appear with the reason it was condensed.\n",
19
19
  "parse-repository.md": "Queue a background job to parse and index the repository for Bridge API's AI agents.\n\n$ARGUMENTS\n\n---\n\n# Instructions\n\nExecute all steps in this command as a simple linear sequence of MCP tool calls.\n\n## Step 1 — Parse Arguments\n\nParse `$ARGUMENTS` for an optional `directory_path` argument (a subdirectory path to scope the parse to, e.g., `src/python`). If no argument is provided, the entire repository will be parsed. If `$ARGUMENTS` is provided but invalid (e.g., contains special characters that suggest it's not a path), report an error.\n\n## Step 2 — Queue Parse Job\n\nCall the `parse_repository` MCP tool with:\n- `directory_path`: set to the parsed `directory_path` from Step 1 if provided, otherwise omit the parameter\n\nIf the response indicates parsing is already in progress, display:\n\n```\nRepository parsing is already in progress. A previous parse job has not yet completed.\n\nRun `/check-parse-status` to monitor progress, or wait a few minutes and try again.\n```\n\nStop and do not proceed to the summary.\n\nIf the call fails or returns an error, stop immediately and display:\n\n```\nFailed to queue parse job: <error message from the tool>\n```\n\n## Summary\n\nOn successful queuing, display:\n\n```\nRepository parse job queued successfully.\n\nScope: <entire repository or directory_path if provided>\n\nProcessing typically takes several minutes for large repositories.\nRun `/check-parse-status` to monitor progress.\n```\n\nAfter the parse completes, AI-generated plans and clarifying questions will reflect the latest code changes.\n",
20
20
  "plan-epic.md": "Plan an epic by decomposing it into sub-tasks with structured exploration documents.\n\n$ARGUMENTS\n\n---\n\n# Instructions\n\nThis command is recipe-driven. Do not call MCP tools directly -- the recipe determines which tools to call and with what parameters.\n\n## Stage 0 — Setup\n\n1. **Parse arguments**: Extract the input from `$ARGUMENTS`. Trim any surrounding whitespace. If the input is empty or whitespace-only, stop immediately and display:\n ```\n Usage: /plan-epic <description of the epic or Jira key>\n ```\n\n2. **Jira key detection**: If the input matches a Jira key pattern (`[A-Z]+-\\d+`), call the `get_ticket` MCP tool with that key to fetch the epic description. Use the ticket's description as the `epic_description`, and set `epic_key` to that Jira key. If the input does not match a Jira key, use the free-form text directly as the `epic_description` and set `epic_key` to an empty string `\"\"` (there is no Jira epic to update). The recipe uses `epic_key` to decide whether to post the goals/NFRs + recommended implementation order as a comment on the epic.\n\n3. **Generate slug**: Create a kebab-case slug from the epic description — take the first 6-8 meaningful words, strip non-alphanumeric characters (except hyphens), lowercase, and truncate to 60 characters. This becomes the `epic_slug`.\n\n4. **Directory existence check**: Call the `get_docs_dir` MCP tool (no parameters) to get the docs directory path. Then run a terminal command to check if the directory `{docs_dir}/epic-plans/{epic_slug}` already exists:\n ```\n test -d {docs_dir}/epic-plans/{epic_slug} && echo \"exists\" || echo \"not_found\"\n ```\n If the directory exists, append `-{unix_timestamp}` to the `epic_slug` (e.g., `add-auth-provider-support-1710000000`).\n\n## Stage 1 — Execution\n\n5. Call the `get_pipeline_recipe` MCP tool with:\n - `pipeline`: `\"plan-epic\"`\n - `variables`: `{ \"epic_description\": \"<resolved_description>\", \"epic_slug\": \"<slug>\", \"epic_key\": \"<jira_key_or_empty_string>\" }`\n\n Note: Do NOT pass `docs_dir` in variables — it is auto-injected by the pipeline system.\n\n If the tool returns an error, stop and report the failure.\n\n6. Read and strictly obey the `agent_instructions` field in the response. Execute each step in order, announcing each as **Step N of M: <description>**.\n\n7. After all steps complete, display a summary:\n ```\n ## Pipeline Complete\n\n **Epic**: <first 80 characters of epic_description>...\n **Slug**: <epic_slug>\n **Output**: <docs_dir>/epic-plans/<epic_slug>/overview.md\n **Steps executed**: N of M\n **Status**: Success / Failed at step N\n ```\n",