@bridge_gpt/mcp-server 0.1.13 → 0.1.16
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 +58 -0
- package/build/agent-registry.js +68 -0
- package/build/commands.generated.js +4 -3
- package/build/doctor.js +172 -0
- package/build/index.js +818 -95
- package/build/pipeline-orchestrator.js +593 -0
- package/build/pipeline-utils.js +50 -12
- package/build/pipelines.generated.js +44 -29
- package/build/start-tickets-prereqs.js +346 -0
- package/build/start-tickets.js +1210 -0
- package/build/version.generated.js +1 -1
- package/package.json +7 -7
- package/pipelines/check-ci-ticket.json +8 -2
- package/pipelines/implement-ticket.json +8 -2
- package/pipelines/pr-ticket.json +1 -2
- package/build/decision-page-schema.test.js +0 -248
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// AUTO-GENERATED — do not edit manually. Regenerate with: npm run build
|
|
2
|
-
export const VERSION = "0.1.
|
|
2
|
+
export const VERSION = "0.1.16";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bridge_gpt/mcp-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.16",
|
|
4
4
|
"description": "Bridge API MCP server — exposes Jira endpoints as MCP tools for Claude Code agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -9,10 +9,8 @@
|
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"build/",
|
|
12
|
-
"!build
|
|
13
|
-
"!build/
|
|
14
|
-
"!build/update-check.test.js",
|
|
15
|
-
"!build/cli-upgrade.test.js",
|
|
12
|
+
"!build/**/*.test.js",
|
|
13
|
+
"!build/integration/**",
|
|
16
14
|
"pipelines/",
|
|
17
15
|
"README.md",
|
|
18
16
|
"LICENSE"
|
|
@@ -21,7 +19,8 @@
|
|
|
21
19
|
"build": "node scripts/bundle-version.js && node scripts/bundle-pipelines.js && node scripts/bundle-commands.js && node scripts/bundle-agents.js && tsc",
|
|
22
20
|
"postbuild": "node scripts/prepend-shebang.cjs",
|
|
23
21
|
"start": "node build/index.js",
|
|
24
|
-
"test": "node --test build/pipeline-utils.test.js build/update-check.test.js build/cli-upgrade.test.js",
|
|
22
|
+
"test": "node --test build/pipeline-utils.test.js build/update-check.test.js build/cli-upgrade.test.js build/decision-page-schema.test.js build/decision-page-template.test.js build/bundle-pipelines.test.js build/instructions-contract.test.js build/pipeline-orchestrator-persistence.test.js build/pipeline-orchestrator-execution.test.js build/pipeline-orchestrator-integration.test.js build/index-static.test.js build/start-tickets.test.js build/agent-registry.test.js build/start-tickets-prereqs.test.js build/doctor.test.js build/package-static.test.js",
|
|
23
|
+
"test:integration": "node --test build/integration/refresh-main.integration.test.js build/integration/start-tickets.integration.test.js build/integration/doctor.integration.test.js",
|
|
25
24
|
"prepublishOnly": "npm run build && node scripts/verify-shebang.cjs"
|
|
26
25
|
},
|
|
27
26
|
"dependencies": {
|
|
@@ -30,7 +29,8 @@
|
|
|
30
29
|
},
|
|
31
30
|
"devDependencies": {
|
|
32
31
|
"@types/node": "^22.0.0",
|
|
33
|
-
"typescript": "^5.7.0"
|
|
32
|
+
"typescript": "^5.7.0",
|
|
33
|
+
"undici": "^6.25.0"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|
|
36
36
|
"node": ">=18.0.0"
|
|
@@ -18,8 +18,14 @@
|
|
|
18
18
|
{
|
|
19
19
|
"type": "agent_task",
|
|
20
20
|
"instruction_file": "create-pr.md",
|
|
21
|
-
"description": "Create a pull request with a title derived from the commit subject"
|
|
22
|
-
|
|
21
|
+
"description": "Create a pull request with a title derived from the commit subject"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"type": "mcp_call",
|
|
25
|
+
"tool": "get_config_field",
|
|
26
|
+
"params": { "field_name": "ci_followup_config" },
|
|
27
|
+
"description": "Fetch repo-specific CI follow-up configuration",
|
|
28
|
+
"on_error": "warn_and_continue"
|
|
23
29
|
},
|
|
24
30
|
{
|
|
25
31
|
"type": "agent_task",
|
|
@@ -34,8 +34,7 @@
|
|
|
34
34
|
{
|
|
35
35
|
"type": "agent_task",
|
|
36
36
|
"instruction_file": "create-pr.md",
|
|
37
|
-
"description": "Create a pull request with a title derived from the commit subject"
|
|
38
|
-
"requires_approval": true
|
|
37
|
+
"description": "Create a pull request with a title derived from the commit subject"
|
|
39
38
|
},
|
|
40
39
|
{
|
|
41
40
|
"type": "mcp_call",
|
|
@@ -47,6 +46,13 @@
|
|
|
47
46
|
"description": "Resolve and transition ticket to post-PR status",
|
|
48
47
|
"on_error": "warn_and_continue"
|
|
49
48
|
},
|
|
49
|
+
{
|
|
50
|
+
"type": "mcp_call",
|
|
51
|
+
"tool": "get_config_field",
|
|
52
|
+
"params": { "field_name": "ci_followup_config" },
|
|
53
|
+
"description": "Fetch repo-specific CI follow-up configuration",
|
|
54
|
+
"on_error": "warn_and_continue"
|
|
55
|
+
},
|
|
50
56
|
{
|
|
51
57
|
"type": "agent_task",
|
|
52
58
|
"instruction_file": "monitor-ci-checks.md",
|
package/pipelines/pr-ticket.json
CHANGED
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
{
|
|
19
19
|
"type": "agent_task",
|
|
20
20
|
"instruction_file": "create-pr.md",
|
|
21
|
-
"description": "Create a pull request with a title derived from the commit subject"
|
|
22
|
-
"requires_approval": true
|
|
21
|
+
"description": "Create a pull request with a title derived from the commit subject"
|
|
23
22
|
}
|
|
24
23
|
]
|
|
25
24
|
}
|
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import { describe, it } from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { ActionableItemSchema } from "./decision-page-schema.js";
|
|
4
|
-
// ---------------------------------------------------------------------------
|
|
5
|
-
// Fixture helpers
|
|
6
|
-
// ---------------------------------------------------------------------------
|
|
7
|
-
function validItemRaw() {
|
|
8
|
-
return {
|
|
9
|
-
id: "E-1",
|
|
10
|
-
question: "E-1: Timeout behavior needs a decision",
|
|
11
|
-
original_question: "Should the ticket specify timeout behavior for slow upstream calls?",
|
|
12
|
-
why_it_matters: "Timeout behavior affects retry paths and determines whether users see stale, failed, or delayed responses.",
|
|
13
|
-
options: ["Keep existing", "Add configurable", "Defer"],
|
|
14
|
-
option_consequences: [
|
|
15
|
-
"No new implementation work, but slow calls keep current failure behavior.",
|
|
16
|
-
"Implementers add configuration and tests for timeout-specific behavior.",
|
|
17
|
-
"The ticket remains smaller, but timeout ambiguity persists for a later change.",
|
|
18
|
-
],
|
|
19
|
-
recommendation_explanation: "Configurable timeout best matches code paths that already branch on external service latency.",
|
|
20
|
-
codebase_evidence: "Assessment: ...\n\nCodebase Evidence:\n- src/api/timeouts.ts:42 — current latency-branching helper",
|
|
21
|
-
source: "Clarifying Q1 (prior round, weak concurrence)",
|
|
22
|
-
recommendation_index: 1,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
// Schema validation — happy path
|
|
27
|
-
// ---------------------------------------------------------------------------
|
|
28
|
-
describe("ActionableItemSchema — happy path", () => {
|
|
29
|
-
it("accepts a valid actionable item using the new contract", () => {
|
|
30
|
-
const result = ActionableItemSchema.safeParse(validItemRaw());
|
|
31
|
-
assert.equal(result.success, true);
|
|
32
|
-
});
|
|
33
|
-
it("does not require a context field", () => {
|
|
34
|
-
const item = validItemRaw();
|
|
35
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
36
|
-
assert.equal(result.success, true);
|
|
37
|
-
if (result.success) {
|
|
38
|
-
assert.equal(result.data.context, undefined);
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
it("accepts the minimum branch count (2 options, 2 consequences)", () => {
|
|
42
|
-
const item = {
|
|
43
|
-
...validItemRaw(),
|
|
44
|
-
options: ["A", "B"],
|
|
45
|
-
option_consequences: ["Consequence A.", "Consequence B."],
|
|
46
|
-
recommendation_index: 0,
|
|
47
|
-
};
|
|
48
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
49
|
-
assert.equal(result.success, true);
|
|
50
|
-
});
|
|
51
|
-
it("accepts the maximum branch count (4 options, 4 consequences)", () => {
|
|
52
|
-
const item = {
|
|
53
|
-
...validItemRaw(),
|
|
54
|
-
options: ["A", "B", "C", "D"],
|
|
55
|
-
option_consequences: ["A.", "B.", "C.", "D."],
|
|
56
|
-
recommendation_index: 0,
|
|
57
|
-
};
|
|
58
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
59
|
-
assert.equal(result.success, true);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
// Schema validation — required fields
|
|
64
|
-
// ---------------------------------------------------------------------------
|
|
65
|
-
describe("ActionableItemSchema — required clarity fields", () => {
|
|
66
|
-
for (const fieldName of [
|
|
67
|
-
"original_question",
|
|
68
|
-
"why_it_matters",
|
|
69
|
-
"recommendation_explanation",
|
|
70
|
-
"codebase_evidence",
|
|
71
|
-
]) {
|
|
72
|
-
it(`rejects payloads missing ${fieldName}`, () => {
|
|
73
|
-
const item = { ...validItemRaw() };
|
|
74
|
-
delete item[fieldName];
|
|
75
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
76
|
-
assert.equal(result.success, false);
|
|
77
|
-
if (!result.success) {
|
|
78
|
-
const paths = result.error.issues.map((issue) => issue.path.join("."));
|
|
79
|
-
assert.ok(paths.includes(fieldName), `expected issue at path ${fieldName}, got ${paths.join(", ")}`);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
it("rejects payloads missing option_consequences", () => {
|
|
84
|
-
const item = { ...validItemRaw() };
|
|
85
|
-
delete item.option_consequences;
|
|
86
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
87
|
-
assert.equal(result.success, false);
|
|
88
|
-
if (!result.success) {
|
|
89
|
-
const paths = result.error.issues.map((issue) => issue.path.join("."));
|
|
90
|
-
assert.ok(paths.includes("option_consequences"));
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
it("rejects payloads that still use a legacy context field instead of the new clarity fields", () => {
|
|
94
|
-
const item = { ...validItemRaw(), context: "legacy context blob" };
|
|
95
|
-
delete item.original_question;
|
|
96
|
-
delete item.why_it_matters;
|
|
97
|
-
delete item.recommendation_explanation;
|
|
98
|
-
delete item.codebase_evidence;
|
|
99
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
100
|
-
assert.equal(result.success, false);
|
|
101
|
-
if (!result.success) {
|
|
102
|
-
const paths = result.error.issues.map((issue) => issue.path.join("."));
|
|
103
|
-
assert.ok(paths.includes("original_question"));
|
|
104
|
-
assert.ok(paths.includes("why_it_matters"));
|
|
105
|
-
assert.ok(paths.includes("recommendation_explanation"));
|
|
106
|
-
assert.ok(paths.includes("codebase_evidence"));
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
});
|
|
110
|
-
// ---------------------------------------------------------------------------
|
|
111
|
-
// Schema validation — branch count boundaries
|
|
112
|
-
// ---------------------------------------------------------------------------
|
|
113
|
-
describe("ActionableItemSchema — 2–4 branch boundary", () => {
|
|
114
|
-
it("rejects options with only one branch", () => {
|
|
115
|
-
const item = {
|
|
116
|
-
...validItemRaw(),
|
|
117
|
-
options: ["Only one"],
|
|
118
|
-
option_consequences: ["Only one."],
|
|
119
|
-
recommendation_index: 0,
|
|
120
|
-
};
|
|
121
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
122
|
-
assert.equal(result.success, false);
|
|
123
|
-
});
|
|
124
|
-
it("rejects options with five branches", () => {
|
|
125
|
-
const item = {
|
|
126
|
-
...validItemRaw(),
|
|
127
|
-
options: ["A", "B", "C", "D", "E"],
|
|
128
|
-
option_consequences: ["A.", "B.", "C.", "D.", "E."],
|
|
129
|
-
recommendation_index: 0,
|
|
130
|
-
};
|
|
131
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
132
|
-
assert.equal(result.success, false);
|
|
133
|
-
});
|
|
134
|
-
it("rejects option_consequences with only one entry", () => {
|
|
135
|
-
const item = {
|
|
136
|
-
...validItemRaw(),
|
|
137
|
-
options: ["A", "B"],
|
|
138
|
-
option_consequences: ["Only one."],
|
|
139
|
-
recommendation_index: 0,
|
|
140
|
-
};
|
|
141
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
142
|
-
assert.equal(result.success, false);
|
|
143
|
-
});
|
|
144
|
-
it("rejects option_consequences with five entries", () => {
|
|
145
|
-
const item = {
|
|
146
|
-
...validItemRaw(),
|
|
147
|
-
options: ["A", "B"],
|
|
148
|
-
option_consequences: ["A.", "B.", "C.", "D.", "E."],
|
|
149
|
-
recommendation_index: 0,
|
|
150
|
-
};
|
|
151
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
152
|
-
assert.equal(result.success, false);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
// ---------------------------------------------------------------------------
|
|
156
|
-
// Schema validation — option/consequence parity
|
|
157
|
-
// ---------------------------------------------------------------------------
|
|
158
|
-
describe("ActionableItemSchema — option/consequence parity", () => {
|
|
159
|
-
it("rejects mismatched lengths and attaches the issue to option_consequences", () => {
|
|
160
|
-
const item = {
|
|
161
|
-
...validItemRaw(),
|
|
162
|
-
options: ["A", "B", "C"],
|
|
163
|
-
option_consequences: ["A.", "B."],
|
|
164
|
-
recommendation_index: 0,
|
|
165
|
-
};
|
|
166
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
167
|
-
assert.equal(result.success, false);
|
|
168
|
-
if (!result.success) {
|
|
169
|
-
const matchingIssue = result.error.issues.find((issue) => issue.path.join(".") === "option_consequences" && /must match options length/.test(issue.message));
|
|
170
|
-
assert.ok(matchingIssue, `expected an option_consequences issue with the parity message; got: ${JSON.stringify(result.error.issues)}`);
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
it("rejects mismatched lengths in the other direction", () => {
|
|
174
|
-
const item = {
|
|
175
|
-
...validItemRaw(),
|
|
176
|
-
options: ["A", "B"],
|
|
177
|
-
option_consequences: ["A.", "B.", "C."],
|
|
178
|
-
recommendation_index: 0,
|
|
179
|
-
};
|
|
180
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
181
|
-
assert.equal(result.success, false);
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
// ---------------------------------------------------------------------------
|
|
185
|
-
// Schema validation — recommendation_index upper bound
|
|
186
|
-
// ---------------------------------------------------------------------------
|
|
187
|
-
describe("ActionableItemSchema — recommendation_index upper bound", () => {
|
|
188
|
-
it("rejects recommendation_index >= options.length and attaches the issue to recommendation_index", () => {
|
|
189
|
-
const item = {
|
|
190
|
-
...validItemRaw(),
|
|
191
|
-
options: ["A", "B", "C"],
|
|
192
|
-
option_consequences: ["A.", "B.", "C."],
|
|
193
|
-
recommendation_index: 99,
|
|
194
|
-
};
|
|
195
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
196
|
-
assert.equal(result.success, false);
|
|
197
|
-
if (!result.success) {
|
|
198
|
-
const matchingIssue = result.error.issues.find((issue) => issue.path.join(".") === "recommendation_index" && /out of bounds/.test(issue.message));
|
|
199
|
-
assert.ok(matchingIssue, `expected a recommendation_index issue with the out-of-bounds message; got: ${JSON.stringify(result.error.issues)}`);
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
it("rejects recommendation_index equal to options.length (off-by-one)", () => {
|
|
203
|
-
const item = {
|
|
204
|
-
...validItemRaw(),
|
|
205
|
-
options: ["A", "B"],
|
|
206
|
-
option_consequences: ["A.", "B."],
|
|
207
|
-
recommendation_index: 2,
|
|
208
|
-
};
|
|
209
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
210
|
-
assert.equal(result.success, false);
|
|
211
|
-
});
|
|
212
|
-
});
|
|
213
|
-
// ---------------------------------------------------------------------------
|
|
214
|
-
// id format — must produce a valid HTML id so getElementById can find the
|
|
215
|
-
// per-item textarea/radio. Whitespace and dots silently break that lookup
|
|
216
|
-
// (and would skip the "no comment selected" validation), so the schema
|
|
217
|
-
// rejects anything outside [A-Za-z0-9_-].
|
|
218
|
-
// ---------------------------------------------------------------------------
|
|
219
|
-
describe("ActionableItemSchema — id format", () => {
|
|
220
|
-
it("rejects an id containing whitespace", () => {
|
|
221
|
-
const item = { ...validItemRaw(), id: "E 1" };
|
|
222
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
223
|
-
assert.equal(result.success, false);
|
|
224
|
-
if (!result.success) {
|
|
225
|
-
assert.ok(result.error.issues.some((issue) => issue.path[0] === "id"));
|
|
226
|
-
}
|
|
227
|
-
});
|
|
228
|
-
it("rejects an id containing only whitespace", () => {
|
|
229
|
-
const item = { ...validItemRaw(), id: " " };
|
|
230
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
231
|
-
assert.equal(result.success, false);
|
|
232
|
-
});
|
|
233
|
-
it("rejects an id containing a dot", () => {
|
|
234
|
-
const item = { ...validItemRaw(), id: "E.1" };
|
|
235
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
236
|
-
assert.equal(result.success, false);
|
|
237
|
-
});
|
|
238
|
-
it("accepts an id with hyphens (matches the instruction's generator format)", () => {
|
|
239
|
-
const item = { ...validItemRaw(), id: "E-1" };
|
|
240
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
241
|
-
assert.equal(result.success, true);
|
|
242
|
-
});
|
|
243
|
-
it("accepts an id with underscores", () => {
|
|
244
|
-
const item = { ...validItemRaw(), id: "decision_1" };
|
|
245
|
-
const result = ActionableItemSchema.safeParse(item);
|
|
246
|
-
assert.equal(result.success, true);
|
|
247
|
-
});
|
|
248
|
-
});
|