@aletheia-works/vivarium-mcp 0.1.4 → 0.2.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AA0DnE,wBAAgB,YAAY,IAAI,MAAM,CAkGrC;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAI/C"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AA+DnE,wBAAgB,YAAY,IAAI,MAAM,CAsGrC;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAI/C"}
package/dist/server.js CHANGED
@@ -4,6 +4,7 @@
4
4
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
5
5
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
6
  import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
7
+ import { CREATE_FORK_PR_TOOL, createForkPr, } from './tools/create_fork_pr.js';
7
8
  import { GET_RECIPE_TOOL, getRecipe } from './tools/get_recipe.js';
8
9
  import { LIST_RECIPES_TOOL, listRecipes, } from './tools/list_recipes.js';
9
10
  import { LOOKUP_VERDICT_TOOL, lookupVerdict, } from './tools/lookup_verdict.js';
@@ -21,7 +22,7 @@ const SERVER_NAME = 'vivarium-mcp';
21
22
  // description / surface refinements) — the project is still pre-1.0
22
23
  // and `prepare_fix_candidate` is meaningful but fully opt-in, so a minor
23
24
  // bump would overstate the impact.
24
- const SERVER_VERSION = '0.1.4';
25
+ const SERVER_VERSION = '0.2.1';
25
26
  export function createServer() {
26
27
  const server = new Server({ name: SERVER_NAME, version: SERVER_VERSION }, { capabilities: { tools: {} } });
27
28
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
@@ -35,6 +36,7 @@ export function createServer() {
35
36
  VERIFY_AND_REPORT_FIX_TOOL,
36
37
  PREPARE_NEW_RECIPE_TOOL,
37
38
  PREPARE_FIX_CANDIDATE_TOOL,
39
+ CREATE_FORK_PR_TOOL,
38
40
  ],
39
41
  }));
40
42
  server.setRequestHandler(CallToolRequestSchema, async (req) => {
@@ -70,6 +72,9 @@ export function createServer() {
70
72
  case 'prepare_fix_candidate':
71
73
  payload = await prepareFixCandidate(args);
72
74
  break;
75
+ case 'create_fork_pr':
76
+ payload = await createForkPr(args);
77
+ break;
73
78
  default:
74
79
  return {
75
80
  isError: true,
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,oEAAoE;AACpE,2CAA2C;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EACL,iBAAiB,EACjB,WAAW,GAEZ,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,mBAAmB,EACnB,aAAa,GACd,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,gBAAgB,EAChB,UAAU,GAEX,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,0BAA0B,EAC1B,mBAAmB,GAEpB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,uBAAuB,EACvB,gBAAgB,GAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,2BAA2B,EAC3B,oBAAoB,GAErB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,0BAA0B,EAC1B,kBAAkB,GAEnB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,sBAAsB,EACtB,eAAe,GAEhB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,WAAW,GAAG,cAAc,CAAC;AACnC,kEAAkE;AAClE,sEAAsE;AACtE,oEAAoE;AACpE,sEAAsE;AACtE,oEAAoE;AACpE,yEAAyE;AACzE,mCAAmC;AACnC,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,cAAc,EAAE,EAC9C,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAC;IAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,EAAE;YACL,iBAAiB;YACjB,eAAe;YACf,mBAAmB;YACnB,gBAAgB;YAChB,2BAA2B;YAC3B,sBAAsB;YACtB,0BAA0B;YAC1B,uBAAuB;YACvB,0BAA0B;SAC3B;KACF,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC7B,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAA4B,CAAC;QAErE,IAAI,OAAgB,CAAC;QACrB,IAAI,CAAC;YACH,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,cAAc;oBACjB,OAAO,GAAG,MAAM,WAAW,CAAC,IAAuB,CAAC,CAAC;oBACrD,MAAM;gBACR,KAAK,YAAY;oBACf,OAAO,GAAG,MAAM,SAAS,CAAC,IAAwB,CAAC,CAAC;oBACpD,MAAM;gBACR,KAAK,gBAAgB;oBACnB,OAAO,GAAG,MAAM,aAAa,CAAC,IAAwB,CAAC,CAAC;oBACxD,MAAM;gBACR,KAAK,aAAa;oBAChB,OAAO,GAAG,MAAM,UAAU,CAAC,IAAiC,CAAC,CAAC;oBAC9D,MAAM;gBACR,KAAK,wBAAwB;oBAC3B,OAAO,GAAG,MAAM,oBAAoB,CAClC,IAA2C,CAC5C,CAAC;oBACF,MAAM;gBACR,KAAK,mBAAmB;oBACtB,OAAO,GAAG,MAAM,eAAe,CAC7B,IAAsC,CACvC,CAAC;oBACF,MAAM;gBACR,KAAK,uBAAuB;oBAC1B,OAAO,GAAG,MAAM,kBAAkB,CAChC,IAAyC,CAC1C,CAAC;oBACF,MAAM;gBACR,KAAK,oBAAoB;oBACvB,OAAO,GAAG,MAAM,gBAAgB,CAC9B,IAAuC,CACxC,CAAC;oBACF,MAAM;gBACR,KAAK,uBAAuB;oBAC1B,OAAO,GAAG,MAAM,mBAAmB,CACjC,IAA0C,CAC3C,CAAC;oBACF,MAAM;gBACR;oBACE,OAAO;wBACL,OAAO,EAAE,IAAI;wBACb,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,iBAAiB,IAAI,EAAE;6BAC9B;yBACF;qBACF,CAAC;YACN,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,QAAQ,IAAI,WAAW,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;qBAChF;iBACF;aACF,CAAC;QACJ,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBACvC;aACF;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import type { RoundtripState } from '../types.js';
2
+ export interface CreateForkPrArgs {
3
+ slug: string;
4
+ current_state: Partial<RoundtripState>;
5
+ pr_title: string;
6
+ pr_body?: string;
7
+ dry_run?: boolean;
8
+ }
9
+ export interface CreateForkPrOk {
10
+ ok: true;
11
+ slug: string;
12
+ upstream_repo: string;
13
+ head: string;
14
+ title: string;
15
+ body: string;
16
+ draft: true;
17
+ dry_run: boolean;
18
+ command: string;
19
+ pr_url?: string;
20
+ }
21
+ export interface CreateForkPrError {
22
+ ok: false;
23
+ error: string;
24
+ }
25
+ export type CreateForkPrResult = CreateForkPrOk | CreateForkPrError;
26
+ export interface GhRunResult {
27
+ status: number | null;
28
+ stdout: string;
29
+ stderr: string;
30
+ }
31
+ export type GhRunner = (args: string[]) => GhRunResult;
32
+ export declare function _setGhRunnerForTesting(runner: GhRunner | null): void;
33
+ export declare function createForkPr(args: CreateForkPrArgs): Promise<CreateForkPrResult>;
34
+ export declare const CREATE_FORK_PR_TOOL: {
35
+ readonly name: "create_fork_pr";
36
+ readonly description: "Open a draft PR on the upstream repository from the contributor's already-pushed fork branch. The output side of the round-trip loop. Conservative by design: `dry_run` defaults to true (returns the gh command without executing); `--draft` is mandatory (caller cannot opt out); AI authorship is disclosed via a boilerplate footer appended to the PR body (the `ai: generated` LABEL from AGENTS.md §4.6 is Vivarium-internal and is intentionally NOT applied — upstream repos rarely carry it and contributors usually lack permission to create it). The tool refuses to run unless `computeNextAction(current_state) === 'open_fork_pr'` — that single check enforces all the round-trip preconditions in one place (verdicts captured with the expected polarity, the Vivarium-side PR already opened, no existing upstream PR, status not blocked/merged). The fork branch must already exist on GitHub — this tool does NOT clone, commit, or push on the caller's behalf, and does NOT create the fork (use `gh repo fork` manually first). Pair with `verify_and_report_fix` upstream of this call and with `prepare_fix_candidate` (Layer 1) when registering a fix-candidate spec.";
37
+ readonly inputSchema: {
38
+ readonly type: "object";
39
+ readonly properties: {
40
+ readonly slug: {
41
+ readonly type: "string";
42
+ readonly pattern: "^[a-z0-9]+(-[a-z0-9]+)*$";
43
+ readonly description: "Kebab-case recipe slug (e.g. 'mpmath-983', 'bash-local-shadows-exit'). Must exist in the catalogue.";
44
+ };
45
+ readonly current_state: {
46
+ readonly type: "object";
47
+ readonly description: "Parsed roundtrip.json contents. Must contain `upstream_issue`, `fork` (owner/repo/branch), and `verdicts` with both `unfixed.verdict='reproduced'` and `fixed.verdict='unreproduced'`. The tool refuses to run otherwise.";
48
+ readonly additionalProperties: true;
49
+ };
50
+ readonly pr_title: {
51
+ readonly type: "string";
52
+ readonly minLength: 1;
53
+ readonly description: "PR title. Caller is responsible for following the upstream project's commit / PR title conventions (Conventional Commits, etc.).";
54
+ };
55
+ readonly pr_body: {
56
+ readonly type: "string";
57
+ readonly description: "PR body (Markdown). Defaults to empty. Include a link back to the Vivarium recipe and the upstream issue, and disclose AI authorship per AGENTS.md §4.6 (the `ai: generated` label is applied automatically; surfacing the disclosure in the body is good practice).";
58
+ };
59
+ readonly dry_run: {
60
+ readonly type: "boolean";
61
+ readonly default: true;
62
+ readonly description: "When true (the default), the tool returns the exact `gh pr create` command + a structured summary WITHOUT calling gh. Set to false to actually open the PR. The MCP server never opens an upstream PR by accident.";
63
+ };
64
+ };
65
+ readonly required: readonly ["slug", "current_state", "pr_title"];
66
+ };
67
+ };
68
+ //# sourceMappingURL=create_fork_pr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_fork_pr.d.ts","sourceRoot":"","sources":["../../src/tools/create_fork_pr.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMlD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IAId,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,IAAI,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,kBAAkB,GAAG,cAAc,GAAG,iBAAiB,CAAC;AAEpE,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,WAAW,CAAC;AAgBvD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAEpE;AA2BD,wBAAsB,YAAY,CAChC,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAkL7B;AAED,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuCtB,CAAC"}
@@ -0,0 +1,261 @@
1
+ // MCP tool that opens a draft PR on the upstream repository from the
2
+ // contributor's already-pushed fork branch. The output side of the
3
+ // round-trip loop — the first step that crosses the boundary from
4
+ // "internal verification" to "publicly visible state change".
5
+ //
6
+ // Phase 4 of the round-trip automation. Conservative by design:
7
+ // - dry_run defaults to true; explicit opt-in needed to actually
8
+ // create the PR.
9
+ // - The PR is always opened with --draft. Merging out of draft
10
+ // stays a human action.
11
+ // - AI authorship is disclosed in the PR body (boilerplate footer
12
+ // appended automatically). Label-based disclosure is NOT
13
+ // attempted: AGENTS.md §4.6's `ai: generated` label is a
14
+ // Vivarium-internal contract — the upstream repo may not have
15
+ // that label and contributors typically lack write permission
16
+ // to create it.
17
+ // - The tool refuses to run unless the recipe's full round-trip
18
+ // state machine selects `open_fork_pr` next — that is, the
19
+ // status is not blocked/merged, an upstream PR is not already
20
+ // open, the unfixed+fixed verdicts are both captured with the
21
+ // expected polarity, and the Vivarium-side PR has already been
22
+ // opened. Each of those conditions is enforced upstream by
23
+ // `computeNextAction` so this tool stays consistent with it.
24
+ // - Local clone, commit, and push are caller responsibilities —
25
+ // this tool does NOT mutate the working tree. The fork branch
26
+ // must already exist on GitHub before calling.
27
+ import { spawnSync } from 'node:child_process';
28
+ import { getCatalogue } from '../catalogue.js';
29
+ import { computeNextAction, parseUpstreamIssue, } from './verify_and_report_fix.js';
30
+ const defaultGhRunner = (args) => {
31
+ const r = spawnSync('gh', args, {
32
+ encoding: 'utf-8',
33
+ timeout: 60_000,
34
+ });
35
+ return {
36
+ status: r.status,
37
+ stdout: r.stdout ?? '',
38
+ stderr: r.stderr ?? '',
39
+ };
40
+ };
41
+ let ghRunner = defaultGhRunner;
42
+ export function _setGhRunnerForTesting(runner) {
43
+ ghRunner = runner ?? defaultGhRunner;
44
+ }
45
+ // Boilerplate appended to every upstream PR body so the AI authorship
46
+ // disclosure is visible to upstream maintainers. The `ai: generated`
47
+ // LABEL from AGENTS.md §4.6 is a Vivarium-internal contract; upstream
48
+ // repos may not carry that label, and contributors typically lack the
49
+ // write permission needed to create it. Disclose in prose instead.
50
+ const AI_AUTHORSHIP_FOOTER = '\n\n---\n\n*This pull request was generated by an AI agent via the Vivarium round-trip automation. The candidate fix was verified against an in-Vivarium reproduction (`verdicts.unfixed = "reproduced"` → `verdicts.fixed = "unreproduced"`). Please review carefully before merging.*\n';
51
+ function appendAuthorshipFooter(body) {
52
+ // Idempotent: a caller that already pasted the footer (or part of
53
+ // it) shouldn't see it duplicated.
54
+ if (body.includes('Vivarium round-trip automation'))
55
+ return body;
56
+ return body.length === 0
57
+ ? AI_AUTHORSHIP_FOOTER.trimStart()
58
+ : body + AI_AUTHORSHIP_FOOTER;
59
+ }
60
+ function quoteShell(value) {
61
+ // Single-quote and escape any embedded single quote — produces
62
+ // a shell-safe representation for the returned `command` string.
63
+ // Real execution goes through spawn with argv arrays, so this
64
+ // affects only what the caller sees as a paste-ready line.
65
+ return `'${value.replace(/'/g, `'\\''`)}'`;
66
+ }
67
+ export async function createForkPr(args) {
68
+ const slug = args.slug?.trim();
69
+ if (!slug) {
70
+ return { ok: false, error: 'missing required argument: slug' };
71
+ }
72
+ const title = args.pr_title?.trim();
73
+ if (!title) {
74
+ return { ok: false, error: 'pr_title is required' };
75
+ }
76
+ const { recipes } = await getCatalogue();
77
+ const recipe = recipes.find((r) => r.slug === slug);
78
+ if (!recipe) {
79
+ return { ok: false, error: `recipe not found: ${slug}` };
80
+ }
81
+ const state = args.current_state;
82
+ if (!state || typeof state !== 'object') {
83
+ return { ok: false, error: 'current_state is required' };
84
+ }
85
+ // State-machine integrity: the upstream PR is only the next legal
86
+ // action when `computeNextAction(state) === 'open_fork_pr'`. That
87
+ // single check enforces all the round-trip preconditions in one
88
+ // place — `status` is not blocked/merged, an upstream_pr is not
89
+ // already recorded, the verdicts are both captured with the
90
+ // expected polarity (unfixed=reproduced + fixed=unreproduced),
91
+ // and a Vivarium-side `vivarium_pr` has already been opened.
92
+ // Using the same function the rest of the tooling uses avoids
93
+ // drift between this tool and `verify_and_report_fix`.
94
+ const nextAction = computeNextAction(state);
95
+ if (nextAction !== 'open_fork_pr') {
96
+ return {
97
+ ok: false,
98
+ error: `state machine expected next_action 'open_fork_pr' but computeNextAction(current_state) returned '${nextAction}'. Resolve the round-trip state first (capture verdicts, open the Vivarium-side PR, or clear status: blocked) before opening the upstream PR.`,
99
+ };
100
+ }
101
+ // Upstream owner/repo from upstream_issue URL.
102
+ const upstream = parseUpstreamIssue(state.upstream_issue);
103
+ if (!upstream) {
104
+ return {
105
+ ok: false,
106
+ error: `cannot derive upstream owner/repo from current_state.upstream_issue (got "${state.upstream_issue ?? 'missing'}"). Expected form: https://github.com/<owner>/<repo>/issues/<n>.`,
107
+ };
108
+ }
109
+ // Fork coordinates.
110
+ const fork = state.fork;
111
+ if (!fork ||
112
+ !fork.owner?.trim() ||
113
+ !fork.repo?.trim() ||
114
+ !fork.branch?.trim()) {
115
+ return {
116
+ ok: false,
117
+ error: 'current_state.fork must have owner, repo, and branch (the contributor fork the candidate fix lives on)',
118
+ };
119
+ }
120
+ const upstreamRepo = `${upstream.owner}/${upstream.repo}`;
121
+ const head = `${fork.owner}:${fork.branch}`;
122
+ const body = appendAuthorshipFooter(args.pr_body ?? '');
123
+ const dryRun = args.dry_run !== false; // default true
124
+ // Build a paste-ready command string. spawn execution below uses an
125
+ // argv array, not this string — they share the same arguments.
126
+ // No `--label` here: upstream repos may not carry the label and
127
+ // contributors usually can't create one. AI authorship is surfaced
128
+ // via the body footer instead.
129
+ const command = [
130
+ 'gh',
131
+ 'pr',
132
+ 'create',
133
+ '--repo',
134
+ upstreamRepo,
135
+ '--head',
136
+ head,
137
+ '--draft',
138
+ '--title',
139
+ quoteShell(title),
140
+ '--body',
141
+ quoteShell(body),
142
+ ].join(' ');
143
+ if (dryRun) {
144
+ return {
145
+ ok: true,
146
+ slug,
147
+ upstream_repo: upstreamRepo,
148
+ head,
149
+ title,
150
+ body,
151
+ draft: true,
152
+ dry_run: true,
153
+ command,
154
+ };
155
+ }
156
+ // dry_run=false → execute. Pre-flight checks first so a partial
157
+ // failure doesn't leave the PR half-opened.
158
+ // Guardrail 2: gh auth must be set up.
159
+ const authCheck = ghRunner(['auth', 'status']);
160
+ if (authCheck.status !== 0) {
161
+ return {
162
+ ok: false,
163
+ error: `gh auth check failed: ${authCheck.stderr.trim() || '<no stderr>'}. Run 'gh auth login' first.`,
164
+ };
165
+ }
166
+ // Fork must exist and be reachable by the active gh auth.
167
+ const forkCheck = ghRunner([
168
+ 'repo',
169
+ 'view',
170
+ `${fork.owner}/${fork.repo}`,
171
+ '--json',
172
+ 'name',
173
+ ]);
174
+ if (forkCheck.status !== 0) {
175
+ return {
176
+ ok: false,
177
+ error: `fork ${fork.owner}/${fork.repo} not found or inaccessible. Create it manually with 'gh repo fork ${upstreamRepo}' first — this tool does not fork on the caller's behalf.`,
178
+ };
179
+ }
180
+ // The named branch must already be pushed to the fork.
181
+ const branchCheck = ghRunner([
182
+ 'api',
183
+ `repos/${fork.owner}/${fork.repo}/branches/${fork.branch}`,
184
+ ]);
185
+ if (branchCheck.status !== 0) {
186
+ return {
187
+ ok: false,
188
+ error: `branch ${fork.branch} not found on fork ${fork.owner}/${fork.repo}. Push the fix branch to the fork before calling this tool.`,
189
+ };
190
+ }
191
+ // Open the PR. --draft is hard-coded; caller cannot opt out.
192
+ // No --label here (see the comment near the command builder above).
193
+ const create = ghRunner([
194
+ 'pr',
195
+ 'create',
196
+ '--repo',
197
+ upstreamRepo,
198
+ '--head',
199
+ head,
200
+ '--draft',
201
+ '--title',
202
+ title,
203
+ '--body',
204
+ body,
205
+ ]);
206
+ if (create.status !== 0) {
207
+ return {
208
+ ok: false,
209
+ error: `gh pr create failed: ${create.stderr.trim() || '<no stderr>'}`,
210
+ };
211
+ }
212
+ // gh pr create prints the PR URL to stdout on success.
213
+ const prUrl = create.stdout.trim().split('\n').pop() ?? '';
214
+ return {
215
+ ok: true,
216
+ slug,
217
+ upstream_repo: upstreamRepo,
218
+ head,
219
+ title,
220
+ body,
221
+ draft: true,
222
+ dry_run: false,
223
+ command,
224
+ pr_url: prUrl,
225
+ };
226
+ }
227
+ export const CREATE_FORK_PR_TOOL = {
228
+ name: 'create_fork_pr',
229
+ description: "Open a draft PR on the upstream repository from the contributor's already-pushed fork branch. The output side of the round-trip loop. Conservative by design: `dry_run` defaults to true (returns the gh command without executing); `--draft` is mandatory (caller cannot opt out); AI authorship is disclosed via a boilerplate footer appended to the PR body (the `ai: generated` LABEL from AGENTS.md §4.6 is Vivarium-internal and is intentionally NOT applied — upstream repos rarely carry it and contributors usually lack permission to create it). The tool refuses to run unless `computeNextAction(current_state) === 'open_fork_pr'` — that single check enforces all the round-trip preconditions in one place (verdicts captured with the expected polarity, the Vivarium-side PR already opened, no existing upstream PR, status not blocked/merged). The fork branch must already exist on GitHub — this tool does NOT clone, commit, or push on the caller's behalf, and does NOT create the fork (use `gh repo fork` manually first). Pair with `verify_and_report_fix` upstream of this call and with `prepare_fix_candidate` (Layer 1) when registering a fix-candidate spec.",
230
+ inputSchema: {
231
+ type: 'object',
232
+ properties: {
233
+ slug: {
234
+ type: 'string',
235
+ pattern: '^[a-z0-9]+(-[a-z0-9]+)*$',
236
+ description: "Kebab-case recipe slug (e.g. 'mpmath-983', 'bash-local-shadows-exit'). Must exist in the catalogue.",
237
+ },
238
+ current_state: {
239
+ type: 'object',
240
+ description: "Parsed roundtrip.json contents. Must contain `upstream_issue`, `fork` (owner/repo/branch), and `verdicts` with both `unfixed.verdict='reproduced'` and `fixed.verdict='unreproduced'`. The tool refuses to run otherwise.",
241
+ additionalProperties: true,
242
+ },
243
+ pr_title: {
244
+ type: 'string',
245
+ minLength: 1,
246
+ description: "PR title. Caller is responsible for following the upstream project's commit / PR title conventions (Conventional Commits, etc.).",
247
+ },
248
+ pr_body: {
249
+ type: 'string',
250
+ description: "PR body (Markdown). Defaults to empty. Include a link back to the Vivarium recipe and the upstream issue, and disclose AI authorship per AGENTS.md §4.6 (the `ai: generated` label is applied automatically; surfacing the disclosure in the body is good practice).",
251
+ },
252
+ dry_run: {
253
+ type: 'boolean',
254
+ default: true,
255
+ description: 'When true (the default), the tool returns the exact `gh pr create` command + a structured summary WITHOUT calling gh. Set to false to actually open the PR. The MCP server never opens an upstream PR by accident.',
256
+ },
257
+ },
258
+ required: ['slug', 'current_state', 'pr_title'],
259
+ },
260
+ };
261
+ //# sourceMappingURL=create_fork_pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create_fork_pr.js","sourceRoot":"","sources":["../../src/tools/create_fork_pr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Verdict } from '../types.js';
2
+ export interface RunLayer1VerdictArgs {
3
+ slug: string;
4
+ fix_url?: string;
5
+ workspace_path?: string;
6
+ }
7
+ export interface RunLayer1VerdictOk {
8
+ ok: true;
9
+ slug: string;
10
+ verdict: Verdict;
11
+ captured_at: string;
12
+ duration_ms: number;
13
+ fix_url: string | null;
14
+ }
15
+ export interface RunLayer1VerdictError {
16
+ ok: false;
17
+ error: string;
18
+ stderr_tail?: string;
19
+ duration_ms: number;
20
+ }
21
+ export type RunLayer1VerdictResult = RunLayer1VerdictOk | RunLayer1VerdictError;
22
+ export interface SpawnRunResult {
23
+ status: number | null;
24
+ stdout: string;
25
+ stderr: string;
26
+ }
27
+ export type SpawnRunner = (input: {
28
+ cwd: string;
29
+ command: string;
30
+ args: string[];
31
+ env: NodeJS.ProcessEnv;
32
+ }) => SpawnRunResult;
33
+ export declare function _setSpawnRunnerForTesting(runner: SpawnRunner | null): void;
34
+ export type VerdictReader = (outputPath: string) => string;
35
+ export declare function _setVerdictReaderForTesting(reader: VerdictReader | null): void;
36
+ export declare function runLayer1Verdict(args: RunLayer1VerdictArgs): Promise<RunLayer1VerdictResult>;
37
+ //# sourceMappingURL=run_layer1_verdict.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run_layer1_verdict.d.ts","sourceRoot":"","sources":["../../src/tools/run_layer1_verdict.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IAKjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,qBAAqB;IACpC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,sBAAsB,GAC9B,kBAAkB,GAClB,qBAAqB,CAAC;AAI1B,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB,KAAK,cAAc,CAAC;AAqBrB,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAE1E;AAID,MAAM,MAAM,aAAa,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,CAAC;AAM3D,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,aAAa,GAAG,IAAI,GAC3B,IAAI,CAEN;AAeD,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,sBAAsB,CAAC,CAiGjC"}
@@ -0,0 +1,134 @@
1
+ // Internal helper for `verify_and_report_fix` on Layer 1 recipes.
2
+ // Drives the existing Playwright harness via a targeted `--grep
3
+ // "verdict-capture: <slug>"` invocation, reads back the verdict JSON
4
+ // the spec writes to `VERDICT_CAPTURE_OUTPUT`. Not exposed as an MCP
5
+ // tool: callers go through `verify_and_report_fix` for the layer-
6
+ // abstracted entrypoint.
7
+ //
8
+ // Phase 3 of the round-trip automation plan. Replaces the Phase 1
9
+ // "return commands as strings" Layer 1 path with real execution.
10
+ import { spawnSync } from 'node:child_process';
11
+ import { readFileSync, unlinkSync } from 'node:fs';
12
+ import { tmpdir } from 'node:os';
13
+ import { join } from 'node:path';
14
+ const defaultSpawnRunner = ({ cwd, command, args, env }) => {
15
+ const r = spawnSync(command, args, {
16
+ cwd,
17
+ env,
18
+ encoding: 'utf-8',
19
+ // Playwright + Pyodide cold-start can sit in the 60-90 second range
20
+ // per case; the spec's own timeout is 75s. Hard-cap the spawn at
21
+ // 5 minutes so a hung Playwright child cannot wedge the MCP server.
22
+ timeout: 5 * 60 * 1000,
23
+ });
24
+ return {
25
+ status: r.status,
26
+ stdout: r.stdout ?? '',
27
+ stderr: r.stderr ?? '',
28
+ };
29
+ };
30
+ let spawnRunner = defaultSpawnRunner;
31
+ export function _setSpawnRunnerForTesting(runner) {
32
+ spawnRunner = runner ?? defaultSpawnRunner;
33
+ }
34
+ const defaultVerdictReader = (p) => readFileSync(p, 'utf-8');
35
+ let verdictReader = defaultVerdictReader;
36
+ export function _setVerdictReaderForTesting(reader) {
37
+ verdictReader = reader ?? defaultVerdictReader;
38
+ }
39
+ const DEFAULT_WORKSPACE_PATH = 'src/layer1_wasm';
40
+ function isVerdict(value) {
41
+ return value === 'reproduced' || value === 'unreproduced';
42
+ }
43
+ export async function runLayer1Verdict(args) {
44
+ const slug = args.slug?.trim();
45
+ if (!slug) {
46
+ return { ok: false, error: 'missing required argument: slug', duration_ms: 0 };
47
+ }
48
+ const workspacePath = args.workspace_path ?? DEFAULT_WORKSPACE_PATH;
49
+ const outputPath = join(tmpdir(), `vivarium-verdict-${slug}-${Date.now()}-${Math.random().toString(36).slice(2)}.json`);
50
+ const env = {
51
+ ...process.env,
52
+ VERDICT_CAPTURE_OUTPUT: outputPath,
53
+ };
54
+ if (args.fix_url)
55
+ env['PLAYWRIGHT_FIX_URL'] = args.fix_url;
56
+ const startedAt = Date.now();
57
+ const spawn = spawnRunner({
58
+ cwd: workspacePath,
59
+ command: 'bun',
60
+ args: ['run', 'test', '--grep', `verdict-capture: ${slug}`],
61
+ env,
62
+ });
63
+ const durationMs = Date.now() - startedAt;
64
+ if (spawn.status !== 0) {
65
+ // Best-effort cleanup of the tmp output if it exists.
66
+ try {
67
+ unlinkSync(outputPath);
68
+ }
69
+ catch {
70
+ /* ignore */
71
+ }
72
+ return {
73
+ ok: false,
74
+ error: `playwright exited with status ${spawn.status}`,
75
+ stderr_tail: spawn.stderr.slice(-2000),
76
+ duration_ms: durationMs,
77
+ };
78
+ }
79
+ let raw;
80
+ try {
81
+ raw = verdictReader(outputPath);
82
+ }
83
+ catch (err) {
84
+ return {
85
+ ok: false,
86
+ error: `failed to read verdict output (${outputPath}): ${err instanceof Error ? err.message : String(err)}`,
87
+ stderr_tail: spawn.stderr.slice(-2000),
88
+ duration_ms: durationMs,
89
+ };
90
+ }
91
+ let parsed;
92
+ try {
93
+ parsed = JSON.parse(raw);
94
+ }
95
+ catch (err) {
96
+ return {
97
+ ok: false,
98
+ error: `verdict output is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,
99
+ duration_ms: durationMs,
100
+ };
101
+ }
102
+ if (parsed.slug !== slug) {
103
+ return {
104
+ ok: false,
105
+ error: `verdict output slug "${parsed.slug}" does not match requested "${slug}"`,
106
+ duration_ms: durationMs,
107
+ };
108
+ }
109
+ if (!isVerdict(parsed.verdict)) {
110
+ return {
111
+ ok: false,
112
+ error: `verdict output contains unexpected verdict value "${parsed.verdict}"`,
113
+ duration_ms: durationMs,
114
+ };
115
+ }
116
+ // Real impl cleans up the tmp file; injected reader (tests) skip.
117
+ if (verdictReader === defaultVerdictReader) {
118
+ try {
119
+ unlinkSync(outputPath);
120
+ }
121
+ catch {
122
+ /* ignore */
123
+ }
124
+ }
125
+ return {
126
+ ok: true,
127
+ slug,
128
+ verdict: parsed.verdict,
129
+ captured_at: parsed.captured_at ?? new Date().toISOString(),
130
+ duration_ms: durationMs,
131
+ fix_url: parsed.fix_url ?? null,
132
+ };
133
+ }
134
+ //# sourceMappingURL=run_layer1_verdict.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run_layer1_verdict.js","sourceRoot":"","sources":["../../src/tools/run_layer1_verdict.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { Verdict, VerdictSnapshot } from '../types.js';
2
+ export interface RunLayer23VerdictArgs {
3
+ slug: string;
4
+ mode: 'unfixed' | 'fixed';
5
+ branch_image?: string;
6
+ expected_verdict?: Verdict;
7
+ poll_interval_ms?: number;
8
+ poll_timeout_ms?: number;
9
+ repo?: string;
10
+ }
11
+ export interface RunLayer23VerdictOk {
12
+ ok: true;
13
+ slug: string;
14
+ mode: 'unfixed' | 'fixed';
15
+ verdict: Verdict;
16
+ captured_at: string;
17
+ duration_ms: number;
18
+ source: 'deployed-snapshot' | 'workflow-artefact';
19
+ workflow_run_id?: number;
20
+ }
21
+ export interface RunLayer23VerdictError {
22
+ ok: false;
23
+ error: string;
24
+ duration_ms: number;
25
+ workflow_run_id?: number;
26
+ }
27
+ export type RunLayer23VerdictResult = RunLayer23VerdictOk | RunLayer23VerdictError;
28
+ export interface GhRunResult {
29
+ status: number | null;
30
+ stdout: string;
31
+ stderr: string;
32
+ }
33
+ export type GhRunner = (args: string[]) => GhRunResult;
34
+ export declare function _setGhRunnerForTesting(runner: GhRunner | null): void;
35
+ export type SnapshotFetcher = (slug: string) => Promise<VerdictSnapshot | null>;
36
+ export declare function _setSnapshotFetcherForTesting(fetcher: SnapshotFetcher | null): void;
37
+ export type Sleeper = (ms: number) => Promise<void>;
38
+ export declare function _setSleeperForTesting(s: Sleeper | null): void;
39
+ export declare function runLayer23Verdict(args: RunLayer23VerdictArgs): Promise<RunLayer23VerdictResult>;
40
+ //# sourceMappingURL=run_layer23_verdict.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run_layer23_verdict.d.ts","sourceRoot":"","sources":["../../src/tools/run_layer23_verdict.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE5D,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,IAAI,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,mBAAmB,GAAG,mBAAmB,CAAC;IAClD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,uBAAuB,GAC/B,mBAAmB,GACnB,sBAAsB,CAAC;AAE3B,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,WAAW,CAAC;AAkBvD,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,GAAG,IAAI,CAEpE;AAKD,MAAM,MAAM,eAAe,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;AAWhF,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,eAAe,GAAG,IAAI,GAC9B,IAAI,CAEN;AAGD,MAAM,MAAM,OAAO,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAOpD,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,IAAI,CAE7D;AAcD,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,qBAAqB,GAC1B,OAAO,CAAC,uBAAuB,CAAC,CAiSlC"}