@joynt/foundry 0.0.0-stage → 0.1.50

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 (216) hide show
  1. package/dist/backends/command.d.ts +37 -0
  2. package/dist/backends/command.d.ts.map +1 -0
  3. package/dist/backends/command.js +79 -0
  4. package/dist/backends/command.js.map +1 -0
  5. package/dist/backends/index.d.ts +9 -0
  6. package/dist/backends/index.d.ts.map +1 -0
  7. package/dist/backends/index.js +37 -0
  8. package/dist/backends/index.js.map +1 -0
  9. package/dist/cli.d.ts +3 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +191 -0
  12. package/dist/cli.js.map +1 -0
  13. package/dist/commands/action.d.ts +6 -0
  14. package/dist/commands/action.d.ts.map +1 -0
  15. package/dist/commands/action.js +171 -0
  16. package/dist/commands/action.js.map +1 -0
  17. package/dist/commands/cancelled.d.ts +5 -0
  18. package/dist/commands/cancelled.d.ts.map +1 -0
  19. package/dist/commands/cancelled.js +107 -0
  20. package/dist/commands/cancelled.js.map +1 -0
  21. package/dist/commands/init.d.ts +5 -0
  22. package/dist/commands/init.d.ts.map +1 -0
  23. package/dist/commands/init.js +323 -0
  24. package/dist/commands/init.js.map +1 -0
  25. package/dist/commands/preview.d.ts +4 -0
  26. package/dist/commands/preview.d.ts.map +1 -0
  27. package/dist/commands/preview.js +108 -0
  28. package/dist/commands/preview.js.map +1 -0
  29. package/dist/commands/release.d.ts +2 -0
  30. package/dist/commands/release.d.ts.map +1 -0
  31. package/dist/commands/release.js +89 -0
  32. package/dist/commands/release.js.map +1 -0
  33. package/dist/commands/report.d.ts +14 -0
  34. package/dist/commands/report.d.ts.map +1 -0
  35. package/dist/commands/report.js +91 -0
  36. package/dist/commands/report.js.map +1 -0
  37. package/dist/commands/reset.d.ts +4 -0
  38. package/dist/commands/reset.d.ts.map +1 -0
  39. package/dist/commands/reset.js +155 -0
  40. package/dist/commands/reset.js.map +1 -0
  41. package/dist/commands/review.d.ts +2 -0
  42. package/dist/commands/review.d.ts.map +1 -0
  43. package/dist/commands/review.js +73 -0
  44. package/dist/commands/review.js.map +1 -0
  45. package/dist/commands/setup-bot.d.ts +31 -0
  46. package/dist/commands/setup-bot.d.ts.map +1 -0
  47. package/dist/commands/setup-bot.js +429 -0
  48. package/dist/commands/setup-bot.js.map +1 -0
  49. package/dist/commands/sync.d.ts +2 -0
  50. package/dist/commands/sync.d.ts.map +1 -0
  51. package/dist/commands/sync.js +77 -0
  52. package/dist/commands/sync.js.map +1 -0
  53. package/dist/config.d.ts +9 -0
  54. package/dist/config.d.ts.map +1 -0
  55. package/dist/config.js +147 -0
  56. package/dist/config.js.map +1 -0
  57. package/dist/index.d.ts +15 -0
  58. package/dist/index.d.ts.map +1 -0
  59. package/dist/index.js +29 -0
  60. package/dist/index.js.map +1 -0
  61. package/dist/lib/agent-output.d.ts +49 -0
  62. package/dist/lib/agent-output.d.ts.map +1 -0
  63. package/dist/lib/agent-output.js +256 -0
  64. package/dist/lib/agent-output.js.map +1 -0
  65. package/dist/lib/agent-report.d.ts +107 -0
  66. package/dist/lib/agent-report.d.ts.map +1 -0
  67. package/dist/lib/agent-report.js +233 -0
  68. package/dist/lib/agent-report.js.map +1 -0
  69. package/dist/lib/authorize.d.ts +3 -0
  70. package/dist/lib/authorize.d.ts.map +1 -0
  71. package/dist/lib/authorize.js +67 -0
  72. package/dist/lib/authorize.js.map +1 -0
  73. package/dist/lib/branches.d.ts +22 -0
  74. package/dist/lib/branches.d.ts.map +1 -0
  75. package/dist/lib/branches.js +82 -0
  76. package/dist/lib/branches.js.map +1 -0
  77. package/dist/lib/claim.d.ts +22 -0
  78. package/dist/lib/claim.d.ts.map +1 -0
  79. package/dist/lib/claim.js +129 -0
  80. package/dist/lib/claim.js.map +1 -0
  81. package/dist/lib/completion.d.ts +5 -0
  82. package/dist/lib/completion.d.ts.map +1 -0
  83. package/dist/lib/completion.js +63 -0
  84. package/dist/lib/completion.js.map +1 -0
  85. package/dist/lib/deployments.d.ts +21 -0
  86. package/dist/lib/deployments.d.ts.map +1 -0
  87. package/dist/lib/deployments.js +104 -0
  88. package/dist/lib/deployments.js.map +1 -0
  89. package/dist/lib/event-handler.d.ts +74 -0
  90. package/dist/lib/event-handler.d.ts.map +1 -0
  91. package/dist/lib/event-handler.js +1002 -0
  92. package/dist/lib/event-handler.js.map +1 -0
  93. package/dist/lib/events.d.ts +72 -0
  94. package/dist/lib/events.d.ts.map +1 -0
  95. package/dist/lib/events.js +3 -0
  96. package/dist/lib/events.js.map +1 -0
  97. package/dist/lib/gh-cli-client.d.ts +46 -0
  98. package/dist/lib/gh-cli-client.d.ts.map +1 -0
  99. package/dist/lib/gh-cli-client.js +260 -0
  100. package/dist/lib/gh-cli-client.js.map +1 -0
  101. package/dist/lib/git.d.ts +42 -0
  102. package/dist/lib/git.d.ts.map +1 -0
  103. package/dist/lib/git.js +247 -0
  104. package/dist/lib/git.js.map +1 -0
  105. package/dist/lib/github-client.d.ts +98 -0
  106. package/dist/lib/github-client.d.ts.map +1 -0
  107. package/dist/lib/github-client.js +3 -0
  108. package/dist/lib/github-client.js.map +1 -0
  109. package/dist/lib/github.d.ts +82 -0
  110. package/dist/lib/github.d.ts.map +1 -0
  111. package/dist/lib/github.js +202 -0
  112. package/dist/lib/github.js.map +1 -0
  113. package/dist/lib/issue-file.d.ts +15 -0
  114. package/dist/lib/issue-file.d.ts.map +1 -0
  115. package/dist/lib/issue-file.js +84 -0
  116. package/dist/lib/issue-file.js.map +1 -0
  117. package/dist/lib/labels.d.ts +14 -0
  118. package/dist/lib/labels.d.ts.map +1 -0
  119. package/dist/lib/labels.js +70 -0
  120. package/dist/lib/labels.js.map +1 -0
  121. package/dist/lib/log.d.ts +11 -0
  122. package/dist/lib/log.d.ts.map +1 -0
  123. package/dist/lib/log.js +53 -0
  124. package/dist/lib/log.js.map +1 -0
  125. package/dist/lib/octokit-client.d.ts +112 -0
  126. package/dist/lib/octokit-client.d.ts.map +1 -0
  127. package/dist/lib/octokit-client.js +507 -0
  128. package/dist/lib/octokit-client.js.map +1 -0
  129. package/dist/lib/preview-verify.d.ts +48 -0
  130. package/dist/lib/preview-verify.d.ts.map +1 -0
  131. package/dist/lib/preview-verify.js +148 -0
  132. package/dist/lib/preview-verify.js.map +1 -0
  133. package/dist/lib/preview.d.ts +33 -0
  134. package/dist/lib/preview.d.ts.map +1 -0
  135. package/dist/lib/preview.js +308 -0
  136. package/dist/lib/preview.js.map +1 -0
  137. package/dist/lib/reconcile.d.ts +14 -0
  138. package/dist/lib/reconcile.d.ts.map +1 -0
  139. package/dist/lib/reconcile.js +114 -0
  140. package/dist/lib/reconcile.js.map +1 -0
  141. package/dist/lib/review.d.ts +38 -0
  142. package/dist/lib/review.d.ts.map +1 -0
  143. package/dist/lib/review.js +284 -0
  144. package/dist/lib/review.js.map +1 -0
  145. package/dist/lib/stale-prs.d.ts +31 -0
  146. package/dist/lib/stale-prs.d.ts.map +1 -0
  147. package/dist/lib/stale-prs.js +161 -0
  148. package/dist/lib/stale-prs.js.map +1 -0
  149. package/dist/lib/state-store.d.ts +23 -0
  150. package/dist/lib/state-store.d.ts.map +1 -0
  151. package/dist/lib/state-store.js +3 -0
  152. package/dist/lib/state-store.js.map +1 -0
  153. package/dist/lib/state.d.ts +23 -0
  154. package/dist/lib/state.d.ts.map +1 -0
  155. package/dist/lib/state.js +57 -0
  156. package/dist/lib/state.js.map +1 -0
  157. package/dist/lib/status-comment.d.ts +14 -0
  158. package/dist/lib/status-comment.d.ts.map +1 -0
  159. package/dist/lib/status-comment.js +195 -0
  160. package/dist/lib/status-comment.js.map +1 -0
  161. package/dist/lib/stores/file-store.d.ts +22 -0
  162. package/dist/lib/stores/file-store.d.ts.map +1 -0
  163. package/dist/lib/stores/file-store.js +172 -0
  164. package/dist/lib/stores/file-store.js.map +1 -0
  165. package/dist/lib/stores/index.d.ts +13 -0
  166. package/dist/lib/stores/index.d.ts.map +1 -0
  167. package/dist/lib/stores/index.js +20 -0
  168. package/dist/lib/stores/index.js.map +1 -0
  169. package/dist/lib/task-recovery.d.ts +22 -0
  170. package/dist/lib/task-recovery.d.ts.map +1 -0
  171. package/dist/lib/task-recovery.js +172 -0
  172. package/dist/lib/task-recovery.js.map +1 -0
  173. package/dist/lib/templates.d.ts +8 -0
  174. package/dist/lib/templates.d.ts.map +1 -0
  175. package/dist/lib/templates.js +58 -0
  176. package/dist/lib/templates.js.map +1 -0
  177. package/dist/lib/thread.d.ts +13 -0
  178. package/dist/lib/thread.d.ts.map +1 -0
  179. package/dist/lib/thread.js +75 -0
  180. package/dist/lib/thread.js.map +1 -0
  181. package/dist/lib/verify.d.ts +31 -0
  182. package/dist/lib/verify.d.ts.map +1 -0
  183. package/dist/lib/verify.js +90 -0
  184. package/dist/lib/verify.js.map +1 -0
  185. package/dist/lib/version.d.ts +9 -0
  186. package/dist/lib/version.d.ts.map +1 -0
  187. package/dist/lib/version.js +134 -0
  188. package/dist/lib/version.js.map +1 -0
  189. package/dist/lib/webhook.d.ts +39 -0
  190. package/dist/lib/webhook.d.ts.map +1 -0
  191. package/dist/lib/webhook.js +248 -0
  192. package/dist/lib/webhook.js.map +1 -0
  193. package/dist/lib/worker.d.ts +42 -0
  194. package/dist/lib/worker.d.ts.map +1 -0
  195. package/dist/lib/worker.js +9 -0
  196. package/dist/lib/worker.js.map +1 -0
  197. package/dist/lib/workers/index.d.ts +11 -0
  198. package/dist/lib/workers/index.d.ts.map +1 -0
  199. package/dist/lib/workers/index.js +18 -0
  200. package/dist/lib/workers/index.js.map +1 -0
  201. package/dist/lib/workers/subprocess.d.ts +8 -0
  202. package/dist/lib/workers/subprocess.d.ts.map +1 -0
  203. package/dist/lib/workers/subprocess.js +105 -0
  204. package/dist/lib/workers/subprocess.js.map +1 -0
  205. package/dist/lib/worktree.d.ts +21 -0
  206. package/dist/lib/worktree.d.ts.map +1 -0
  207. package/dist/lib/worktree.js +113 -0
  208. package/dist/lib/worktree.js.map +1 -0
  209. package/dist/types.d.ts +201 -0
  210. package/dist/types.d.ts.map +1 -0
  211. package/dist/types.js +6 -0
  212. package/dist/types.js.map +1 -0
  213. package/package.json +44 -4
  214. package/templates/foundry.yml +121 -0
  215. package/templates/vercel-preview-url.sh +61 -0
  216. package/README.md +0 -3
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.waitForUrl = waitForUrl;
37
+ exports.expandReadyMatch = expandReadyMatch;
38
+ exports.isConfigured = isConfigured;
39
+ exports.verifyPreview = verifyPreview;
40
+ exports.formatPreviewVerify = formatPreviewVerify;
41
+ /**
42
+ * Preview verification — commands run against a live preview URL.
43
+ *
44
+ * `verify` proves the branch builds and its unit tests pass. `verify_preview`
45
+ * proves the deployed thing works: it runs after the preview is up, with
46
+ * FOUNDRY_PREVIEW_URL in the environment, and gates
47
+ * `state:ready-for-human-review`. This is where end-to-end and integration
48
+ * tests live once there is no shared test environment to run them in.
49
+ *
50
+ * A preview can take a while to become reachable (a static-site build, a
51
+ * container rollout), so the pipeline first waits for the URL to answer.
52
+ */
53
+ const verify_js_1 = require("./verify.js");
54
+ const log = __importStar(require("./log.js"));
55
+ const DEFAULT_READY_TIMEOUT_S = 300;
56
+ const READY_POLL_MS = 5_000;
57
+ /** Poll until the URL answers with a non-5xx status, or the timeout passes. */
58
+ async function waitForUrl(url, timeoutMs, pollMs = READY_POLL_MS, fetchImpl = fetch, bodyMatch) {
59
+ const deadline = Date.now() + timeoutMs;
60
+ let attempts = 0;
61
+ let status;
62
+ let matched;
63
+ while (true) {
64
+ attempts++;
65
+ try {
66
+ const res = await fetchImpl(url, { method: 'GET', redirect: 'follow' });
67
+ status = res.status;
68
+ if (res.status < 500 && res.status !== 404) {
69
+ if (!bodyMatch)
70
+ return { ready: true, status, attempts };
71
+ // A redeploy serves the previous version until the new one lands; the
72
+ // marker (usually the commit SHA) tells them apart.
73
+ matched = (await res.text()).includes(bodyMatch);
74
+ if (matched)
75
+ return { ready: true, status, attempts, matched };
76
+ }
77
+ }
78
+ catch {
79
+ status = undefined;
80
+ }
81
+ if (Date.now() >= deadline)
82
+ return { ready: false, status, attempts, matched };
83
+ await new Promise(r => setTimeout(r, Math.min(pollMs, Math.max(0, deadline - Date.now()))));
84
+ }
85
+ }
86
+ /** `{sha}`, `{branch}`, `{pr_number}` in ready_match. Undefined when unset. */
87
+ function expandReadyMatch(template, input) {
88
+ if (!template)
89
+ return undefined;
90
+ return template
91
+ .replace(/\{sha\}/g, input.sha ?? '')
92
+ .replace(/\{branch\}/g, input.branch ?? '')
93
+ .replace(/\{pr_number\}/g, input.pr_number === undefined ? '' : String(input.pr_number));
94
+ }
95
+ function isConfigured(config) {
96
+ return (config.verify_preview ?? []).length > 0;
97
+ }
98
+ /**
99
+ * Wait for the preview, then run every `verify_preview` command fail-fast.
100
+ * Never throws; a preview that never comes up is reported as a failed step.
101
+ */
102
+ async function verifyPreview(config, input) {
103
+ const commands = config.verify_preview ?? [];
104
+ const results = [];
105
+ const timeoutS = config.preview?.ready_timeout_seconds ?? DEFAULT_READY_TIMEOUT_S;
106
+ const start = Date.now();
107
+ const match = expandReadyMatch(config.preview?.ready_match, input);
108
+ const ready = await waitForUrl(input.url, timeoutS * 1000, undefined, undefined, match);
109
+ if (!ready.ready) {
110
+ const why = ready.matched === false
111
+ ? `answered (${ready.status}) but never contained "${match}"`
112
+ : `did not answer (last status ${ready.status ?? 'no response'})`;
113
+ results.push({
114
+ command: `wait for ${input.url}`,
115
+ success: false,
116
+ output: `Preview ${why} within ${timeoutS}s (${ready.attempts} attempts).`,
117
+ duration_ms: Date.now() - start,
118
+ });
119
+ return { passed: false, url: input.url, results };
120
+ }
121
+ log.info(`Preview is up (${ready.status}${match ? `, contains "${match}"` : ''}) after ${ready.attempts} attempt${ready.attempts === 1 ? '' : 's'}.`);
122
+ const env = {
123
+ ...(input.env ?? {}),
124
+ ...(input.sha ? { FOUNDRY_SHA: input.sha } : {}),
125
+ FOUNDRY_PREVIEW_URL: input.url,
126
+ };
127
+ for (const cmd of commands) {
128
+ const r = (0, verify_js_1.runVerifyStep)(cmd, input.cwd, env);
129
+ results.push(r);
130
+ if (!r.success)
131
+ return { passed: false, url: input.url, results };
132
+ }
133
+ return { passed: true, url: input.url, results };
134
+ }
135
+ /** Markdown summary for a status comment or PR comment. */
136
+ function formatPreviewVerify(outcome) {
137
+ const lines = [
138
+ `**Preview verification ${outcome.passed ? 'passed' : 'FAILED'}** against ${outcome.url}`,
139
+ '',
140
+ ...outcome.results.map(r => `- \`${r.command}\`: ${r.success ? 'passed' : 'FAILED'} (${r.duration_ms}ms)`),
141
+ ];
142
+ const failed = outcome.results.filter(r => !r.success);
143
+ if (failed.length > 0) {
144
+ lines.push('', ...failed.map(r => `\`\`\`\n${r.output.slice(-1000)}\n\`\`\``));
145
+ }
146
+ return lines.join('\n');
147
+ }
148
+ //# sourceMappingURL=preview-verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-verify.js","sourceRoot":"","sources":["../../src/lib/preview-verify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { FoundryConfig, TaskState } from '../types.js';
2
+ /**
3
+ * What a preview is for. A task's PR and a plain pull request (such as the
4
+ * promotion PR from integration into main) both become one of these; only
5
+ * the task path persists results to local state.
6
+ */
7
+ export interface PreviewTarget {
8
+ branch: string;
9
+ sha: string;
10
+ pr_number?: number;
11
+ issue?: number;
12
+ preview_url?: string;
13
+ deployment_id?: number;
14
+ }
15
+ /** The preview URL a PR's comment currently advertises, if Foundry posted one. */
16
+ export declare function previewUrlFromComments(bodies: string[]): string | undefined;
17
+ export declare function findPreviewUrlOnPR(repo: string, prNumber: number): Promise<string | undefined>;
18
+ export declare function previewUp(config: FoundryConfig, task: TaskState): Promise<void>;
19
+ /** Deploy a preview for any target. Returns what was created, or null when no URL could be resolved. */
20
+ export declare function previewUpTarget(config: FoundryConfig, target: PreviewTarget): Promise<{
21
+ url: string;
22
+ deploymentId?: number;
23
+ } | null>;
24
+ export declare function previewDown(config: FoundryConfig, task: TaskState): Promise<void>;
25
+ /** Tear down a preview for any target. `preview_url` must be set. */
26
+ export declare function previewDownTarget(config: FoundryConfig, target: PreviewTarget): Promise<void>;
27
+ export interface PreviewStatus {
28
+ url: string | null;
29
+ deploymentId: number | null;
30
+ state: 'active' | 'inactive' | 'none';
31
+ }
32
+ export declare function getPreviewStatus(config: FoundryConfig, task: TaskState): PreviewStatus;
33
+ //# sourceMappingURL=preview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.d.ts","sourceRoot":"","sources":["../../src/lib/preview.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAoC5D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAUD,kFAAkF;AAClF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,SAAS,CAO3E;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAOpG;AAmGD,wBAAsB,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAarF;AAED,wGAAwG;AACxG,wBAAsB,eAAe,CACnC,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAyDxD;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAWvF;AAED,qEAAqE;AACrE,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAiCnG;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;CACvC;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,GAAG,aAAa,CAYtF"}
@@ -0,0 +1,308 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.previewUrlFromComments = previewUrlFromComments;
37
+ exports.findPreviewUrlOnPR = findPreviewUrlOnPR;
38
+ exports.previewUp = previewUp;
39
+ exports.previewUpTarget = previewUpTarget;
40
+ exports.previewDown = previewDown;
41
+ exports.previewDownTarget = previewDownTarget;
42
+ exports.getPreviewStatus = getPreviewStatus;
43
+ /**
44
+ * Preview orchestration — URL resolution, provider command execution,
45
+ * comment upsert, and GitHub Deployment coordination.
46
+ */
47
+ const node_child_process_1 = require("node:child_process");
48
+ const github = __importStar(require("./github.js"));
49
+ const state = __importStar(require("./state.js"));
50
+ const deployments = __importStar(require("./deployments.js"));
51
+ const log = __importStar(require("./log.js"));
52
+ const git_js_1 = require("./git.js");
53
+ const COMMENT_MARKER = '<!-- foundry-preview -->';
54
+ function expandTemplate(template, vars) {
55
+ return template
56
+ .replace(/\{branch_slug\}/g, (0, git_js_1.slugify)(vars.branch))
57
+ .replace(/\{branch\}/g, vars.branch)
58
+ .replace(/\{issue\}/g, String(vars.issue ?? ''))
59
+ .replace(/\{repo\}/g, vars.repo)
60
+ .replace(/\{pr_number\}/g, String(vars.pr_number ?? ''))
61
+ .replace(/\{sha\}/g, vars.sha);
62
+ }
63
+ function makeEnvVars(vars) {
64
+ return {
65
+ FOUNDRY_BRANCH: vars.branch,
66
+ FOUNDRY_BRANCH_SLUG: (0, git_js_1.slugify)(vars.branch),
67
+ FOUNDRY_ISSUE: String(vars.issue ?? ''),
68
+ FOUNDRY_REPO: vars.repo,
69
+ FOUNDRY_PR_NUMBER: String(vars.pr_number ?? ''),
70
+ FOUNDRY_SHA: vars.sha,
71
+ };
72
+ }
73
+ function targetLabel(t) {
74
+ return t.issue !== undefined ? `#${t.issue}` : `PR #${t.pr_number ?? '?'} (${t.branch})`;
75
+ }
76
+ function targetVars(config, t) {
77
+ return { branch: t.branch, issue: t.issue, repo: config.repo, pr_number: t.pr_number, sha: t.sha };
78
+ }
79
+ /** The preview URL a PR's comment currently advertises, if Foundry posted one. */
80
+ function previewUrlFromComments(bodies) {
81
+ for (const body of bodies) {
82
+ if (!body.includes(COMMENT_MARKER))
83
+ continue;
84
+ const m = body.match(/Preview URL:\s*(\S+)/);
85
+ if (m)
86
+ return m[1];
87
+ }
88
+ return undefined;
89
+ }
90
+ async function findPreviewUrlOnPR(repo, prNumber) {
91
+ try {
92
+ const comments = await github.getComments(repo, prNumber);
93
+ return previewUrlFromComments(comments.map(c => c.body));
94
+ }
95
+ catch {
96
+ return undefined;
97
+ }
98
+ }
99
+ function resolveHeadSha(worktree) {
100
+ try {
101
+ return (0, node_child_process_1.execSync)('git rev-parse HEAD', { cwd: worktree, encoding: 'utf-8', timeout: 10_000 }).trim();
102
+ }
103
+ catch {
104
+ return '';
105
+ }
106
+ }
107
+ // ── URL resolution ───────────────────────────────────────────────────────
108
+ function resolveTemplateUrl(config, vars) {
109
+ if (!config.preview?.url_template)
110
+ return null;
111
+ return expandTemplate(config.preview.url_template, vars);
112
+ }
113
+ /**
114
+ * Run the provider's up command. Returns the URL it printed, or null.
115
+ *
116
+ * When `expectUrl` is false the caller has a url_template and only needs the
117
+ * command to run; its output is ignored and no warning is logged about it.
118
+ * This matters because commands like `gh workflow run` print an Actions run
119
+ * URL, which is a URL but not the preview.
120
+ */
121
+ function runProviderCommand(command, vars, expectUrl) {
122
+ const expanded = expandTemplate(command, vars);
123
+ const env = { ...process.env, ...makeEnvVars(vars) };
124
+ try {
125
+ const output = (0, node_child_process_1.execSync)(expanded, {
126
+ encoding: 'utf-8',
127
+ timeout: 120_000,
128
+ env,
129
+ }).trim();
130
+ if (!expectUrl)
131
+ return null;
132
+ // Try to parse as JSON with a `url` field
133
+ try {
134
+ const parsed = JSON.parse(output);
135
+ if (parsed.url)
136
+ return parsed.url;
137
+ }
138
+ catch {
139
+ // Not JSON — treat entire output as URL
140
+ }
141
+ // Validate it looks like a URL
142
+ if (output.startsWith('http://') || output.startsWith('https://')) {
143
+ return output.split('\n').pop().trim();
144
+ }
145
+ log.warn(`Provider command output does not look like a URL: ${output.slice(0, 200)}`);
146
+ return null;
147
+ }
148
+ catch (err) {
149
+ log.warn(`Provider up command failed: ${err.message}`);
150
+ return null;
151
+ }
152
+ }
153
+ // ── Comment upsert ───────────────────────────────────────────────────────
154
+ function buildPreviewComment(url, state) {
155
+ const status = state === 'active' ? 'Live' : 'Torn down';
156
+ const timestamp = new Date().toISOString().replace('T', ' ').slice(0, 19) + ' UTC';
157
+ return [
158
+ COMMENT_MARKER,
159
+ `**Preview Environment** — ${status}`,
160
+ '',
161
+ state === 'active' ? `Preview URL: ${url}` : `~~${url}~~ (inactive)`,
162
+ '',
163
+ `_Updated: ${timestamp}_`,
164
+ ].join('\n');
165
+ }
166
+ async function upsertPreviewComment(repo, prNumber, url, commentState) {
167
+ const body = buildPreviewComment(url, commentState);
168
+ try {
169
+ const comments = await github.getComments(repo, prNumber);
170
+ const existing = comments.find(c => c.body.includes(COMMENT_MARKER));
171
+ if (existing) {
172
+ await github.updateComment(repo, existing.id, body);
173
+ }
174
+ else {
175
+ await github.commentOnPR(repo, prNumber, body);
176
+ }
177
+ }
178
+ catch (err) {
179
+ log.warn(`Failed to upsert preview comment on PR #${prNumber}: ${err.message}`);
180
+ }
181
+ }
182
+ // ── Main exports ─────────────────────────────────────────────────────────
183
+ async function previewUp(config, task) {
184
+ if (!config.preview)
185
+ return;
186
+ const result = await previewUpTarget(config, {
187
+ branch: task.branch,
188
+ issue: task.issue,
189
+ pr_number: task.pr_number,
190
+ sha: resolveHeadSha(task.worktree),
191
+ });
192
+ if (!result)
193
+ return;
194
+ state.updateTaskStatus(config.repo, task.issue, task.status, {
195
+ preview_url: result.url,
196
+ ...(result.deploymentId !== undefined ? { deployment_id: result.deploymentId } : {}),
197
+ });
198
+ }
199
+ /** Deploy a preview for any target. Returns what was created, or null when no URL could be resolved. */
200
+ async function previewUpTarget(config, target) {
201
+ if (!config.preview)
202
+ return null;
203
+ const vars = targetVars(config, target);
204
+ const label = targetLabel(target);
205
+ // Resolve URL. url_template, when set, is always the preview URL: the
206
+ // provider command still runs (it does the deploy) but its output is not
207
+ // consulted. Only without a template do we read the URL from the command.
208
+ const hasTemplate = Boolean(config.preview.url_template);
209
+ let url = null;
210
+ if (config.preview.mode === 'provider' && config.preview.up_command) {
211
+ url = runProviderCommand(config.preview.up_command, vars, !hasTemplate);
212
+ }
213
+ if (hasTemplate) {
214
+ url = resolveTemplateUrl(config, vars);
215
+ }
216
+ if (!url) {
217
+ log.warn(`Preview up: could not resolve URL for ${label}`);
218
+ return null;
219
+ }
220
+ log.info(`Preview URL for ${label}: ${url}`);
221
+ // Create GitHub Deployment (if enabled)
222
+ let deploymentId;
223
+ if (config.github_deployments?.enabled) {
224
+ const deployment = await deployments.createDeployment({
225
+ repo: config.repo,
226
+ ref: target.branch,
227
+ environment: config.github_deployments.environment ?? 'preview',
228
+ description: `Preview for ${label}`,
229
+ transientEnvironment: !(config.github_deployments.production ?? false),
230
+ productionEnvironment: config.github_deployments.production ?? false,
231
+ });
232
+ if (deployment) {
233
+ deploymentId = deployment.id;
234
+ await deployments.createDeploymentStatus({
235
+ repo: config.repo,
236
+ deploymentId: deployment.id,
237
+ state: 'success',
238
+ environmentUrl: url,
239
+ description: 'Preview is live',
240
+ autoInactive: config.github_deployments.auto_inactive ?? true,
241
+ });
242
+ }
243
+ }
244
+ // Post/update PR comment
245
+ if (config.preview.comment !== false && target.pr_number) {
246
+ await upsertPreviewComment(config.repo, target.pr_number, url, 'active');
247
+ }
248
+ return { url, deploymentId };
249
+ }
250
+ async function previewDown(config, task) {
251
+ if (!config.preview)
252
+ return;
253
+ if (!task.preview_url)
254
+ return;
255
+ await previewDownTarget(config, {
256
+ branch: task.branch,
257
+ issue: task.issue,
258
+ pr_number: task.pr_number,
259
+ sha: resolveHeadSha(task.worktree),
260
+ preview_url: task.preview_url,
261
+ deployment_id: task.deployment_id,
262
+ });
263
+ }
264
+ /** Tear down a preview for any target. `preview_url` must be set. */
265
+ async function previewDownTarget(config, target) {
266
+ if (!config.preview || !target.preview_url)
267
+ return;
268
+ const vars = targetVars(config, target);
269
+ const label = targetLabel(target);
270
+ // Run down command (provider mode only)
271
+ if (config.preview.mode === 'provider' && config.preview.down_command) {
272
+ const expanded = expandTemplate(config.preview.down_command, vars);
273
+ const env = { ...process.env, ...makeEnvVars(vars) };
274
+ try {
275
+ (0, node_child_process_1.execSync)(expanded, { encoding: 'utf-8', timeout: 120_000, env });
276
+ }
277
+ catch (err) {
278
+ log.warn(`Preview down command failed for ${label}: ${err.message}`);
279
+ }
280
+ }
281
+ // Set deployment status to inactive
282
+ if (config.github_deployments?.enabled && target.deployment_id) {
283
+ await deployments.createDeploymentStatus({
284
+ repo: config.repo,
285
+ deploymentId: target.deployment_id,
286
+ state: 'inactive',
287
+ description: 'Preview torn down',
288
+ autoInactive: config.github_deployments.auto_inactive ?? true,
289
+ });
290
+ }
291
+ // Update PR comment
292
+ if (config.preview.comment !== false && target.pr_number) {
293
+ await upsertPreviewComment(config.repo, target.pr_number, target.preview_url, 'inactive');
294
+ }
295
+ log.info(`Preview torn down for ${label}`);
296
+ }
297
+ function getPreviewStatus(config, task) {
298
+ if (!config.preview || !task.preview_url) {
299
+ return { url: null, deploymentId: null, state: 'none' };
300
+ }
301
+ const isActive = ['pr-open', 'reviewing', 'pr-changes-requested', 'agent-running', 'verifying'].includes(task.status);
302
+ return {
303
+ url: task.preview_url,
304
+ deploymentId: task.deployment_id ?? null,
305
+ state: isActive ? 'active' : 'inactive',
306
+ };
307
+ }
308
+ //# sourceMappingURL=preview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview.js","sourceRoot":"","sources":["../../src/lib/preview.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoEA,wDAOC;AAED,gDAOC;AAmGD,8BAaC;AAGD,0CA4DC;AAED,kCAWC;AAGD,8CAiCC;AAQD,4CAYC;AAxUD;;;GAGG;AACH,2DAA8C;AAC9C,oDAAsC;AACtC,kDAAoC;AACpC,8DAAgD;AAChD,8CAAgC;AAEhC,qCAAmC;AAEnC,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAYlD,SAAS,cAAc,CAAC,QAAgB,EAAE,IAAkB;IAC1D,OAAO,QAAQ;SACZ,OAAO,CAAC,kBAAkB,EAAE,IAAA,gBAAO,EAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SACjD,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,MAAM,CAAC;SACnC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;SAC/C,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC;SAC/B,OAAO,CAAC,gBAAgB,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;SACvD,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC;AAED,SAAS,WAAW,CAAC,IAAkB;IACrC,OAAO;QACL,cAAc,EAAE,IAAI,CAAC,MAAM;QAC3B,mBAAmB,EAAE,IAAA,gBAAO,EAAC,IAAI,CAAC,MAAM,CAAC;QACzC,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QACvC,YAAY,EAAE,IAAI,CAAC,IAAI;QACvB,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;QAC/C,WAAW,EAAE,IAAI,CAAC,GAAG;KACtB,CAAC;AACJ,CAAC;AAgBD,SAAS,WAAW,CAAC,CAAgB;IACnC,OAAO,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC;AAC3F,CAAC;AAED,SAAS,UAAU,CAAC,MAAqB,EAAE,CAAgB;IACzD,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;AACrG,CAAC;AAED,kFAAkF;AAClF,SAAgB,sBAAsB,CAAC,MAAgB;IACrD,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC;YAAE,SAAS;QAC7C,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC7C,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAEM,KAAK,UAAU,kBAAkB,CAAC,IAAY,EAAE,QAAgB;IACrE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,sBAAsB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,QAAgB;IACtC,IAAI,CAAC;QACH,OAAO,IAAA,6BAAQ,EAAC,oBAAoB,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACtG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,4EAA4E;AAE5E,SAAS,kBAAkB,CAAC,MAAqB,EAAE,IAAkB;IACnE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,kBAAkB,CAAC,OAAe,EAAE,IAAkB,EAAE,SAAkB;IACjF,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC/C,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,6BAAQ,EAAC,QAAQ,EAAE;YAChC,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,OAAO;YAChB,GAAG;SACJ,CAAC,CAAC,IAAI,EAAE,CAAC;QAEV,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAE5B,0CAA0C;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,MAAM,CAAC,GAAG;gBAAE,OAAO,MAAM,CAAC,GAAG,CAAC;QACpC,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;QAC1C,CAAC;QAED,+BAA+B;QAC/B,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAClE,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAG,CAAC,IAAI,EAAE,CAAC;QAC1C,CAAC;QAED,GAAG,CAAC,IAAI,CAAC,qDAAqD,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACtF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,IAAI,CAAC,+BAA+B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACvD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,4EAA4E;AAE5E,SAAS,mBAAmB,CAAC,GAAW,EAAE,KAA4B;IACpE,MAAM,MAAM,GAAG,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC;IACzD,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC;IAEnF,OAAO;QACL,cAAc;QACd,6BAA6B,MAAM,EAAE;QACrC,EAAE;QACF,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,eAAe;QACpE,EAAE;QACF,aAAa,SAAS,GAAG;KAC1B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,IAAY,EACZ,QAAgB,EAChB,GAAW,EACX,YAAmC;IAEnC,MAAM,IAAI,GAAG,mBAAmB,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEpD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC1D,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC;QAErE,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACtD,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,IAAI,CAAC,2CAA2C,QAAQ,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED,4EAA4E;AAErE,KAAK,UAAU,SAAS,CAAC,MAAqB,EAAE,IAAe;IACpE,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO;IAC5B,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE;QAC3C,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;KACnC,CAAC,CAAC;IACH,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE;QAC3D,WAAW,EAAE,MAAM,CAAC,GAAG;QACvB,GAAG,CAAC,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrF,CAAC,CAAC;AACL,CAAC;AAED,wGAAwG;AACjG,KAAK,UAAU,eAAe,CACnC,MAAqB,EACrB,MAAqB;IAErB,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACjC,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAElC,sEAAsE;IACtE,yEAAyE;IACzE,0EAA0E;IAC1E,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACzD,IAAI,GAAG,GAAkB,IAAI,CAAC;IAE9B,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACpE,GAAG,GAAG,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,WAAW,CAAC,CAAC;IAC1E,CAAC;IAED,IAAI,WAAW,EAAE,CAAC;QAChB,GAAG,GAAG,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,CAAC,IAAI,CAAC,yCAAyC,KAAK,EAAE,CAAC,CAAC;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,mBAAmB,KAAK,KAAK,GAAG,EAAE,CAAC,CAAC;IAE7C,wCAAwC;IACxC,IAAI,YAAgC,CAAC;IACrC,IAAI,MAAM,CAAC,kBAAkB,EAAE,OAAO,EAAE,CAAC;QACvC,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,gBAAgB,CAAC;YACpD,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,GAAG,EAAE,MAAM,CAAC,MAAM;YAClB,WAAW,EAAE,MAAM,CAAC,kBAAkB,CAAC,WAAW,IAAI,SAAS;YAC/D,WAAW,EAAE,eAAe,KAAK,EAAE;YACnC,oBAAoB,EAAE,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC,UAAU,IAAI,KAAK,CAAC;YACtE,qBAAqB,EAAE,MAAM,CAAC,kBAAkB,CAAC,UAAU,IAAI,KAAK;SACrE,CAAC,CAAC;QAEH,IAAI,UAAU,EAAE,CAAC;YACf,YAAY,GAAG,UAAU,CAAC,EAAE,CAAC;YAC7B,MAAM,WAAW,CAAC,sBAAsB,CAAC;gBACvC,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,YAAY,EAAE,UAAU,CAAC,EAAE;gBAC3B,KAAK,EAAE,SAAS;gBAChB,cAAc,EAAE,GAAG;gBACnB,WAAW,EAAE,iBAAiB;gBAC9B,YAAY,EAAE,MAAM,CAAC,kBAAkB,CAAC,aAAa,IAAI,IAAI;aAC9D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,yBAAyB;IACzB,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACzD,MAAM,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC3E,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,CAAC;AAC/B,CAAC;AAEM,KAAK,UAAU,WAAW,CAAC,MAAqB,EAAE,IAAe;IACtE,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO;IAC5B,IAAI,CAAC,IAAI,CAAC,WAAW;QAAE,OAAO;IAC9B,MAAM,iBAAiB,CAAC,MAAM,EAAE;QAC9B,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,GAAG,EAAE,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC;QAClC,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,aAAa,EAAE,IAAI,CAAC,aAAa;KAClC,CAAC,CAAC;AACL,CAAC;AAED,qEAAqE;AAC9D,KAAK,UAAU,iBAAiB,CAAC,MAAqB,EAAE,MAAqB;IAClF,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW;QAAE,OAAO;IACnD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IAElC,wCAAwC;IACxC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QACtE,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QACnE,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD,IAAI,CAAC;YACH,IAAA,6BAAQ,EAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,GAAG,CAAC,IAAI,CAAC,mCAAmC,KAAK,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;IAED,oCAAoC;IACpC,IAAI,MAAM,CAAC,kBAAkB,EAAE,OAAO,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;QAC/D,MAAM,WAAW,CAAC,sBAAsB,CAAC;YACvC,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,YAAY,EAAE,MAAM,CAAC,aAAa;YAClC,KAAK,EAAE,UAAU;YACjB,WAAW,EAAE,mBAAmB;YAChC,YAAY,EAAE,MAAM,CAAC,kBAAkB,CAAC,aAAa,IAAI,IAAI;SAC9D,CAAC,CAAC;IACL,CAAC;IAED,oBAAoB;IACpB,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,KAAK,KAAK,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACzD,MAAM,oBAAoB,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAC5F,CAAC;IAED,GAAG,CAAC,IAAI,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;AAC7C,CAAC;AAQD,SAAgB,gBAAgB,CAAC,MAAqB,EAAE,IAAe;IACrE,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACzC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC1D,CAAC;IAED,MAAM,QAAQ,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,sBAAsB,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEtH,OAAO;QACL,GAAG,EAAE,IAAI,CAAC,WAAW;QACrB,YAAY,EAAE,IAAI,CAAC,aAAa,IAAI,IAAI;QACxC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU;KACxC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { FoundryConfig } from '../types.js';
2
+ export declare const DEFAULT_STALE_MINUTES = 120;
3
+ /** Parse the `| Updated | 2026-10-21 06:35:19 UTC |` row of a status comment. */
4
+ export declare function parseStatusUpdatedAt(body: string): Date | null;
5
+ export interface StaleTask {
6
+ issue: number;
7
+ lastUpdate: Date | null;
8
+ ageMinutes: number | null;
9
+ }
10
+ /** In-progress issues whose last status update is older than the threshold. */
11
+ export declare function findStaleTasks(config: FoundryConfig, now?: Date): Promise<StaleTask[]>;
12
+ /** Mark each stale task failed with a note. Returns what was changed. */
13
+ export declare function reconcile(config: FoundryConfig, repoDir: string, now?: Date): Promise<StaleTask[]>;
14
+ //# sourceMappingURL=reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.d.ts","sourceRoot":"","sources":["../../src/lib/reconcile.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,eAAO,MAAM,qBAAqB,MAAM,CAAC;AAEzC,iFAAiF;AACjF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAK9D;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,IAAI,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,+EAA+E;AAC/E,wBAAsB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAiBxG;AAED,yEAAyE;AACzE,wBAAsB,SAAS,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CA2BpH"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.DEFAULT_STALE_MINUTES = void 0;
37
+ exports.parseStatusUpdatedAt = parseStatusUpdatedAt;
38
+ exports.findStaleTasks = findStaleTasks;
39
+ exports.reconcile = reconcile;
40
+ /**
41
+ * Reconciliation — find tasks that claim to be running but are not.
42
+ *
43
+ * A job can die without a trace: the six-hour limit, a runner failure, a
44
+ * cancel that skipped cleanup. The issue then sits at `state:in-progress`
45
+ * forever. On a schedule, Foundry looks at every in-progress issue and, when
46
+ * its status comment has not been touched for longer than any job could
47
+ * live, marks it failed with a note so a human can re-queue it.
48
+ *
49
+ * Waiting states (`waiting-for-input`, `plan-review`, `ready-for-review`)
50
+ * are never touched: no job is expected to be running for them.
51
+ */
52
+ const github = __importStar(require("./github.js"));
53
+ const log = __importStar(require("./log.js"));
54
+ const statusComment = __importStar(require("./status-comment.js"));
55
+ const labels_js_1 = require("./labels.js");
56
+ const task_recovery_js_1 = require("./task-recovery.js");
57
+ exports.DEFAULT_STALE_MINUTES = 120;
58
+ /** Parse the `| Updated | 2026-10-21 06:35:19 UTC |` row of a status comment. */
59
+ function parseStatusUpdatedAt(body) {
60
+ const m = body.match(/\|\s*Updated\s*\|\s*(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) UTC\s*\|/);
61
+ if (!m)
62
+ return null;
63
+ const d = new Date(`${m[1]}T${m[2]}Z`);
64
+ return Number.isNaN(d.getTime()) ? null : d;
65
+ }
66
+ /** In-progress issues whose last status update is older than the threshold. */
67
+ async function findStaleTasks(config, now = new Date()) {
68
+ const staleAfterMs = (config.reconcile_stale_minutes ?? exports.DEFAULT_STALE_MINUTES) * 60_000;
69
+ const issues = await github.listIssuesByLabel(config.repo, config.labels.in_progress);
70
+ const stale = [];
71
+ for (const issue of issues) {
72
+ const comments = await github.getComments(config.repo, issue.number);
73
+ const status = [...comments].reverse().find(c => c.body.includes('<!-- foundry-status -->'));
74
+ const lastUpdate = status ? parseStatusUpdatedAt(status.body) : null;
75
+ const ageMinutes = lastUpdate ? Math.round((now.getTime() - lastUpdate.getTime()) / 60_000) : null;
76
+ // No status comment at all means the claim never got as far as starting an
77
+ // agent; treat it as stale too, since nothing will ever update it.
78
+ if (lastUpdate === null || now.getTime() - lastUpdate.getTime() > staleAfterMs) {
79
+ stale.push({ issue: issue.number, lastUpdate, ageMinutes });
80
+ }
81
+ }
82
+ return stale;
83
+ }
84
+ /** Mark each stale task failed with a note. Returns what was changed. */
85
+ async function reconcile(config, repoDir, now = new Date()) {
86
+ const stale = await findStaleTasks(config, now);
87
+ if (stale.length === 0) {
88
+ log.info('Reconcile: every in-progress issue has a recent status update.');
89
+ return [];
90
+ }
91
+ for (const s of stale) {
92
+ const age = s.ageMinutes === null ? 'no status comment' : `last update ${s.ageMinutes} min ago`;
93
+ log.warn(`#${s.issue} is in-progress with no live run (${age}). Marking failed.`);
94
+ try {
95
+ await (0, labels_js_1.setStateLabel)(config, s.issue, 'failed');
96
+ const task = await (0, task_recovery_js_1.recoverTask)(config, repoDir, s.issue);
97
+ if (task) {
98
+ await statusComment.updateStatusComment(config.repo, s.issue, {
99
+ task: { ...task, status: 'failed' },
100
+ message: `No Foundry job has reported on this issue for ${s.ageMinutes ?? 'an unknown number of'} minutes; the run that claimed it is gone (cancelled, timed out, or the runner died).\n\n\`@foundry go\` to continue from the branch · \`@foundry restart\` to start over`,
101
+ historyEntry: 'Reconciled: no live run',
102
+ });
103
+ }
104
+ else {
105
+ await github.addComment(config.repo, s.issue, 'Foundry found this issue marked in-progress with no live run and no claim record. Marked failed; comment `@foundry go` to try again.');
106
+ }
107
+ }
108
+ catch (err) {
109
+ log.warn(`Reconcile: could not update #${s.issue}: ${err.message}`);
110
+ }
111
+ }
112
+ return stale;
113
+ }
114
+ //# sourceMappingURL=reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile.js","sourceRoot":"","sources":["../../src/lib/reconcile.ts"],"names":[],"mappings":"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"}