@joynt/foundry 0.0.0-stage → 0.1.51

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,233 @@
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.AGENT_REPORT_SCHEMA = exports.REPORT_FILE_ENV = exports.REPORT_SCHEMA_ENV = exports.REPORT_STATUSES = void 0;
37
+ exports.reportSchemaJson = reportSchemaJson;
38
+ exports.validateReport = validateReport;
39
+ exports.reportFilePath = reportFilePath;
40
+ exports.readReportFile = readReportFile;
41
+ exports.writeReportFile = writeReportFile;
42
+ exports.prepareLaunch = prepareLaunch;
43
+ /**
44
+ * Agent report — the typed contract between a coding agent and Foundry.
45
+ *
46
+ * Foundry never interprets an agent's prose to decide what happens next. The
47
+ * agent ends its run by submitting a report that matches AGENT_REPORT_SCHEMA,
48
+ * and Foundry branches on `status`. Two transports feed the same type:
49
+ *
50
+ * 1. Structured output. Claude Code, given `--json-schema`, validates the
51
+ * report itself and puts it on the final `result` event as
52
+ * `structured_output`. The schema is handed to the backend command in the
53
+ * FOUNDRY_REPORT_SCHEMA environment variable.
54
+ * 2. A report file. Any other agent runs `foundry report ...`, which
55
+ * validates and writes FOUNDRY_REPORT_FILE.
56
+ *
57
+ * No report means no transition: the task fails closed with a reason.
58
+ */
59
+ const fs = __importStar(require("node:fs"));
60
+ const path = __importStar(require("node:path"));
61
+ exports.REPORT_STATUSES = ['done', 'needs_input', 'plan_ready', 'blocked'];
62
+ exports.REPORT_SCHEMA_ENV = 'FOUNDRY_REPORT_SCHEMA';
63
+ exports.REPORT_FILE_ENV = 'FOUNDRY_REPORT_FILE';
64
+ /**
65
+ * JSON Schema for the report. The descriptions are instructions to the agent;
66
+ * they are the only place the meaning of each status is defined.
67
+ */
68
+ exports.AGENT_REPORT_SCHEMA = {
69
+ type: 'object',
70
+ properties: {
71
+ status: {
72
+ type: 'string',
73
+ enum: exports.REPORT_STATUSES,
74
+ description: [
75
+ 'done: the task is implemented and every change is committed.',
76
+ 'needs_input: you need a decision from a human before you can continue or finish; put it in `questions`. Commit any work in progress first.',
77
+ 'plan_ready: you were asked to plan, not implement; put the plan in `plan`.',
78
+ 'blocked: you cannot proceed and no answer from a human would unblock you (missing access, broken environment, impossible request); explain in `summary`.',
79
+ ].join(' '),
80
+ },
81
+ summary: {
82
+ type: 'string',
83
+ description: 'What you did, or why you stopped. Written for the person reviewing the pull request. Plain prose, a few sentences.',
84
+ },
85
+ assumptions: {
86
+ type: 'array',
87
+ items: { type: 'string' },
88
+ description: 'Decisions you made without asking, one per entry, so the reviewer can check them.',
89
+ },
90
+ questions: {
91
+ type: 'array',
92
+ description: 'Required when status is needs_input. Ask only what materially changes the work; offer options when you can.',
93
+ items: {
94
+ type: 'object',
95
+ properties: {
96
+ question: { type: 'string' },
97
+ options: {
98
+ type: 'array',
99
+ items: {
100
+ type: 'object',
101
+ properties: {
102
+ label: { type: 'string' },
103
+ description: { type: 'string' },
104
+ },
105
+ required: ['label'],
106
+ },
107
+ },
108
+ multi_select: { type: 'boolean' },
109
+ },
110
+ required: ['question'],
111
+ },
112
+ },
113
+ plan: {
114
+ type: 'string',
115
+ description: 'Required when status is plan_ready. The full plan in Markdown.',
116
+ },
117
+ },
118
+ required: ['status', 'summary'],
119
+ };
120
+ function reportSchemaJson() {
121
+ return JSON.stringify(exports.AGENT_REPORT_SCHEMA);
122
+ }
123
+ function isStringArray(v) {
124
+ return Array.isArray(v) && v.every(x => typeof x === 'string');
125
+ }
126
+ /**
127
+ * Validate an untrusted value as an AgentReport. Structural errors are
128
+ * rejected. Two cross-field gaps are repaired deterministically rather than
129
+ * rejected, because the status is unambiguous and the content exists:
130
+ * needs_input with no questions asks the summary; plan_ready with no plan
131
+ * uses the summary as the plan.
132
+ */
133
+ function validateReport(value) {
134
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) {
135
+ return { ok: false, error: 'report is not an object' };
136
+ }
137
+ const v = value;
138
+ if (typeof v.status !== 'string' || !exports.REPORT_STATUSES.includes(v.status)) {
139
+ return { ok: false, error: `status must be one of ${exports.REPORT_STATUSES.join(', ')}` };
140
+ }
141
+ if (typeof v.summary !== 'string' || v.summary.trim() === '') {
142
+ return { ok: false, error: 'summary must be a non-empty string' };
143
+ }
144
+ if (v.assumptions !== undefined && !isStringArray(v.assumptions)) {
145
+ return { ok: false, error: 'assumptions must be an array of strings' };
146
+ }
147
+ if (v.plan !== undefined && typeof v.plan !== 'string') {
148
+ return { ok: false, error: 'plan must be a string' };
149
+ }
150
+ let questions;
151
+ if (v.questions !== undefined) {
152
+ if (!Array.isArray(v.questions))
153
+ return { ok: false, error: 'questions must be an array' };
154
+ questions = [];
155
+ for (const q of v.questions) {
156
+ if (q === null || typeof q !== 'object' || typeof q.question !== 'string' || q.question.trim() === '') {
157
+ return { ok: false, error: 'each question needs a non-empty `question` string' };
158
+ }
159
+ const rawOptions = q.options;
160
+ let options;
161
+ if (rawOptions !== undefined) {
162
+ if (!Array.isArray(rawOptions) || !rawOptions.every((o) => o && typeof o.label === 'string')) {
163
+ return { ok: false, error: 'each option needs a `label` string' };
164
+ }
165
+ options = rawOptions.map((o) => ({
166
+ label: o.label,
167
+ ...(typeof o.description === 'string' ? { description: o.description } : {}),
168
+ }));
169
+ }
170
+ questions.push({
171
+ question: q.question,
172
+ ...(options ? { options } : {}),
173
+ ...(q.multi_select === true ? { multi_select: true } : {}),
174
+ });
175
+ }
176
+ }
177
+ const status = v.status;
178
+ const summary = v.summary;
179
+ if (status === 'needs_input' && (!questions || questions.length === 0)) {
180
+ questions = [{ question: summary }];
181
+ }
182
+ let plan = v.plan;
183
+ if (status === 'plan_ready' && (!plan || plan.trim() === '')) {
184
+ plan = summary;
185
+ }
186
+ return {
187
+ ok: true,
188
+ report: {
189
+ status,
190
+ summary,
191
+ ...(v.assumptions ? { assumptions: v.assumptions } : {}),
192
+ ...(questions ? { questions } : {}),
193
+ ...(plan ? { plan } : {}),
194
+ },
195
+ };
196
+ }
197
+ // ── Transports ───────────────────────────────────────────────────────────
198
+ function reportFilePath(stateDir) {
199
+ return path.join(stateDir, 'report.json');
200
+ }
201
+ /** Read and validate a report file. Null when the file does not exist. */
202
+ function readReportFile(file) {
203
+ if (!fs.existsSync(file))
204
+ return null;
205
+ try {
206
+ return validateReport(JSON.parse(fs.readFileSync(file, 'utf-8')));
207
+ }
208
+ catch (err) {
209
+ return { ok: false, error: `report file is not valid JSON: ${err.message}` };
210
+ }
211
+ }
212
+ function writeReportFile(file, report) {
213
+ fs.mkdirSync(path.dirname(file), { recursive: true });
214
+ const tmp = `${file}.${process.pid}.tmp`;
215
+ fs.writeFileSync(tmp, JSON.stringify(report, null, 2) + '\n', 'utf-8');
216
+ fs.renameSync(tmp, file);
217
+ }
218
+ /**
219
+ * Environment for an agent launch, and a clean slate: a report left by a
220
+ * previous launch of the same task must never be read as this launch's.
221
+ */
222
+ function prepareLaunch(stateDir) {
223
+ const file = reportFilePath(stateDir);
224
+ try {
225
+ fs.rmSync(file, { force: true });
226
+ }
227
+ catch { }
228
+ return {
229
+ [exports.REPORT_SCHEMA_ENV]: reportSchemaJson(),
230
+ [exports.REPORT_FILE_ENV]: file,
231
+ };
232
+ }
233
+ //# sourceMappingURL=agent-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-report.js","sourceRoot":"","sources":["../../src/lib/agent-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { FoundryConfig } from '../types.js';
2
+ export declare function canCommand(config: FoundryConfig, login: string): Promise<boolean>;
3
+ //# sourceMappingURL=authorize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/lib/authorize.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD,wBAAsB,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWvF"}
@@ -0,0 +1,67 @@
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.canCommand = canCommand;
37
+ /**
38
+ * Who may command Foundry.
39
+ *
40
+ * Anyone can comment on a public repository's issues, and a comment is all it
41
+ * takes to start a paid agent run. The workflow's `if:` filters on
42
+ * `author_association` before a runner is even started; this is the precise
43
+ * check inside the job: the commenter must hold write or admin permission on
44
+ * the repository. Commands Foundry dispatches to itself are not checked here
45
+ * (`workflow_dispatch` already requires `actions: write`).
46
+ *
47
+ * Fails closed: if the permission cannot be read, the command is ignored.
48
+ */
49
+ const github = __importStar(require("./github.js"));
50
+ const log = __importStar(require("./log.js"));
51
+ const ALLOWED = new Set(['admin', 'write']);
52
+ async function canCommand(config, login) {
53
+ if (!login)
54
+ return false;
55
+ try {
56
+ const permission = await github.getCollaboratorPermission(config.repo, login);
57
+ if (ALLOWED.has(permission))
58
+ return true;
59
+ log.warn(`${login} has "${permission}" permission on ${config.repo}; write is required to command Foundry.`);
60
+ return false;
61
+ }
62
+ catch (err) {
63
+ log.warn(`Could not read ${login}'s permission on ${config.repo}: ${err.message}. Command ignored.`);
64
+ return false;
65
+ }
66
+ }
67
+ //# sourceMappingURL=authorize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../src/lib/authorize.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,gCAWC;AA7BD;;;;;;;;;;;GAWG;AACH,oDAAsC;AACtC,8CAAgC;AAGhC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAErC,KAAK,UAAU,UAAU,CAAC,MAAqB,EAAE,KAAa;IACnE,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9E,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,UAAU,mBAAmB,MAAM,CAAC,IAAI,yCAAyC,CAAC,CAAC;QAC7G,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,IAAI,CAAC,kBAAkB,KAAK,oBAAoB,MAAM,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,oBAAoB,CAAC,CAAC;QACrG,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { FoundryConfig } from '../types.js';
2
+ export declare const DEFAULT_BRANCHES: {
3
+ readonly integration: "integration";
4
+ readonly production: "main";
5
+ };
6
+ /** The moving branch feature PRs merge into. */
7
+ export declare function integrationBranch(config: FoundryConfig): string;
8
+ /** The branch the integration branch is promoted to. */
9
+ export declare function productionBranch(config: FoundryConfig): string;
10
+ export declare class MissingBranchError extends Error {
11
+ readonly branch: string;
12
+ constructor(branch: string);
13
+ }
14
+ /**
15
+ * The ref agent branches are cut from and measured against:
16
+ * `origin/<integration>`. Throws when that branch does not exist on the
17
+ * remote. There is deliberately no fallback to the production branch: work
18
+ * silently based on `main` when `integration` was misspelled is worse than a
19
+ * clear error.
20
+ */
21
+ export declare function resolveBaseBranch(config: FoundryConfig, repoDir?: string): string;
22
+ //# sourceMappingURL=branches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branches.d.ts","sourceRoot":"","sources":["../../src/lib/branches.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,eAAO,MAAM,gBAAgB;;;CAA8D,CAAC;AAE5F,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAE/D;AAED,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAE9D;AAED,qBAAa,kBAAmB,SAAQ,KAAK;aACf,MAAM,EAAE,MAAM;gBAAd,MAAM,EAAE,MAAM;CAO3C;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAIjF"}
@@ -0,0 +1,82 @@
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.MissingBranchError = exports.DEFAULT_BRANCHES = void 0;
37
+ exports.integrationBranch = integrationBranch;
38
+ exports.productionBranch = productionBranch;
39
+ exports.resolveBaseBranch = resolveBaseBranch;
40
+ /**
41
+ * The two long-lived branches Foundry works against, by configured name.
42
+ *
43
+ * Nothing in Foundry may assume `integration` or `main`: a repo being
44
+ * onboarded already has branch names that its deploy pipeline, protection
45
+ * rules, and hosting provider key on, and renaming them to suit Foundry is
46
+ * not a reasonable precondition. `branches:` in .joynt-foundry.yml names
47
+ * them; the defaults are `integration` and `main`.
48
+ */
49
+ const git = __importStar(require("./git.js"));
50
+ exports.DEFAULT_BRANCHES = { integration: 'integration', production: 'main' };
51
+ /** The moving branch feature PRs merge into. */
52
+ function integrationBranch(config) {
53
+ return config.branches?.integration || exports.DEFAULT_BRANCHES.integration;
54
+ }
55
+ /** The branch the integration branch is promoted to. */
56
+ function productionBranch(config) {
57
+ return config.branches?.production || exports.DEFAULT_BRANCHES.production;
58
+ }
59
+ class MissingBranchError extends Error {
60
+ branch;
61
+ constructor(branch) {
62
+ super(`The integration branch "${branch}" does not exist on origin. ` +
63
+ `Create it (\`git push origin HEAD:${branch}\`), or set \`branches.integration\` in .joynt-foundry.yml to the branch feature work should be based on and merged into.`);
64
+ this.branch = branch;
65
+ this.name = 'MissingBranchError';
66
+ }
67
+ }
68
+ exports.MissingBranchError = MissingBranchError;
69
+ /**
70
+ * The ref agent branches are cut from and measured against:
71
+ * `origin/<integration>`. Throws when that branch does not exist on the
72
+ * remote. There is deliberately no fallback to the production branch: work
73
+ * silently based on `main` when `integration` was misspelled is worse than a
74
+ * clear error.
75
+ */
76
+ function resolveBaseBranch(config, repoDir) {
77
+ const branch = integrationBranch(config);
78
+ if (!git.remoteBranchExists(branch, repoDir))
79
+ throw new MissingBranchError(branch);
80
+ return `origin/${branch}`;
81
+ }
82
+ //# sourceMappingURL=branches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branches.js","sourceRoot":"","sources":["../../src/lib/branches.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeA,8CAEC;AAGD,4CAEC;AAmBD,8CAIC;AA7CD;;;;;;;;GAQG;AACH,8CAAgC;AAGnB,QAAA,gBAAgB,GAAG,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAW,CAAC;AAE5F,gDAAgD;AAChD,SAAgB,iBAAiB,CAAC,MAAqB;IACrD,OAAO,MAAM,CAAC,QAAQ,EAAE,WAAW,IAAI,wBAAgB,CAAC,WAAW,CAAC;AACtE,CAAC;AAED,wDAAwD;AACxD,SAAgB,gBAAgB,CAAC,MAAqB;IACpD,OAAO,MAAM,CAAC,QAAQ,EAAE,UAAU,IAAI,wBAAgB,CAAC,UAAU,CAAC;AACpE,CAAC;AAED,MAAa,kBAAmB,SAAQ,KAAK;IACf;IAA5B,YAA4B,MAAc;QACxC,KAAK,CACH,2BAA2B,MAAM,8BAA8B;YAC/D,qCAAqC,MAAM,2HAA2H,CACvK,CAAC;QAJwB,WAAM,GAAN,MAAM,CAAQ;QAKxC,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AARD,gDAQC;AAED;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAAC,MAAqB,EAAE,OAAgB;IACvE,MAAM,MAAM,GAAG,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,GAAG,CAAC,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC;QAAE,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACnF,OAAO,UAAU,MAAM,EAAE,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { FoundryConfig, GitHubIssue } from '../types.js';
2
+ export interface ClaimInfo {
3
+ runner_id: string;
4
+ branch: string;
5
+ worktree: string;
6
+ tmux_session: string;
7
+ agent_backend: string;
8
+ }
9
+ export declare function parseClaimComment(body: string): ClaimInfo | null;
10
+ /**
11
+ * Attempt to claim an issue. Returns true if this runner owns it.
12
+ */
13
+ export declare function claimIssue(config: FoundryConfig, issue: GitHubIssue, claimInfo: ClaimInfo): Promise<boolean>;
14
+ /**
15
+ * Check if issue is already claimed by this runner.
16
+ */
17
+ export declare function isClaimedByUs(config: FoundryConfig, issue: number): boolean;
18
+ /**
19
+ * Mark an issue as failed on GitHub: `failed` becomes the sole state label.
20
+ */
21
+ export declare function markFailed(config: FoundryConfig, issue: number): Promise<void>;
22
+ //# sourceMappingURL=claim.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim.d.ts","sourceRoot":"","sources":["../../src/lib/claim.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAa,MAAM,aAAa,CAAC;AAEzE,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AA+BD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAchE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,WAAW,EAClB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,OAAO,CAAC,CAwBlB;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAG3E;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpF"}
@@ -0,0 +1,129 @@
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.parseClaimComment = parseClaimComment;
37
+ exports.claimIssue = claimIssue;
38
+ exports.isClaimedByUs = isClaimedByUs;
39
+ exports.markFailed = markFailed;
40
+ /**
41
+ * Issue claim protocol — safe, idempotent, verifiable.
42
+ */
43
+ const github = __importStar(require("./github.js"));
44
+ const state = __importStar(require("./state.js"));
45
+ const labels_js_1 = require("./labels.js");
46
+ function buildClaimComment(info) {
47
+ return [
48
+ '<!-- foundry-claim-block -->',
49
+ '**Foundry Claim**',
50
+ '',
51
+ '| Field | Value |',
52
+ '|-------|-------|',
53
+ `| Runner | \`${info.runner_id}\` |`,
54
+ `| Branch | \`${info.branch}\` |`,
55
+ `| Worktree | \`${info.worktree}\` |`,
56
+ `| Worker | \`${info.tmux_session}\` |`,
57
+ `| Agent Backend | \`${info.agent_backend}\` |`,
58
+ `| Claimed At | ${new Date().toISOString()} |`,
59
+ '',
60
+ '<details><summary><b>Commands</b></summary>',
61
+ '',
62
+ '| Command | Description |',
63
+ '|---------|-------------|',
64
+ '| `@foundry go [message]` | Continue from the branch: answer a question, approve a plan, resume after a failure |',
65
+ '| `@foundry restart` | Discard the branch and start over |',
66
+ '| `@foundry stop` | Stop the agent; the branch stays |',
67
+ '',
68
+ 'Every comment on this issue is given to the agent on its next launch; only these three start or stop it. The message can be on the same line or start on the next line.',
69
+ '',
70
+ '</details>',
71
+ '<!-- /foundry-claim-block -->',
72
+ ].join('\n');
73
+ }
74
+ function parseClaimComment(body) {
75
+ if (!body.includes('<!-- foundry-claim-block -->'))
76
+ return null;
77
+ const extract = (field) => {
78
+ const re = new RegExp('\\| ' + field + ' \\| `([^`]+)` \\|');
79
+ const m = body.match(re);
80
+ return m?.[1] ?? '';
81
+ };
82
+ return {
83
+ runner_id: extract('Runner'),
84
+ branch: extract('Branch'),
85
+ worktree: extract('Worktree'),
86
+ tmux_session: extract('Worker') || extract('tmux Session'),
87
+ agent_backend: extract('Agent Backend'),
88
+ };
89
+ }
90
+ /**
91
+ * Attempt to claim an issue. Returns true if this runner owns it.
92
+ */
93
+ async function claimIssue(config, issue, claimInfo) {
94
+ const runnerId = state.getRunnerId();
95
+ // Step 1: Make in-progress the sole state label
96
+ const currentLabels = issue.labels.map(l => l.name);
97
+ await (0, labels_js_1.setStateLabel)(config, issue.number, 'in_progress', currentLabels);
98
+ // Step 2: Post claim comment
99
+ await github.addComment(config.repo, issue.number, buildClaimComment(claimInfo));
100
+ // Step 3: Verify — re-fetch issue and check our claim is the active one
101
+ await sleep(1000); // brief delay to avoid race
102
+ const comments = await github.getComments(config.repo, issue.number);
103
+ const claimComments = comments
104
+ .filter(c => c.body.includes('<!-- foundry-claim-block -->'))
105
+ .sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
106
+ if (claimComments.length === 0)
107
+ return false;
108
+ const latestClaim = parseClaimComment(claimComments[0].body);
109
+ if (!latestClaim)
110
+ return false;
111
+ return latestClaim.runner_id === runnerId;
112
+ }
113
+ /**
114
+ * Check if issue is already claimed by this runner.
115
+ */
116
+ function isClaimedByUs(config, issue) {
117
+ const tasks = state.getAllTasks(config.repo);
118
+ return tasks.some(t => t.issue === issue && !['done', 'failed', 'stopped'].includes(t.status));
119
+ }
120
+ /**
121
+ * Mark an issue as failed on GitHub: `failed` becomes the sole state label.
122
+ */
123
+ async function markFailed(config, issue) {
124
+ await (0, labels_js_1.setStateLabel)(config, issue, 'failed');
125
+ }
126
+ function sleep(ms) {
127
+ return new Promise(resolve => setTimeout(resolve, ms));
128
+ }
129
+ //# sourceMappingURL=claim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim.js","sourceRoot":"","sources":["../../src/lib/claim.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CA,8CAcC;AAKD,gCA4BC;AAKD,sCAGC;AAKD,gCAEC;AA3GD;;GAEG;AACH,oDAAsC;AACtC,kDAAoC;AACpC,2CAA4C;AAW5C,SAAS,iBAAiB,CAAC,IAAe;IACxC,OAAO;QACL,8BAA8B;QAC9B,mBAAmB;QACnB,EAAE;QACF,mBAAmB;QACnB,mBAAmB;QACnB,gBAAgB,IAAI,CAAC,SAAS,MAAM;QACpC,gBAAgB,IAAI,CAAC,MAAM,MAAM;QACjC,kBAAkB,IAAI,CAAC,QAAQ,MAAM;QACrC,gBAAgB,IAAI,CAAC,YAAY,MAAM;QACvC,uBAAuB,IAAI,CAAC,aAAa,MAAM;QAC/C,kBAAkB,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI;QAC9C,EAAE;QACF,6CAA6C;QAC7C,EAAE;QACF,2BAA2B;QAC3B,2BAA2B;QAC3B,mHAAmH;QACnH,4DAA4D;QAC5D,wDAAwD;QACxD,EAAE;QACF,yKAAyK;QACzK,EAAE;QACF,YAAY;QACZ,+BAA+B;KAChC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,SAAgB,iBAAiB,CAAC,IAAY;IAC5C,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,8BAA8B,CAAC;QAAE,OAAO,IAAI,CAAC;IAChE,MAAM,OAAO,GAAG,CAAC,KAAa,EAAU,EAAE;QACxC,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,MAAM,GAAG,KAAK,GAAG,oBAAoB,CAAC,CAAC;QAC7D,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzB,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC;IACF,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC;QAC5B,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC;QACzB,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC;QAC7B,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC;QAC1D,aAAa,EAAE,OAAO,CAAC,eAAe,CAAC;KACxC,CAAC;AACJ,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,UAAU,CAC9B,MAAqB,EACrB,KAAkB,EAClB,SAAoB;IAEpB,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAErC,gDAAgD;IAChD,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,IAAA,yBAAa,EAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;IAExE,6BAA6B;IAC7B,MAAM,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC;IAEjF,wEAAwE;IACxE,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,4BAA4B;IAE/C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACrE,MAAM,aAAa,GAAG,QAAQ;SAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,8BAA8B,CAAC,CAAC;SAC5D,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;IAEvF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE7C,MAAM,WAAW,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC7D,IAAI,CAAC,WAAW;QAAE,OAAO,KAAK,CAAC;IAE/B,OAAO,WAAW,CAAC,SAAS,KAAK,QAAQ,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,MAAqB,EAAE,KAAa;IAChE,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AACjG,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,UAAU,CAAC,MAAqB,EAAE,KAAa;IACnE,MAAM,IAAA,yBAAa,EAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AACzD,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { FoundryConfig, TaskState } from '../types.js';
2
+ import type { AgentCompletedEvent } from './events.js';
3
+ export declare function agentLogPath(config: FoundryConfig, issue: number): string;
4
+ export declare function buildAgentCompletedEvent(config: FoundryConfig, repoDir: string, task: TaskState, exitCode?: number | null): AgentCompletedEvent;
5
+ //# sourceMappingURL=completion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/lib/completion.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGvD,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,EACf,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GACvB,mBAAmB,CASrB"}