@h-rig/bundle-default-lifecycle 0.0.6-alpha.156 → 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.
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
@@ -15,6 +15,19 @@ var __export = (target, all) => {
15
15
  };
16
16
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
17
17
 
18
+ // packages/bundle-default-lifecycle/src/control-plane/pr-merge-gate-cap.ts
19
+ import { PR_MERGE_GATE } from "@rig/contracts";
20
+ import { defineCapability } from "@rig/core/capability";
21
+ import { resolvePluginHost } from "@rig/core/project-plugins";
22
+ async function resolvePrMergeGateService(projectRoot) {
23
+ const { host } = await resolvePluginHost(projectRoot);
24
+ return PrMergeGateCap.require(host);
25
+ }
26
+ var PrMergeGateCap;
27
+ var init_pr_merge_gate_cap = __esm(() => {
28
+ PrMergeGateCap = defineCapability(PR_MERGE_GATE);
29
+ });
30
+
18
31
  // packages/bundle-default-lifecycle/src/control-plane/pr-automation.ts
19
32
  var exports_pr_automation = {};
20
33
  __export(exports_pr_automation, {
@@ -32,11 +45,7 @@ __export(exports_pr_automation, {
32
45
  buildPrAutomationBody: () => buildPrAutomationBody,
33
46
  UPLOADED_SNAPSHOT_PR_MARKER: () => UPLOADED_SNAPSHOT_PR_MARKER
34
47
  });
35
- import { assertSafeGitBranchName } from "@rig/shared/safe-identifiers";
36
- import { runStrictPrMergeGate } from "@rig/pr-review-plugin";
37
- import {
38
- strictMergeHeadShaFromGate
39
- } from "@rig/contracts";
48
+ import { assertSafeGitBranchName } from "@rig/core/safe-identifiers";
40
49
  function positiveInt(value, fallback) {
41
50
  return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
42
51
  }
@@ -339,7 +348,7 @@ async function commitRunChanges(input) {
339
348
  async function closeIssueAfterMergedPr(input) {
340
349
  await input.updateTaskSource(input.projectRoot, {
341
350
  taskId: input.taskId,
342
- sourceTask: input.sourceTask,
351
+ ...input.sourceTask !== undefined ? { sourceTask: input.sourceTask } : {},
343
352
  update: {
344
353
  status: "closed",
345
354
  comment: [
@@ -385,11 +394,12 @@ async function runRepoDefaultMerge(input) {
385
394
  if (merge.mode === "off")
386
395
  return;
387
396
  const requireGreptile = (input.config?.review?.provider ?? "greptile") === "greptile";
388
- const matchHeadSha = strictMergeHeadShaFromGate(input.strictGate, input.prUrl, requireGreptile);
397
+ const mergeGate = await resolvePrMergeGateService(input.projectRoot ?? input.cwd ?? process.cwd());
398
+ const matchHeadSha = mergeGate.resolveHeadSha({ result: input.strictGate, prUrl: input.prUrl, requireGreptile });
389
399
  const method = merge.method ?? "repo-default";
390
400
  const args = ["pr", "merge", input.prUrl];
391
401
  if (method === "repo-default") {
392
- args.push(await resolveRepoDefaultMergeFlag({ prUrl: input.prUrl, command: input.command, cwd: input.cwd }));
402
+ args.push(await resolveRepoDefaultMergeFlag({ prUrl: input.prUrl, command: input.command, ...input.cwd !== undefined ? { cwd: input.cwd } : {} }));
393
403
  } else {
394
404
  args.push(`--${method}`);
395
405
  }
@@ -466,6 +476,7 @@ async function syncBranchAfterPrFeedback(input) {
466
476
  }
467
477
  async function runPrAutomation(input) {
468
478
  const branch = assertSafeGitBranchName(input.branch, "PR branch");
479
+ const mergeGate = await resolvePrMergeGateService(input.projectRoot);
469
480
  const prConfig = input.config?.pr ?? {};
470
481
  const requireGreptile = (input.config?.review?.provider ?? "greptile") === "greptile";
471
482
  if (prConfig.mode === "off" || prConfig.mode === "ask") {
@@ -475,7 +486,7 @@ async function runPrAutomation(input) {
475
486
  taskId: input.taskId,
476
487
  runId: input.runId,
477
488
  summary: input.sourceTask?.title ? `Rig completed: ${input.sourceTask.title}` : null,
478
- uploadedSnapshot: input.uploadedSnapshot
489
+ ...input.uploadedSnapshot !== undefined ? { uploadedSnapshot: input.uploadedSnapshot } : {}
479
490
  });
480
491
  if (input.gitCommand) {
481
492
  await pushBranchSyncedWithOrigin({ projectRoot: input.projectRoot, branch, gitCommand: input.gitCommand });
@@ -547,16 +558,16 @@ ${createResult.stdout ?? ""}`) : null;
547
558
  await syncBranchAfterPrFeedback({ projectRoot: input.projectRoot, taskId: input.taskId, branch, gitCommand: input.gitCommand });
548
559
  continue;
549
560
  }
550
- const gate = await runStrictPrMergeGate({
561
+ const gate = await mergeGate.runGate({
551
562
  projectRoot: input.projectRoot,
552
563
  prUrl,
553
564
  taskId: input.taskId,
554
565
  runId: input.runId,
555
566
  cycle: iteration,
556
567
  command: input.command,
557
- artifactRoot: input.artifactRoot,
568
+ ...input.artifactRoot !== undefined ? { artifactRoot: input.artifactRoot } : {},
558
569
  allowedFailures: input.config?.merge?.allowedFailures ?? [],
559
- greptileApi: requireGreptile ? input.greptileApi : undefined,
570
+ ...requireGreptile && input.greptileApi ? { greptileApi: input.greptileApi } : {},
560
571
  requireGreptile
561
572
  });
562
573
  latestFeedback = [...gate.actionableFeedback];
@@ -586,22 +597,22 @@ ${createResult.stdout ?? ""}`) : null;
586
597
  }
587
598
  if (gate.approved) {
588
599
  pendingElapsedMs = 0;
589
- const finalGate = await runStrictPrMergeGate({
600
+ const finalGate = await mergeGate.runGate({
590
601
  projectRoot: input.projectRoot,
591
602
  prUrl,
592
603
  taskId: input.taskId,
593
604
  runId: input.runId,
594
605
  cycle: iteration,
595
606
  command: input.command,
596
- artifactRoot: input.artifactRoot,
607
+ ...input.artifactRoot !== undefined ? { artifactRoot: input.artifactRoot } : {},
597
608
  allowedFailures: input.config?.merge?.allowedFailures ?? [],
598
- greptileApi: requireGreptile ? input.greptileApi : undefined,
609
+ ...requireGreptile && input.greptileApi ? { greptileApi: input.greptileApi } : {},
599
610
  requireGreptile,
600
611
  final: true
601
612
  });
602
613
  if (finalGate.approved) {
603
614
  await input.lifecycle?.onMergeStarted?.({ prUrl });
604
- await runRepoDefaultMerge({ prUrl, config: input.config, command: input.command, cwd: input.projectRoot, strictGate: finalGate });
615
+ await runRepoDefaultMerge({ prUrl, ...input.config !== undefined ? { config: input.config } : {}, command: input.command, cwd: input.projectRoot, strictGate: finalGate });
605
616
  await input.lifecycle?.onMerged?.({ prUrl });
606
617
  return { status: "merged", prUrl, iterations: iteration, actionableFeedback: [], merged: true };
607
618
  }
@@ -648,6 +659,7 @@ ${createResult.stdout ?? ""}`) : null;
648
659
  }
649
660
  var UPLOADED_SNAPSHOT_PR_MARKER = "<!-- rig:uploaded-snapshot -->", RIG_RUNTIME_COMMIT_EXCLUDES, GREPTILE_REREVIEW_MARKER_PREFIX = "rig:greptile-rereview";
650
661
  var init_pr_automation = __esm(() => {
662
+ init_pr_merge_gate_cap();
651
663
  RIG_RUNTIME_COMMIT_EXCLUDES = [
652
664
  ".rig",
653
665
  "artifacts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@h-rig/bundle-default-lifecycle",
3
- "version": "0.0.6-alpha.156",
3
+ "version": "0.0.6-alpha.158",
4
4
  "type": "module",
5
5
  "description": "Default Rig run lifecycle stage bundle wrapping the existing closeout runtime.",
6
6
  "license": "UNLICENSED",
@@ -13,14 +13,6 @@
13
13
  "types": "./dist/src/plugin.d.ts",
14
14
  "import": "./dist/src/plugin.js"
15
15
  },
16
- "./closeout-equivalence": {
17
- "types": "./dist/src/closeoutEquivalence.d.ts",
18
- "import": "./dist/src/closeoutEquivalence.js"
19
- },
20
- "./closeout-shadow-harness": {
21
- "types": "./dist/src/closeoutShadowHarness.d.ts",
22
- "import": "./dist/src/closeoutShadowHarness.js"
23
- },
24
16
  "./default-pipeline": {
25
17
  "types": "./dist/src/defaultPipeline.d.ts",
26
18
  "import": "./dist/src/defaultPipeline.js"
@@ -56,6 +48,30 @@
56
48
  "./control-plane/verifier": {
57
49
  "types": "./dist/src/control-plane/verifier.d.ts",
58
50
  "import": "./dist/src/control-plane/verifier.js"
51
+ },
52
+ "./control-plane/native/git-ops": {
53
+ "types": "./dist/src/control-plane/native/git-ops.d.ts",
54
+ "import": "./dist/src/control-plane/native/git-ops.js"
55
+ },
56
+ "./control-plane/materialize-task-config": {
57
+ "types": "./dist/src/control-plane/materialize-task-config.d.ts",
58
+ "import": "./dist/src/control-plane/materialize-task-config.js"
59
+ },
60
+ "./control-plane/hooks/inject-context": {
61
+ "types": "./dist/src/control-plane/hooks/inject-context.d.ts",
62
+ "import": "./dist/src/control-plane/hooks/inject-context.js"
63
+ },
64
+ "./control-plane/hooks/task-runtime-start": {
65
+ "types": "./dist/src/control-plane/hooks/task-runtime-start.d.ts",
66
+ "import": "./dist/src/control-plane/hooks/task-runtime-start.js"
67
+ },
68
+ "./control-plane/hooks/submodule-branch": {
69
+ "types": "./dist/src/control-plane/hooks/submodule-branch.d.ts",
70
+ "import": "./dist/src/control-plane/hooks/submodule-branch.js"
71
+ },
72
+ "./control-plane/hooks/shared": {
73
+ "types": "./dist/src/control-plane/hooks/shared.d.ts",
74
+ "import": "./dist/src/control-plane/hooks/shared.js"
59
75
  }
60
76
  },
61
77
  "engines": {
@@ -65,12 +81,9 @@
65
81
  "module": "./dist/src/index.js",
66
82
  "types": "./dist/src/index.d.ts",
67
83
  "dependencies": {
68
- "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.156",
69
- "@rig/core": "npm:@h-rig/core@0.0.6-alpha.156",
70
- "@rig/hook-kit": "npm:@h-rig/hook-kit@0.0.6-alpha.156",
71
- "@rig/kernel": "npm:@h-rig/kernel@0.0.6-alpha.156",
72
- "@rig/pr-review-plugin": "npm:@h-rig/pr-review-plugin@0.0.6-alpha.156",
73
- "@rig/runtime": "npm:@h-rig/runtime@0.0.6-alpha.156",
74
- "@rig/shared": "npm:@h-rig/shared@0.0.6-alpha.156"
84
+ "@rig/contracts": "npm:@h-rig/contracts@0.0.6-alpha.158",
85
+ "@rig/core": "npm:@h-rig/core@0.0.6-alpha.158",
86
+ "@rig/hook-kit": "npm:@h-rig/hook-kit@0.0.6-alpha.158",
87
+ "@rig/kernel-seed": "npm:@h-rig/kernel-seed@0.0.6-alpha.158"
75
88
  }
76
89
  }
@@ -1,15 +0,0 @@
1
- /**
2
- * Sanitize an arbitrary string into a valid, lowercase git branch fragment.
3
- * Strips quotes, collapses separators, limits to 64 chars.
4
- */
5
- export declare function sanitizeBranchFragment(raw: string): string;
6
- /**
7
- * Sanitize a string into a `feature/…` branch name.
8
- * Preserves an existing `feature/` prefix or slash-separated namespace.
9
- */
10
- export declare function sanitizeFeatureBranchName(raw: string): string;
11
- /**
12
- * Resolve a unique `feature/…` branch name that doesn't collide with
13
- * any existing branch. Appends a numeric suffix when needed.
14
- */
15
- export declare function resolveAutoFeatureBranchName(existingBranchNames: readonly string[], preferredBranch?: string): string;
@@ -1,33 +0,0 @@
1
- // @bun
2
- // packages/bundle-default-lifecycle/src/branch-naming.ts
3
- function sanitizeBranchFragment(raw) {
4
- const normalized = raw.trim().toLowerCase().replace(/['"`]/g, "").replace(/^[./\s_-]+|[./\s_-]+$/g, "");
5
- const branchFragment = normalized.replace(/[^a-z0-9/_-]+/g, "-").replace(/\/+/g, "/").replace(/-+/g, "-").replace(/^[./_-]+|[./_-]+$/g, "").slice(0, 64).replace(/[./_-]+$/g, "");
6
- return branchFragment.length > 0 ? branchFragment : "update";
7
- }
8
- function sanitizeFeatureBranchName(raw) {
9
- const sanitized = sanitizeBranchFragment(raw);
10
- if (sanitized.includes("/")) {
11
- return sanitized.startsWith("feature/") ? sanitized : `feature/${sanitized}`;
12
- }
13
- return `feature/${sanitized}`;
14
- }
15
- var AUTO_FEATURE_BRANCH_FALLBACK = "feature/update";
16
- function resolveAutoFeatureBranchName(existingBranchNames, preferredBranch) {
17
- const preferred = preferredBranch?.trim();
18
- const resolvedBase = sanitizeFeatureBranchName(preferred && preferred.length > 0 ? preferred : AUTO_FEATURE_BRANCH_FALLBACK);
19
- const existingNames = new Set(existingBranchNames.map((branch) => branch.toLowerCase()));
20
- if (!existingNames.has(resolvedBase)) {
21
- return resolvedBase;
22
- }
23
- let suffix = 2;
24
- while (existingNames.has(`${resolvedBase}-${suffix}`)) {
25
- suffix += 1;
26
- }
27
- return `${resolvedBase}-${suffix}`;
28
- }
29
- export {
30
- sanitizeFeatureBranchName,
31
- sanitizeBranchFragment,
32
- resolveAutoFeatureBranchName
33
- };
@@ -1,37 +0,0 @@
1
- import type { InProcessCloseoutResult } from "./native/in-process-closeout";
2
- export declare const CLOSEOUT_EQUIVALENCE_ARTIFACTS: readonly ["review-status.txt", "review-feedback.md", "review-state.json", "pr-state.json", "git-state.txt", "validation-summary.json"];
3
- export declare const CLOSEOUT_EQUIVALENCE_STATE_FILES: readonly ["task-repo-commits.json", "failed_approaches.md"];
4
- export type CloseoutEquivalenceArtifactName = typeof CLOSEOUT_EQUIVALENCE_ARTIFACTS[number] | typeof CLOSEOUT_EQUIVALENCE_STATE_FILES[number];
5
- export type CloseoutArtifactSnapshot = Readonly<Record<CloseoutEquivalenceArtifactName, string | null>>;
6
- export type CloseoutTaskSourceCall = {
7
- readonly method: string;
8
- readonly taskId: string;
9
- readonly status?: string;
10
- readonly summary?: string;
11
- };
12
- export type CloseoutEquivalenceRun = {
13
- readonly label: "imperative" | "staged";
14
- readonly result: InProcessCloseoutResult;
15
- readonly artifacts: CloseoutArtifactSnapshot;
16
- readonly taskSourceCalls: readonly CloseoutTaskSourceCall[];
17
- };
18
- export type CloseoutEquivalenceDiff = {
19
- readonly kind: "artifact" | "task-source" | "result";
20
- readonly path: string;
21
- readonly imperative: string | null;
22
- readonly staged: string | null;
23
- };
24
- export type CloseoutEquivalenceReport = {
25
- readonly equivalent: boolean;
26
- readonly diffs: readonly CloseoutEquivalenceDiff[];
27
- };
28
- export declare function snapshotCloseoutArtifacts(input: {
29
- readonly projectRoot: string;
30
- readonly taskId: string;
31
- readonly artifactRoot?: string;
32
- readonly stateRoot?: string;
33
- }): CloseoutArtifactSnapshot;
34
- export declare function compareCloseoutEquivalence(input: {
35
- readonly imperative: CloseoutEquivalenceRun;
36
- readonly staged: CloseoutEquivalenceRun;
37
- }): CloseoutEquivalenceReport;
@@ -1,78 +0,0 @@
1
- // @bun
2
- // packages/bundle-default-lifecycle/src/closeoutEquivalence.ts
3
- import { existsSync, readFileSync } from "fs";
4
- import { resolve } from "path";
5
- var CLOSEOUT_EQUIVALENCE_ARTIFACTS = [
6
- "review-status.txt",
7
- "review-feedback.md",
8
- "review-state.json",
9
- "pr-state.json",
10
- "git-state.txt",
11
- "validation-summary.json"
12
- ];
13
- var CLOSEOUT_EQUIVALENCE_STATE_FILES = [
14
- "task-repo-commits.json",
15
- "failed_approaches.md"
16
- ];
17
- function snapshotCloseoutArtifacts(input) {
18
- const artifactRoot = input.artifactRoot ?? resolve(input.projectRoot, "artifacts", input.taskId);
19
- const stateRoot = input.stateRoot ?? resolve(input.projectRoot, ".rig", "state");
20
- const entries = [
21
- ...CLOSEOUT_EQUIVALENCE_ARTIFACTS.map((name) => {
22
- const path = resolve(artifactRoot, name);
23
- return [name, existsSync(path) ? readFileSync(path, "utf-8") : null];
24
- }),
25
- ...CLOSEOUT_EQUIVALENCE_STATE_FILES.map((name) => {
26
- const path = resolve(stateRoot, name);
27
- return [name, existsSync(path) ? readFileSync(path, "utf-8") : null];
28
- })
29
- ];
30
- return Object.fromEntries(entries);
31
- }
32
- function compareCloseoutEquivalence(input) {
33
- const diffs = [];
34
- for (const name of [...CLOSEOUT_EQUIVALENCE_ARTIFACTS, ...CLOSEOUT_EQUIVALENCE_STATE_FILES]) {
35
- const imperative = input.imperative.artifacts[name];
36
- const staged = input.staged.artifacts[name];
37
- if (imperative !== staged) {
38
- diffs.push({ kind: "artifact", path: name, imperative, staged });
39
- }
40
- }
41
- const imperativeCalls = JSON.stringify(input.imperative.taskSourceCalls.map((call) => ({
42
- method: call.method,
43
- taskId: call.taskId,
44
- status: call.status ?? null,
45
- summary: call.summary ?? null
46
- })));
47
- const stagedCalls = JSON.stringify(input.staged.taskSourceCalls.map((call) => ({
48
- method: call.method,
49
- taskId: call.taskId,
50
- status: call.status ?? null,
51
- summary: call.summary ?? null
52
- })));
53
- if (imperativeCalls !== stagedCalls) {
54
- diffs.push({ kind: "task-source", path: "task-source-calls", imperative: imperativeCalls, staged: stagedCalls });
55
- }
56
- const imperativeResult = JSON.stringify({
57
- status: input.imperative.result.status,
58
- prUrl: input.imperative.result.prUrl ?? null,
59
- iterations: input.imperative.result.iterations,
60
- feedback: [...input.imperative.result.feedback]
61
- });
62
- const stagedResult = JSON.stringify({
63
- status: input.staged.result.status,
64
- prUrl: input.staged.result.prUrl ?? null,
65
- iterations: input.staged.result.iterations,
66
- feedback: [...input.staged.result.feedback]
67
- });
68
- if (imperativeResult !== stagedResult) {
69
- diffs.push({ kind: "result", path: "closeout-result", imperative: imperativeResult, staged: stagedResult });
70
- }
71
- return { equivalent: diffs.length === 0, diffs };
72
- }
73
- export {
74
- snapshotCloseoutArtifacts,
75
- compareCloseoutEquivalence,
76
- CLOSEOUT_EQUIVALENCE_STATE_FILES,
77
- CLOSEOUT_EQUIVALENCE_ARTIFACTS
78
- };
@@ -1,27 +0,0 @@
1
- export type CloseoutShadowEffectKind = "git-push" | "pr-open" | "review-gate" | "merge" | "task-source";
2
- export type CloseoutShadowEffect = {
3
- readonly kind: CloseoutShadowEffectKind;
4
- readonly target: string;
5
- readonly detail?: string;
6
- };
7
- export type CloseoutShadowRun = {
8
- readonly label: "imperative" | "staged";
9
- readonly effects: readonly CloseoutShadowEffect[];
10
- };
11
- export type CloseoutShadowDiff = {
12
- readonly index: number;
13
- readonly imperative: CloseoutShadowEffect | null;
14
- readonly staged: CloseoutShadowEffect | null;
15
- };
16
- export type CloseoutShadowComparison = {
17
- readonly equivalent: boolean;
18
- readonly diffs: readonly CloseoutShadowDiff[];
19
- };
20
- export declare function compareCloseoutShadowRuns(input: {
21
- readonly imperative: CloseoutShadowRun;
22
- readonly staged: CloseoutShadowRun;
23
- }): CloseoutShadowComparison;
24
- export declare function assertCloseoutShadowEquivalent(input: {
25
- readonly imperative: CloseoutShadowRun;
26
- readonly staged: CloseoutShadowRun;
27
- }): CloseoutShadowComparison;
@@ -1,29 +0,0 @@
1
- // @bun
2
- // packages/bundle-default-lifecycle/src/closeoutShadowHarness.ts
3
- function effectKey(effect) {
4
- return effect === null ? null : JSON.stringify({ kind: effect.kind, target: effect.target, detail: effect.detail ?? null });
5
- }
6
- function compareCloseoutShadowRuns(input) {
7
- const max = Math.max(input.imperative.effects.length, input.staged.effects.length);
8
- const diffs = [];
9
- for (let index = 0;index < max; index += 1) {
10
- const imperative = input.imperative.effects[index] ?? null;
11
- const staged = input.staged.effects[index] ?? null;
12
- if (effectKey(imperative) !== effectKey(staged)) {
13
- diffs.push({ index, imperative, staged });
14
- }
15
- }
16
- return { equivalent: diffs.length === 0, diffs };
17
- }
18
- function assertCloseoutShadowEquivalent(input) {
19
- const comparison = compareCloseoutShadowRuns(input);
20
- if (!comparison.equivalent) {
21
- const details = comparison.diffs.map((diff) => `#${diff.index}: imperative=${effectKey(diff.imperative) ?? "<missing>"} staged=${effectKey(diff.staged) ?? "<missing>"}`).join("; ");
22
- throw new Error(`Closeout shadow side effects differ: ${details}`);
23
- }
24
- return comparison;
25
- }
26
- export {
27
- compareCloseoutShadowRuns,
28
- assertCloseoutShadowEquivalent
29
- };