@h-rig/bundle-default-lifecycle 0.0.6-alpha.134 → 0.0.6-alpha.136

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.
@@ -0,0 +1,465 @@
1
+ // @bun
2
+ // packages/bundle-default-lifecycle/src/pipelineCloseout.ts
3
+ import { resolve } from "path";
4
+ import { loadConfig } from "@rig/core/load-config";
5
+ import { createPluginHost } from "@rig/core";
6
+ import { createDefaultKernel } from "@rig/kernel/default-kernel";
7
+ import { buildPluginHostContext } from "@rig/runtime/control-plane/plugin-host-context";
8
+ import {
9
+ CloseoutValidationError
10
+ } from "@rig/runtime/control-plane/native/in-process-closeout";
11
+ import { taskValidate } from "@rig/runtime/control-plane/native/task-ops";
12
+
13
+ // packages/bundle-default-lifecycle/src/defaultPipeline.ts
14
+ import { resolveKernelStages } from "@rig/kernel/resolver";
15
+ import { createDefaultKernelPlugin } from "@rig/kernel/default-kernel";
16
+
17
+ // packages/bundle-default-lifecycle/src/stages/auto-merge.ts
18
+ import { runRepoDefaultMerge } from "@rig/runtime/control-plane/native/pr-automation";
19
+
20
+ // packages/bundle-default-lifecycle/src/stages/types.ts
21
+ function defineDefaultLifecycleStage(input) {
22
+ return {
23
+ ...input,
24
+ protected: input.protected ?? false,
25
+ priority: input.priority ?? 0
26
+ };
27
+ }
28
+
29
+ // packages/bundle-default-lifecycle/src/stages/auto-merge.ts
30
+ var autoMergeStage = defineDefaultLifecycleStage({
31
+ id: "auto-merge",
32
+ kind: "transform",
33
+ description: "Merge an approved PR using the repository default merge method through the runtime helper.",
34
+ calls: ["runRepoDefaultMerge"]
35
+ });
36
+ async function runAutoMergeStage(input) {
37
+ await runRepoDefaultMerge(input);
38
+ }
39
+
40
+ // packages/bundle-default-lifecycle/src/stages/commit.ts
41
+ import { commitRunChanges } from "@rig/runtime/control-plane/native/pr-automation";
42
+ var commitStage = defineDefaultLifecycleStage({
43
+ id: "commit",
44
+ kind: "transform",
45
+ description: "Commit the agent worktree changes using the runtime git closeout helper.",
46
+ calls: ["commitRunChanges"]
47
+ });
48
+ async function runCommitStage(input) {
49
+ return await commitRunChanges(input);
50
+ }
51
+
52
+ // packages/bundle-default-lifecycle/src/stages/isolation.ts
53
+ import { ensureAgentRuntime } from "@rig/runtime/control-plane/runtime/isolation";
54
+ var isolationStage = defineDefaultLifecycleStage({
55
+ id: "isolation",
56
+ kind: "transform",
57
+ description: "Provision the isolated runtime worktree through the runtime isolation subsystem.",
58
+ calls: ["ensureAgentRuntime"],
59
+ protected: true
60
+ });
61
+
62
+ // packages/bundle-default-lifecycle/src/stages/journal-append.ts
63
+ var journalAppendStage = defineDefaultLifecycleStage({
64
+ id: "journal-append",
65
+ kind: "observe",
66
+ description: "Record resolved pipeline and per-stage outcome entries through the kernel journal capability.",
67
+ calls: ["journalCapability.append"],
68
+ protected: true
69
+ });
70
+
71
+ // packages/bundle-default-lifecycle/src/stages/merge-gate.ts
72
+ import {
73
+ runStrictPrMergeGate
74
+ } from "@rig/runtime/control-plane/native/pr-review-gate";
75
+ var mergeGateStage = defineDefaultLifecycleStage({
76
+ id: "merge-gate",
77
+ kind: "gate",
78
+ description: "Enforce GitHub review state, required checks, and configured review gates through runtime PR automation.",
79
+ calls: ["runStrictPrMergeGate"],
80
+ protected: true
81
+ });
82
+ async function runMergeGateStage(input) {
83
+ return await runStrictPrMergeGate({
84
+ projectRoot: input.projectRoot,
85
+ prUrl: input.prUrl,
86
+ taskId: input.taskId,
87
+ runId: input.runId,
88
+ cycle: input.cycle,
89
+ command: input.command,
90
+ ...input.artifactRoot !== undefined ? { artifactRoot: input.artifactRoot } : {},
91
+ ...input.allowedFailures !== undefined ? { allowedFailures: input.allowedFailures } : {},
92
+ ...input.greptileApi !== undefined ? { greptileApi: input.greptileApi } : {},
93
+ ...input.final !== undefined ? { final: input.final } : {},
94
+ ...input.requireGreptile !== undefined ? { requireGreptile: input.requireGreptile } : {}
95
+ });
96
+ }
97
+
98
+ // packages/bundle-default-lifecycle/src/stages/open-pr.ts
99
+ import { runPrAutomation } from "@rig/runtime/control-plane/native/pr-automation";
100
+ var openPrStage = defineDefaultLifecycleStage({
101
+ id: "open-pr",
102
+ kind: "transform",
103
+ description: "Open or reuse the closeout PR through the existing runtime PR automation seam.",
104
+ calls: ["runPrAutomation"]
105
+ });
106
+ async function runOpenPrStage(input) {
107
+ return await runPrAutomation({
108
+ projectRoot: input.workspace,
109
+ taskId: input.taskId,
110
+ runId: input.runId,
111
+ branch: input.branch,
112
+ sourceTask: input.sourceTask ? { title: typeof input.sourceTask.title === "string" ? input.sourceTask.title : null } : null,
113
+ command: input.command,
114
+ gitCommand: input.gitCommand,
115
+ steerPi: input.steerPi,
116
+ ...input.config ? { config: input.config } : {},
117
+ ...input.artifactRoot !== undefined ? { artifactRoot: input.artifactRoot } : {},
118
+ ...input.greptileApi !== undefined ? { greptileApi: input.greptileApi } : {},
119
+ ...input.lifecycle !== undefined ? { lifecycle: input.lifecycle } : {},
120
+ ...input.uploadedSnapshot !== undefined ? { uploadedSnapshot: input.uploadedSnapshot } : {}
121
+ });
122
+ }
123
+
124
+ // packages/bundle-default-lifecycle/src/stages/push.ts
125
+ import { pushBranchSyncedWithOrigin } from "@rig/runtime/control-plane/native/pr-automation";
126
+ var pushStage = defineDefaultLifecycleStage({
127
+ id: "push",
128
+ kind: "transform",
129
+ description: "Synchronize and push the task branch using the runtime closeout git helper.",
130
+ calls: ["pushBranchSyncedWithOrigin"]
131
+ });
132
+ async function runPushStage(input) {
133
+ await pushBranchSyncedWithOrigin(input);
134
+ }
135
+
136
+ // packages/bundle-default-lifecycle/src/stages/source-closeout.ts
137
+ import { closeIssueAfterMergedPr } from "@rig/runtime/control-plane/native/pr-automation";
138
+ var sourceCloseoutStage = defineDefaultLifecycleStage({
139
+ id: "source-closeout",
140
+ kind: "transform",
141
+ description: "Reflect the merged PR into the task source using the existing runtime closeout helper.",
142
+ calls: ["closeIssueAfterMergedPr"]
143
+ });
144
+ async function runSourceCloseoutStage(input) {
145
+ if (input.pr.status !== "merged" || !input.pr.prUrl)
146
+ return;
147
+ await closeIssueAfterMergedPr({
148
+ projectRoot: input.projectRoot,
149
+ taskId: input.taskId,
150
+ runId: input.runId,
151
+ prUrl: input.pr.prUrl,
152
+ updateTaskSource: input.updateTaskSource,
153
+ ...input.sourceTask !== undefined ? { sourceTask: input.sourceTask } : {}
154
+ });
155
+ }
156
+
157
+ // packages/bundle-default-lifecycle/src/stages/validate.ts
158
+ var validateStage = defineDefaultLifecycleStage({
159
+ id: "validate",
160
+ kind: "transform",
161
+ description: "Run plugin-host validators against the isolated worktree before closeout side effects.",
162
+ calls: ["taskValidate"]
163
+ });
164
+ async function runValidateStage(input, runner) {
165
+ return await runner(input);
166
+ }
167
+
168
+ // packages/bundle-default-lifecycle/src/stages/verify.ts
169
+ var verifyStage = defineDefaultLifecycleStage({
170
+ id: "verify",
171
+ kind: "gate",
172
+ description: "Run the local verifier preflight and block closeout when it rejects the worktree.",
173
+ calls: ["verifierPreflight"]
174
+ });
175
+
176
+ // packages/bundle-default-lifecycle/src/defaultPipeline.ts
177
+ var DEFAULT_STAGE_AFTER = {
178
+ verify: ["validate"],
179
+ commit: ["verify"],
180
+ push: ["commit"],
181
+ "open-pr": ["push"],
182
+ "merge-gate": ["open-pr"],
183
+ "auto-merge": ["merge-gate"],
184
+ "source-closeout": ["auto-merge"],
185
+ isolation: ["source-closeout"],
186
+ "journal-append": ["isolation"]
187
+ };
188
+ function withDefaultAnchors(stage) {
189
+ const after = DEFAULT_STAGE_AFTER[stage.id];
190
+ return after ? { ...stage, after } : stage;
191
+ }
192
+ var defaultLifecycleStages = [
193
+ validateStage,
194
+ verifyStage,
195
+ commitStage,
196
+ pushStage,
197
+ openPrStage,
198
+ mergeGateStage,
199
+ autoMergeStage,
200
+ sourceCloseoutStage,
201
+ isolationStage,
202
+ journalAppendStage
203
+ ].map(withDefaultAnchors);
204
+ function resolveDefaultLifecycle(input = {}) {
205
+ const grants = { protectedStageGrants: input.protectedStageGrants ?? [] };
206
+ return resolveKernelStages(defaultLifecycleStages, input.mutations ?? [], grants);
207
+ }
208
+
209
+ // packages/bundle-default-lifecycle/src/pipelineCloseout.ts
210
+ function cleanString(value) {
211
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
212
+ }
213
+ function closeoutOutcome(status) {
214
+ switch (status) {
215
+ case "completed":
216
+ return "completed";
217
+ case "failed":
218
+ case "needs-attention":
219
+ return "failed";
220
+ case "pending":
221
+ case "running":
222
+ return "started";
223
+ }
224
+ }
225
+ async function loadRigAutomationConfig(projectRoot) {
226
+ try {
227
+ return await loadConfig(projectRoot);
228
+ } catch {
229
+ return null;
230
+ }
231
+ }
232
+ async function runRigProjectValidation({ projectRoot, taskId }) {
233
+ const pluginHostCtx = await buildPluginHostContext(projectRoot);
234
+ return taskValidate(projectRoot, taskId, pluginHostCtx?.validatorRegistry ?? undefined);
235
+ }
236
+ function shouldAttemptRigMerge(config) {
237
+ const mode = config.merge?.mode;
238
+ return mode !== "off" && mode !== "pr-ready";
239
+ }
240
+ async function loadPluginStageContributions(projectRoot) {
241
+ try {
242
+ const config = await loadConfig(projectRoot);
243
+ const host = createPluginHost(config.plugins ?? []);
244
+ return { executors: host.listStageExecutors(), mutations: host.listStageMutations() };
245
+ } catch {
246
+ return { executors: {}, mutations: [] };
247
+ }
248
+ }
249
+ async function runPipelineCloseout(input) {
250
+ const taskId = cleanString(input.taskId);
251
+ if (!taskId) {
252
+ throw new Error("Pipeline closeout requires a task id.");
253
+ }
254
+ const loadedConfig = input.config ?? await loadRigAutomationConfig(input.projectRoot);
255
+ const prMode = loadedConfig?.pr?.mode ?? "off";
256
+ const reviewProvider = loadedConfig?.review?.provider ?? "github";
257
+ const effectiveConfig = {
258
+ ...loadedConfig ?? {},
259
+ pr: { ...loadedConfig?.pr ?? {}, mode: prMode },
260
+ review: { ...loadedConfig?.review ?? {}, provider: reviewProvider }
261
+ };
262
+ const openOnlyConfig = {
263
+ ...effectiveConfig,
264
+ merge: { ...effectiveConfig.merge ?? {}, mode: "pr-ready" }
265
+ };
266
+ const shouldMerge = shouldAttemptRigMerge(effectiveConfig);
267
+ const workspace = input.workspace;
268
+ const artifactRoot = input.artifactRoot ?? resolve(input.projectRoot, "artifacts", taskId);
269
+ const journal = async (phase, status, detail) => {
270
+ await input.journalPhase(phase, closeoutOutcome(status), detail ?? null);
271
+ };
272
+ if (prMode === "off" || prMode === "ask") {
273
+ const reason = prMode === "ask" ? "PR creation awaits operator approval." : "PR automation disabled.";
274
+ await input.reflect("under_review", reason);
275
+ await journal("completed", "completed", reason);
276
+ return {
277
+ mode: "pipeline",
278
+ pipelineStageIds: [...resolveDefaultLifecycle().order],
279
+ result: { status: "skipped", iterations: 0, feedback: [] }
280
+ };
281
+ }
282
+ const state = {
283
+ branch: input.branch,
284
+ validationPassed: false,
285
+ committed: false,
286
+ pushed: false,
287
+ prUrl: null,
288
+ prReady: false,
289
+ pr: null,
290
+ gate: null,
291
+ mergeGate: null,
292
+ merged: false,
293
+ iterations: 0,
294
+ feedback: [],
295
+ blockedDetail: null
296
+ };
297
+ const cont = (ctx2) => ({ kind: "continue", ctx: ctx2 });
298
+ const executors = {
299
+ isolation: (ctx2) => cont(ctx2),
300
+ validate: async (ctx2) => {
301
+ await input.onValidationStart?.();
302
+ await journal("queued", "running", `Validating task ${taskId} before closeout.`);
303
+ let passed = false;
304
+ try {
305
+ passed = await runValidateStage({ projectRoot: input.projectRoot, taskId }, input.runValidation ?? runRigProjectValidation);
306
+ } catch (error) {
307
+ const detail = `Rig validation failed before closeout: ${error instanceof Error ? error.message : String(error)}`;
308
+ await input.reflect("needs_attention", "Rig validation failed before closeout; commit/push/PR automation is blocked.", { errorText: detail });
309
+ throw new CloseoutValidationError(detail);
310
+ }
311
+ if (!passed) {
312
+ const detail = `Rig validation failed for task ${taskId}; closeout blocked before commit.`;
313
+ await input.reflect("needs_attention", "Rig validation failed before closeout; commit/push/PR automation is blocked.", { errorText: detail });
314
+ throw new CloseoutValidationError(detail);
315
+ }
316
+ state.validationPassed = true;
317
+ await journal("queued", "completed", `Validation passed for task ${taskId}.`);
318
+ const workspaceBranch = await input.gitCommand(["rev-parse", "--abbrev-ref", "HEAD"], { cwd: workspace });
319
+ const currentWorkspaceBranch = workspaceBranch.exitCode === 0 ? cleanString(workspaceBranch.stdout) : null;
320
+ if (currentWorkspaceBranch && currentWorkspaceBranch !== "HEAD" && currentWorkspaceBranch !== state.branch) {
321
+ state.branch = currentWorkspaceBranch;
322
+ }
323
+ return cont(ctx2);
324
+ },
325
+ verify: () => state.validationPassed ? { kind: "allow" } : { kind: "block", reason: "validation did not pass" },
326
+ commit: async (ctx2) => {
327
+ await journal("commit", "running", `Committing changes in ${workspace}.`);
328
+ const committed = await runCommitStage({ cwd: workspace, message: `rig: complete task ${taskId}`, command: input.gitCommand });
329
+ state.committed = committed.committed;
330
+ return cont(ctx2);
331
+ },
332
+ push: async (ctx2) => {
333
+ await journal("push", "running", `Pushing branch ${state.branch}.`);
334
+ await runPushStage({ projectRoot: workspace, branch: state.branch, gitCommand: input.gitCommand });
335
+ state.pushed = true;
336
+ return cont(ctx2);
337
+ },
338
+ "open-pr": async (ctx2) => {
339
+ await journal("pr-review-merge", "running", `Opening a pull request for ${state.branch}.`);
340
+ const pr = await runOpenPrStage({
341
+ ...input,
342
+ taskId,
343
+ branch: state.branch,
344
+ artifactRoot,
345
+ config: openOnlyConfig,
346
+ sourceTask: { title: cleanString(input.sourceTask?.title) },
347
+ lifecycle: {
348
+ onPrOpened: async ({ prUrl }) => {
349
+ await journal("pr-opened", "running", prUrl);
350
+ await input.reflect("under_review", "Rig opened a pull request for this task.");
351
+ },
352
+ onFeedback: async ({ feedback }) => {
353
+ await input.reflect("ci_fixing", "Rig is fixing CI/review feedback for this task.", { errorText: feedback.join(`
354
+ `) || null });
355
+ }
356
+ }
357
+ });
358
+ state.pr = pr;
359
+ state.prUrl = pr.prUrl ?? null;
360
+ state.prReady = pr.status === "opened" || pr.status === "merged";
361
+ state.iterations = pr.iterations;
362
+ state.feedback = [...pr.actionableFeedback];
363
+ if (pr.status === "needs_attention") {
364
+ state.blockedDetail = pr.actionableFeedback.join(`
365
+ `) || "PR automation did not produce a mergeable PR.";
366
+ }
367
+ return cont(ctx2);
368
+ },
369
+ "merge-gate": async (ctx2) => {
370
+ if (!shouldMerge || !state.prReady || !state.prUrl) {
371
+ state.mergeGate = state.prReady ? "skipped" : null;
372
+ return state.prReady ? cont(ctx2) : { kind: "block", reason: state.blockedDetail ?? "no mergeable PR to gate" };
373
+ }
374
+ const gate = await runMergeGateStage({
375
+ projectRoot: workspace,
376
+ prUrl: state.prUrl,
377
+ taskId,
378
+ runId: input.runId,
379
+ cycle: 1,
380
+ command: input.command,
381
+ artifactRoot,
382
+ final: true,
383
+ ...effectiveConfig.merge?.allowedFailures ? { allowedFailures: effectiveConfig.merge.allowedFailures } : {},
384
+ ...input.greptileApi !== undefined ? { greptileApi: input.greptileApi } : {},
385
+ requireGreptile: reviewProvider === "greptile"
386
+ });
387
+ state.gate = gate;
388
+ if (gate.approved) {
389
+ state.mergeGate = "passed";
390
+ return cont(ctx2);
391
+ }
392
+ state.mergeGate = "blocked";
393
+ const detail = gate.actionableFeedback.join(`
394
+ `) || gate.reasons.join("; ") || "merge gate blocked the PR.";
395
+ state.blockedDetail = detail;
396
+ await input.reflect("needs_attention", "Rig needs operator attention before this task can merge.", { errorText: detail });
397
+ await journal("pr-review-merge", "needs-attention", detail);
398
+ return { kind: "block", reason: detail };
399
+ },
400
+ "auto-merge": async (ctx2) => {
401
+ if (!shouldMerge || state.mergeGate !== "passed" || !state.prUrl || !state.gate) {
402
+ return cont(ctx2);
403
+ }
404
+ await journal("merge", "running", state.prUrl);
405
+ await input.reflect("merging", "Rig is merging the pull request for this task.");
406
+ await runAutoMergeStage({ prUrl: state.prUrl, config: effectiveConfig, command: input.command, cwd: workspace, strictGate: state.gate });
407
+ state.merged = true;
408
+ return cont(ctx2);
409
+ },
410
+ "source-closeout": async (ctx2) => {
411
+ if (!state.merged || !state.prUrl)
412
+ return cont(ctx2);
413
+ await journal("close-source", "running", state.prUrl);
414
+ const mergedPr = { ...state.pr ?? { iterations: state.iterations, actionableFeedback: state.feedback }, status: "merged", prUrl: state.prUrl, merged: true };
415
+ await runSourceCloseoutStage({
416
+ projectRoot: input.projectRoot,
417
+ taskId,
418
+ runId: input.runId,
419
+ pr: mergedPr,
420
+ ...input.sourceTask !== undefined ? { sourceTask: input.sourceTask } : {},
421
+ updateTaskSource: async () => {
422
+ await input.reflect("closed", "Rig merged the pull request and closed this task source.");
423
+ return { updated: true, taskId, status: "closed", source: "runtime", sourceKind: "runtime" };
424
+ }
425
+ });
426
+ return cont(ctx2);
427
+ },
428
+ "journal-append": (ctx2) => cont(ctx2)
429
+ };
430
+ const pluginStages = await loadPluginStageContributions(input.projectRoot);
431
+ const kernel = createDefaultKernel({ stageExecutors: { ...executors, ...pluginStages.executors } });
432
+ const resolved = kernel.stageRunner.resolve(defaultLifecycleStages, pluginStages.mutations);
433
+ const ctx = {
434
+ runId: input.runId,
435
+ taskId,
436
+ state,
437
+ metadata: { projectRoot: input.projectRoot, workspace }
438
+ };
439
+ await kernel.stageRunner.runPipeline(input.runId, resolved, ctx);
440
+ const result = mapStateToResult(state);
441
+ if (result.status === "merged" || result.status === "opened") {
442
+ await journal("completed", "completed", result.prUrl ? `${result.status === "merged" ? "PR merged and issue closed" : "PR ready without merge"}: ${result.prUrl}` : result.status);
443
+ }
444
+ return { mode: "pipeline", pipelineStageIds: [...resolved.order], result };
445
+ }
446
+ function mapStateToResult(state) {
447
+ if (state.merged && state.prUrl) {
448
+ return { status: "merged", prUrl: state.prUrl, iterations: state.iterations, feedback: state.feedback };
449
+ }
450
+ if (state.mergeGate === "blocked" || state.blockedDetail) {
451
+ return {
452
+ status: "needs-attention",
453
+ ...state.prUrl ? { prUrl: state.prUrl } : {},
454
+ iterations: state.iterations,
455
+ feedback: state.feedback
456
+ };
457
+ }
458
+ if (state.prReady && state.prUrl) {
459
+ return { status: "opened", prUrl: state.prUrl, iterations: state.iterations, feedback: state.feedback };
460
+ }
461
+ return { status: "needs-attention", ...state.prUrl ? { prUrl: state.prUrl } : {}, iterations: state.iterations, feedback: state.feedback };
462
+ }
463
+ export {
464
+ runPipelineCloseout
465
+ };
@@ -1,6 +1,7 @@
1
1
  // @bun
2
2
  // packages/bundle-default-lifecycle/src/defaultPipeline.ts
3
3
  import { resolveKernelStages } from "@rig/kernel/resolver";
4
+ import { createDefaultKernelPlugin } from "@rig/kernel/default-kernel";
4
5
 
5
6
  // packages/bundle-default-lifecycle/src/stages/auto-merge.ts
6
7
  import { runRepoDefaultMerge } from "@rig/runtime/control-plane/native/pr-automation";
@@ -51,6 +52,9 @@ var journalAppendStage = defineDefaultLifecycleStage({
51
52
  });
52
53
 
53
54
  // packages/bundle-default-lifecycle/src/stages/merge-gate.ts
55
+ import {
56
+ runStrictPrMergeGate
57
+ } from "@rig/runtime/control-plane/native/pr-review-gate";
54
58
  var mergeGateStage = defineDefaultLifecycleStage({
55
59
  id: "merge-gate",
56
60
  kind: "gate",
@@ -103,6 +107,21 @@ var verifyStage = defineDefaultLifecycleStage({
103
107
  });
104
108
 
105
109
  // packages/bundle-default-lifecycle/src/defaultPipeline.ts
110
+ var DEFAULT_STAGE_AFTER = {
111
+ verify: ["validate"],
112
+ commit: ["verify"],
113
+ push: ["commit"],
114
+ "open-pr": ["push"],
115
+ "merge-gate": ["open-pr"],
116
+ "auto-merge": ["merge-gate"],
117
+ "source-closeout": ["auto-merge"],
118
+ isolation: ["source-closeout"],
119
+ "journal-append": ["isolation"]
120
+ };
121
+ function withDefaultAnchors(stage) {
122
+ const after = DEFAULT_STAGE_AFTER[stage.id];
123
+ return after ? { ...stage, after } : stage;
124
+ }
106
125
  var defaultLifecycleStages = [
107
126
  validateStage,
108
127
  verifyStage,
@@ -114,7 +133,7 @@ var defaultLifecycleStages = [
114
133
  sourceCloseoutStage,
115
134
  isolationStage,
116
135
  journalAppendStage
117
- ];
136
+ ].map(withDefaultAnchors);
118
137
 
119
138
  // packages/bundle-default-lifecycle/src/plugin.ts
120
139
  var DEFAULT_LIFECYCLE_PLUGIN_ID = "@rig/bundle-default-lifecycle";
@@ -1 +1,24 @@
1
+ import { type StrictPrGreptileApiOptions, type StrictPrMergeGateResult } from "@rig/runtime/control-plane/native/pr-review-gate";
2
+ import type { GitHubCommandRunner } from "@rig/runtime/control-plane/native/pr-automation";
3
+ export type MergeGateStageInput = {
4
+ readonly projectRoot: string;
5
+ readonly prUrl: string;
6
+ readonly taskId: string;
7
+ readonly runId: string;
8
+ readonly cycle: number;
9
+ readonly command: GitHubCommandRunner;
10
+ readonly artifactRoot?: string | null;
11
+ readonly allowedFailures?: readonly string[];
12
+ readonly greptileApi?: StrictPrGreptileApiOptions;
13
+ readonly final?: boolean;
14
+ readonly requireGreptile?: boolean;
15
+ };
1
16
  export declare const mergeGateStage: import("./types").DefaultLifecycleStageDescriptor;
17
+ /**
18
+ * Executable for the protected `merge-gate` stage. Wraps the runtime's strict
19
+ * merge gate (`runStrictPrMergeGate`) so the gate runs as a discrete resolved
20
+ * pipeline stage rather than only as logic embedded inside `runPrAutomation`.
21
+ * Returns the full {@link StrictPrMergeGateResult}; the caller maps it to a
22
+ * gate allow/block from `result.approved` / `result.pending`.
23
+ */
24
+ export declare function runMergeGateStage(input: MergeGateStageInput): Promise<StrictPrMergeGateResult>;
@@ -1,4 +1,9 @@
1
1
  // @bun
2
+ // packages/bundle-default-lifecycle/src/stages/merge-gate.ts
3
+ import {
4
+ runStrictPrMergeGate
5
+ } from "@rig/runtime/control-plane/native/pr-review-gate";
6
+
2
7
  // packages/bundle-default-lifecycle/src/stages/types.ts
3
8
  function defineDefaultLifecycleStage(input) {
4
9
  return {
@@ -16,6 +21,22 @@ var mergeGateStage = defineDefaultLifecycleStage({
16
21
  calls: ["runStrictPrMergeGate"],
17
22
  protected: true
18
23
  });
24
+ async function runMergeGateStage(input) {
25
+ return await runStrictPrMergeGate({
26
+ projectRoot: input.projectRoot,
27
+ prUrl: input.prUrl,
28
+ taskId: input.taskId,
29
+ runId: input.runId,
30
+ cycle: input.cycle,
31
+ command: input.command,
32
+ ...input.artifactRoot !== undefined ? { artifactRoot: input.artifactRoot } : {},
33
+ ...input.allowedFailures !== undefined ? { allowedFailures: input.allowedFailures } : {},
34
+ ...input.greptileApi !== undefined ? { greptileApi: input.greptileApi } : {},
35
+ ...input.final !== undefined ? { final: input.final } : {},
36
+ ...input.requireGreptile !== undefined ? { requireGreptile: input.requireGreptile } : {}
37
+ });
38
+ }
19
39
  export {
40
+ runMergeGateStage,
20
41
  mergeGateStage
21
42
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/bundle-default-lifecycle",
3
- "version": "0.0.6-alpha.134",
3
+ "version": "0.0.6-alpha.136",
4
4
  "type": "module",
5
5
  "description": "Default Rig run lifecycle stage bundle wrapping the existing closeout runtime.",
6
6
  "license": "UNLICENSED",
@@ -25,9 +25,9 @@
25
25
  "types": "./dist/src/defaultPipeline.d.ts",
26
26
  "import": "./dist/src/defaultPipeline.js"
27
27
  },
28
- "./staged-closeout": {
29
- "types": "./dist/src/stagedCloseout.d.ts",
30
- "import": "./dist/src/stagedCloseout.js"
28
+ "./pipeline-closeout": {
29
+ "types": "./dist/src/pipelineCloseout.d.ts",
30
+ "import": "./dist/src/pipelineCloseout.js"
31
31
  },
32
32
  "./plugin": {
33
33
  "types": "./dist/src/plugin.d.ts",
@@ -41,9 +41,9 @@
41
41
  "module": "./dist/src/index.js",
42
42
  "types": "./dist/src/index.d.ts",
43
43
  "dependencies": {
44
- "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.134",
45
- "@rig/core": "npm:@h-rig/core@0.0.6-alpha.134",
46
- "@rig/kernel": "npm:@h-rig/kernel@0.0.6-alpha.134",
47
- "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.134"
44
+ "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.136",
45
+ "@rig/core": "npm:@h-rig/core@0.0.6-alpha.136",
46
+ "@rig/kernel": "npm:@h-rig/kernel@0.0.6-alpha.136",
47
+ "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.136"
48
48
  }
49
49
  }
@@ -1,7 +0,0 @@
1
- import { type InProcessCloseoutInput, type InProcessCloseoutResult } from "@rig/runtime/control-plane/native/in-process-closeout";
2
- export type StagedCloseoutResult = {
3
- readonly mode: "staged";
4
- readonly pipelineStageIds: readonly string[];
5
- readonly result: InProcessCloseoutResult;
6
- };
7
- export declare function runStagedCloseout(input: InProcessCloseoutInput): Promise<StagedCloseoutResult>;