@bridge_gpt/mcp-server 0.1.16 → 0.2.0
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 +333 -162
- package/build/agent-capabilities/cli.js +152 -0
- package/build/agent-capabilities/default-deps.js +45 -0
- package/build/agent-capabilities/probe-context.js +111 -0
- package/build/agent-capabilities/probes.js +278 -0
- package/build/agent-capabilities/reporter.js +50 -0
- package/build/agent-capabilities/runner.js +56 -0
- package/build/agent-capabilities/types.js +10 -0
- package/build/agent-launchers/claude.js +85 -0
- package/build/agent-launchers/index.js +17 -0
- package/build/agent-launchers/types.js +1 -0
- package/build/agents.generated.js +1 -1
- package/build/brainstorm-files.js +89 -0
- package/build/bridge-config.js +404 -0
- package/build/chain-orchestrator.js +1364 -0
- package/build/chain-utils.js +68 -0
- package/build/commands.generated.js +5 -3
- package/build/credential-materialization.js +128 -0
- package/build/credential-store.js +232 -0
- package/build/decision-page-schema.js +39 -6
- package/build/decision-page-template.js +54 -18
- package/build/doctor.js +18 -2
- package/build/fetch-stub.js +139 -0
- package/build/git-ignore-utils.js +63 -0
- package/build/index.js +1623 -546
- package/build/mcp-invoke.js +417 -0
- package/build/mcp-provisioning.js +249 -0
- package/build/mcp-registration-doctor.js +96 -0
- package/build/pipeline-orchestrator.js +66 -1
- package/build/pipeline-utils.js +33 -0
- package/build/pipelines.generated.js +165 -5
- package/build/schedule-run.js +951 -0
- package/build/schedule-store.js +132 -0
- package/build/scheduler-backends/at-fallback.js +144 -0
- package/build/scheduler-backends/escaping.js +113 -0
- package/build/scheduler-backends/index.js +72 -0
- package/build/scheduler-backends/launchd.js +216 -0
- package/build/scheduler-backends/systemd-user.js +237 -0
- package/build/scheduler-backends/task-scheduler.js +219 -0
- package/build/scheduler-backends/types.js +23 -0
- package/build/start-tickets-prereqs.js +90 -1
- package/build/start-tickets.js +222 -70
- package/build/third-party-mcp-targets.js +75 -0
- package/build/version.generated.js +1 -1
- package/package.json +8 -8
- package/pipelines/full-automation.json +49 -0
- package/pipelines/idea-to-ticket.json +71 -0
- package/pipelines/implement-ticket.json +28 -2
- package/smoke-test/SMOKE-TEST.md +511 -0
- package/smoke-test/smoke-test-mcp.md +23 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "full-automation",
|
|
3
|
+
"description": "Drive an idea end-to-end: create ticket(s) (idea-to-ticket), review each ticket (review-ticket fan-out), then hand off to the /start-tickets CLI seam to spawn worktrees.",
|
|
4
|
+
"variables": [
|
|
5
|
+
"idea",
|
|
6
|
+
"auto_approve",
|
|
7
|
+
"scheduled_at",
|
|
8
|
+
"max_children",
|
|
9
|
+
"allow_duplicate",
|
|
10
|
+
"agent"
|
|
11
|
+
],
|
|
12
|
+
"stages": [
|
|
13
|
+
{
|
|
14
|
+
"pipeline_name": "idea-to-ticket",
|
|
15
|
+
"description": "Convert the idea into one or more Jira tickets.",
|
|
16
|
+
"variables": {
|
|
17
|
+
"idea": "{idea}",
|
|
18
|
+
"max_children": "{max_children}",
|
|
19
|
+
"allow_duplicate": "{allow_duplicate}",
|
|
20
|
+
"auto_approve_external": "{auto_approve}"
|
|
21
|
+
},
|
|
22
|
+
"outputs": {
|
|
23
|
+
"child_ticket_keys": "child_ticket_keys",
|
|
24
|
+
"epic_parent_key": "epic_parent_key",
|
|
25
|
+
"created_ticket_keys": "created_ticket_keys"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"pipeline_name": "review-ticket",
|
|
30
|
+
"description": "Review each created ticket (one child pipeline run per ticket).",
|
|
31
|
+
"fan_out_input": "child_ticket_keys",
|
|
32
|
+
"fan_out_variable": "ticket_key",
|
|
33
|
+
"variables": {
|
|
34
|
+
"ticket_key": "{ticket_key}"
|
|
35
|
+
},
|
|
36
|
+
"outputs": {
|
|
37
|
+
"reviewed_ticket_keys": "reviewed_ticket_keys"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"pipeline_name": "start-tickets",
|
|
42
|
+
"description": "Hand off the reviewed tickets to the /start-tickets CLI seam (agent-task; not a server pipeline).",
|
|
43
|
+
"fan_out_input": "reviewed_ticket_keys",
|
|
44
|
+
"outputs": {
|
|
45
|
+
"started_ticket_keys": "started_ticket_keys"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Idea to Ticket",
|
|
3
|
+
"description": "Convert a short human idea into either a single Jira Task/Spike or a Jira Epic plus decomposed child tickets.",
|
|
4
|
+
"variables": [
|
|
5
|
+
"idea",
|
|
6
|
+
"idea_hash",
|
|
7
|
+
"slug",
|
|
8
|
+
"run_id",
|
|
9
|
+
"docs_dir",
|
|
10
|
+
"allow_duplicate",
|
|
11
|
+
"auto_approve_external",
|
|
12
|
+
"max_children"
|
|
13
|
+
],
|
|
14
|
+
"steps": [
|
|
15
|
+
{
|
|
16
|
+
"type": "mcp_call",
|
|
17
|
+
"tool": "ping",
|
|
18
|
+
"params": {},
|
|
19
|
+
"description": "Verify Bridge API connectivity"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"type": "mcp_call",
|
|
23
|
+
"tool": "get_docs_dir",
|
|
24
|
+
"params": {},
|
|
25
|
+
"description": "Resolve the docs directory for run artifacts"
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"type": "mcp_call",
|
|
29
|
+
"tool": "get_project_standards",
|
|
30
|
+
"params": {},
|
|
31
|
+
"description": "Fetch project standards for screening (optional)",
|
|
32
|
+
"on_error": "warn_and_continue"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"type": "agent_task",
|
|
36
|
+
"instruction_file": "preflight-and-readiness.md",
|
|
37
|
+
"description": "Initialize run directory, classify readiness and scope"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"type": "agent_task",
|
|
41
|
+
"instruction_file": "research-decision.md",
|
|
42
|
+
"description": "Decide which research tools to run for this idea"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"type": "agent_task",
|
|
46
|
+
"instruction_file": "execute-research.md",
|
|
47
|
+
"description": "Execute the planned research and produce the research pack",
|
|
48
|
+
"on_error": "warn_and_continue"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"type": "agent_task",
|
|
52
|
+
"instruction_file": "duplicate-and-context-scan.md",
|
|
53
|
+
"description": "Scan Jira for duplicate/related tickets"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"type": "agent_task",
|
|
57
|
+
"instruction_file": "screen-and-resolve.md",
|
|
58
|
+
"description": "Build standards checklist and resolve open questions"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"type": "agent_task",
|
|
62
|
+
"instruction_file": "draft-and-critique.md",
|
|
63
|
+
"description": "Draft the ticket(s) and run a hygiene/critique pass"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"type": "agent_task",
|
|
67
|
+
"instruction_file": "upload-and-track.md",
|
|
68
|
+
"description": "Upload to Jira and track the new ticket(s) idempotently"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
24
|
"type": "agent_task",
|
|
25
|
-
"instruction_file": "execute-plan.md",
|
|
25
|
+
"instruction_file": "execute-plan-sectioned.md",
|
|
26
26
|
"description": "Execute the implementation plan"
|
|
27
27
|
},
|
|
28
28
|
{
|
|
@@ -58,5 +58,31 @@
|
|
|
58
58
|
"instruction_file": "monitor-ci-checks.md",
|
|
59
59
|
"description": "Monitor CI checks and report results"
|
|
60
60
|
}
|
|
61
|
-
]
|
|
61
|
+
],
|
|
62
|
+
"tiered_executor_policy": {
|
|
63
|
+
"supported_hosts": ["claude_code"],
|
|
64
|
+
"sequential_only": true,
|
|
65
|
+
"tier_model_mapping": {
|
|
66
|
+
"cheap": "haiku",
|
|
67
|
+
"basic": "sonnet",
|
|
68
|
+
"premium": "opus"
|
|
69
|
+
},
|
|
70
|
+
"final_review_policy": {
|
|
71
|
+
"default": "premium_whole_diff_when_below_coordinator_tier_touched_code",
|
|
72
|
+
"skip_when": "entire_run_inline_default_at_coordinator_tier"
|
|
73
|
+
},
|
|
74
|
+
"escalation_policy": {
|
|
75
|
+
"max_section_escalations": 1,
|
|
76
|
+
"allowed_hops": {
|
|
77
|
+
"cheap": "basic",
|
|
78
|
+
"basic": "premium"
|
|
79
|
+
},
|
|
80
|
+
"final_review_fix_reverify_passes": 1
|
|
81
|
+
},
|
|
82
|
+
"budget_policy": {
|
|
83
|
+
"cache_hit_rate_source": "measurement_spike_go_marker",
|
|
84
|
+
"default_cache_hit_rate": 0.0,
|
|
85
|
+
"abort_mode": "inline_default"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
62
88
|
}
|
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
# Bridge API MCP Cross-Platform Smoke-Test Runbook
|
|
2
|
+
|
|
3
|
+
This runbook is executed **by an AI agent running inside a host** (Claude Code,
|
|
4
|
+
Cursor, OpenAI Codex, Windsurf, or VS Code/Copilot). The agent calls real Bridge
|
|
5
|
+
API MCP tools through the host's own MCP client and records a PASS/FAIL verdict
|
|
6
|
+
for each one in a markdown report. The point is to prove that the MCP server
|
|
7
|
+
actually works end-to-end *inside this specific host*, not just that the server
|
|
8
|
+
process started.
|
|
9
|
+
|
|
10
|
+
## Sequestered, not part of the tool surface
|
|
11
|
+
|
|
12
|
+
- This runbook **adds no MCP tool.** It is documentation the host agent reads and
|
|
13
|
+
follows; it never registers a `registerTool(...)` call.
|
|
14
|
+
- The server's **registered MCP tool set remains unchanged** at its existing
|
|
15
|
+
count. Running the smoke test does not add, remove, or rename any tool.
|
|
16
|
+
- The companion `/smoke-test-mcp` command is **opt-in**: it is not scaffolded by
|
|
17
|
+
the default `--init` flow and must be copied in manually (see
|
|
18
|
+
`smoke-test-mcp.md`).
|
|
19
|
+
|
|
20
|
+
## Why protocol-level success is not enough
|
|
21
|
+
|
|
22
|
+
**Protocol-level MCP success is insufficient** to judge a tool as passing. The
|
|
23
|
+
server's `handleResponse()` helper (`mcp_server/src/index.ts`) does **not throw**
|
|
24
|
+
on HTTP errors — it **returns HTTP errors as JSON text content**:
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{ "error": "NOT_FOUND", "status": 404, "message": "..." }
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
So an MCP call can "succeed" at the protocol level (the host returns content with
|
|
31
|
+
no transport error) while the content itself describes a failure. **Agents must
|
|
32
|
+
inspect the returned content** rather than treating invocation success as `PASS`.
|
|
33
|
+
|
|
34
|
+
### Content-based grading
|
|
35
|
+
|
|
36
|
+
For every tool result:
|
|
37
|
+
|
|
38
|
+
1. Read the returned text content.
|
|
39
|
+
2. **Parse the JSON text when possible.** If it parses, inspect fields such as
|
|
40
|
+
`error`, `status`, `message`, and any known success fields for that tool
|
|
41
|
+
(e.g. `status: "decision_page_generated"`, a `file_path`, a `task_id`).
|
|
42
|
+
3. If the content is plain text (e.g. `get_docs_dir` returns a bare path), check
|
|
43
|
+
for expected success markers or saved-file path evidence.
|
|
44
|
+
4. Only then assign a verdict from the vocabulary below.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Phase 0 — Prerequisites
|
|
49
|
+
|
|
50
|
+
Before running anything, confirm:
|
|
51
|
+
|
|
52
|
+
- The host has the `bridge-api` MCP server configured and connected (the tools
|
|
53
|
+
are visible to the agent).
|
|
54
|
+
- You can call `ping` and get a non-error result (this is the first metadata
|
|
55
|
+
check in Phase 2).
|
|
56
|
+
- You have permission to write files under the host's project (the report and
|
|
57
|
+
the local-write canary file are written locally).
|
|
58
|
+
|
|
59
|
+
### Environment variables
|
|
60
|
+
|
|
61
|
+
The server reads these environment variables:
|
|
62
|
+
|
|
63
|
+
| Variable | Meaning |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `BAPI_BASE_URL` | Bridge API base URL |
|
|
66
|
+
| `BAPI_REPO_NAME` | Jira project/repository identifier |
|
|
67
|
+
| `BAPI_API_KEY` | API key used for all calls |
|
|
68
|
+
| `BAPI_PROJECT_ROOT` | Absolute path to the project root |
|
|
69
|
+
| `BAPI_DOCS_DIR` | Local docs directory (default `docs/tmp`) for file output |
|
|
70
|
+
|
|
71
|
+
Project-root resolution detail: in the server, `PROJECT_ROOT` **falls back to
|
|
72
|
+
`process.cwd()`** when `BAPI_PROJECT_ROOT` is unset, and `BAPI_DOCS_DIR` is then
|
|
73
|
+
resolved relative to that root. **Codex-like hosts may need `BAPI_PROJECT_ROOT`
|
|
74
|
+
set manually**, because the working directory the host launches the server from
|
|
75
|
+
is not guaranteed to be the project root.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Phase 1 — Input Collection (collect inputs before starting)
|
|
80
|
+
|
|
81
|
+
Ask the user for the following before making any tool calls:
|
|
82
|
+
|
|
83
|
+
1. **Required:** a **read-only Jira ticket key** that the configured
|
|
84
|
+
`BAPI_API_KEY` can read (used for the Tier 1 read-only checks). It only needs
|
|
85
|
+
to be readable — comments, attachments, tracked state, and generated
|
|
86
|
+
artifacts are all optional.
|
|
87
|
+
2. **Optional:** a **config field name** (for `get_config_field`).
|
|
88
|
+
3. **Optional:** a **pipeline name** (for `get_pipeline_recipe`).
|
|
89
|
+
4. **Optional:** an **attachment identifier or filename** (for
|
|
90
|
+
`download_attachment` / `list_attachments`).
|
|
91
|
+
5. **Optional:** any **artifact or task IDs** (e.g. a `task_id`, `brainstorm_id`,
|
|
92
|
+
or commit ref) for retriever and CI tools.
|
|
93
|
+
6. **Required decision:** explicit **Tier 3 consent** (Tier 3 spends tokens and
|
|
94
|
+
is skipped without it).
|
|
95
|
+
|
|
96
|
+
### Optional input omission rule
|
|
97
|
+
|
|
98
|
+
If the user does not supply an optional input, **omit that parameter from the MCP
|
|
99
|
+
call entirely.** Do **not** send it as `null`, an empty string `""`, or a
|
|
100
|
+
placeholder value. Tools whose only input is missing are graded
|
|
101
|
+
`SKIP_USER_INPUT`, not `FAIL`.
|
|
102
|
+
|
|
103
|
+
### Report redaction rule
|
|
104
|
+
|
|
105
|
+
Never write **`BAPI_API_KEY`**, **authorization headers**, **raw stack traces**,
|
|
106
|
+
or **raw protocol noise** into the report. Base URL and repo name may be
|
|
107
|
+
recorded; secrets must be redacted. (Repeated in the report template below.)
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Phase 2 — Metadata Discovery
|
|
112
|
+
|
|
113
|
+
Run these first; their output populates the report's metadata header and anchors
|
|
114
|
+
all local writes:
|
|
115
|
+
|
|
116
|
+
1. `ping` — connectivity + API key validity.
|
|
117
|
+
2. `get_my_role` — the role of the configured key.
|
|
118
|
+
3. **`get_docs_dir` — call this as one of the first calls.** Store the **exact
|
|
119
|
+
returned docs path** verbatim. This path is the **root for every local write**
|
|
120
|
+
in this run (the report and the local-write canary file). Do not recompute it
|
|
121
|
+
from environment variables.
|
|
122
|
+
|
|
123
|
+
### Path discipline
|
|
124
|
+
|
|
125
|
+
- Every local write **must be anchored to the exact docs directory returned by
|
|
126
|
+
`get_docs_dir`.**
|
|
127
|
+
- Before recording any local write as evidence, **verify the path is absolute and
|
|
128
|
+
resides under the returned docs directory** (a strict prefix containment
|
|
129
|
+
check). A path outside that directory is a `FAIL` for that step.
|
|
130
|
+
- The report file path is:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
<docs_dir>/smoke-test/REPORT-<host>-<timestamp>.md
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- `<host>` sanitization: replace every character outside `[A-Za-z0-9._-]` with
|
|
137
|
+
`-`, collapse repeated separators, and trim leading/trailing separators.
|
|
138
|
+
- `<timestamp>` is a filesystem-safe **UTC** timestamp such as
|
|
139
|
+
`YYYYMMDDTHHMMSSZ` (e.g. `20260525T174500Z`).
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Verdict Vocabulary
|
|
144
|
+
|
|
145
|
+
### Per-tool verdicts
|
|
146
|
+
|
|
147
|
+
| Verdict | Meaning |
|
|
148
|
+
|---|---|
|
|
149
|
+
| `PASS` | Content confirms success. |
|
|
150
|
+
| `PASS_EXPECTED_404` | Artifact retriever returned a clean 404 indicating the artifact is simply absent. |
|
|
151
|
+
| `FAIL` | Content describes an error, or required content is missing. |
|
|
152
|
+
| `SKIP_USER_INPUT` | A required input for this tool was not supplied. |
|
|
153
|
+
| `SKIP_NOT_APPROVED` | Tier 3 (or another gated tool) was not consented to. |
|
|
154
|
+
| `SKIP_NOT_APPLICABLE` | Tool is disabled/not applicable in this environment. |
|
|
155
|
+
| `WARN` | Non-blocking anomaly, including host serialization quirks. |
|
|
156
|
+
|
|
157
|
+
### Overall verdicts
|
|
158
|
+
|
|
159
|
+
`PASS`, `PASS_WITH_WARNINGS`, `FAIL`, `INCOMPLETE`.
|
|
160
|
+
|
|
161
|
+
### Grading rules
|
|
162
|
+
|
|
163
|
+
- Parsed content containing an **`error` key** is a **`FAIL`**, *unless* it is an
|
|
164
|
+
explicitly expected clean-empty condition (an empty artifact retriever).
|
|
165
|
+
- Parsed **`status >= 400`** is a **`FAIL`**, *except* a clean expected **404**
|
|
166
|
+
for an artifact retriever or optional-empty retriever, which is
|
|
167
|
+
`PASS_EXPECTED_404`.
|
|
168
|
+
- **`401` and `403` are always `FAIL`.**
|
|
169
|
+
- **`5xx` is always `FAIL`**, *except* `poll_ci_checks` returning a
|
|
170
|
+
`TOOL_DISABLED` / `503` self-disable response, which is `SKIP_NOT_APPLICABLE`.
|
|
171
|
+
- **Expected-empty artifact retrievers** that return a clean 404 (no artifact
|
|
172
|
+
yet) are **`PASS_EXPECTED_404`**.
|
|
173
|
+
- **Artifact retrievers that return valid non-empty content** are **`PASS`**
|
|
174
|
+
(not `PASS_EXPECTED_404`).
|
|
175
|
+
- **Host/tool invocation errors**, **schema validation failures outside the
|
|
176
|
+
documented host-risk probes**, **empty responses where non-empty content is
|
|
177
|
+
required**, and **failure-prefixed text** such as `Failed to request ...` are
|
|
178
|
+
all **`FAIL`**.
|
|
179
|
+
- A **host boolean-serialization rejection during the dedicated boolean probe**
|
|
180
|
+
(Phase 7) is a **`WARN`** for host behavior — **not** an MCP server `FAIL`.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Phase 3 — Default Pass
|
|
185
|
+
|
|
186
|
+
The default pass is the release-blocking fast path. It runs all Tier 0 tools by
|
|
187
|
+
default plus the read-only ticket checks when a readable ticket was supplied.
|
|
188
|
+
|
|
189
|
+
### All Tier 0 tools run by default
|
|
190
|
+
|
|
191
|
+
`ping`, `get_my_role`, `get_docs_dir`, `get_project_standards`,
|
|
192
|
+
`list_config_fields`, `list_pipelines`, `get_parse_status`,
|
|
193
|
+
`list_pipeline_runs`.
|
|
194
|
+
|
|
195
|
+
(The "fast-pass" list is the minimum release-blocking subset; the tier
|
|
196
|
+
definition is "always run", so do not exclude the other Tier 0 tools.)
|
|
197
|
+
|
|
198
|
+
### Default read-only ticket checks (when a readable ticket is supplied)
|
|
199
|
+
|
|
200
|
+
Run `get_ticket`, `get_comments`, and `get_plan` against the user-supplied
|
|
201
|
+
ticket.
|
|
202
|
+
|
|
203
|
+
- **`get_comments` is preferred**; **`list_attachments` is the fallback** if
|
|
204
|
+
comments are unavailable for the selected ticket.
|
|
205
|
+
- **`get_plan` must be called with a real boolean `save_locally: false`** (a true
|
|
206
|
+
JSON boolean, not the string `"false"`).
|
|
207
|
+
- Grade `get_plan` as **`PASS`** if it returns valid plan content, or
|
|
208
|
+
**`PASS_EXPECTED_404`** if it returns a clean missing-plan 404.
|
|
209
|
+
|
|
210
|
+
### Default overall verdict
|
|
211
|
+
|
|
212
|
+
The default run can be overall **`PASS`** when **all required default calls are
|
|
213
|
+
`PASS` or `PASS_EXPECTED_404`** and the optional tools are skipped for lack of
|
|
214
|
+
input or consent. Add `PASS_WITH_WARNINGS` if any `WARN` was recorded. Reserve
|
|
215
|
+
`INCOMPLETE` for missing required metadata, interrupted execution, or a
|
|
216
|
+
default-set tool that did not run.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Phase 4 — Optional Tier 1
|
|
221
|
+
|
|
222
|
+
Tier 1 tools are read-only but require an input. Run each only when the user
|
|
223
|
+
supplied the relevant input; otherwise record `SKIP_USER_INPUT`.
|
|
224
|
+
|
|
225
|
+
- `get_tickets` — a query/filter (a default project query is acceptable).
|
|
226
|
+
- `get_ticket_state`, `get_jira_transitions`, `resolve_target_status` — the
|
|
227
|
+
ticket key.
|
|
228
|
+
- `get_config_field` — the optional config field name.
|
|
229
|
+
- `get_pipeline_recipe` — the optional pipeline name.
|
|
230
|
+
- `list_attachments` / `download_attachment` — the optional attachment input.
|
|
231
|
+
- The artifact retrievers `get_architecture`, `get_clarifying_questions`,
|
|
232
|
+
`get_ticket_critique`, `get_reimplement_context`, `get_deep_research`,
|
|
233
|
+
`get_brainstorm` — grade a clean empty result as `PASS_EXPECTED_404` and valid
|
|
234
|
+
content as `PASS`.
|
|
235
|
+
- `poll_ci_checks` — see the matrix note; `SKIP_NOT_APPLICABLE` when CI is not
|
|
236
|
+
configured.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Phase 5 — Tier 2 Canary (`generate_decision_page`)
|
|
241
|
+
|
|
242
|
+
Tier 2 is the **local-only file-write canary** and **always runs**. It forces a
|
|
243
|
+
real HTML file write instead of the no-decision fast path (which writes nothing).
|
|
244
|
+
|
|
245
|
+
Call `generate_decision_page` with this **verbatim** payload. It is a fixed,
|
|
246
|
+
local-only fixture: the handler validates `ticket_key` against
|
|
247
|
+
`^[A-Za-z][A-Za-z0-9_-]*$` (which `BAPI-SMOKE` satisfies) and writes
|
|
248
|
+
`<docs_dir>/review/<ticket_key>-decisions.html` **without ever calling Jira**, so
|
|
249
|
+
the literal `BAPI-SMOKE` key is safe and deterministic across all hosts. Do not
|
|
250
|
+
substitute the user's ticket key.
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
{
|
|
254
|
+
"ticket_key": "BAPI-SMOKE",
|
|
255
|
+
"actionable_items": [
|
|
256
|
+
{
|
|
257
|
+
"id": "E-1",
|
|
258
|
+
"question": "Should the smoke-test canary write a real decision-page HTML file?",
|
|
259
|
+
"original_question": "Does generate_decision_page write a local file when given one actionable item?",
|
|
260
|
+
"why_it_matters": "Proves the MCP server's local file-write path works end to end inside this host.",
|
|
261
|
+
"recommendation_explanation": "Writing a real file is the only way to verify the disk-write canary instead of taking the no-op no-decisions fast path.",
|
|
262
|
+
"codebase_evidence": "generate_decision_page writes <docs_dir>/review/<ticket_key>-decisions.html when actionable_items is non-empty (mcp_server/src/index.ts generate_decision_page handler).",
|
|
263
|
+
"source": "BAPI-314 smoke-test runbook — Tier 2 canary",
|
|
264
|
+
"recommendation_index": 0,
|
|
265
|
+
"options": ["Write the decision page file", "Skip the file write"],
|
|
266
|
+
"option_consequences": [
|
|
267
|
+
"A real HTML file is created under the docs directory — the desired canary signal.",
|
|
268
|
+
"No file is written and the canary cannot prove local writes — undesired."
|
|
269
|
+
]
|
|
270
|
+
}
|
|
271
|
+
],
|
|
272
|
+
"clear_improvements": [
|
|
273
|
+
{
|
|
274
|
+
"id": "CI-1",
|
|
275
|
+
"title": "Anchor all local writes under get_docs_dir",
|
|
276
|
+
"action": "Resolve the report path and the canary file path from the exact get_docs_dir result.",
|
|
277
|
+
"confidence": "high",
|
|
278
|
+
"source": "BAPI-314 smoke-test runbook — path discipline"
|
|
279
|
+
}
|
|
280
|
+
]
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Tier 2 grading
|
|
285
|
+
|
|
286
|
+
- **`PASS`**: the response JSON contains `status: "decision_page_generated"`
|
|
287
|
+
**and** an **absolute** `file_path` that resides **under the exact
|
|
288
|
+
`get_docs_dir` result**. Verify containment by checking that `file_path`
|
|
289
|
+
begins with the stored docs directory prefix.
|
|
290
|
+
- **`FAIL`**: the response is `no_decisions_needed`, **or** `file_path` is absent,
|
|
291
|
+
**or** the path is **not absolute**, **or** the path is **outside the returned
|
|
292
|
+
docs directory**.
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Phase 6 — Optional Tier 3
|
|
297
|
+
|
|
298
|
+
**Tier 3 is skipped by default and requires explicit user consent**, because it
|
|
299
|
+
**may spend tokens** and can take **up to roughly 15 minutes**. Without consent,
|
|
300
|
+
record each Tier 3 tool as `SKIP_NOT_APPROVED`.
|
|
301
|
+
|
|
302
|
+
Ask for one explicit Tier 3 consent decision; if granted, the user may pick which
|
|
303
|
+
flows to run. Use **bounded polling with increasing intervals and a maximum wait
|
|
304
|
+
of about 15 minutes** for any async flow.
|
|
305
|
+
|
|
306
|
+
### Synchronous Tier 3 tool
|
|
307
|
+
|
|
308
|
+
- **`second_opinion` is synchronous and token-costing.** It blocks and returns
|
|
309
|
+
its result directly — it is **not** an async request/get flow. Do not try to
|
|
310
|
+
capture an ID for it.
|
|
311
|
+
|
|
312
|
+
### Async request/get Tier 3 tools
|
|
313
|
+
|
|
314
|
+
| Submit tool | Returns | Retrieve with |
|
|
315
|
+
|---|---|---|
|
|
316
|
+
| `request_deep_research` | a **`task_id`** | `get_deep_research` |
|
|
317
|
+
| `request_brainstorm` | a **`brainstorm_id`** | `get_brainstorm` |
|
|
318
|
+
| `request_plan_generation` | (ticket-key based) | `get_plan` |
|
|
319
|
+
| `request_architecture` | (ticket-key based) | `get_architecture` |
|
|
320
|
+
| `request_clarifying_questions` | (ticket-key based) | `get_clarifying_questions` |
|
|
321
|
+
| `request_ticket_critique` | (ticket-key based) | `get_ticket_critique` |
|
|
322
|
+
| `request_reimplement_context` | (ticket-key based) | `get_reimplement_context` |
|
|
323
|
+
|
|
324
|
+
- **`request_ticket_review`** is the combined submit side for review. There is
|
|
325
|
+
**no dedicated `get_*` review-retrieval tool** for it. Retrieve its results
|
|
326
|
+
with **`get_clarifying_questions`** and **`get_ticket_critique`**, or pass
|
|
327
|
+
`wait_for_result: true` **only if explicitly approved**.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Phase 7 — Host Probes (host-specific probes)
|
|
332
|
+
|
|
333
|
+
Record evidence for the cross-platform risks that differ between Claude Code,
|
|
334
|
+
Cursor, Codex, Windsurf, and VS Code/Copilot.
|
|
335
|
+
|
|
336
|
+
### Boolean serialization probe
|
|
337
|
+
|
|
338
|
+
Target an artifact retriever with a **real `save_locally` boolean** — preferably
|
|
339
|
+
**`get_plan` with `save_locally: false`** when a plan artifact exists.
|
|
340
|
+
|
|
341
|
+
- `get_plan`'s `save_locally` is a strict `z.boolean().optional()`; the schema
|
|
342
|
+
performs **no string coercion**. If the **host serializes `false` as the string
|
|
343
|
+
`"false"`** and Zod rejects it with a 400, record **`WARN`** for the host's
|
|
344
|
+
serialization behavior — this is the cross-platform quirk the probe exists to
|
|
345
|
+
surface, **not** an MCP server `FAIL`.
|
|
346
|
+
- If **no artifact exists** and the probe returns a clean 404, record
|
|
347
|
+
**`SKIP_NOT_APPLICABLE`**.
|
|
348
|
+
- If content exists and a **file is saved despite `save_locally: false`**, record
|
|
349
|
+
**`WARN`**.
|
|
350
|
+
|
|
351
|
+
### Optional-parameter omission probe
|
|
352
|
+
|
|
353
|
+
Record whether the agent **avoided sending `null`, empty strings, or
|
|
354
|
+
placeholders** for `.optional()` schema fields throughout the run.
|
|
355
|
+
|
|
356
|
+
### Codex project-root probe
|
|
357
|
+
|
|
358
|
+
Record whether **`BAPI_PROJECT_ROOT` is set** and whether **`get_docs_dir`
|
|
359
|
+
resolves to the expected project-root-relative docs directory**.
|
|
360
|
+
|
|
361
|
+
### Windows separator probe
|
|
362
|
+
|
|
363
|
+
Record the **returned path formats** (separator style) and **still perform the
|
|
364
|
+
containment checks** against the exact docs directory regardless of separator
|
|
365
|
+
differences.
|
|
366
|
+
|
|
367
|
+
### Tier 3 async round-trip probe
|
|
368
|
+
|
|
369
|
+
Only with explicit consent, run one `request_*` → `get_*` round trip end-to-end
|
|
370
|
+
(bounded polling) to prove the async pattern works in this host.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Phase 8 — Report Writing
|
|
375
|
+
|
|
376
|
+
Write the report to `<docs_dir>/smoke-test/REPORT-<host>-<timestamp>.md` using the
|
|
377
|
+
template below. Create the `<docs_dir>/smoke-test/` directory if needed. Use the
|
|
378
|
+
host's normal file-write capability (no new MCP tool is involved).
|
|
379
|
+
|
|
380
|
+
### Report template
|
|
381
|
+
|
|
382
|
+
```markdown
|
|
383
|
+
# MCP Smoke-Test Report
|
|
384
|
+
|
|
385
|
+
## Metadata
|
|
386
|
+
- Host name / version: <host and version>
|
|
387
|
+
- OS: <operating system>
|
|
388
|
+
- MCP package version: <version if known>
|
|
389
|
+
- Base URL: <BAPI_BASE_URL>
|
|
390
|
+
- Repo name: <BAPI_REPO_NAME>
|
|
391
|
+
- Project root: <BAPI_PROJECT_ROOT or resolved root>
|
|
392
|
+
- Docs dir: <exact get_docs_dir result>
|
|
393
|
+
- Role: <get_my_role result>
|
|
394
|
+
- Test ticket: <user-supplied ticket key>
|
|
395
|
+
- Tier 3 consent: <yes/no>
|
|
396
|
+
|
|
397
|
+
## Summary counts
|
|
398
|
+
- PASS: <n>
|
|
399
|
+
- PASS_EXPECTED_404: <n>
|
|
400
|
+
- FAIL: <n>
|
|
401
|
+
- SKIP_USER_INPUT: <n>
|
|
402
|
+
- SKIP_NOT_APPROVED: <n>
|
|
403
|
+
- SKIP_NOT_APPLICABLE: <n>
|
|
404
|
+
- WARN: <n>
|
|
405
|
+
|
|
406
|
+
## Overall verdict
|
|
407
|
+
<PASS | PASS_WITH_WARNINGS | FAIL | INCOMPLETE>
|
|
408
|
+
|
|
409
|
+
## Per-tool results
|
|
410
|
+
| Tier | Tool | Inputs | Expected result | Actual summary | Verdict | Evidence | File paths | Duration | Notes |
|
|
411
|
+
|---|---|---|---|---|---|---|---|---|---|
|
|
412
|
+
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
|
|
413
|
+
|
|
414
|
+
## Host-specific probes
|
|
415
|
+
- Boolean serialization probe: <result>
|
|
416
|
+
- Optional-parameter omission probe: <result>
|
|
417
|
+
- Codex project-root probe: <result>
|
|
418
|
+
- Windows separator probe: <result>
|
|
419
|
+
- Tier 3 async round-trip probe: <result or skipped>
|
|
420
|
+
|
|
421
|
+
## Path evidence
|
|
422
|
+
- get_docs_dir: <exact path>
|
|
423
|
+
- Tier 2 HTML file path: <absolute path under docs dir>
|
|
424
|
+
- Report file path: <absolute path under docs dir>
|
|
425
|
+
|
|
426
|
+
## Cleanup
|
|
427
|
+
v1 default execution creates **no Jira/server-side cleanup requirement**. The
|
|
428
|
+
Tier 2 generated HTML decision page is **retained as evidence** that local writes
|
|
429
|
+
work. (This section is reserved for future Tier 4 runs.)
|
|
430
|
+
|
|
431
|
+
## Redaction note
|
|
432
|
+
This report excludes **secrets, authorization headers, API keys, stack traces,
|
|
433
|
+
and raw protocol noise.** Sensitive values are redacted.
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Phase 9 — Cleanup
|
|
439
|
+
|
|
440
|
+
- v1 default execution requires **no Jira/server-side cleanup**.
|
|
441
|
+
- The Tier 2 `generate_decision_page` HTML file is **kept** as evidence; do not
|
|
442
|
+
delete it unless the user asks.
|
|
443
|
+
- This section is reserved for future Tier 4 (mutating) runs, which are out of
|
|
444
|
+
scope for v1.
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
## Full 55-Tool Smoke Tier Matrix
|
|
449
|
+
|
|
450
|
+
Every registered MCP tool appears **exactly once** below with its smoke tier.
|
|
451
|
+
Tier 4 (mutating/hazardous) tools are **deferred in v1**.
|
|
452
|
+
|
|
453
|
+
Coverage reconciliation: **8 + 18 + 1 + 10 + 18 = 55**.
|
|
454
|
+
|
|
455
|
+
| Tier | Tool | Default action / expected-empty / special handling |
|
|
456
|
+
|---|---|---|
|
|
457
|
+
| Tier 0 | `ping` | Zero-input read; always run. |
|
|
458
|
+
| Tier 0 | `get_my_role` | Zero-input read; always run. |
|
|
459
|
+
| Tier 0 | `get_docs_dir` | Zero-input read; always run; call first to anchor writes. |
|
|
460
|
+
| Tier 0 | `get_project_standards` | Zero-input read; always run. |
|
|
461
|
+
| Tier 0 | `list_config_fields` | Zero-input read; always run. |
|
|
462
|
+
| Tier 0 | `list_pipelines` | Zero-input read; always run. |
|
|
463
|
+
| Tier 0 | `get_parse_status` | Zero-input read; always run. |
|
|
464
|
+
| Tier 0 | `list_pipeline_runs` | Zero-input read; always run. |
|
|
465
|
+
| Tier 1 | `get_tickets` | Read-only; needs a query/filter. |
|
|
466
|
+
| Tier 1 | `get_ticket` | Read-only; needs ticket key (default-pass tool). |
|
|
467
|
+
| Tier 1 | `get_comments` | Read-only; needs ticket key (preferred default-pass tool). |
|
|
468
|
+
| Tier 1 | `get_plan` | Artifact retriever; `PASS` with content, `PASS_EXPECTED_404` when cleanly empty; boolean probe target. |
|
|
469
|
+
| Tier 1 | `get_architecture` | Artifact retriever; `PASS_EXPECTED_404` when cleanly empty. |
|
|
470
|
+
| Tier 1 | `get_clarifying_questions` | Artifact retriever; `PASS_EXPECTED_404` when cleanly empty. |
|
|
471
|
+
| Tier 1 | `get_ticket_critique` | Artifact retriever; `PASS_EXPECTED_404` when cleanly empty. |
|
|
472
|
+
| Tier 1 | `get_reimplement_context` | Artifact retriever; `PASS_EXPECTED_404` when cleanly empty. |
|
|
473
|
+
| Tier 1 | `get_deep_research` | Artifact retriever; `PASS_EXPECTED_404` when cleanly empty. |
|
|
474
|
+
| Tier 1 | `get_brainstorm` | Artifact retriever; `PASS_EXPECTED_404` when cleanly empty. |
|
|
475
|
+
| Tier 1 | `get_ticket_state` | Read-only; needs ticket key. |
|
|
476
|
+
| Tier 1 | `get_jira_transitions` | Read-only; needs ticket key. |
|
|
477
|
+
| Tier 1 | `resolve_target_status` | Read-only; needs ticket key. |
|
|
478
|
+
| Tier 1 | `get_config_field` | Read-only; needs a config field name. |
|
|
479
|
+
| Tier 1 | `list_attachments` | Read-only; needs ticket key; comments-fallback tool. |
|
|
480
|
+
| Tier 1 | `download_attachment` | Tier 1 network read; secondary **path-canary** — saves locally only when an attachment input is supplied; omit `file_path` or keep any override under `get_docs_dir`. |
|
|
481
|
+
| Tier 1 | `poll_ci_checks` | `SKIP_NOT_APPLICABLE` when disabled with `TOOL_DISABLED`/503, or when `resolve_ci_checks` has not populated CI configuration. |
|
|
482
|
+
| Tier 1 | `get_pipeline_recipe` | Read-only; needs a pipeline name. |
|
|
483
|
+
| Tier 2 | `generate_decision_page` | Local-only file-write canary; always run with the verbatim payload above. |
|
|
484
|
+
| Tier 3 | `second_opinion` | Synchronous, token-costing; opt-in. |
|
|
485
|
+
| Tier 3 | `generate_image` | Synchronous, token/credit-costing; spends provider credits; opt-in. |
|
|
486
|
+
| Tier 3 | `request_plan_generation` | Async (ticket-key based); retrieve with `get_plan`; opt-in. |
|
|
487
|
+
| Tier 3 | `request_architecture` | Async (ticket-key based); retrieve with `get_architecture`; opt-in. |
|
|
488
|
+
| Tier 3 | `request_clarifying_questions` | Async (ticket-key based); retrieve with `get_clarifying_questions`; opt-in. |
|
|
489
|
+
| Tier 3 | `request_ticket_critique` | Async (ticket-key based); retrieve with `get_ticket_critique`; opt-in. |
|
|
490
|
+
| Tier 3 | `request_ticket_review` | Async submit; retrieve with `get_clarifying_questions` + `get_ticket_critique`; opt-in. |
|
|
491
|
+
| Tier 3 | `request_reimplement_context` | Async (ticket-key based); retrieve with `get_reimplement_context`; opt-in. |
|
|
492
|
+
| Tier 3 | `request_deep_research` | Async; returns `task_id`; retrieve with `get_deep_research`; opt-in. |
|
|
493
|
+
| Tier 3 | `request_brainstorm` | Async; returns `brainstorm_id`; retrieve with `get_brainstorm`; opt-in. |
|
|
494
|
+
| Tier 4 | `create_ticket` | Mutating; deferred in v1. |
|
|
495
|
+
| Tier 4 | `add_comment` | Mutating; deferred in v1. |
|
|
496
|
+
| Tier 4 | `update_ticket_description` | Mutating; deferred in v1. |
|
|
497
|
+
| Tier 4 | `upload_attachment` | Mutating; deferred in v1. |
|
|
498
|
+
| Tier 4 | `track_ticket` | Mutating; deferred in v1. |
|
|
499
|
+
| Tier 4 | `update_ticket_state` | Mutating; deferred in v1. |
|
|
500
|
+
| Tier 4 | `update_jira_status` | Mutating; deferred in v1. |
|
|
501
|
+
| Tier 4 | `update_config_field` | Mutating; deferred in v1. |
|
|
502
|
+
| Tier 4 | `create_pull_request` | Mutating; deferred in v1. |
|
|
503
|
+
| Tier 4 | `resolve_ci_checks` | Cache-mutating/orchestration; deferred in v1. |
|
|
504
|
+
| Tier 4 | `run_pipeline` | Orchestration (can dispatch mutating tools); deferred in v1. |
|
|
505
|
+
| Tier 4 | `resume_pipeline` | Orchestration; deferred in v1. |
|
|
506
|
+
| Tier 4 | `delete_pipeline_run` | Mutating (deletes run state); deferred in v1. |
|
|
507
|
+
| Tier 4 | `parse_repository` | Hazardous (Pinecone index); deferred in v1. |
|
|
508
|
+
| Tier 4 | `regenerate_directory_map` | Hazardous; deferred in v1. |
|
|
509
|
+
| Tier 4 | `run_full_automation` | Orchestration (dispatches mutating child pipelines / spawns worktrees); deferred in v1. |
|
|
510
|
+
| Tier 4 | `resume_full_automation` | Orchestration; deferred in v1. |
|
|
511
|
+
| Tier 4 | `record_tiered_section_metric` | Writes server-side telemetry state (tiered_section_metrics row); deferred in v1. |
|