@h-rig/bundle-default-lifecycle 0.0.6-alpha.157 → 0.0.6-alpha.159

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 (54) hide show
  1. package/dist/src/cli.d.ts +1 -7
  2. package/dist/src/cli.js +5 -2
  3. package/dist/src/control-plane/completion-verification.js +1591 -118
  4. package/dist/src/control-plane/hooks/inject-context.d.ts +2 -0
  5. package/dist/src/control-plane/hooks/inject-context.js +175 -0
  6. package/dist/src/control-plane/hooks/shared.d.ts +11 -0
  7. package/dist/src/control-plane/hooks/shared.js +44 -0
  8. package/dist/src/control-plane/hooks/submodule-branch.d.ts +2 -0
  9. package/dist/src/control-plane/hooks/submodule-branch.js +432 -0
  10. package/dist/src/control-plane/hooks/task-runtime-start.d.ts +2 -0
  11. package/dist/src/control-plane/hooks/task-runtime-start.js +429 -0
  12. package/dist/src/control-plane/materialize-task-config.d.ts +29 -0
  13. package/dist/src/control-plane/materialize-task-config.js +95 -0
  14. package/dist/src/control-plane/native/git-ops.d.ts +67 -0
  15. package/dist/src/control-plane/native/git-ops.js +1390 -0
  16. package/dist/src/control-plane/policy.d.ts +3 -0
  17. package/dist/src/control-plane/policy.js +226 -0
  18. package/dist/src/control-plane/pr-automation.d.ts +2 -0
  19. package/dist/src/control-plane/pr-automation.js +26 -16
  20. package/dist/src/control-plane/pr-merge-gate-cap.d.ts +10 -0
  21. package/dist/src/control-plane/pr-merge-gate-cap.js +13 -0
  22. package/dist/src/control-plane/task-data.d.ts +13 -0
  23. package/dist/src/control-plane/task-data.js +12 -0
  24. package/dist/src/control-plane/task-verify.js +131 -59
  25. package/dist/src/control-plane/verifier.d.ts +1 -3
  26. package/dist/src/control-plane/verifier.js +133 -57
  27. package/dist/src/defaultPipeline.d.ts +1 -1
  28. package/dist/src/defaultPipeline.js +5 -2
  29. package/dist/src/index.d.ts +0 -2
  30. package/dist/src/index.js +1908 -290
  31. package/dist/src/native/closeout-runners.js +22 -2
  32. package/dist/src/native/github-auth-env.d.ts +2 -0
  33. package/dist/src/native/github-auth-env.js +25 -0
  34. package/dist/src/native/host-git.d.ts +6 -0
  35. package/dist/src/native/host-git.js +62 -0
  36. package/dist/src/native/in-process-closeout.d.ts +1 -3
  37. package/dist/src/native/in-process-closeout.js +0 -794
  38. package/dist/src/pipelineCloseout.js +1905 -185
  39. package/dist/src/plugin.js +2843 -145
  40. package/dist/src/stages/auto-merge.js +28 -16
  41. package/dist/src/stages/commit.js +28 -16
  42. package/dist/src/stages/isolation.d.ts +1 -1
  43. package/dist/src/stages/isolation.js +5 -3
  44. package/dist/src/stages/merge-gate.js +35 -3
  45. package/dist/src/stages/open-pr.js +28 -16
  46. package/dist/src/stages/push.js +28 -16
  47. package/dist/src/stages/source-closeout.js +28 -16
  48. package/package.json +29 -16
  49. package/dist/src/branch-naming.d.ts +0 -15
  50. package/dist/src/branch-naming.js +0 -33
  51. package/dist/src/closeoutEquivalence.d.ts +0 -37
  52. package/dist/src/closeoutEquivalence.js +0 -78
  53. package/dist/src/closeoutShadowHarness.d.ts +0 -27
  54. package/dist/src/closeoutShadowHarness.js +0 -29
@@ -1,32 +1,101 @@
1
1
  // @bun
2
- // packages/bundle-default-lifecycle/src/control-plane/task-verify.ts
3
- import { currentTaskId } from "@rig/runtime/control-plane/native/task-state";
2
+ // packages/bundle-default-lifecycle/src/control-plane/task-data.ts
3
+ import { TASK_DATA_SERVICE_CAPABILITY } from "@rig/contracts";
4
+ import { defineCapability } from "@rig/core/capability";
5
+ import { requireInstalledCapability } from "@rig/core/capability-loaders";
6
+ var TaskDataCap = defineCapability(TASK_DATA_SERVICE_CAPABILITY);
7
+ function taskData() {
8
+ return requireInstalledCapability(TaskDataCap, "task-data capability unavailable: load @rig/task-sources-plugin (default bundle) before running the lifecycle.");
9
+ }
10
+
11
+ // packages/bundle-default-lifecycle/src/control-plane/verifier.ts
12
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
13
+ import { resolve as resolve2 } from "path";
14
+ import { resolveRuntimeSecrets as resolveRuntimeSecrets2 } from "@rig/core/baked-secrets";
15
+
16
+ // packages/bundle-default-lifecycle/src/control-plane/native/git-ops.ts
17
+ import { existsSync, lstatSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
18
+ import { dirname, isAbsolute, resolve } from "path";
19
+ import { loadDotEnvSecrets, resolveRuntimeSecrets } from "@rig/core/baked-secrets";
20
+ import { loadRuntimeContext, loadRuntimeContextFromEnv } from "@rig/core/runtime-context";
21
+ import { nowIso, runCapture as baseRunCapture } from "@rig/core/exec";
22
+ import { resolveCheckoutRoot as resolveMonorepoRoot } from "@rig/core/checkout-root";
23
+ import { getScopeRules } from "@rig/core/scope-rules";
24
+ import { safePathSegment } from "@rig/core/safe-identifiers";
25
+ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
26
+ "changed-files.txt",
27
+ "contract-changes.md",
28
+ "decision-log.md",
29
+ "git-state.txt",
30
+ "next-actions.md",
31
+ "pr-state.json",
32
+ "task-result.json",
33
+ "validation-summary.json"
34
+ ]);
35
+ function readPrMetadata(projectRoot, taskId) {
36
+ const path = resolve(taskData().artifactDirForId(projectRoot, taskId), "pr-state.json");
37
+ if (!existsSync(path)) {
38
+ return [];
39
+ }
40
+ try {
41
+ const parsed = JSON.parse(readFileSync(path, "utf-8"));
42
+ if (!parsed || typeof parsed !== "object") {
43
+ return [];
44
+ }
45
+ if (parsed.prs && typeof parsed.prs === "object") {
46
+ return Object.values(parsed.prs).filter(isGitOpenPrResult);
47
+ }
48
+ return isGitOpenPrResult(parsed) ? [parsed] : [];
49
+ } catch {
50
+ return [];
51
+ }
52
+ }
53
+ function isGitOpenPrResult(value) {
54
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
55
+ return false;
56
+ }
57
+ const record = value;
58
+ return typeof record.url === "string" && typeof record.branch === "string" && typeof record.base === "string" && (record.target === "project" || record.target === "monorepo") && typeof record.repoLabel === "string";
59
+ }
4
60
 
5
61
  // packages/bundle-default-lifecycle/src/control-plane/verifier.ts
6
- import { existsSync, mkdirSync, writeFileSync } from "fs";
7
- import { resolve } from "path";
8
- import { resolveRuntimeSecrets } from "@rig/runtime/control-plane/runtime/baked-secrets";
9
- import { readPrMetadata } from "@rig/runtime/control-plane/native/git-ops";
10
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
11
- import { readConfiguredTaskSourceTask } from "@rig/runtime/control-plane/tasks/source-lifecycle";
12
- import { artifactDirForId, lookupTask, readTaskConfig } from "@rig/runtime/control-plane/native/task-state";
13
- import { nowIso, resolveHarnessPaths, runCapture } from "@rig/runtime/control-plane/native/utils";
14
- import {
15
- collectPrReviewEvidence,
16
- evaluateStrictPrMergeGate,
17
- parseGreptileScore,
18
- stripHtml
19
- } from "@rig/pr-review-plugin";
62
+ import { loadRuntimeContextFromEnv as loadRuntimeContextFromEnv2 } from "@rig/core/runtime-context";
63
+ import { nowIso as nowIso2, runCapture } from "@rig/core/exec";
64
+ import { resolveHarnessPaths } from "@rig/core/harness-paths";
65
+
66
+ // packages/bundle-default-lifecycle/src/control-plane/pr-merge-gate-cap.ts
67
+ import { PR_MERGE_GATE } from "@rig/contracts";
68
+ import { defineCapability as defineCapability2 } from "@rig/core/capability";
69
+ import { resolvePluginHost } from "@rig/core/project-plugins";
70
+ var PrMergeGateCap = defineCapability2(PR_MERGE_GATE);
71
+ async function resolvePrMergeGateService(projectRoot) {
72
+ const { host } = await resolvePluginHost(projectRoot);
73
+ return PrMergeGateCap.require(host);
74
+ }
75
+
76
+ // packages/bundle-default-lifecycle/src/control-plane/verifier.ts
77
+ var mergeGateHolder = null;
78
+ async function ensureMergeGate(projectRoot) {
79
+ mergeGateHolder = await resolvePrMergeGateService(projectRoot);
80
+ return mergeGateHolder;
81
+ }
82
+ function mg() {
83
+ if (!mergeGateHolder) {
84
+ throw new Error("PR merge-gate capability not resolved (verifyTask must run first).");
85
+ }
86
+ return mergeGateHolder;
87
+ }
20
88
  async function verifyTask(options) {
89
+ await ensureMergeGate(options.projectRoot);
21
90
  const paths = resolveHarnessPaths(options.projectRoot);
22
91
  const taskId = options.taskId;
23
- const normalizedTaskId = lookupTask(options.projectRoot, taskId);
24
- const artifactDir = artifactDirForId(options.projectRoot, taskId);
25
- mkdirSync(artifactDir, { recursive: true });
26
- const validationSummaryPath = resolve(artifactDir, "validation-summary.json");
27
- const reviewFeedbackPath = resolve(artifactDir, "review-feedback.md");
28
- const reviewStatePath = resolve(artifactDir, "review-state.json");
29
- const greptileRawPath = resolve(artifactDir, "review-greptile-raw.json");
92
+ const normalizedTaskId = taskData().lookupTask(options.projectRoot, taskId);
93
+ const artifactDir = taskData().artifactDirForId(options.projectRoot, taskId);
94
+ mkdirSync2(artifactDir, { recursive: true });
95
+ const validationSummaryPath = resolve2(artifactDir, "validation-summary.json");
96
+ const reviewFeedbackPath = resolve2(artifactDir, "review-feedback.md");
97
+ const reviewStatePath = resolve2(artifactDir, "review-state.json");
98
+ const greptileRawPath = resolve2(artifactDir, "review-greptile-raw.json");
30
99
  const prStates = readPrMetadata(options.projectRoot, taskId);
31
100
  const prState = prStates[0] || null;
32
101
  const localReasons = [];
@@ -38,7 +107,7 @@ async function verifyTask(options) {
38
107
  if (!normalizedTaskId && !await hasConfiguredSourceTask(options.projectRoot, taskId)) {
39
108
  localReasons.push(`[Task Config] Unknown task id '${taskId}' in task-config or configured task source.`);
40
109
  }
41
- if (!existsSync(validationSummaryPath)) {
110
+ if (!existsSync2(validationSummaryPath)) {
42
111
  localReasons.push(`[Artifact Quality] validation-summary.json not found at ${validationSummaryPath}.`);
43
112
  } else {
44
113
  const summary = await parseValidationSummary(validationSummaryPath);
@@ -47,13 +116,13 @@ async function verifyTask(options) {
47
116
  }
48
117
  }
49
118
  for (const file of ["task-result.json", "decision-log.md", "next-actions.md", "changed-files.txt"]) {
50
- const requiredPath = resolve(artifactDir, file);
51
- if (!existsSync(requiredPath)) {
119
+ const requiredPath = resolve2(artifactDir, file);
120
+ if (!existsSync2(requiredPath)) {
52
121
  localReasons.push(`[Artifact Quality] Missing required artifact file: ${requiredPath}`);
53
122
  }
54
123
  }
55
- const taskResultPath = resolve(artifactDir, "task-result.json");
56
- if (existsSync(taskResultPath)) {
124
+ const taskResultPath = resolve2(artifactDir, "task-result.json");
125
+ if (existsSync2(taskResultPath)) {
57
126
  const taskResult = await readJsonFile(taskResultPath);
58
127
  const artifactStatus = typeof taskResult?.status === "string" ? taskResult.status.trim().toLowerCase() : "";
59
128
  if (artifactStatus === "partial") {
@@ -66,8 +135,8 @@ async function verifyTask(options) {
66
135
  localReasons.push("[Artifact Quality] task-result.json next actions indicate remaining implementation scope.");
67
136
  }
68
137
  }
69
- const nextActionsPath = resolve(artifactDir, "next-actions.md");
70
- if (existsSync(nextActionsPath)) {
138
+ const nextActionsPath = resolve2(artifactDir, "next-actions.md");
139
+ if (existsSync2(nextActionsPath)) {
71
140
  const nextActionsContent = await Bun.file(nextActionsPath).text();
72
141
  if (nextActionsContent.includes("TODO: Replace this scaffold") || nextActionsContent.includes("bd-<downstream-task-id>")) {
73
142
  localReasons.push("[Artifact Quality] next-actions.md still contains scaffold placeholder text. Replace with real recommendations.");
@@ -98,7 +167,7 @@ async function verifyTask(options) {
98
167
  aiReasons.push(`[AI Review] Required mode needs a completed Greptile approval; current verdict is ${ai.verdict}.`);
99
168
  }
100
169
  if (persistArtifacts && ai.rawResponse) {
101
- writeFileSync(greptileRawPath, `${ai.rawResponse}
170
+ writeFileSync2(greptileRawPath, `${ai.rawResponse}
102
171
  `, "utf-8");
103
172
  }
104
173
  } else if (!options.skipAiReview && reviewMode === "off") {
@@ -220,15 +289,15 @@ function nextActionsIndicateRemainingScope(content) {
220
289
  return /^\s*- \[ \]/m.test(normalized) || /\b(remaining scope|still need|needs? to be implemented|not yet implemented|not implemented|follow[- ]?up required|blocked by|blocker:)\b/i.test(lower);
221
290
  }
222
291
  async function hasConfiguredSourceTask(projectRoot, taskId) {
223
- return readConfiguredTaskSourceTask(projectRoot, taskId).then((result) => result.task !== null).catch(() => false);
292
+ return taskData().readConfiguredTaskSourceTask(projectRoot, taskId).then((result) => result.task !== null).catch(() => false);
224
293
  }
225
294
  function resolveGithubSourceIssueId(projectRoot, taskId) {
226
- const fromRuntime = loadRuntimeContextFromEnv()?.sourceTask?.sourceIssueId;
295
+ const fromRuntime = loadRuntimeContextFromEnv2()?.sourceTask?.sourceIssueId;
227
296
  if (typeof fromRuntime === "string" && isGithubSourceIssueId(fromRuntime)) {
228
297
  return fromRuntime;
229
298
  }
230
299
  try {
231
- const taskConfig = readTaskConfig(projectRoot);
300
+ const taskConfig = taskData().readTaskConfig(projectRoot);
232
301
  const entry = taskConfig[taskId];
233
302
  const sourceIssueId = typeof entry?.sourceIssueId === "string" ? entry.sourceIssueId : typeof entry?.source_issue_id === "string" ? entry.source_issue_id : null;
234
303
  if (sourceIssueId && isGithubSourceIssueId(sourceIssueId)) {
@@ -299,14 +368,15 @@ function loadGithubPullRequestCloseoutSnapshot(projectRoot, prState) {
299
368
  "--json",
300
369
  "state,isDraft,mergeable,mergeStateStatus,reviewDecision,title,body,statusCheckRollup"
301
370
  ]);
371
+ const isDraft = booleanField(view, "isDraft");
302
372
  return {
303
- state: stringField(view, "state"),
304
- isDraft: booleanField(view, "isDraft"),
305
- mergeable: stringField(view, "mergeable"),
306
- mergeStateStatus: stringField(view, "mergeStateStatus"),
307
- reviewDecision: stringField(view, "reviewDecision"),
308
- title: stringField(view, "title"),
309
- body: stringField(view, "body"),
373
+ ...objectField("state", stringField(view, "state")),
374
+ ...isDraft !== undefined ? { isDraft } : {},
375
+ ...objectField("mergeable", stringField(view, "mergeable")),
376
+ ...objectField("mergeStateStatus", stringField(view, "mergeStateStatus")),
377
+ ...objectField("reviewDecision", stringField(view, "reviewDecision")),
378
+ ...objectField("title", stringField(view, "title")),
379
+ ...objectField("body", stringField(view, "body")),
310
380
  statusCheckRollup: statusCheckRollupField(view, "statusCheckRollup"),
311
381
  reviewThreads: loadGithubReviewThreads(projectRoot, repoName, prNumber)
312
382
  };
@@ -381,6 +451,9 @@ function stringField(record, key) {
381
451
  const value = record[key];
382
452
  return typeof value === "string" ? value : undefined;
383
453
  }
454
+ function objectField(key, value) {
455
+ return value === undefined ? {} : { [key]: value };
456
+ }
384
457
  function booleanField(record, key) {
385
458
  const value = record[key];
386
459
  return typeof value === "boolean" ? value : undefined;
@@ -437,7 +510,7 @@ function isAcceptedValidationSummary(summary) {
437
510
  return summary.status === "skipped" && summary.total === 0 && summary.failed === 0;
438
511
  }
439
512
  async function loadReviewMode(reviewProfilePath, fallback) {
440
- const parsed = existsSync(reviewProfilePath) ? await readJsonFile(reviewProfilePath) : null;
513
+ const parsed = existsSync2(reviewProfilePath) ? await readJsonFile(reviewProfilePath) : null;
441
514
  const mode = parsed?.mode;
442
515
  if (mode === "off" || mode === "advisory" || mode === "required") {
443
516
  return mode;
@@ -448,7 +521,7 @@ async function loadReviewMode(reviewProfilePath, fallback) {
448
521
  return "advisory";
449
522
  }
450
523
  async function loadReviewProvider(reviewProfilePath, fallback) {
451
- const parsed = existsSync(reviewProfilePath) ? await readJsonFile(reviewProfilePath) : null;
524
+ const parsed = existsSync2(reviewProfilePath) ? await readJsonFile(reviewProfilePath) : null;
452
525
  const provider = parsed?.provider;
453
526
  if (typeof provider === "string" && provider.trim().length > 0) {
454
527
  return provider;
@@ -471,7 +544,7 @@ function resolveRepoSlug(projectRoot) {
471
544
  async function runGreptileReview(options) {
472
545
  const reasons = [];
473
546
  const warnings = [];
474
- const secrets = resolveRuntimeSecrets(process.env);
547
+ const secrets = resolveRuntimeSecrets2(process.env);
475
548
  const apiKey = secrets.GREPTILE_API_KEY || "";
476
549
  const apiBase = secrets.GREPTILE_API_BASE || "https://api.greptile.com/mcp";
477
550
  const remote = secrets.GREPTILE_REMOTE || "github";
@@ -607,7 +680,7 @@ function writeFeedbackFile(options) {
607
680
  if (options.aiRawFeedback) {
608
681
  lines.push("## Raw Reviewer Feedback", "", "```text", options.aiRawFeedback, "```", "");
609
682
  }
610
- writeFileSync(options.output, `${lines.join(`
683
+ writeFileSync2(options.output, `${lines.join(`
611
684
  `)}
612
685
  `, "utf-8");
613
686
  }
@@ -622,9 +695,9 @@ function writeReviewStateFile(options) {
622
695
  local_reasons: options.localReasons,
623
696
  ai_reasons: options.aiReasons,
624
697
  ai_warnings: options.aiWarnings,
625
- updated_at: nowIso()
698
+ updated_at: nowIso2()
626
699
  };
627
- writeFileSync(options.output, `${JSON.stringify(payload, null, 2)}
700
+ writeFileSync2(options.output, `${JSON.stringify(payload, null, 2)}
628
701
  `, "utf-8");
629
702
  }
630
703
  async function runGreptileReviewForPr(options) {
@@ -649,7 +722,6 @@ async function runGreptileReviewForPr(options) {
649
722
  taskId: options.taskId,
650
723
  prState: options.prState,
651
724
  reviewMode: options.reviewMode,
652
- infrastructureError: undefined,
653
725
  pollAttempts: options.pollAttempts,
654
726
  pollIntervalMs: options.pollIntervalMs
655
727
  });
@@ -777,7 +849,7 @@ async function runGreptileReviewForPr(options) {
777
849
  });
778
850
  const actionableComments = filterActionableGreptileComments(commentsPayload.comments || []);
779
851
  const reviewBody = reviewDetails.codeReview?.body || "";
780
- const score = parseGreptileScore(reviewBody);
852
+ const score = mg().parseGreptileScore(reviewBody);
781
853
  const feedback = [
782
854
  `## ${options.prState.repoLabel || repoName} PR Review`,
783
855
  "",
@@ -785,7 +857,7 @@ async function runGreptileReviewForPr(options) {
785
857
  `- Review ID: ${selectedReview.id}`,
786
858
  `- Status: ${selectedReview.status}`,
787
859
  "",
788
- reviewBody ? stripHtml(reviewBody).trim() : "Greptile completed without summary body."
860
+ reviewBody ? mg().stripHtml(reviewBody).trim() : "Greptile completed without summary body."
789
861
  ].filter(Boolean).join(`
790
862
  `);
791
863
  if (actionableComments.length > 0) {
@@ -806,7 +878,7 @@ async function runGreptileReviewForPr(options) {
806
878
  }
807
879
  };
808
880
  }
809
- const blockerScanBody = stripHtml(reviewBody).replace(/\b(?:no|without|zero)\s+blockers?\b/gi, " ").replace(/\bno\s+changes\s+requested\b/gi, " ");
881
+ const blockerScanBody = mg().stripHtml(reviewBody).replace(/\b(?:no|without|zero)\s+blockers?\b/gi, " ").replace(/\bno\s+changes\s+requested\b/gi, " ");
810
882
  if (/not safe(?: to merge)?|unsafe(?: to merge)?|do not merge|cannot merge|blockers?|must fix|changes requested|please fix|needs? fix|fix this|address this|\breject(?:ed|ion)?\b|\bskip(?:ped)?\b|status\s*:\s*(?:reject(?:ed)?|skip(?:ped)?|failed)/i.test(blockerScanBody)) {
811
883
  reasons.push(`[AI Review] ${repoName}#${prNumber} summary indicates the PR is not safe to merge.`);
812
884
  return {
@@ -854,7 +926,7 @@ async function runGreptileReviewForPr(options) {
854
926
  status: selectedReview.status
855
927
  }]
856
928
  });
857
- strictGate = evaluateStrictPrMergeGate(strictEvidence);
929
+ strictGate = mg().evaluateGate(strictEvidence);
858
930
  } catch (error) {
859
931
  reasons.push(`[AI Review] Strict Greptile evidence collection failed for ${repoName}#${prNumber}: ${error instanceof Error ? error.message : String(error)}`);
860
932
  return {
@@ -981,7 +1053,7 @@ async function runGithubGreptileFallbackReviewForPr(options) {
981
1053
  fallbackReview?.html_url ? `- Review: ${fallbackReview.html_url}` : "",
982
1054
  fallbackReview?.state ? `- Status: ${fallbackReview.state}` : "",
983
1055
  "",
984
- fallbackReview?.body?.trim() ? stripHtml(fallbackReview.body).trim() : "Greptile MCP was unavailable, so verification used GitHub review threads instead."
1056
+ fallbackReview?.body?.trim() ? mg().stripHtml(fallbackReview.body).trim() : "Greptile MCP was unavailable, so verification used GitHub review threads instead."
985
1057
  ].filter(Boolean).join(`
986
1058
  `);
987
1059
  const warnings = buildGithubGreptileFallbackWarnings(options);
@@ -1004,7 +1076,7 @@ async function runGithubGreptileFallbackReviewForPr(options) {
1004
1076
  taskId: options.taskId,
1005
1077
  prUrl
1006
1078
  });
1007
- strictGate = evaluateStrictPrMergeGate(strictEvidence);
1079
+ strictGate = mg().evaluateGate(strictEvidence);
1008
1080
  } catch (error) {
1009
1081
  return {
1010
1082
  verdict: "REJECT",
@@ -1229,7 +1301,7 @@ function loadGithubPullRequestState(projectRoot, repoName, prNumber) {
1229
1301
  ]);
1230
1302
  return {
1231
1303
  state: response.state || "",
1232
- merged: response.merged,
1304
+ ...response.merged !== undefined ? { merged: response.merged } : {},
1233
1305
  merged_at: response.merged_at ?? null
1234
1306
  };
1235
1307
  }
@@ -1258,7 +1330,7 @@ function runGhJson(projectRoot, args) {
1258
1330
  }
1259
1331
  }
1260
1332
  async function collectStrictPrEvidenceForVerifier(input) {
1261
- return collectPrReviewEvidence({
1333
+ return mg().collectEvidence({
1262
1334
  projectRoot: input.projectRoot,
1263
1335
  prUrl: input.prUrl,
1264
1336
  taskId: input.taskId,
@@ -1423,7 +1495,7 @@ function filterActionableGithubGreptileThreads(threads) {
1423
1495
  }
1424
1496
  function resolvePrRepoRoot(projectRoot, prState) {
1425
1497
  const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
1426
- if (prState.target === "monorepo" && runtimeWorkspace && existsSync(resolve(runtimeWorkspace, ".git"))) {
1498
+ if (prState.target === "monorepo" && runtimeWorkspace && existsSync2(resolve2(runtimeWorkspace, ".git"))) {
1427
1499
  return runtimeWorkspace;
1428
1500
  }
1429
1501
  const paths = resolveHarnessPaths(projectRoot);
@@ -1437,7 +1509,7 @@ function isCommitAncestorOfPrHead(projectRoot, prState, reviewedCommit, headComm
1437
1509
  return runCapture(["git", "-C", repoRoot, "merge-base", "--is-ancestor", reviewedCommit, headCommit], projectRoot).exitCode === 0;
1438
1510
  }
1439
1511
  function summarizeComment(input) {
1440
- const text = stripHtml(input).replace(/\s+/g, " ").trim();
1512
+ const text = mg().stripHtml(input).replace(/\s+/g, " ").trim();
1441
1513
  return text.length > 160 ? `${text.slice(0, 157)}...` : text;
1442
1514
  }
1443
1515
  function asGreptileInfrastructureWarning(reason) {
@@ -1455,7 +1527,7 @@ function isAiReviewApproved(input) {
1455
1527
 
1456
1528
  // packages/bundle-default-lifecycle/src/control-plane/task-verify.ts
1457
1529
  async function taskVerify(projectRoot, taskId) {
1458
- const activeTask = taskId || currentTaskId(projectRoot);
1530
+ const activeTask = taskId || taskData().currentTaskId(projectRoot);
1459
1531
  if (!activeTask) {
1460
1532
  throw new Error("No active task.");
1461
1533
  }
@@ -1,4 +1,3 @@
1
- import { parseGreptileScore } from "@rig/pr-review-plugin";
2
1
  export type VerifyOutcome = {
3
2
  approved: boolean;
4
3
  localReasons: string[];
@@ -104,7 +103,7 @@ declare function shouldPreferGithubGreptileFallback(prState: {
104
103
  declare function pickRelevantGithubGreptileReview(reviews: GithubPullRequestReview[], expectedHeadSha: string): GithubPullRequestReview | null;
105
104
  declare function pickLatestGithubGreptileReview(reviews: GithubPullRequestReview[]): GithubPullRequestReview | null;
106
105
  export declare function evaluatePullRequestCiChecks(checks: GithubStatusCheckRollupItem[], repoName: string, prNumber: number, options?: {
107
- mergeStateStatus?: string;
106
+ mergeStateStatus?: string | undefined;
108
107
  }): {
109
108
  verdict: "APPROVE" | "REJECT" | "SKIP";
110
109
  reasons: string[];
@@ -125,7 +124,6 @@ export declare const __testOnly: {
125
124
  filterActionableGithubGreptileThreads: typeof filterActionableGithubGreptileThreads;
126
125
  isGithubGreptileCheckApproved: typeof isGithubGreptileCheckApproved;
127
126
  isAiReviewApproved: typeof isAiReviewApproved;
128
- parseGreptileScore: typeof parseGreptileScore;
129
127
  pickLatestGithubGreptileReview: typeof pickLatestGithubGreptileReview;
130
128
  pickRelevantGithubGreptileReview: typeof pickRelevantGithubGreptileReview;
131
129
  resolveGreptileRequestTimeoutMs: typeof resolveGreptileRequestTimeoutMs;