dev-loops 0.1.0

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 (156) hide show
  1. package/.pi/dev-loop/defaults.yaml +477 -0
  2. package/AGENTS.md +25 -0
  3. package/CHANGELOG.md +18 -0
  4. package/LICENSE +21 -0
  5. package/README.md +178 -0
  6. package/agents/dev-loop.agent.md +82 -0
  7. package/agents/developer.agent.md +37 -0
  8. package/agents/docs.agent.md +33 -0
  9. package/agents/fixer.agent.md +53 -0
  10. package/agents/quality.agent.md +28 -0
  11. package/agents/refiner.agent.md +87 -0
  12. package/agents/review.agent.md +64 -0
  13. package/cli/index.mjs +424 -0
  14. package/extension/README.md +233 -0
  15. package/extension/checks.ts +94 -0
  16. package/extension/index.ts +131 -0
  17. package/extension/post-merge-update.ts +512 -0
  18. package/extension/presentation.ts +107 -0
  19. package/lib/dev-loops-core.mjs +284 -0
  20. package/package.json +103 -0
  21. package/scripts/README.md +1007 -0
  22. package/scripts/_cli-primitives.mjs +10 -0
  23. package/scripts/_core-helpers.mjs +30 -0
  24. package/scripts/docs/validate-links.mjs +567 -0
  25. package/scripts/docs/validate-no-duplicate-rules.mjs +250 -0
  26. package/scripts/github/_review-thread-mutations.mjs +214 -0
  27. package/scripts/github/capture-review-threads.mjs +180 -0
  28. package/scripts/github/create-draft-pr.mjs +108 -0
  29. package/scripts/github/detect-checkpoint-evidence.mjs +393 -0
  30. package/scripts/github/detect-linked-issue-pr.mjs +331 -0
  31. package/scripts/github/manage-sub-issues.mjs +394 -0
  32. package/scripts/github/probe-copilot-review.mjs +323 -0
  33. package/scripts/github/ready-for-review.mjs +93 -0
  34. package/scripts/github/reconcile-draft-gate.mjs +328 -0
  35. package/scripts/github/reply-resolve-review-thread.mjs +42 -0
  36. package/scripts/github/reply-resolve-review-threads.mjs +329 -0
  37. package/scripts/github/request-copilot-review.mjs +551 -0
  38. package/scripts/github/resolve-tracker-local-spec.mjs +205 -0
  39. package/scripts/github/stage-reviewer-draft.mjs +191 -0
  40. package/scripts/github/upsert-checkpoint-verdict.mjs +694 -0
  41. package/scripts/github/verify-fresh-review-context.mjs +125 -0
  42. package/scripts/github/write-gate-findings-log.mjs +212 -0
  43. package/scripts/loop/_checkpoint-io.mjs +55 -0
  44. package/scripts/loop/_checkpoint-paths.mjs +28 -0
  45. package/scripts/loop/_handoff-contract.mjs +230 -0
  46. package/scripts/loop/_inspect-run-viewer-adapter.mjs +345 -0
  47. package/scripts/loop/_loop-evidence.mjs +32 -0
  48. package/scripts/loop/_pr-runner-coordination.mjs +611 -0
  49. package/scripts/loop/_stale-runner-detection.mjs +145 -0
  50. package/scripts/loop/_steering-state-file.mjs +134 -0
  51. package/scripts/loop/build-handoff-envelope.mjs +181 -0
  52. package/scripts/loop/checkpoint-contract.mjs +49 -0
  53. package/scripts/loop/conductor-monitor.mjs +1850 -0
  54. package/scripts/loop/conductor.mjs +214 -0
  55. package/scripts/loop/copilot-pr-handoff.mjs +493 -0
  56. package/scripts/loop/debt-remediate.mjs +304 -0
  57. package/scripts/loop/detect-change-scope.mjs +102 -0
  58. package/scripts/loop/detect-copilot-loop-state.mjs +454 -0
  59. package/scripts/loop/detect-copilot-session-activity.mjs +186 -0
  60. package/scripts/loop/detect-initial-copilot-pr-state.mjs +318 -0
  61. package/scripts/loop/detect-internal-only-pr.mjs +270 -0
  62. package/scripts/loop/detect-issue-refinement-artifact.mjs +163 -0
  63. package/scripts/loop/detect-pr-gate-coordination-state.mjs +509 -0
  64. package/scripts/loop/detect-reviewer-loop-state.mjs +231 -0
  65. package/scripts/loop/detect-stale-runner.mjs +250 -0
  66. package/scripts/loop/detect-tracker-first-loop-state.mjs +76 -0
  67. package/scripts/loop/detect-tracker-pr-state.mjs +102 -0
  68. package/scripts/loop/info.mjs +267 -0
  69. package/scripts/loop/inspect-run-viewer/cli.mjs +117 -0
  70. package/scripts/loop/inspect-run-viewer/constants.mjs +80 -0
  71. package/scripts/loop/inspect-run-viewer/graph.mjs +757 -0
  72. package/scripts/loop/inspect-run-viewer/handoff-envelope-renderer.mjs +398 -0
  73. package/scripts/loop/inspect-run-viewer/inbox.mjs +308 -0
  74. package/scripts/loop/inspect-run-viewer/managed-instance.mjs +750 -0
  75. package/scripts/loop/inspect-run-viewer/rendering.mjs +411 -0
  76. package/scripts/loop/inspect-run-viewer/server.mjs +638 -0
  77. package/scripts/loop/inspect-run-viewer/shared.mjs +103 -0
  78. package/scripts/loop/inspect-run-viewer/status.mjs +715 -0
  79. package/scripts/loop/inspect-run-viewer-ci-changes.mjs +77 -0
  80. package/scripts/loop/inspect-run-viewer.mjs +82 -0
  81. package/scripts/loop/inspect-run.mjs +382 -0
  82. package/scripts/loop/outer-loop.mjs +419 -0
  83. package/scripts/loop/pr-runner-coordination.mjs +143 -0
  84. package/scripts/loop/pre-commit-branch-guard.mjs +68 -0
  85. package/scripts/loop/pre-flight-gate.mjs +236 -0
  86. package/scripts/loop/pre-pr-ready-gate.mjs +183 -0
  87. package/scripts/loop/pre-push-main-guard.mjs +103 -0
  88. package/scripts/loop/pre-write-remote-freshness-guard.mjs +32 -0
  89. package/scripts/loop/print-gates.mjs +42 -0
  90. package/scripts/loop/resolve-dev-loop-startup.mjs +533 -0
  91. package/scripts/loop/run-conductor-cycle.mjs +322 -0
  92. package/scripts/loop/run-queue.mjs +124 -0
  93. package/scripts/loop/run-refinement-audit.mjs +513 -0
  94. package/scripts/loop/run-watch-cycle.mjs +358 -0
  95. package/scripts/loop/steer-loop.mjs +841 -0
  96. package/scripts/loop/ui-designer-review-contract.mjs +76 -0
  97. package/scripts/loop/watch-initial-copilot-pr.mjs +253 -0
  98. package/scripts/projects/add-queue-item.mjs +528 -0
  99. package/scripts/projects/ensure-queue-board.mjs +837 -0
  100. package/scripts/projects/list-queue-items.mjs +489 -0
  101. package/scripts/projects/move-queue-item.mjs +549 -0
  102. package/scripts/projects/reorder-queue-item.mjs +518 -0
  103. package/scripts/refine/_refine-helpers.mjs +258 -0
  104. package/scripts/refine/prose-linkage-detector.mjs +92 -0
  105. package/scripts/refine/refinement-completeness-checker.mjs +88 -0
  106. package/scripts/refine/scope-boundary-cross-checker.mjs +163 -0
  107. package/scripts/refine/tree-integrity-validator.mjs +211 -0
  108. package/scripts/refine/verify.mjs +178 -0
  109. package/scripts/repo-wiki-local.mjs +156 -0
  110. package/scripts/repo-wiki.mjs +119 -0
  111. package/skills/copilot-pr-followup/SKILL.md +380 -0
  112. package/skills/dev-loop/SKILL.md +141 -0
  113. package/skills/dev-loop/scripts/dev-mode-context.mjs +152 -0
  114. package/skills/dev-loop/scripts/dev-mode-context.test.mjs +80 -0
  115. package/skills/dev-loop/scripts/init-phase.mjs +71 -0
  116. package/skills/dev-loop/scripts/log-bash-exit-1.mjs +25 -0
  117. package/skills/dev-loop/scripts/phase-files.mjs +29 -0
  118. package/skills/dev-loop/scripts/post-gate-verdict-fallback.mjs +480 -0
  119. package/skills/dev-loop/scripts/post-gate-verdict-fallback.test.mjs +732 -0
  120. package/skills/dev-loop/scripts/render-template.mjs +82 -0
  121. package/skills/dev-loop/scripts/render-template.test.mjs +63 -0
  122. package/skills/dev-loop/templates/bootstrap-agents.md +26 -0
  123. package/skills/dev-loop/templates/bootstrap-implementation-state.md +31 -0
  124. package/skills/dev-loop/templates/bootstrap-implementation-workflow.md +17 -0
  125. package/skills/dev-loop/templates/dev-mode-retrospective.md +15 -0
  126. package/skills/dev-loop/templates/dev-mode-review.md +17 -0
  127. package/skills/dev-loop/templates/dev-mode-skill-changes.md +11 -0
  128. package/skills/dev-loop/templates/merged-phase-plan.md +19 -0
  129. package/skills/dev-loop/templates/phase-doc.md +27 -0
  130. package/skills/dev-loop/templates/phase-summary.md +13 -0
  131. package/skills/dev-loop/templates/phase-variant.md +15 -0
  132. package/skills/dev-loop/templates/retrospective.md +11 -0
  133. package/skills/dev-loop/templates/review.md +32 -0
  134. package/skills/dev-loop/templates/ui-vision-review.md +55 -0
  135. package/skills/docs/acceptance-criteria-verification.md +21 -0
  136. package/skills/docs/anti-patterns.md +21 -0
  137. package/skills/docs/artifact-authority-contract.md +119 -0
  138. package/skills/docs/confirmation-rules.md +28 -0
  139. package/skills/docs/copilot-ci-status-contract.md +52 -0
  140. package/skills/docs/copilot-loop-operations.md +233 -0
  141. package/skills/docs/debt-remediation-contract.md +107 -0
  142. package/skills/docs/entrypoint-strategies.md +115 -0
  143. package/skills/docs/epic-tree-refinement-procedure.md +234 -0
  144. package/skills/docs/issue-intake-procedure.md +235 -0
  145. package/skills/docs/main-agent-contract.md +72 -0
  146. package/skills/docs/merge-preconditions.md +29 -0
  147. package/skills/docs/pr-lifecycle-contract.md +209 -0
  148. package/skills/docs/public-dev-loop-contract.md +497 -0
  149. package/skills/docs/retrospective-checkpoint-contract.md +159 -0
  150. package/skills/docs/stop-conditions.md +29 -0
  151. package/skills/docs/structural-quality.md +42 -0
  152. package/skills/docs/tracker-first-loop-state.md +281 -0
  153. package/skills/docs/validation-policy.md +27 -0
  154. package/skills/docs/workflow-handoff-contract.md +135 -0
  155. package/skills/final-approval/SKILL.md +19 -0
  156. package/skills/local-implementation/SKILL.md +640 -0
@@ -0,0 +1,152 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { pathToFileURL } from "node:url";
4
+
5
+ import { buildPhasePaths } from "./phase-files.mjs";
6
+
7
+ async function readTextIfExists(filePath) {
8
+ try {
9
+ return await readFile(filePath, "utf8");
10
+ } catch (error) {
11
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
12
+ return undefined;
13
+ }
14
+
15
+ throw error;
16
+ }
17
+ }
18
+
19
+ function countLines(text) {
20
+ if (!text || text.trim().length === 0) {
21
+ return 0;
22
+ }
23
+
24
+ return text.trimEnd().split("\n").length;
25
+ }
26
+
27
+ export function parseJsonLines(text) {
28
+ if (!text || text.trim().length === 0) {
29
+ return [];
30
+ }
31
+
32
+ return text
33
+ .trim()
34
+ .split("\n")
35
+ .filter((line) => line.trim().length > 0)
36
+ .map((line) => JSON.parse(line));
37
+ }
38
+
39
+ export async function collectDevModeContext(projectRoot, phase) {
40
+ const paths = buildPhasePaths(projectRoot, phase);
41
+ const summaryPath = path.join(paths.phaseDir, "summary.md");
42
+ const retrospectivePath = path.join(paths.phaseDir, "retrospective.md");
43
+ const reviewPath = path.join(paths.phaseDir, "review.md");
44
+ const mergedPlanPath = path.join(paths.phaseDir, "merged-plan.md");
45
+
46
+ const [manifestText, summaryText, retrospectiveText, reviewText, mergedPlanText, bashExitOneText] = await Promise.all([
47
+ readTextIfExists(paths.manifestPath),
48
+ readTextIfExists(summaryPath),
49
+ readTextIfExists(retrospectivePath),
50
+ readTextIfExists(reviewPath),
51
+ readTextIfExists(mergedPlanPath),
52
+ readTextIfExists(paths.bashExitOnePath),
53
+ ]);
54
+
55
+ const manifest = manifestText ? JSON.parse(manifestText) : undefined;
56
+ const bashExitOneRecords = parseJsonLines(bashExitOneText);
57
+
58
+ return {
59
+ phase: paths.phase,
60
+ projectRoot,
61
+ paths: {
62
+ manifestPath: path.relative(projectRoot, paths.manifestPath),
63
+ bashExitOnePath: path.relative(projectRoot, paths.bashExitOnePath),
64
+ summaryPath: path.relative(projectRoot, summaryPath),
65
+ retrospectivePath: path.relative(projectRoot, retrospectivePath),
66
+ reviewPath: path.relative(projectRoot, reviewPath),
67
+ mergedPlanPath: path.relative(projectRoot, mergedPlanPath),
68
+ devModeContextPath: path.relative(projectRoot, path.join(paths.phaseDir, "dev-mode-context.json")),
69
+ },
70
+ manifest,
71
+ artifactPresence: {
72
+ summary: Boolean(summaryText),
73
+ retrospective: Boolean(retrospectiveText),
74
+ review: Boolean(reviewText),
75
+ mergedPlan: Boolean(mergedPlanText),
76
+ bashExitOneLog: Boolean(bashExitOneText),
77
+ },
78
+ lineCounts: {
79
+ summary: countLines(summaryText),
80
+ retrospective: countLines(retrospectiveText),
81
+ review: countLines(reviewText),
82
+ mergedPlan: countLines(mergedPlanText),
83
+ bashExitOneLog: countLines(bashExitOneText),
84
+ },
85
+ bashExitOne: {
86
+ count: bashExitOneRecords.length,
87
+ commands: [...new Set(bashExitOneRecords.map((record) => record.command))].sort(),
88
+ records: bashExitOneRecords,
89
+ },
90
+ };
91
+ }
92
+
93
+ export async function writeDevModeContext(outputPath, context) {
94
+ await mkdir(path.dirname(outputPath), { recursive: true });
95
+ await writeFile(outputPath, `${JSON.stringify(context, null, 2)}\n`, "utf8");
96
+ return outputPath;
97
+ }
98
+
99
+ export function parseCliArgs(argv) {
100
+ const args = [...argv];
101
+ const options = {
102
+ projectRoot: process.cwd(),
103
+ phase: undefined,
104
+ output: undefined,
105
+ };
106
+
107
+ while (args.length > 0) {
108
+ const token = args.shift();
109
+
110
+ if (token === "--project-root") {
111
+ options.projectRoot = args.shift();
112
+ continue;
113
+ }
114
+
115
+ if (token === "--phase") {
116
+ options.phase = args.shift();
117
+ continue;
118
+ }
119
+
120
+ if (token === "--output") {
121
+ options.output = args.shift();
122
+ continue;
123
+ }
124
+
125
+ throw new Error(`Unknown argument: ${token}`);
126
+ }
127
+
128
+ if (!options.phase) {
129
+ throw new Error("Missing required --phase <phase-name> argument");
130
+ }
131
+
132
+ return options;
133
+ }
134
+
135
+ export async function runCli(argv = process.argv.slice(2)) {
136
+ const options = parseCliArgs(argv);
137
+ const context = await collectDevModeContext(options.projectRoot, options.phase);
138
+ const outputPath = options.output ?? path.join(options.projectRoot, "tmp", "phases", options.phase, "dev-mode-context.json");
139
+ await writeDevModeContext(outputPath, context);
140
+ process.stdout.write(`${JSON.stringify({ ok: true, outputPath, phase: context.phase })}\n`);
141
+ }
142
+
143
+ const invokedAsScript = process.argv[1]
144
+ ? import.meta.url === pathToFileURL(process.argv[1]).href
145
+ : false;
146
+
147
+ if (invokedAsScript) {
148
+ runCli().catch((error) => {
149
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
150
+ process.exitCode = 1;
151
+ });
152
+ }
@@ -0,0 +1,80 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+
7
+ import {
8
+ collectDevModeContext,
9
+ parseCliArgs,
10
+ parseJsonLines,
11
+ writeDevModeContext,
12
+ } from "./dev-mode-context.mjs";
13
+
14
+ test("dev-mode-context parses json lines deterministically", () => {
15
+ assert.deepEqual(parseJsonLines('{"command":"npm test"}\n{"command":"npm run check"}\n'), [
16
+ { command: "npm test" },
17
+ { command: "npm run check" },
18
+ ]);
19
+ assert.deepEqual(parseJsonLines(""), []);
20
+ });
21
+
22
+ test("dev-mode-context collects context for an existing phase directory", async () => {
23
+ const tempDir = await mkdtemp(path.join(os.tmpdir(), "dev-loop-dev-mode-"));
24
+ const phaseDir = path.join(tempDir, "tmp", "phases", "phase-3");
25
+
26
+ try {
27
+ await mkdir(phaseDir, { recursive: true });
28
+ await writeFile(path.join(phaseDir, "manifest.json"), JSON.stringify({ phase: "phase-3", status: "completed" }), { encoding: "utf8", flag: "w" });
29
+ await writeFile(path.join(phaseDir, "summary.md"), "# Summary\nline\n", { encoding: "utf8", flag: "w" });
30
+ await writeFile(path.join(phaseDir, "retrospective.md"), "# Retro\n", { encoding: "utf8", flag: "w" });
31
+ await writeFile(path.join(phaseDir, "review.md"), "# Review\n", { encoding: "utf8", flag: "w" });
32
+ await writeFile(path.join(phaseDir, "merged-plan.md"), "# Plan\n", { encoding: "utf8", flag: "w" });
33
+ await writeFile(
34
+ path.join(phaseDir, "bash-exit-1.jsonl"),
35
+ '{"command":"npm test","exitCode":1}\n{"command":"npm run test:coverage","exitCode":1}\n',
36
+ { encoding: "utf8", flag: "w" },
37
+ );
38
+
39
+ const context = await collectDevModeContext(tempDir, "phase-3");
40
+
41
+ assert.equal(context.phase, "phase-3");
42
+ assert.deepEqual(context.manifest, { phase: "phase-3", status: "completed" });
43
+ assert.deepEqual(context.artifactPresence, {
44
+ summary: true,
45
+ retrospective: true,
46
+ review: true,
47
+ mergedPlan: true,
48
+ bashExitOneLog: true,
49
+ });
50
+ assert.equal(context.bashExitOne.count, 2);
51
+ assert.deepEqual(context.bashExitOne.commands, ["npm run test:coverage", "npm test"]);
52
+ } finally {
53
+ await rm(tempDir, { recursive: true, force: true });
54
+ }
55
+ });
56
+
57
+ test("dev-mode-context writes collected context to disk", async () => {
58
+ const tempDir = await mkdtemp(path.join(os.tmpdir(), "dev-loop-dev-mode-write-"));
59
+ const outputPath = path.join(tempDir, "dev-mode-context.json");
60
+
61
+ try {
62
+ await writeDevModeContext(outputPath, { phase: "phase-1", ok: true });
63
+ const written = JSON.parse(await readFile(outputPath, "utf8"));
64
+ assert.deepEqual(written, { phase: "phase-1", ok: true });
65
+ } finally {
66
+ await rm(tempDir, { recursive: true, force: true });
67
+ }
68
+ });
69
+
70
+ test("dev-mode-context parses cli args", () => {
71
+ assert.deepEqual(parseCliArgs(["--project-root", "/repo", "--phase", "phase-4", "--output", "tmp/x.json"]), {
72
+ projectRoot: "/repo",
73
+ phase: "phase-4",
74
+ output: "tmp/x.json",
75
+ });
76
+ });
77
+
78
+ test("dev-mode-context requires phase arg", () => {
79
+ assert.throws(() => parseCliArgs(["--output", "tmp/x.json"]), /missing required --phase/i);
80
+ });
@@ -0,0 +1,71 @@
1
+ import path from "node:path";
2
+ import { fileURLToPath, pathToFileURL } from "node:url";
3
+
4
+ import { ensurePhaseFiles, parseCliArgs as parsePhaseFileArgs } from "./phase-files.mjs";
5
+ import { materializeTemplate } from "./render-template.mjs";
6
+
7
+ export const DEFAULT_PHASE_ARTIFACTS = [
8
+ "manifest.json",
9
+ "variant-a.md",
10
+ "variant-b.md",
11
+ "merged-plan.md",
12
+ "review.md",
13
+ ];
14
+
15
+ export function parseCliArgs(argv) {
16
+ return parsePhaseFileArgs(argv);
17
+ }
18
+
19
+ const scriptDir = path.dirname(fileURLToPath(import.meta.url));
20
+ const skillRoot = path.resolve(scriptDir, "..");
21
+ const templateRoot = path.join(skillRoot, "templates");
22
+
23
+ export async function initializePhase(projectRoot, phase, patch = {}) {
24
+ const phasePlanArtifact = path.relative(
25
+ path.join(projectRoot, "tmp", "phases", phase),
26
+ path.join(projectRoot, "docs", "phases", `${phase}.md`),
27
+ );
28
+
29
+ const nextPatch = {
30
+ ...patch,
31
+ artifacts: [...(patch.artifacts ?? []), ...DEFAULT_PHASE_ARTIFACTS, phasePlanArtifact],
32
+ };
33
+
34
+ const result = await ensurePhaseFiles(projectRoot, phase, nextPatch);
35
+
36
+ const outputs = [
37
+ ["phase-doc.md", result.paths.phasePlanPath, { phase }],
38
+ ["phase-variant.md", path.join(result.paths.phaseDir, "variant-a.md"), { phase, variant: "a" }],
39
+ ["phase-variant.md", path.join(result.paths.phaseDir, "variant-b.md"), { phase, variant: "b" }],
40
+ ["merged-phase-plan.md", path.join(result.paths.phaseDir, "merged-plan.md"), { phase }],
41
+ ["review.md", path.join(result.paths.phaseDir, "review.md"), { phase }],
42
+ ];
43
+
44
+ for (const [templateName, outputPath, variables] of outputs) {
45
+ await materializeTemplate(path.join(templateRoot, templateName), outputPath, variables);
46
+ }
47
+
48
+ return {
49
+ ...result,
50
+ generated: outputs.map(([, outputPath]) => path.relative(projectRoot, outputPath)),
51
+ };
52
+ }
53
+
54
+ export async function runCli(argv = process.argv.slice(2)) {
55
+ const options = parseCliArgs(argv);
56
+ const result = await initializePhase(options.projectRoot, options.phase, options.patch);
57
+ process.stdout.write(
58
+ `${JSON.stringify({ ok: true, phase: result.paths.phase, generated: result.generated })}\n`,
59
+ );
60
+ }
61
+
62
+ const invokedAsScript = process.argv[1]
63
+ ? import.meta.url === pathToFileURL(process.argv[1]).href
64
+ : false;
65
+
66
+ if (invokedAsScript) {
67
+ runCli().catch((error) => {
68
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
69
+ process.exitCode = 1;
70
+ });
71
+ }
@@ -0,0 +1,25 @@
1
+ import { pathToFileURL } from "node:url";
2
+
3
+ export {
4
+ DEFAULT_OUTPUT_LIMIT,
5
+ appendBashExitOneRecord,
6
+ formatBashExitOneRecord,
7
+ normalizeBashExitOneRecord,
8
+ parseCliArgs,
9
+ readRecordFromStdin,
10
+ runCli,
11
+ truncateText,
12
+ } from "../../../packages/core/src/bash-exit-one.mjs";
13
+
14
+ import { runCli } from "../../../packages/core/src/bash-exit-one.mjs";
15
+
16
+ const invokedAsScript = process.argv[1]
17
+ ? import.meta.url === pathToFileURL(process.argv[1]).href
18
+ : false;
19
+
20
+ if (invokedAsScript) {
21
+ runCli().catch((error) => {
22
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
23
+ process.exitCode = 1;
24
+ });
25
+ }
@@ -0,0 +1,29 @@
1
+ import { pathToFileURL } from "node:url";
2
+
3
+ export {
4
+ applyManifestPatch,
5
+ buildPhasePaths,
6
+ createDefaultPhaseIndex,
7
+ createDefaultPhaseManifest,
8
+ ensurePhaseFiles,
9
+ normalizePhaseName,
10
+ parseCliArgs,
11
+ readJsonIfExists,
12
+ runCli,
13
+ uniqueSortedStrings,
14
+ upsertPhaseIndex,
15
+ writeJson,
16
+ } from "../../../packages/core/src/loop/phase-files.mjs";
17
+
18
+ import { runCli } from "../../../packages/core/src/loop/phase-files.mjs";
19
+
20
+ const invokedAsScript = process.argv[1]
21
+ ? import.meta.url === pathToFileURL(process.argv[1]).href
22
+ : false;
23
+
24
+ if (invokedAsScript) {
25
+ runCli().catch((error) => {
26
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
27
+ process.exitCode = 1;
28
+ });
29
+ }