@wildorder/nightshift 0.4.0 → 0.6.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.
- package/dist/author.d.ts +3 -0
- package/dist/author.d.ts.map +1 -1
- package/dist/author.js +169 -18
- package/dist/author.js.map +1 -1
- package/dist/ci-init.d.ts +51 -0
- package/dist/ci-init.d.ts.map +1 -0
- package/dist/ci-init.js +274 -0
- package/dist/ci-init.js.map +1 -0
- package/dist/cli.js +99 -11
- package/dist/cli.js.map +1 -1
- package/dist/decide.d.ts.map +1 -1
- package/dist/decide.js +1 -1
- package/dist/decide.js.map +1 -1
- package/dist/exit-codes.d.ts +44 -0
- package/dist/exit-codes.d.ts.map +1 -0
- package/dist/exit-codes.js +49 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/findings.d.ts +3 -21
- package/dist/findings.d.ts.map +1 -1
- package/dist/findings.js +0 -7
- package/dist/findings.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/program-branch.d.ts +65 -0
- package/dist/program-branch.d.ts.map +1 -0
- package/dist/program-branch.js +123 -0
- package/dist/program-branch.js.map +1 -0
- package/dist/publish.d.ts +105 -0
- package/dist/publish.d.ts.map +1 -0
- package/dist/publish.js +549 -0
- package/dist/publish.js.map +1 -0
- package/dist/report-path.d.ts +7 -0
- package/dist/report-path.d.ts.map +1 -0
- package/dist/report-path.js +10 -0
- package/dist/report-path.js.map +1 -0
- package/dist/review-pass.d.ts +64 -0
- package/dist/review-pass.d.ts.map +1 -0
- package/dist/review-pass.js +370 -0
- package/dist/review-pass.js.map +1 -0
- package/dist/run-program.d.ts +18 -0
- package/dist/run-program.d.ts.map +1 -1
- package/dist/run-program.js +369 -28
- package/dist/run-program.js.map +1 -1
- package/dist/run-publish.d.ts +41 -0
- package/dist/run-publish.d.ts.map +1 -0
- package/dist/run-publish.js +33 -0
- package/dist/run-publish.js.map +1 -0
- package/package.json +4 -3
- package/skills/plan-program/SKILL.md +14 -0
package/dist/publish.js
ADDED
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { sanitizedEnvironment } from "./agent-runner.js";
|
|
7
|
+
import { readDecisionLedger } from "./decision-ledger.js";
|
|
8
|
+
import { loadManifest } from "./manifest.js";
|
|
9
|
+
import { detectDefaultBranch, programBranchName } from "./program-branch.js";
|
|
10
|
+
import { runReportPath } from "./report-path.js";
|
|
11
|
+
const execFileAsync = promisify(execFile);
|
|
12
|
+
/**
|
|
13
|
+
* The handover from a finished run to a reviewable pull request: pushes the
|
|
14
|
+
* program branch, opens or updates exactly one draft PR through `gh`,
|
|
15
|
+
* renders the run report as its body (continuing oversized reports into
|
|
16
|
+
* comments), and upserts one comment per escalated decision. Idempotent —
|
|
17
|
+
* re-publishing edits the existing PR and its comments rather than
|
|
18
|
+
* duplicating them.
|
|
19
|
+
*
|
|
20
|
+
* `publish` is deliberately separate from `runProgram`: the runner owns
|
|
21
|
+
* commits and knows nothing about forges, and this command owns the forge
|
|
22
|
+
* and knows nothing about building. Authentication is entirely `gh`'s job —
|
|
23
|
+
* nightshift never reads, stores, or passes a token.
|
|
24
|
+
*/
|
|
25
|
+
// GitHub's documented maximum issue/PR body length.
|
|
26
|
+
export const GITHUB_PR_BODY_LIMIT = 65_536;
|
|
27
|
+
const REPORT_CONTINUATION_POINTER = "\n\n---\n_The run report continues in the comments below._";
|
|
28
|
+
const DEGENERATE_CUT_SUFFIX = "\n\n_… (continued)_";
|
|
29
|
+
// Reserve enough headroom that a pre-split atomic unit, plus whichever
|
|
30
|
+
// decoration (pointer or marker line) it ends up rendered with, never
|
|
31
|
+
// itself exceeds the limit.
|
|
32
|
+
const SPLIT_RESERVE = 256;
|
|
33
|
+
const MAX_ATOMIC_SECTION_LENGTH = GITHUB_PR_BODY_LIMIT - SPLIT_RESERVE;
|
|
34
|
+
export const defaultPublishGit = {
|
|
35
|
+
async currentBranch(cwd) {
|
|
36
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd });
|
|
37
|
+
return stdout.trim();
|
|
38
|
+
},
|
|
39
|
+
async commitsAhead(cwd, base, branch) {
|
|
40
|
+
const { stdout } = await execFileAsync("git", ["rev-list", "--count", `${base}..${branch}`], { cwd });
|
|
41
|
+
return Number.parseInt(stdout.trim(), 10);
|
|
42
|
+
},
|
|
43
|
+
async push(cwd, remote, branch) {
|
|
44
|
+
try {
|
|
45
|
+
await execFileAsync("git", ["push", "-u", remote, branch], { cwd });
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
const stderr = String(error.stderr ?? error.message);
|
|
49
|
+
throw new Error(`git push -u ${remote} ${branch} failed:\n${stderr.trim()}`, { cause: error });
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Spawns `gh` through the same primitives the rest of the codebase spawns
|
|
55
|
+
* subprocesses with (`spawn` + `sanitizedEnvironment()`, `windowsHide`), but
|
|
56
|
+
* keeps stdout and stderr separate — `runProcess` in `agent-runner.ts` merges
|
|
57
|
+
* them, which is fine for agent transcripts but wrong for parsing `gh`'s JSON.
|
|
58
|
+
*/
|
|
59
|
+
function runGh(cwd, args, input) {
|
|
60
|
+
return new Promise((resolvePromise, rejectPromise) => {
|
|
61
|
+
const child = spawn("gh", args, {
|
|
62
|
+
cwd,
|
|
63
|
+
windowsHide: true,
|
|
64
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
65
|
+
env: sanitizedEnvironment(),
|
|
66
|
+
});
|
|
67
|
+
let stdout = "";
|
|
68
|
+
let stderr = "";
|
|
69
|
+
child.stdout.setEncoding("utf8");
|
|
70
|
+
child.stderr.setEncoding("utf8");
|
|
71
|
+
child.stdout.on("data", (chunk) => {
|
|
72
|
+
stdout += chunk;
|
|
73
|
+
});
|
|
74
|
+
child.stderr.on("data", (chunk) => {
|
|
75
|
+
stderr += chunk;
|
|
76
|
+
});
|
|
77
|
+
child.on("error", rejectPromise);
|
|
78
|
+
child.on("close", (code) => {
|
|
79
|
+
resolvePromise({ exitCode: code ?? 1, stdout, stderr });
|
|
80
|
+
});
|
|
81
|
+
if (input !== undefined)
|
|
82
|
+
child.stdin.end(input);
|
|
83
|
+
else
|
|
84
|
+
child.stdin.end();
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
async function withTempBodyFile(body, fn) {
|
|
88
|
+
const dir = await mkdtemp(join(tmpdir(), "nightshift-publish-"));
|
|
89
|
+
const file = join(dir, "body.md");
|
|
90
|
+
await writeFile(file, body, "utf8");
|
|
91
|
+
try {
|
|
92
|
+
return await fn(file);
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
await rm(dir, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function ghErrorMessage(action, result) {
|
|
99
|
+
const detail = result.stderr.trim() || result.stdout.trim();
|
|
100
|
+
return `${action} failed:\n${detail}`;
|
|
101
|
+
}
|
|
102
|
+
function normalizeState(raw) {
|
|
103
|
+
const value = raw.toLowerCase();
|
|
104
|
+
if (value === "open" || value === "closed" || value === "merged")
|
|
105
|
+
return value;
|
|
106
|
+
throw new Error(`gh reported an unrecognized pull request state "${raw}"`);
|
|
107
|
+
}
|
|
108
|
+
export const defaultGhClient = {
|
|
109
|
+
async checkAuth(cwd) {
|
|
110
|
+
let result;
|
|
111
|
+
try {
|
|
112
|
+
result = await runGh(cwd, ["auth", "status"]);
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (error.code === "ENOENT") {
|
|
116
|
+
throw new Error("The GitHub CLI (gh) is not installed or not on PATH. Install it " +
|
|
117
|
+
"from https://cli.github.com and run `gh auth login`, then " +
|
|
118
|
+
"re-run publish.", { cause: error });
|
|
119
|
+
}
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
if (result.exitCode !== 0) {
|
|
123
|
+
throw new Error("gh is not authenticated. Run `gh auth login` (or set GH_TOKEN in " +
|
|
124
|
+
"CI), then re-run publish.");
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
async findOpenPullRequest(cwd, headBranch) {
|
|
128
|
+
const result = await runGh(cwd, [
|
|
129
|
+
"pr",
|
|
130
|
+
"list",
|
|
131
|
+
"--head",
|
|
132
|
+
headBranch,
|
|
133
|
+
"--state",
|
|
134
|
+
"open",
|
|
135
|
+
"--json",
|
|
136
|
+
"number,url,state,isDraft",
|
|
137
|
+
"--limit",
|
|
138
|
+
"1",
|
|
139
|
+
]);
|
|
140
|
+
if (result.exitCode !== 0) {
|
|
141
|
+
throw new Error(ghErrorMessage("gh pr list", result));
|
|
142
|
+
}
|
|
143
|
+
const parsed = JSON.parse(result.stdout);
|
|
144
|
+
const entry = parsed[0];
|
|
145
|
+
if (!entry)
|
|
146
|
+
return undefined;
|
|
147
|
+
return {
|
|
148
|
+
number: entry.number,
|
|
149
|
+
url: entry.url,
|
|
150
|
+
state: normalizeState(entry.state),
|
|
151
|
+
isDraft: entry.isDraft,
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
async createDraftPullRequest(cwd, input) {
|
|
155
|
+
await withTempBodyFile(input.body, async (bodyFile) => {
|
|
156
|
+
const result = await runGh(cwd, [
|
|
157
|
+
"pr",
|
|
158
|
+
"create",
|
|
159
|
+
"--draft",
|
|
160
|
+
"--head",
|
|
161
|
+
input.headBranch,
|
|
162
|
+
"--base",
|
|
163
|
+
input.baseBranch,
|
|
164
|
+
"--title",
|
|
165
|
+
input.title,
|
|
166
|
+
"--body-file",
|
|
167
|
+
bodyFile,
|
|
168
|
+
]);
|
|
169
|
+
if (result.exitCode !== 0) {
|
|
170
|
+
throw new Error(ghErrorMessage("gh pr create", result));
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
const view = await runGh(cwd, [
|
|
174
|
+
"pr",
|
|
175
|
+
"view",
|
|
176
|
+
input.headBranch,
|
|
177
|
+
"--json",
|
|
178
|
+
"number,url,state,isDraft",
|
|
179
|
+
]);
|
|
180
|
+
if (view.exitCode !== 0) {
|
|
181
|
+
throw new Error(ghErrorMessage("gh pr view (after create)", view));
|
|
182
|
+
}
|
|
183
|
+
const parsed = JSON.parse(view.stdout);
|
|
184
|
+
return {
|
|
185
|
+
number: parsed.number,
|
|
186
|
+
url: parsed.url,
|
|
187
|
+
state: normalizeState(parsed.state),
|
|
188
|
+
isDraft: parsed.isDraft,
|
|
189
|
+
};
|
|
190
|
+
},
|
|
191
|
+
async updatePullRequestBody(cwd, number, body) {
|
|
192
|
+
await withTempBodyFile(body, async (bodyFile) => {
|
|
193
|
+
const result = await runGh(cwd, [
|
|
194
|
+
"pr",
|
|
195
|
+
"edit",
|
|
196
|
+
String(number),
|
|
197
|
+
"--body-file",
|
|
198
|
+
bodyFile,
|
|
199
|
+
]);
|
|
200
|
+
if (result.exitCode !== 0) {
|
|
201
|
+
throw new Error(ghErrorMessage("gh pr edit", result));
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
},
|
|
205
|
+
async listComments(cwd, number) {
|
|
206
|
+
const result = await runGh(cwd, [
|
|
207
|
+
"api",
|
|
208
|
+
"--paginate",
|
|
209
|
+
`repos/{owner}/{repo}/issues/${number}/comments`,
|
|
210
|
+
]);
|
|
211
|
+
if (result.exitCode !== 0) {
|
|
212
|
+
throw new Error(ghErrorMessage("gh api (list comments)", result));
|
|
213
|
+
}
|
|
214
|
+
const parsed = JSON.parse(result.stdout);
|
|
215
|
+
return parsed.map((entry) => ({ id: String(entry.id), body: entry.body }));
|
|
216
|
+
},
|
|
217
|
+
async createComment(cwd, number, body) {
|
|
218
|
+
await withTempBodyFile(body, async (bodyFile) => {
|
|
219
|
+
const result = await runGh(cwd, [
|
|
220
|
+
"pr",
|
|
221
|
+
"comment",
|
|
222
|
+
String(number),
|
|
223
|
+
"--body-file",
|
|
224
|
+
bodyFile,
|
|
225
|
+
]);
|
|
226
|
+
if (result.exitCode !== 0) {
|
|
227
|
+
throw new Error(ghErrorMessage("gh pr comment", result));
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
},
|
|
231
|
+
async updateComment(cwd, commentId, body) {
|
|
232
|
+
await withTempBodyFile(body, async (bodyFile) => {
|
|
233
|
+
const result = await runGh(cwd, [
|
|
234
|
+
"api",
|
|
235
|
+
"-X",
|
|
236
|
+
"PATCH",
|
|
237
|
+
`repos/{owner}/{repo}/issues/comments/${commentId}`,
|
|
238
|
+
"-F",
|
|
239
|
+
`body=@${bodyFile}`,
|
|
240
|
+
]);
|
|
241
|
+
if (result.exitCode !== 0) {
|
|
242
|
+
throw new Error(ghErrorMessage("gh api (update comment)", result));
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
},
|
|
246
|
+
async deleteComment(cwd, commentId) {
|
|
247
|
+
const result = await runGh(cwd, [
|
|
248
|
+
"api",
|
|
249
|
+
"-X",
|
|
250
|
+
"DELETE",
|
|
251
|
+
`repos/{owner}/{repo}/issues/comments/${commentId}`,
|
|
252
|
+
]);
|
|
253
|
+
if (result.exitCode !== 0) {
|
|
254
|
+
throw new Error(ghErrorMessage("gh api (delete comment)", result));
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
const SECTION_BOUNDARY_RE = /^#{2,3} .*/gmu;
|
|
259
|
+
/** Splits the report into contiguous slices at `## `/`### ` heading lines. */
|
|
260
|
+
function splitIntoSections(report) {
|
|
261
|
+
const boundaries = [];
|
|
262
|
+
for (const match of report.matchAll(SECTION_BOUNDARY_RE)) {
|
|
263
|
+
if (match.index !== undefined)
|
|
264
|
+
boundaries.push(match.index);
|
|
265
|
+
}
|
|
266
|
+
if (boundaries.length === 0)
|
|
267
|
+
return [report];
|
|
268
|
+
const sections = [];
|
|
269
|
+
let start = 0;
|
|
270
|
+
for (const boundary of boundaries) {
|
|
271
|
+
if (boundary > start)
|
|
272
|
+
sections.push(report.slice(start, boundary));
|
|
273
|
+
start = boundary;
|
|
274
|
+
}
|
|
275
|
+
sections.push(report.slice(start));
|
|
276
|
+
return sections;
|
|
277
|
+
}
|
|
278
|
+
/** Splits `text` into pieces at `delimiterRe` matches, delimiters kept with the preceding piece. */
|
|
279
|
+
function splitPreservingDelimiter(text, delimiterRe) {
|
|
280
|
+
const flags = delimiterRe.flags.includes("g")
|
|
281
|
+
? delimiterRe.flags
|
|
282
|
+
: `${delimiterRe.flags}g`;
|
|
283
|
+
const re = new RegExp(delimiterRe.source, flags);
|
|
284
|
+
const parts = [];
|
|
285
|
+
let lastIndex = 0;
|
|
286
|
+
for (const match of text.matchAll(re)) {
|
|
287
|
+
const end = (match.index ?? 0) + match[0].length;
|
|
288
|
+
parts.push(text.slice(lastIndex, end));
|
|
289
|
+
lastIndex = end;
|
|
290
|
+
}
|
|
291
|
+
if (lastIndex < text.length)
|
|
292
|
+
parts.push(text.slice(lastIndex));
|
|
293
|
+
return parts;
|
|
294
|
+
}
|
|
295
|
+
/** Greedily packs verbatim units into pieces no longer than `maxSize`. */
|
|
296
|
+
function packAtomic(units, maxSize) {
|
|
297
|
+
const pieces = [];
|
|
298
|
+
let current = "";
|
|
299
|
+
for (const unit of units) {
|
|
300
|
+
if (current !== "" && (current + unit).length > maxSize) {
|
|
301
|
+
pieces.push(current);
|
|
302
|
+
current = "";
|
|
303
|
+
}
|
|
304
|
+
current += unit;
|
|
305
|
+
}
|
|
306
|
+
if (current !== "")
|
|
307
|
+
pieces.push(current);
|
|
308
|
+
return pieces;
|
|
309
|
+
}
|
|
310
|
+
function chunkString(text, size) {
|
|
311
|
+
const out = [];
|
|
312
|
+
for (let i = 0; i < text.length; i += size)
|
|
313
|
+
out.push(text.slice(i, i + size));
|
|
314
|
+
return out;
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* A single section larger than the limit on its own cannot be split on a
|
|
318
|
+
* heading. Falls back to a paragraph (blank-line) boundary, and if even a
|
|
319
|
+
* paragraph exceeds the limit, a hard character boundary. Last resort only.
|
|
320
|
+
*/
|
|
321
|
+
function expandOversizedSection(section) {
|
|
322
|
+
if (section.length <= MAX_ATOMIC_SECTION_LENGTH) {
|
|
323
|
+
return [{ text: section, cutMidSection: false }];
|
|
324
|
+
}
|
|
325
|
+
const paragraphs = splitPreservingDelimiter(section, /\n\n+/u);
|
|
326
|
+
let pieces = packAtomic(paragraphs, MAX_ATOMIC_SECTION_LENGTH);
|
|
327
|
+
if (pieces.some((piece) => piece.length > MAX_ATOMIC_SECTION_LENGTH)) {
|
|
328
|
+
pieces = pieces.flatMap((piece) => piece.length <= MAX_ATOMIC_SECTION_LENGTH
|
|
329
|
+
? [piece]
|
|
330
|
+
: chunkString(piece, MAX_ATOMIC_SECTION_LENGTH));
|
|
331
|
+
}
|
|
332
|
+
return pieces.map((text, index) => ({
|
|
333
|
+
text,
|
|
334
|
+
cutMidSection: index < pieces.length - 1,
|
|
335
|
+
}));
|
|
336
|
+
}
|
|
337
|
+
function continuationMarkerLine(index) {
|
|
338
|
+
return `<!-- nightshift:report-continuation:${index} -->\n`;
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Splits the run report into chunks whose payloads are verbatim, contiguous
|
|
342
|
+
* slices of the report — concatenating every payload in order reproduces the
|
|
343
|
+
* report byte-for-byte. A report that fits under the limit is a single
|
|
344
|
+
* chunk; an oversized report is packed on section boundaries, falling back
|
|
345
|
+
* to paragraph/character boundaries only for a section too large on its own.
|
|
346
|
+
*/
|
|
347
|
+
export function splitReportIntoChunks(report) {
|
|
348
|
+
if (report.length <= GITHUB_PR_BODY_LIMIT) {
|
|
349
|
+
return [{ payload: report, cutMidSection: false }];
|
|
350
|
+
}
|
|
351
|
+
const sections = splitIntoSections(report).flatMap(expandOversizedSection);
|
|
352
|
+
const chunks = [];
|
|
353
|
+
let current = "";
|
|
354
|
+
let currentCut = false;
|
|
355
|
+
let index = 0;
|
|
356
|
+
while (index < sections.length) {
|
|
357
|
+
const section = sections[index];
|
|
358
|
+
if (section === undefined)
|
|
359
|
+
break;
|
|
360
|
+
const overhead = chunks.length === 0
|
|
361
|
+
? REPORT_CONTINUATION_POINTER.length
|
|
362
|
+
: continuationMarkerLine(chunks.length).length;
|
|
363
|
+
const candidateLength = current.length + section.text.length + overhead;
|
|
364
|
+
if (candidateLength > GITHUB_PR_BODY_LIMIT && current !== "") {
|
|
365
|
+
chunks.push({ payload: current, cutMidSection: currentCut });
|
|
366
|
+
current = "";
|
|
367
|
+
currentCut = false;
|
|
368
|
+
continue;
|
|
369
|
+
}
|
|
370
|
+
current += section.text;
|
|
371
|
+
currentCut = section.cutMidSection;
|
|
372
|
+
index += 1;
|
|
373
|
+
}
|
|
374
|
+
if (current !== "")
|
|
375
|
+
chunks.push({ payload: current, cutMidSection: currentCut });
|
|
376
|
+
return chunks;
|
|
377
|
+
}
|
|
378
|
+
function renderChunk(chunks, index) {
|
|
379
|
+
const chunk = chunks[index];
|
|
380
|
+
if (!chunk)
|
|
381
|
+
throw new Error(`chunk index ${index} out of range`);
|
|
382
|
+
const isLast = index === chunks.length - 1;
|
|
383
|
+
const suffix = !isLast && chunk.cutMidSection ? DEGENERATE_CUT_SUFFIX : "";
|
|
384
|
+
if (index === 0) {
|
|
385
|
+
const pointer = chunks.length > 1 ? REPORT_CONTINUATION_POINTER : "";
|
|
386
|
+
return chunk.payload + suffix + pointer;
|
|
387
|
+
}
|
|
388
|
+
return `${continuationMarkerLine(index)}${chunk.payload}${suffix}`;
|
|
389
|
+
}
|
|
390
|
+
// ---- comment identity and upsert --------------------------------------
|
|
391
|
+
function decisionMarker(fingerprint) {
|
|
392
|
+
return `nightshift:decision:${fingerprint}`;
|
|
393
|
+
}
|
|
394
|
+
function markerLine(marker) {
|
|
395
|
+
return `<!-- ${marker} -->`;
|
|
396
|
+
}
|
|
397
|
+
const MARKER_RE = /^<!-- (nightshift:(?:decision|report-continuation):\S+) -->/u;
|
|
398
|
+
function extractMarker(body) {
|
|
399
|
+
const firstLine = (body.split(/\r?\n/u)[0] ?? "").trim();
|
|
400
|
+
return MARKER_RE.exec(firstLine)?.[1];
|
|
401
|
+
}
|
|
402
|
+
/** POSIX single-quote escaping: wraps in `'...'`, replacing each `'` with `'\''`. */
|
|
403
|
+
function shellQuoteSingle(value) {
|
|
404
|
+
return `'${value.replaceAll("'", String.raw `'\''`)}'`;
|
|
405
|
+
}
|
|
406
|
+
function decideAlternativesSection(programId, record) {
|
|
407
|
+
const currentChoice = record.humanChosen ?? record.decision.chosen;
|
|
408
|
+
const alternatives = record.decision.options.filter((option) => option.label !== currentChoice);
|
|
409
|
+
if (alternatives.length === 0)
|
|
410
|
+
return [];
|
|
411
|
+
const lines = ["To flip this decision:", ""];
|
|
412
|
+
for (const option of alternatives) {
|
|
413
|
+
const reason = `Overriding nightshift's choice for "${record.decision.title}" after review`;
|
|
414
|
+
const command = `npx --yes @wildorder/nightshift decide ${programId} ${record.id} ` +
|
|
415
|
+
`--choose ${shellQuoteSingle(option.label)} --reason ${shellQuoteSingle(reason)}`;
|
|
416
|
+
lines.push("```", command, "```", "");
|
|
417
|
+
}
|
|
418
|
+
return lines;
|
|
419
|
+
}
|
|
420
|
+
function renderEscalationComment(programId, record) {
|
|
421
|
+
const lines = [
|
|
422
|
+
markerLine(decisionMarker(record.id)),
|
|
423
|
+
`### ${record.decision.title}`,
|
|
424
|
+
"",
|
|
425
|
+
`- **Workstream:** ${record.workstream}`,
|
|
426
|
+
`- **Chosen:** ${record.decision.chosen}`,
|
|
427
|
+
`- **Decider says:** ${record.reviewRationale ?? "(no rationale recorded)"}`,
|
|
428
|
+
...(record.baseCommit
|
|
429
|
+
? [`- **Anchor commit:** \`${record.baseCommit}\``]
|
|
430
|
+
: []),
|
|
431
|
+
"",
|
|
432
|
+
...decideAlternativesSection(programId, record),
|
|
433
|
+
];
|
|
434
|
+
return lines.join("\n").trimEnd();
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Reconciles the PR's nightshift-authored comments to exactly the desired
|
|
438
|
+
* set: upserts every desired marker, and deletes every nightshift marker
|
|
439
|
+
* that is no longer desired (a settled decision, or a shrunk report's
|
|
440
|
+
* higher-index continuation chunk).
|
|
441
|
+
*/
|
|
442
|
+
async function reconcileComments(gh, cwd, prNumber, desired) {
|
|
443
|
+
const existing = await gh.listComments(cwd, prNumber);
|
|
444
|
+
const byMarker = new Map();
|
|
445
|
+
for (const comment of existing) {
|
|
446
|
+
const marker = extractMarker(comment.body);
|
|
447
|
+
if (marker !== undefined)
|
|
448
|
+
byMarker.set(marker, comment);
|
|
449
|
+
}
|
|
450
|
+
for (const [marker, body] of desired) {
|
|
451
|
+
const found = byMarker.get(marker);
|
|
452
|
+
if (found) {
|
|
453
|
+
if (found.body !== body)
|
|
454
|
+
await gh.updateComment(cwd, found.id, body);
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
await gh.createComment(cwd, prNumber, body);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
for (const [marker, comment] of byMarker) {
|
|
461
|
+
if (!desired.has(marker))
|
|
462
|
+
await gh.deleteComment(cwd, comment.id);
|
|
463
|
+
}
|
|
464
|
+
let escalationComments = 0;
|
|
465
|
+
let continuationComments = 0;
|
|
466
|
+
for (const marker of desired.keys()) {
|
|
467
|
+
if (marker.startsWith("nightshift:decision:"))
|
|
468
|
+
escalationComments += 1;
|
|
469
|
+
else
|
|
470
|
+
continuationComments += 1;
|
|
471
|
+
}
|
|
472
|
+
return { escalationComments, continuationComments };
|
|
473
|
+
}
|
|
474
|
+
// ---- publish ------------------------------------------------------------
|
|
475
|
+
export async function publish(options) {
|
|
476
|
+
const root = resolve(options.cwd);
|
|
477
|
+
const gh = options.gh ?? defaultGhClient;
|
|
478
|
+
const git = options.git ?? defaultPublishGit;
|
|
479
|
+
const log = options.log ?? ((line) => console.log(line));
|
|
480
|
+
// Auth preflight -> current-branch and no-run checks -> push ->
|
|
481
|
+
// create/update PR -> comments. Checked first so the common failure
|
|
482
|
+
// surfaces as one clean message instead of a confusing mid-operation error.
|
|
483
|
+
await gh.checkAuth(root);
|
|
484
|
+
const manifest = await loadManifest(root, options.programId);
|
|
485
|
+
const branch = programBranchName(options.programId);
|
|
486
|
+
const currentBranch = await git.currentBranch(root);
|
|
487
|
+
if (currentBranch !== branch) {
|
|
488
|
+
throw new Error("publish reads the run report, ledger, and manifest from the working " +
|
|
489
|
+
`tree, but HEAD is \`${currentBranch}\`, not the program branch ` +
|
|
490
|
+
`\`${branch}\`. Check out \`${branch}\` (\`git switch ${branch}\`) ` +
|
|
491
|
+
"and re-run publish.");
|
|
492
|
+
}
|
|
493
|
+
const base = await detectDefaultBranch(root);
|
|
494
|
+
let report;
|
|
495
|
+
try {
|
|
496
|
+
report = await readFile(runReportPath(root, options.programId), "utf8");
|
|
497
|
+
}
|
|
498
|
+
catch {
|
|
499
|
+
throw new Error(`Program ${options.programId} has no run report at ` +
|
|
500
|
+
`\`docs/programs/${options.programId}-run-report.md\`; it has not ` +
|
|
501
|
+
"been run yet. Run the program first: `npx --yes " +
|
|
502
|
+
`@wildorder/nightshift run ${options.programId}\`.`);
|
|
503
|
+
}
|
|
504
|
+
const commitsAhead = await git.commitsAhead(root, base, branch);
|
|
505
|
+
if (commitsAhead === 0) {
|
|
506
|
+
throw new Error(`Program ${options.programId} has no commits on \`${branch}\` beyond ` +
|
|
507
|
+
`\`${base}\`; there is nothing to publish.`);
|
|
508
|
+
}
|
|
509
|
+
await git.push(root, "origin", branch);
|
|
510
|
+
log(`pushed ${branch} to origin`);
|
|
511
|
+
const chunks = splitReportIntoChunks(report);
|
|
512
|
+
const body = renderChunk(chunks, 0);
|
|
513
|
+
const title = `${manifest.program.name} (${options.programId})`;
|
|
514
|
+
const existing = await gh.findOpenPullRequest(root, branch);
|
|
515
|
+
let prNumber;
|
|
516
|
+
let prUrl;
|
|
517
|
+
let action;
|
|
518
|
+
if (existing) {
|
|
519
|
+
await gh.updatePullRequestBody(root, existing.number, body);
|
|
520
|
+
prNumber = existing.number;
|
|
521
|
+
prUrl = existing.url;
|
|
522
|
+
action = "updated";
|
|
523
|
+
log(`updated PR #${prNumber}`);
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
const created = await gh.createDraftPullRequest(root, {
|
|
527
|
+
headBranch: branch,
|
|
528
|
+
baseBranch: base,
|
|
529
|
+
title,
|
|
530
|
+
body,
|
|
531
|
+
});
|
|
532
|
+
prNumber = created.number;
|
|
533
|
+
prUrl = created.url;
|
|
534
|
+
action = "created";
|
|
535
|
+
log(`created draft PR #${prNumber}: ${prUrl}`);
|
|
536
|
+
}
|
|
537
|
+
const ledger = await readDecisionLedger(root, options.programId);
|
|
538
|
+
const escalations = ledger.decisions.filter((record) => record.status === "escalated");
|
|
539
|
+
const desired = new Map();
|
|
540
|
+
for (const record of escalations) {
|
|
541
|
+
desired.set(decisionMarker(record.id), renderEscalationComment(options.programId, record));
|
|
542
|
+
}
|
|
543
|
+
for (let index = 1; index < chunks.length; index += 1) {
|
|
544
|
+
desired.set(`nightshift:report-continuation:${index}`, renderChunk(chunks, index));
|
|
545
|
+
}
|
|
546
|
+
const { escalationComments, continuationComments } = await reconcileComments(gh, root, prNumber, desired);
|
|
547
|
+
return { prNumber, prUrl, action, escalationComments, continuationComments };
|
|
548
|
+
}
|
|
549
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../src/publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single source of the run report's location on disk. `run-program.ts`
|
|
3
|
+
* writes here; `publish.ts` reads from here — importing this instead of
|
|
4
|
+
* re-deriving the path keeps the two from drifting apart.
|
|
5
|
+
*/
|
|
6
|
+
export declare function runReportPath(root: string, programId: string): string;
|
|
7
|
+
//# sourceMappingURL=report-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-path.d.ts","sourceRoot":"","sources":["../src/report-path.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAErE"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* The single source of the run report's location on disk. `run-program.ts`
|
|
4
|
+
* writes here; `publish.ts` reads from here — importing this instead of
|
|
5
|
+
* re-deriving the path keeps the two from drifting apart.
|
|
6
|
+
*/
|
|
7
|
+
export function runReportPath(root, programId) {
|
|
8
|
+
return join(root, "docs", "programs", `${programId}-run-report.md`);
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=report-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report-path.js","sourceRoot":"","sources":["../src/report-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,SAAiB;IAC3D,OAAO,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS,gBAAgB,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type Finding, type Severity } from "./findings.js";
|
|
2
|
+
import type { LedgerEvent } from "./decision-ledger.js";
|
|
3
|
+
export interface ParsedFindings {
|
|
4
|
+
findings: Finding[];
|
|
5
|
+
/** Malformed entries/blocks, described. Never fatal — reported to the run report. */
|
|
6
|
+
errors: string[];
|
|
7
|
+
}
|
|
8
|
+
/** Every fenced ```findings block in an agent's output, in order. */
|
|
9
|
+
export declare function extractFindings(output: string): ParsedFindings;
|
|
10
|
+
/** The ```findings block-format instructions, composed into every reviewer brief. */
|
|
11
|
+
export declare function findingsContract(): string;
|
|
12
|
+
export type FindingDestination = "decision-oneway" | "decision" | "report";
|
|
13
|
+
/**
|
|
14
|
+
* blocker -> "decision-oneway" (a decision recorded reversible:false — a one-way door)
|
|
15
|
+
* major -> "decision" (an ordinary reversible, risk-accepted decision)
|
|
16
|
+
* minor -> "report" (the run report only)
|
|
17
|
+
* advisory -> "report"
|
|
18
|
+
*/
|
|
19
|
+
export declare function findingDestination(severity: Severity): FindingDestination;
|
|
20
|
+
export declare const REVIEW_ROUND_CAP = 2;
|
|
21
|
+
export type StopReason = "converged" | "cap-reached" | "reviewer-error" | "no-reviewer";
|
|
22
|
+
export interface ReviewRoundResult {
|
|
23
|
+
findings: Finding[];
|
|
24
|
+
errors: string[];
|
|
25
|
+
ran: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface ReviewPassOutcome {
|
|
28
|
+
ran: boolean;
|
|
29
|
+
roundsRun: number;
|
|
30
|
+
stopReason: StopReason;
|
|
31
|
+
open: Finding[];
|
|
32
|
+
resolved: Finding[];
|
|
33
|
+
errors: string[];
|
|
34
|
+
writerNotes: string[];
|
|
35
|
+
severityCounts: Record<Severity, number>;
|
|
36
|
+
}
|
|
37
|
+
export interface RunReviewPassOptions {
|
|
38
|
+
cap?: number;
|
|
39
|
+
/** Invoke the reviewer for round `n`; parse and return its findings. Stage-owned. */
|
|
40
|
+
review: (round: number, priorOpen: Finding[]) => Promise<ReviewRoundResult>;
|
|
41
|
+
/** Re-brief the writer with this round's findings; return its prose reply. Stage-owned. */
|
|
42
|
+
respond: (round: number, findings: Finding[]) => Promise<{
|
|
43
|
+
note?: string;
|
|
44
|
+
}>;
|
|
45
|
+
}
|
|
46
|
+
/** The pass a stage records when no reviewerAgent is configured (SC-08). */
|
|
47
|
+
export declare function reviewerAbsentOutcome(): ReviewPassOutcome;
|
|
48
|
+
export declare function runReviewPass(options: RunReviewPassOptions): Promise<ReviewPassOutcome>;
|
|
49
|
+
export interface FindingsToLedgerOptions {
|
|
50
|
+
workstreamId: string;
|
|
51
|
+
findings: readonly Finding[];
|
|
52
|
+
baseCommit?: string;
|
|
53
|
+
now: () => Date;
|
|
54
|
+
}
|
|
55
|
+
/** Blocker/major findings -> decision-recorded events; minor/advisory dropped (report-only). */
|
|
56
|
+
export declare function findingsToLedgerEvents(options: FindingsToLedgerOptions): LedgerEvent[];
|
|
57
|
+
/**
|
|
58
|
+
* A human-facing summary of one completed (or absent) pass, for the run
|
|
59
|
+
* report. `label` is the pass name the stage supplies ("Spec critique",
|
|
60
|
+
* "Test critique"). Returns markdown lines; the caller splices them under
|
|
61
|
+
* its own section heading.
|
|
62
|
+
*/
|
|
63
|
+
export declare function renderPassReport(label: string, outcome: ReviewPassOutcome): string[];
|
|
64
|
+
//# sourceMappingURL=review-pass.d.ts.map
|