@h-rig/bundle-default-lifecycle 0.0.6-alpha.157 → 0.0.6-alpha.158
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/dist/src/cli.d.ts +1 -7
- package/dist/src/cli.js +5 -2
- package/dist/src/control-plane/completion-verification.js +1591 -118
- package/dist/src/control-plane/hooks/inject-context.d.ts +2 -0
- package/dist/src/control-plane/hooks/inject-context.js +175 -0
- package/dist/src/control-plane/hooks/shared.d.ts +11 -0
- package/dist/src/control-plane/hooks/shared.js +44 -0
- package/dist/src/control-plane/hooks/submodule-branch.d.ts +2 -0
- package/dist/src/control-plane/hooks/submodule-branch.js +432 -0
- package/dist/src/control-plane/hooks/task-runtime-start.d.ts +2 -0
- package/dist/src/control-plane/hooks/task-runtime-start.js +429 -0
- package/dist/src/control-plane/materialize-task-config.d.ts +29 -0
- package/dist/src/control-plane/materialize-task-config.js +95 -0
- package/dist/src/control-plane/native/git-ops.d.ts +67 -0
- package/dist/src/control-plane/native/git-ops.js +1390 -0
- package/dist/src/control-plane/policy.d.ts +3 -0
- package/dist/src/control-plane/policy.js +226 -0
- package/dist/src/control-plane/pr-automation.d.ts +2 -0
- package/dist/src/control-plane/pr-automation.js +26 -16
- package/dist/src/control-plane/pr-merge-gate-cap.d.ts +10 -0
- package/dist/src/control-plane/pr-merge-gate-cap.js +13 -0
- package/dist/src/control-plane/task-data.d.ts +13 -0
- package/dist/src/control-plane/task-data.js +12 -0
- package/dist/src/control-plane/task-verify.js +131 -59
- package/dist/src/control-plane/verifier.d.ts +1 -3
- package/dist/src/control-plane/verifier.js +133 -57
- package/dist/src/defaultPipeline.d.ts +1 -1
- package/dist/src/defaultPipeline.js +5 -2
- package/dist/src/index.d.ts +0 -2
- package/dist/src/index.js +1908 -290
- package/dist/src/native/closeout-runners.js +22 -2
- package/dist/src/native/github-auth-env.d.ts +2 -0
- package/dist/src/native/github-auth-env.js +25 -0
- package/dist/src/native/host-git.d.ts +6 -0
- package/dist/src/native/host-git.js +62 -0
- package/dist/src/native/in-process-closeout.d.ts +1 -3
- package/dist/src/native/in-process-closeout.js +0 -794
- package/dist/src/pipelineCloseout.js +1905 -185
- package/dist/src/plugin.js +2843 -145
- package/dist/src/stages/auto-merge.js +28 -16
- package/dist/src/stages/commit.js +28 -16
- package/dist/src/stages/isolation.d.ts +1 -1
- package/dist/src/stages/isolation.js +5 -3
- package/dist/src/stages/merge-gate.js +35 -3
- package/dist/src/stages/open-pr.js +28 -16
- package/dist/src/stages/push.js +28 -16
- package/dist/src/stages/source-closeout.js +28 -16
- package/package.json +29 -16
- package/dist/src/branch-naming.d.ts +0 -15
- package/dist/src/branch-naming.js +0 -33
- package/dist/src/closeoutEquivalence.d.ts +0 -37
- package/dist/src/closeoutEquivalence.js +0 -78
- package/dist/src/closeoutShadowHarness.d.ts +0 -27
- package/dist/src/closeoutShadowHarness.js +0 -29
|
@@ -1,29 +1,103 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/bundle-default-lifecycle/src/control-plane/verifier.ts
|
|
3
|
-
import { existsSync, mkdirSync, writeFileSync } from "fs";
|
|
4
|
-
import { resolve } from "path";
|
|
5
|
-
import { resolveRuntimeSecrets } from "@rig/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} from "@rig/
|
|
3
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
4
|
+
import { resolve as resolve2 } from "path";
|
|
5
|
+
import { resolveRuntimeSecrets as resolveRuntimeSecrets2 } from "@rig/core/baked-secrets";
|
|
6
|
+
|
|
7
|
+
// packages/bundle-default-lifecycle/src/control-plane/native/git-ops.ts
|
|
8
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
9
|
+
import { dirname, isAbsolute, resolve } from "path";
|
|
10
|
+
import { loadDotEnvSecrets, resolveRuntimeSecrets } from "@rig/core/baked-secrets";
|
|
11
|
+
import { loadRuntimeContext, loadRuntimeContextFromEnv } from "@rig/core/runtime-context";
|
|
12
|
+
|
|
13
|
+
// packages/bundle-default-lifecycle/src/control-plane/task-data.ts
|
|
14
|
+
import { TASK_DATA_SERVICE_CAPABILITY } from "@rig/contracts";
|
|
15
|
+
import { defineCapability } from "@rig/core/capability";
|
|
16
|
+
import { requireInstalledCapability } from "@rig/core/capability-loaders";
|
|
17
|
+
var TaskDataCap = defineCapability(TASK_DATA_SERVICE_CAPABILITY);
|
|
18
|
+
function taskData() {
|
|
19
|
+
return requireInstalledCapability(TaskDataCap, "task-data capability unavailable: load @rig/task-sources-plugin (default bundle) before running the lifecycle.");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// packages/bundle-default-lifecycle/src/control-plane/native/git-ops.ts
|
|
23
|
+
import { nowIso, runCapture as baseRunCapture } from "@rig/core/exec";
|
|
24
|
+
import { resolveCheckoutRoot as resolveMonorepoRoot } from "@rig/core/checkout-root";
|
|
25
|
+
import { getScopeRules } from "@rig/core/scope-rules";
|
|
26
|
+
import { safePathSegment } from "@rig/core/safe-identifiers";
|
|
27
|
+
var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
|
|
28
|
+
"changed-files.txt",
|
|
29
|
+
"contract-changes.md",
|
|
30
|
+
"decision-log.md",
|
|
31
|
+
"git-state.txt",
|
|
32
|
+
"next-actions.md",
|
|
33
|
+
"pr-state.json",
|
|
34
|
+
"task-result.json",
|
|
35
|
+
"validation-summary.json"
|
|
36
|
+
]);
|
|
37
|
+
function readPrMetadata(projectRoot, taskId) {
|
|
38
|
+
const path = resolve(taskData().artifactDirForId(projectRoot, taskId), "pr-state.json");
|
|
39
|
+
if (!existsSync(path)) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
44
|
+
if (!parsed || typeof parsed !== "object") {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
if (parsed.prs && typeof parsed.prs === "object") {
|
|
48
|
+
return Object.values(parsed.prs).filter(isGitOpenPrResult);
|
|
49
|
+
}
|
|
50
|
+
return isGitOpenPrResult(parsed) ? [parsed] : [];
|
|
51
|
+
} catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function isGitOpenPrResult(value) {
|
|
56
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const record = value;
|
|
60
|
+
return typeof record.url === "string" && typeof record.branch === "string" && typeof record.base === "string" && (record.target === "project" || record.target === "monorepo") && typeof record.repoLabel === "string";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// packages/bundle-default-lifecycle/src/control-plane/verifier.ts
|
|
64
|
+
import { loadRuntimeContextFromEnv as loadRuntimeContextFromEnv2 } from "@rig/core/runtime-context";
|
|
65
|
+
import { nowIso as nowIso2, runCapture } from "@rig/core/exec";
|
|
66
|
+
import { resolveHarnessPaths } from "@rig/core/harness-paths";
|
|
67
|
+
|
|
68
|
+
// packages/bundle-default-lifecycle/src/control-plane/pr-merge-gate-cap.ts
|
|
69
|
+
import { PR_MERGE_GATE } from "@rig/contracts";
|
|
70
|
+
import { defineCapability as defineCapability2 } from "@rig/core/capability";
|
|
71
|
+
import { resolvePluginHost } from "@rig/core/project-plugins";
|
|
72
|
+
var PrMergeGateCap = defineCapability2(PR_MERGE_GATE);
|
|
73
|
+
async function resolvePrMergeGateService(projectRoot) {
|
|
74
|
+
const { host } = await resolvePluginHost(projectRoot);
|
|
75
|
+
return PrMergeGateCap.require(host);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// packages/bundle-default-lifecycle/src/control-plane/verifier.ts
|
|
79
|
+
var mergeGateHolder = null;
|
|
80
|
+
async function ensureMergeGate(projectRoot) {
|
|
81
|
+
mergeGateHolder = await resolvePrMergeGateService(projectRoot);
|
|
82
|
+
return mergeGateHolder;
|
|
83
|
+
}
|
|
84
|
+
function mg() {
|
|
85
|
+
if (!mergeGateHolder) {
|
|
86
|
+
throw new Error("PR merge-gate capability not resolved (verifyTask must run first).");
|
|
87
|
+
}
|
|
88
|
+
return mergeGateHolder;
|
|
89
|
+
}
|
|
17
90
|
async function verifyTask(options) {
|
|
91
|
+
await ensureMergeGate(options.projectRoot);
|
|
18
92
|
const paths = resolveHarnessPaths(options.projectRoot);
|
|
19
93
|
const taskId = options.taskId;
|
|
20
|
-
const normalizedTaskId = lookupTask(options.projectRoot, taskId);
|
|
21
|
-
const artifactDir = artifactDirForId(options.projectRoot, taskId);
|
|
22
|
-
|
|
23
|
-
const validationSummaryPath =
|
|
24
|
-
const reviewFeedbackPath =
|
|
25
|
-
const reviewStatePath =
|
|
26
|
-
const greptileRawPath =
|
|
94
|
+
const normalizedTaskId = taskData().lookupTask(options.projectRoot, taskId);
|
|
95
|
+
const artifactDir = taskData().artifactDirForId(options.projectRoot, taskId);
|
|
96
|
+
mkdirSync2(artifactDir, { recursive: true });
|
|
97
|
+
const validationSummaryPath = resolve2(artifactDir, "validation-summary.json");
|
|
98
|
+
const reviewFeedbackPath = resolve2(artifactDir, "review-feedback.md");
|
|
99
|
+
const reviewStatePath = resolve2(artifactDir, "review-state.json");
|
|
100
|
+
const greptileRawPath = resolve2(artifactDir, "review-greptile-raw.json");
|
|
27
101
|
const prStates = readPrMetadata(options.projectRoot, taskId);
|
|
28
102
|
const prState = prStates[0] || null;
|
|
29
103
|
const localReasons = [];
|
|
@@ -35,7 +109,7 @@ async function verifyTask(options) {
|
|
|
35
109
|
if (!normalizedTaskId && !await hasConfiguredSourceTask(options.projectRoot, taskId)) {
|
|
36
110
|
localReasons.push(`[Task Config] Unknown task id '${taskId}' in task-config or configured task source.`);
|
|
37
111
|
}
|
|
38
|
-
if (!
|
|
112
|
+
if (!existsSync2(validationSummaryPath)) {
|
|
39
113
|
localReasons.push(`[Artifact Quality] validation-summary.json not found at ${validationSummaryPath}.`);
|
|
40
114
|
} else {
|
|
41
115
|
const summary = await parseValidationSummary(validationSummaryPath);
|
|
@@ -44,13 +118,13 @@ async function verifyTask(options) {
|
|
|
44
118
|
}
|
|
45
119
|
}
|
|
46
120
|
for (const file of ["task-result.json", "decision-log.md", "next-actions.md", "changed-files.txt"]) {
|
|
47
|
-
const requiredPath =
|
|
48
|
-
if (!
|
|
121
|
+
const requiredPath = resolve2(artifactDir, file);
|
|
122
|
+
if (!existsSync2(requiredPath)) {
|
|
49
123
|
localReasons.push(`[Artifact Quality] Missing required artifact file: ${requiredPath}`);
|
|
50
124
|
}
|
|
51
125
|
}
|
|
52
|
-
const taskResultPath =
|
|
53
|
-
if (
|
|
126
|
+
const taskResultPath = resolve2(artifactDir, "task-result.json");
|
|
127
|
+
if (existsSync2(taskResultPath)) {
|
|
54
128
|
const taskResult = await readJsonFile(taskResultPath);
|
|
55
129
|
const artifactStatus = typeof taskResult?.status === "string" ? taskResult.status.trim().toLowerCase() : "";
|
|
56
130
|
if (artifactStatus === "partial") {
|
|
@@ -63,8 +137,8 @@ async function verifyTask(options) {
|
|
|
63
137
|
localReasons.push("[Artifact Quality] task-result.json next actions indicate remaining implementation scope.");
|
|
64
138
|
}
|
|
65
139
|
}
|
|
66
|
-
const nextActionsPath =
|
|
67
|
-
if (
|
|
140
|
+
const nextActionsPath = resolve2(artifactDir, "next-actions.md");
|
|
141
|
+
if (existsSync2(nextActionsPath)) {
|
|
68
142
|
const nextActionsContent = await Bun.file(nextActionsPath).text();
|
|
69
143
|
if (nextActionsContent.includes("TODO: Replace this scaffold") || nextActionsContent.includes("bd-<downstream-task-id>")) {
|
|
70
144
|
localReasons.push("[Artifact Quality] next-actions.md still contains scaffold placeholder text. Replace with real recommendations.");
|
|
@@ -95,7 +169,7 @@ async function verifyTask(options) {
|
|
|
95
169
|
aiReasons.push(`[AI Review] Required mode needs a completed Greptile approval; current verdict is ${ai.verdict}.`);
|
|
96
170
|
}
|
|
97
171
|
if (persistArtifacts && ai.rawResponse) {
|
|
98
|
-
|
|
172
|
+
writeFileSync2(greptileRawPath, `${ai.rawResponse}
|
|
99
173
|
`, "utf-8");
|
|
100
174
|
}
|
|
101
175
|
} else if (!options.skipAiReview && reviewMode === "off") {
|
|
@@ -217,15 +291,15 @@ function nextActionsIndicateRemainingScope(content) {
|
|
|
217
291
|
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);
|
|
218
292
|
}
|
|
219
293
|
async function hasConfiguredSourceTask(projectRoot, taskId) {
|
|
220
|
-
return readConfiguredTaskSourceTask(projectRoot, taskId).then((result) => result.task !== null).catch(() => false);
|
|
294
|
+
return taskData().readConfiguredTaskSourceTask(projectRoot, taskId).then((result) => result.task !== null).catch(() => false);
|
|
221
295
|
}
|
|
222
296
|
function resolveGithubSourceIssueId(projectRoot, taskId) {
|
|
223
|
-
const fromRuntime =
|
|
297
|
+
const fromRuntime = loadRuntimeContextFromEnv2()?.sourceTask?.sourceIssueId;
|
|
224
298
|
if (typeof fromRuntime === "string" && isGithubSourceIssueId(fromRuntime)) {
|
|
225
299
|
return fromRuntime;
|
|
226
300
|
}
|
|
227
301
|
try {
|
|
228
|
-
const taskConfig = readTaskConfig(projectRoot);
|
|
302
|
+
const taskConfig = taskData().readTaskConfig(projectRoot);
|
|
229
303
|
const entry = taskConfig[taskId];
|
|
230
304
|
const sourceIssueId = typeof entry?.sourceIssueId === "string" ? entry.sourceIssueId : typeof entry?.source_issue_id === "string" ? entry.source_issue_id : null;
|
|
231
305
|
if (sourceIssueId && isGithubSourceIssueId(sourceIssueId)) {
|
|
@@ -296,14 +370,15 @@ function loadGithubPullRequestCloseoutSnapshot(projectRoot, prState) {
|
|
|
296
370
|
"--json",
|
|
297
371
|
"state,isDraft,mergeable,mergeStateStatus,reviewDecision,title,body,statusCheckRollup"
|
|
298
372
|
]);
|
|
373
|
+
const isDraft = booleanField(view, "isDraft");
|
|
299
374
|
return {
|
|
300
|
-
state
|
|
301
|
-
isDraft
|
|
302
|
-
mergeable
|
|
303
|
-
mergeStateStatus
|
|
304
|
-
reviewDecision
|
|
305
|
-
title
|
|
306
|
-
body
|
|
375
|
+
...objectField("state", stringField(view, "state")),
|
|
376
|
+
...isDraft !== undefined ? { isDraft } : {},
|
|
377
|
+
...objectField("mergeable", stringField(view, "mergeable")),
|
|
378
|
+
...objectField("mergeStateStatus", stringField(view, "mergeStateStatus")),
|
|
379
|
+
...objectField("reviewDecision", stringField(view, "reviewDecision")),
|
|
380
|
+
...objectField("title", stringField(view, "title")),
|
|
381
|
+
...objectField("body", stringField(view, "body")),
|
|
307
382
|
statusCheckRollup: statusCheckRollupField(view, "statusCheckRollup"),
|
|
308
383
|
reviewThreads: loadGithubReviewThreads(projectRoot, repoName, prNumber)
|
|
309
384
|
};
|
|
@@ -378,6 +453,9 @@ function stringField(record, key) {
|
|
|
378
453
|
const value = record[key];
|
|
379
454
|
return typeof value === "string" ? value : undefined;
|
|
380
455
|
}
|
|
456
|
+
function objectField(key, value) {
|
|
457
|
+
return value === undefined ? {} : { [key]: value };
|
|
458
|
+
}
|
|
381
459
|
function booleanField(record, key) {
|
|
382
460
|
const value = record[key];
|
|
383
461
|
return typeof value === "boolean" ? value : undefined;
|
|
@@ -434,7 +512,7 @@ function isAcceptedValidationSummary(summary) {
|
|
|
434
512
|
return summary.status === "skipped" && summary.total === 0 && summary.failed === 0;
|
|
435
513
|
}
|
|
436
514
|
async function loadReviewMode(reviewProfilePath, fallback) {
|
|
437
|
-
const parsed =
|
|
515
|
+
const parsed = existsSync2(reviewProfilePath) ? await readJsonFile(reviewProfilePath) : null;
|
|
438
516
|
const mode = parsed?.mode;
|
|
439
517
|
if (mode === "off" || mode === "advisory" || mode === "required") {
|
|
440
518
|
return mode;
|
|
@@ -445,7 +523,7 @@ async function loadReviewMode(reviewProfilePath, fallback) {
|
|
|
445
523
|
return "advisory";
|
|
446
524
|
}
|
|
447
525
|
async function loadReviewProvider(reviewProfilePath, fallback) {
|
|
448
|
-
const parsed =
|
|
526
|
+
const parsed = existsSync2(reviewProfilePath) ? await readJsonFile(reviewProfilePath) : null;
|
|
449
527
|
const provider = parsed?.provider;
|
|
450
528
|
if (typeof provider === "string" && provider.trim().length > 0) {
|
|
451
529
|
return provider;
|
|
@@ -468,7 +546,7 @@ function resolveRepoSlug(projectRoot) {
|
|
|
468
546
|
async function runGreptileReview(options) {
|
|
469
547
|
const reasons = [];
|
|
470
548
|
const warnings = [];
|
|
471
|
-
const secrets =
|
|
549
|
+
const secrets = resolveRuntimeSecrets2(process.env);
|
|
472
550
|
const apiKey = secrets.GREPTILE_API_KEY || "";
|
|
473
551
|
const apiBase = secrets.GREPTILE_API_BASE || "https://api.greptile.com/mcp";
|
|
474
552
|
const remote = secrets.GREPTILE_REMOTE || "github";
|
|
@@ -604,7 +682,7 @@ function writeFeedbackFile(options) {
|
|
|
604
682
|
if (options.aiRawFeedback) {
|
|
605
683
|
lines.push("## Raw Reviewer Feedback", "", "```text", options.aiRawFeedback, "```", "");
|
|
606
684
|
}
|
|
607
|
-
|
|
685
|
+
writeFileSync2(options.output, `${lines.join(`
|
|
608
686
|
`)}
|
|
609
687
|
`, "utf-8");
|
|
610
688
|
}
|
|
@@ -619,9 +697,9 @@ function writeReviewStateFile(options) {
|
|
|
619
697
|
local_reasons: options.localReasons,
|
|
620
698
|
ai_reasons: options.aiReasons,
|
|
621
699
|
ai_warnings: options.aiWarnings,
|
|
622
|
-
updated_at:
|
|
700
|
+
updated_at: nowIso2()
|
|
623
701
|
};
|
|
624
|
-
|
|
702
|
+
writeFileSync2(options.output, `${JSON.stringify(payload, null, 2)}
|
|
625
703
|
`, "utf-8");
|
|
626
704
|
}
|
|
627
705
|
async function runGreptileReviewForPr(options) {
|
|
@@ -646,7 +724,6 @@ async function runGreptileReviewForPr(options) {
|
|
|
646
724
|
taskId: options.taskId,
|
|
647
725
|
prState: options.prState,
|
|
648
726
|
reviewMode: options.reviewMode,
|
|
649
|
-
infrastructureError: undefined,
|
|
650
727
|
pollAttempts: options.pollAttempts,
|
|
651
728
|
pollIntervalMs: options.pollIntervalMs
|
|
652
729
|
});
|
|
@@ -774,7 +851,7 @@ async function runGreptileReviewForPr(options) {
|
|
|
774
851
|
});
|
|
775
852
|
const actionableComments = filterActionableGreptileComments(commentsPayload.comments || []);
|
|
776
853
|
const reviewBody = reviewDetails.codeReview?.body || "";
|
|
777
|
-
const score = parseGreptileScore(reviewBody);
|
|
854
|
+
const score = mg().parseGreptileScore(reviewBody);
|
|
778
855
|
const feedback = [
|
|
779
856
|
`## ${options.prState.repoLabel || repoName} PR Review`,
|
|
780
857
|
"",
|
|
@@ -782,7 +859,7 @@ async function runGreptileReviewForPr(options) {
|
|
|
782
859
|
`- Review ID: ${selectedReview.id}`,
|
|
783
860
|
`- Status: ${selectedReview.status}`,
|
|
784
861
|
"",
|
|
785
|
-
reviewBody ? stripHtml(reviewBody).trim() : "Greptile completed without summary body."
|
|
862
|
+
reviewBody ? mg().stripHtml(reviewBody).trim() : "Greptile completed without summary body."
|
|
786
863
|
].filter(Boolean).join(`
|
|
787
864
|
`);
|
|
788
865
|
if (actionableComments.length > 0) {
|
|
@@ -803,7 +880,7 @@ async function runGreptileReviewForPr(options) {
|
|
|
803
880
|
}
|
|
804
881
|
};
|
|
805
882
|
}
|
|
806
|
-
const blockerScanBody = stripHtml(reviewBody).replace(/\b(?:no|without|zero)\s+blockers?\b/gi, " ").replace(/\bno\s+changes\s+requested\b/gi, " ");
|
|
883
|
+
const blockerScanBody = mg().stripHtml(reviewBody).replace(/\b(?:no|without|zero)\s+blockers?\b/gi, " ").replace(/\bno\s+changes\s+requested\b/gi, " ");
|
|
807
884
|
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)) {
|
|
808
885
|
reasons.push(`[AI Review] ${repoName}#${prNumber} summary indicates the PR is not safe to merge.`);
|
|
809
886
|
return {
|
|
@@ -851,7 +928,7 @@ async function runGreptileReviewForPr(options) {
|
|
|
851
928
|
status: selectedReview.status
|
|
852
929
|
}]
|
|
853
930
|
});
|
|
854
|
-
strictGate =
|
|
931
|
+
strictGate = mg().evaluateGate(strictEvidence);
|
|
855
932
|
} catch (error) {
|
|
856
933
|
reasons.push(`[AI Review] Strict Greptile evidence collection failed for ${repoName}#${prNumber}: ${error instanceof Error ? error.message : String(error)}`);
|
|
857
934
|
return {
|
|
@@ -978,7 +1055,7 @@ async function runGithubGreptileFallbackReviewForPr(options) {
|
|
|
978
1055
|
fallbackReview?.html_url ? `- Review: ${fallbackReview.html_url}` : "",
|
|
979
1056
|
fallbackReview?.state ? `- Status: ${fallbackReview.state}` : "",
|
|
980
1057
|
"",
|
|
981
|
-
fallbackReview?.body?.trim() ? stripHtml(fallbackReview.body).trim() : "Greptile MCP was unavailable, so verification used GitHub review threads instead."
|
|
1058
|
+
fallbackReview?.body?.trim() ? mg().stripHtml(fallbackReview.body).trim() : "Greptile MCP was unavailable, so verification used GitHub review threads instead."
|
|
982
1059
|
].filter(Boolean).join(`
|
|
983
1060
|
`);
|
|
984
1061
|
const warnings = buildGithubGreptileFallbackWarnings(options);
|
|
@@ -1001,7 +1078,7 @@ async function runGithubGreptileFallbackReviewForPr(options) {
|
|
|
1001
1078
|
taskId: options.taskId,
|
|
1002
1079
|
prUrl
|
|
1003
1080
|
});
|
|
1004
|
-
strictGate =
|
|
1081
|
+
strictGate = mg().evaluateGate(strictEvidence);
|
|
1005
1082
|
} catch (error) {
|
|
1006
1083
|
return {
|
|
1007
1084
|
verdict: "REJECT",
|
|
@@ -1226,7 +1303,7 @@ function loadGithubPullRequestState(projectRoot, repoName, prNumber) {
|
|
|
1226
1303
|
]);
|
|
1227
1304
|
return {
|
|
1228
1305
|
state: response.state || "",
|
|
1229
|
-
merged: response.merged,
|
|
1306
|
+
...response.merged !== undefined ? { merged: response.merged } : {},
|
|
1230
1307
|
merged_at: response.merged_at ?? null
|
|
1231
1308
|
};
|
|
1232
1309
|
}
|
|
@@ -1255,7 +1332,7 @@ function runGhJson(projectRoot, args) {
|
|
|
1255
1332
|
}
|
|
1256
1333
|
}
|
|
1257
1334
|
async function collectStrictPrEvidenceForVerifier(input) {
|
|
1258
|
-
return
|
|
1335
|
+
return mg().collectEvidence({
|
|
1259
1336
|
projectRoot: input.projectRoot,
|
|
1260
1337
|
prUrl: input.prUrl,
|
|
1261
1338
|
taskId: input.taskId,
|
|
@@ -1423,7 +1500,7 @@ function filterActionableGithubGreptileThreads(threads) {
|
|
|
1423
1500
|
}
|
|
1424
1501
|
function resolvePrRepoRoot(projectRoot, prState) {
|
|
1425
1502
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
1426
|
-
if (prState.target === "monorepo" && runtimeWorkspace &&
|
|
1503
|
+
if (prState.target === "monorepo" && runtimeWorkspace && existsSync2(resolve2(runtimeWorkspace, ".git"))) {
|
|
1427
1504
|
return runtimeWorkspace;
|
|
1428
1505
|
}
|
|
1429
1506
|
const paths = resolveHarnessPaths(projectRoot);
|
|
@@ -1437,7 +1514,7 @@ function isCommitAncestorOfPrHead(projectRoot, prState, reviewedCommit, headComm
|
|
|
1437
1514
|
return runCapture(["git", "-C", repoRoot, "merge-base", "--is-ancestor", reviewedCommit, headCommit], projectRoot).exitCode === 0;
|
|
1438
1515
|
}
|
|
1439
1516
|
function summarizeComment(input) {
|
|
1440
|
-
const text = stripHtml(input).replace(/\s+/g, " ").trim();
|
|
1517
|
+
const text = mg().stripHtml(input).replace(/\s+/g, " ").trim();
|
|
1441
1518
|
return text.length > 160 ? `${text.slice(0, 157)}...` : text;
|
|
1442
1519
|
}
|
|
1443
1520
|
function asGreptileInfrastructureWarning(reason) {
|
|
@@ -1459,7 +1536,6 @@ var __testOnly = {
|
|
|
1459
1536
|
filterActionableGithubGreptileThreads,
|
|
1460
1537
|
isGithubGreptileCheckApproved,
|
|
1461
1538
|
isAiReviewApproved,
|
|
1462
|
-
parseGreptileScore,
|
|
1463
1539
|
pickLatestGithubGreptileReview,
|
|
1464
1540
|
pickRelevantGithubGreptileReview,
|
|
1465
1541
|
resolveGreptileRequestTimeoutMs,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { StageMutation } from "@rig/contracts";
|
|
2
|
-
import { type KernelStageResolverResult } from "@rig/kernel/resolver";
|
|
2
|
+
import { type KernelStageResolverResult } from "@rig/kernel-seed/resolver";
|
|
3
3
|
import type { DefaultLifecycleStageDescriptor, DefaultLifecycleStageId } from "./stages/types";
|
|
4
4
|
export declare const DEFAULT_LIFECYCLE_STAGE_IDS: readonly ["validate", "verify", "commit", "push", "open-pr", "merge-gate", "auto-merge", "source-closeout", "isolation", "journal-append"];
|
|
5
5
|
export declare const defaultLifecycleStages: readonly DefaultLifecycleStageDescriptor[];
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @bun
|
|
2
2
|
// packages/bundle-default-lifecycle/src/defaultPipeline.ts
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { createDefaultKernelPlugin } from "@rig/kernel-seed/default-kernel";
|
|
4
|
+
import { resolveKernelStages } from "@rig/kernel-seed/resolver";
|
|
5
5
|
|
|
6
6
|
// packages/bundle-default-lifecycle/src/stages/types.ts
|
|
7
7
|
function defineDefaultLifecycleStage(input) {
|
|
@@ -29,6 +29,9 @@ var commitStage = defineDefaultLifecycleStage({
|
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
// packages/bundle-default-lifecycle/src/stages/isolation.ts
|
|
32
|
+
import { ISOLATION_BACKEND } from "@rig/contracts";
|
|
33
|
+
import { defineCapability } from "@rig/core/capability";
|
|
34
|
+
import { requireCapabilityForRoot } from "@rig/core/capability-loaders";
|
|
32
35
|
var isolationStage = defineDefaultLifecycleStage({
|
|
33
36
|
id: "isolation",
|
|
34
37
|
kind: "transform",
|