@wildorder/nightshift 0.3.0 → 0.4.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/README.md +48 -1
- package/dist/agent-runner.d.ts +18 -0
- package/dist/agent-runner.d.ts.map +1 -1
- package/dist/agent-runner.js +26 -0
- package/dist/agent-runner.js.map +1 -1
- package/dist/author.d.ts +61 -0
- package/dist/author.d.ts.map +1 -0
- package/dist/author.js +476 -0
- package/dist/author.js.map +1 -0
- package/dist/cli.js +110 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +14 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -1
- package/dist/config.js.map +1 -1
- package/dist/decide.d.ts +49 -0
- package/dist/decide.d.ts.map +1 -0
- package/dist/decide.js +178 -0
- package/dist/decide.js.map +1 -0
- package/dist/decider-review.d.ts +21 -0
- package/dist/decider-review.d.ts.map +1 -0
- package/dist/decider-review.js +98 -0
- package/dist/decider-review.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +2 -0
- package/dist/manifest.d.ts.map +1 -1
- package/dist/manifest.js +2 -0
- package/dist/manifest.js.map +1 -1
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +18 -1
- package/dist/prompt.js.map +1 -1
- package/dist/run-program.d.ts +8 -0
- package/dist/run-program.d.ts.map +1 -1
- package/dist/run-program.js +156 -112
- package/dist/run-program.js.map +1 -1
- package/package.json +2 -1
package/dist/author.js
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { defaultAgentRunner, describeAgent, invokeAgent, resolveAuthorAgent, resolveDeciderAgent, } from "./agent-runner.js";
|
|
4
|
+
import { resolveSummary, summaryContract } from "./agent-summary.js";
|
|
5
|
+
import { decisionContract, decisionFingerprint, extractDecisions, } from "./decision.js";
|
|
6
|
+
import { appendLedgerEvents } from "./decision-ledger.js";
|
|
7
|
+
import { reviewDecisions } from "./decider-review.js";
|
|
8
|
+
import { findCycles, topologicalLevels } from "./graph.js";
|
|
9
|
+
import { loadManifest, saveManifest, } from "./manifest.js";
|
|
10
|
+
import { defaultGitOps, downstreamCone } from "./run-program.js";
|
|
11
|
+
/**
|
|
12
|
+
* The authoring stage: for every workstream whose spec does not exist, a
|
|
13
|
+
* clean agent writes it — human-first, grounded in the repository,
|
|
14
|
+
* accounting for the manifest's success criteria — before the build stage
|
|
15
|
+
* runs. Decisions authors surface flow through the same ledger and decider
|
|
16
|
+
* review as build decisions, and dependencies an author discovers merge into
|
|
17
|
+
* the manifest rather than stopping the run. Only an unorderable graph (a
|
|
18
|
+
* merge that creates a cycle) terminates it.
|
|
19
|
+
*/
|
|
20
|
+
/** Total character budget for dependency specs included in one brief. */
|
|
21
|
+
const DEPENDENCY_SPEC_BUDGET = 100_000;
|
|
22
|
+
/** A finished spec's content, or undefined when missing or whitespace-only. */
|
|
23
|
+
async function readFinishedSpec(root, workstream) {
|
|
24
|
+
try {
|
|
25
|
+
const content = await readFile(join(root, workstream.taskFile), "utf8");
|
|
26
|
+
return content.trim() === "" ? undefined : content;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function programDocumentSection(root, manifest) {
|
|
33
|
+
const relPath = join("docs", "programs", `${manifest.program.id}-program.md`);
|
|
34
|
+
let content;
|
|
35
|
+
try {
|
|
36
|
+
content = await readFile(join(root, relPath), "utf8");
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return [
|
|
40
|
+
"## Program document",
|
|
41
|
+
"",
|
|
42
|
+
`No program document exists at ${relPath.replaceAll("\\", "/")}.`,
|
|
43
|
+
"",
|
|
44
|
+
];
|
|
45
|
+
}
|
|
46
|
+
return ["## Program document", "", content.trim(), ""];
|
|
47
|
+
}
|
|
48
|
+
function successCriteriaSection(manifest) {
|
|
49
|
+
if (manifest.successCriteria.length === 0) {
|
|
50
|
+
return ["## Success criteria", "", "None recorded in the manifest.", ""];
|
|
51
|
+
}
|
|
52
|
+
const lines = [
|
|
53
|
+
"## Success criteria",
|
|
54
|
+
"",
|
|
55
|
+
"Account in the spec for every criterion relevant to this workstream's",
|
|
56
|
+
"scope, referring to each by its id below. This list is canonical in the",
|
|
57
|
+
"manifest — refer to ids in the spec, never restate the text as a second",
|
|
58
|
+
"copy.",
|
|
59
|
+
"",
|
|
60
|
+
];
|
|
61
|
+
for (const criterion of manifest.successCriteria) {
|
|
62
|
+
lines.push(`- **${criterion.id}**: ${criterion.description}`);
|
|
63
|
+
}
|
|
64
|
+
lines.push("");
|
|
65
|
+
return lines;
|
|
66
|
+
}
|
|
67
|
+
function scopeSection(workstream) {
|
|
68
|
+
const scope = workstream.scope;
|
|
69
|
+
if (!scope)
|
|
70
|
+
return ["## Scope", "", "No scope recorded in the manifest.", ""];
|
|
71
|
+
const lines = ["## Scope", "", scope.summary, ""];
|
|
72
|
+
if (scope.includes.length > 0) {
|
|
73
|
+
lines.push("Includes:", "", ...scope.includes.map((entry) => `- ${entry}`), "");
|
|
74
|
+
}
|
|
75
|
+
if (scope.excludes.length > 0) {
|
|
76
|
+
lines.push("Excludes:", "", ...scope.excludes.map((entry) => `- ${entry}`), "");
|
|
77
|
+
}
|
|
78
|
+
return lines;
|
|
79
|
+
}
|
|
80
|
+
function rosterSection(manifest) {
|
|
81
|
+
return [
|
|
82
|
+
"## Roster",
|
|
83
|
+
"",
|
|
84
|
+
"Every workstream in the program, so you know what exists and never",
|
|
85
|
+
"write a spec that quietly absorbs a neighbor's job — it says what",
|
|
86
|
+
"exists, not how it works:",
|
|
87
|
+
"",
|
|
88
|
+
...manifest.workstreams.map((entry) => `- ${entry.id} ${entry.name}: ${entry.scope?.summary ?? entry.name}`),
|
|
89
|
+
"",
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
async function dependencySpecsSection(root, workstream, rosterById) {
|
|
93
|
+
if (workstream.dependencies.length === 0) {
|
|
94
|
+
return {
|
|
95
|
+
section: ["## Dependency specs", "", "No dependencies declared.", ""],
|
|
96
|
+
demoted: [],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
const entries = await Promise.all(workstream.dependencies
|
|
100
|
+
.map((id) => rosterById.get(id))
|
|
101
|
+
.filter((entry) => entry !== undefined)
|
|
102
|
+
.map(async (entry) => ({
|
|
103
|
+
entry,
|
|
104
|
+
content: await readFinishedSpec(root, entry),
|
|
105
|
+
})));
|
|
106
|
+
let total = entries.reduce((sum, e) => sum + (e.content?.length ?? 0), 0);
|
|
107
|
+
const demoted = new Set();
|
|
108
|
+
const bySizeDesc = entries
|
|
109
|
+
.filter((e) => e.content !== undefined)
|
|
110
|
+
.sort((a, b) => (b.content?.length ?? 0) - (a.content?.length ?? 0));
|
|
111
|
+
for (const e of bySizeDesc) {
|
|
112
|
+
if (total <= DEPENDENCY_SPEC_BUDGET)
|
|
113
|
+
break;
|
|
114
|
+
demoted.add(e.entry.id);
|
|
115
|
+
total -= e.content?.length ?? 0;
|
|
116
|
+
}
|
|
117
|
+
const lines = ["## Dependency specs", ""];
|
|
118
|
+
for (const { entry, content } of entries) {
|
|
119
|
+
const scopeSummary = entry.scope?.summary ?? entry.name;
|
|
120
|
+
if (content === undefined) {
|
|
121
|
+
lines.push(`- ${entry.id} ${entry.name}: ${scopeSummary} — no finished spec yet.`);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (demoted.has(entry.id)) {
|
|
125
|
+
lines.push(`- ${entry.id} ${entry.name}: ${scopeSummary} — its spec was too large ` +
|
|
126
|
+
"to include in full; ask for what you need in your dependencies " +
|
|
127
|
+
"declaration rather than guessing.");
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
lines.push(`### ${entry.id} ${entry.name}`, "", content.trim(), "");
|
|
131
|
+
}
|
|
132
|
+
lines.push("");
|
|
133
|
+
return { section: lines, demoted: [...demoted] };
|
|
134
|
+
}
|
|
135
|
+
const SPEC_CONTRACT = [
|
|
136
|
+
"## Write a spec for a human",
|
|
137
|
+
"",
|
|
138
|
+
"Write a narrative document for a human reader first — what this",
|
|
139
|
+
"workstream is, why it exists, how it fits the program, and the tricky",
|
|
140
|
+
"parts spelled out plainly. A suggested skeleton, offered as a",
|
|
141
|
+
"convenience and not a contract — use these headings, different ones, or",
|
|
142
|
+
"none at all, whatever serves the reader best:",
|
|
143
|
+
"",
|
|
144
|
+
"- Objective and context",
|
|
145
|
+
"- Design",
|
|
146
|
+
"- Files to create or modify",
|
|
147
|
+
"- Testing",
|
|
148
|
+
"- Definition of done",
|
|
149
|
+
"",
|
|
150
|
+
].join("\n");
|
|
151
|
+
const GROUNDING_CONTRACT = [
|
|
152
|
+
"## Ground the spec in the repository",
|
|
153
|
+
"",
|
|
154
|
+
"Explore the actual codebase before writing — entry points, signatures,",
|
|
155
|
+
"existing patterns — so the spec checks the plan's assumptions instead of",
|
|
156
|
+
"inheriting them unexamined.",
|
|
157
|
+
"",
|
|
158
|
+
].join("\n");
|
|
159
|
+
const DEPENDENCIES_CONTRACT = `
|
|
160
|
+
## Dependencies you discover (when you find one)
|
|
161
|
+
|
|
162
|
+
While grounding this spec in the repository you may find that this
|
|
163
|
+
workstream actually consumes another workstream's output, beyond what the
|
|
164
|
+
roster above already declares as a dependency. Report every such id in one
|
|
165
|
+
fenced block, anywhere in your reply before the summary:
|
|
166
|
+
|
|
167
|
+
\`\`\`dependencies
|
|
168
|
+
["WS-02", "WS-05"]
|
|
169
|
+
\`\`\`
|
|
170
|
+
|
|
171
|
+
A JSON array of workstream ids this spec depends on. Use only ids that
|
|
172
|
+
already appear in the roster — never invent a new workstream. Omit the
|
|
173
|
+
block entirely when you have nothing to add.
|
|
174
|
+
`.trim();
|
|
175
|
+
function dependenciesContract() {
|
|
176
|
+
return DEPENDENCIES_CONTRACT;
|
|
177
|
+
}
|
|
178
|
+
async function authorBrief(root, manifest, workstream, rosterById, reauthorNote) {
|
|
179
|
+
const programDoc = await programDocumentSection(root, manifest);
|
|
180
|
+
const deps = await dependencySpecsSection(root, workstream, rosterById);
|
|
181
|
+
const brief = [
|
|
182
|
+
`# Workstream ${workstream.id}: ${workstream.name}`,
|
|
183
|
+
"",
|
|
184
|
+
`Program: ${manifest.program.id} — ${manifest.program.name}`,
|
|
185
|
+
"",
|
|
186
|
+
"Write this workstream's specification document — the narrative file a",
|
|
187
|
+
"human and a later implementing agent will both read to build it.",
|
|
188
|
+
"",
|
|
189
|
+
...programDoc,
|
|
190
|
+
...successCriteriaSection(manifest),
|
|
191
|
+
...scopeSection(workstream),
|
|
192
|
+
...rosterSection(manifest),
|
|
193
|
+
...deps.section,
|
|
194
|
+
...(reauthorNote ? [reauthorNote, ""] : []),
|
|
195
|
+
SPEC_CONTRACT,
|
|
196
|
+
GROUNDING_CONTRACT,
|
|
197
|
+
dependenciesContract(),
|
|
198
|
+
"",
|
|
199
|
+
"## Rules",
|
|
200
|
+
"",
|
|
201
|
+
"- Write exactly one file: this workstream's taskFile (create parent",
|
|
202
|
+
" directories as needed). Do not write or edit any other file.",
|
|
203
|
+
"- Never commit; the runner owns commits.",
|
|
204
|
+
"",
|
|
205
|
+
decisionContract(),
|
|
206
|
+
"",
|
|
207
|
+
summaryContract(),
|
|
208
|
+
].join("\n");
|
|
209
|
+
return { brief, demoted: deps.demoted };
|
|
210
|
+
}
|
|
211
|
+
function mergeDependencies(workstream, rosterIds, declaredIds) {
|
|
212
|
+
const merged = [];
|
|
213
|
+
const unknown = [];
|
|
214
|
+
for (const id of declaredIds) {
|
|
215
|
+
if (!rosterIds.has(id)) {
|
|
216
|
+
unknown.push(id);
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
if (workstream.dependencies.includes(id))
|
|
220
|
+
continue;
|
|
221
|
+
workstream.dependencies.push(id);
|
|
222
|
+
merged.push(id);
|
|
223
|
+
}
|
|
224
|
+
return { merged, unknown };
|
|
225
|
+
}
|
|
226
|
+
const DEPENDENCIES_BLOCK_PATTERN = /```dependencies[^\S\r\n]*\r?\n([\s\S]*?)```/gu;
|
|
227
|
+
/** The last ```dependencies block in an agent's reply; tolerates garbage. */
|
|
228
|
+
function extractDependenciesDeclaration(output) {
|
|
229
|
+
const matches = [...output.matchAll(DEPENDENCIES_BLOCK_PATTERN)];
|
|
230
|
+
if (matches.length === 0)
|
|
231
|
+
return { ids: [] };
|
|
232
|
+
const body = matches[matches.length - 1]?.[1]?.trim() ?? "";
|
|
233
|
+
if (body === "")
|
|
234
|
+
return { ids: [] };
|
|
235
|
+
let json;
|
|
236
|
+
try {
|
|
237
|
+
json = JSON.parse(body);
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
return {
|
|
241
|
+
ids: [],
|
|
242
|
+
error: `dependencies block is not valid JSON: ${error.message}`,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
if (!Array.isArray(json) || !json.every((item) => typeof item === "string")) {
|
|
246
|
+
return {
|
|
247
|
+
ids: [],
|
|
248
|
+
error: "dependencies block must be a JSON array of workstream id strings",
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
return { ids: json };
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* The authoring stage: writes every missing workstream spec, one clean agent
|
|
255
|
+
* at a time, in dependency-level order. Shaped like `runProgram` — plain
|
|
256
|
+
* inputs, injected boundaries, a structured result the CLI and `run` both
|
|
257
|
+
* consume.
|
|
258
|
+
*/
|
|
259
|
+
export async function authorProgram(options) {
|
|
260
|
+
const root = resolve(options.cwd);
|
|
261
|
+
const config = options.config;
|
|
262
|
+
const agentRunner = options.agentRunner ?? defaultAgentRunner;
|
|
263
|
+
const git = options.git ?? defaultGitOps;
|
|
264
|
+
const log = options.log ?? ((line) => console.log(line));
|
|
265
|
+
const now = options.now ?? (() => new Date());
|
|
266
|
+
const only = options.only;
|
|
267
|
+
const force = options.force === true;
|
|
268
|
+
const manifest = await loadManifest(root, options.programId);
|
|
269
|
+
const resolvedAuthor = resolveAuthorAgent(config);
|
|
270
|
+
if (!resolvedAuthor) {
|
|
271
|
+
throw new Error("No author agent configured, and no implementer to fall back to. Set " +
|
|
272
|
+
"the `authorAgent` or `agent` block in nightshift.config.json.");
|
|
273
|
+
}
|
|
274
|
+
const author = resolvedAuthor.agent;
|
|
275
|
+
const borrowedImplementer = resolvedAuthor.borrowedImplementer;
|
|
276
|
+
log(borrowedImplementer
|
|
277
|
+
? `author: ${describeAgent(author)} (borrowed from the implementer — ` +
|
|
278
|
+
"configure `authorAgent` for a dedicated model)"
|
|
279
|
+
: `author: ${describeAgent(author)}`);
|
|
280
|
+
const decider = resolveDeciderAgent(config);
|
|
281
|
+
const cycles = findCycles(manifest.workstreams);
|
|
282
|
+
if (cycles.length > 0) {
|
|
283
|
+
throw new Error(`Dependency cycle(s) in the manifest: ${cycles
|
|
284
|
+
.map((cycle) => cycle.join(" -> "))
|
|
285
|
+
.join("; ")}. Re-plan with /plan-program.`);
|
|
286
|
+
}
|
|
287
|
+
const isRepository = await git.isRepository(root);
|
|
288
|
+
if (!isRepository) {
|
|
289
|
+
log("warning: not a git repository — commits and decision anchors are unavailable");
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
// Authoring commits with `git add -A`, same sweep risk as the build
|
|
293
|
+
// stage — refuse a dirty start except when resuming a run whose own
|
|
294
|
+
// leftover work (a prior parked or failed attempt) is exactly what a
|
|
295
|
+
// resume needs.
|
|
296
|
+
const dirty = (await git.dirtyPaths(root)).filter((path) => !path.replaceAll("\\", "/").startsWith("docs/programs/"));
|
|
297
|
+
const resuming = manifest.workstreams.some((workstream) => workstream.status === "failed" ||
|
|
298
|
+
workstream.status === "in_progress" ||
|
|
299
|
+
workstream.status === "parked");
|
|
300
|
+
if (dirty.length > 0 && !resuming) {
|
|
301
|
+
throw new Error(`The working tree has uncommitted changes authoring would sweep into its commits:\n` +
|
|
302
|
+
dirty.map((path) => ` ${path}`).join("\n") +
|
|
303
|
+
`\nCommit or stash them, then re-run.`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const results = [];
|
|
307
|
+
const processed = new Set();
|
|
308
|
+
const blockedCone = new Set();
|
|
309
|
+
while (processed.size < manifest.workstreams.length) {
|
|
310
|
+
const remaining = manifest.workstreams.filter((w) => !processed.has(w.id));
|
|
311
|
+
const levels = topologicalLevels(remaining);
|
|
312
|
+
const next = levels[0]?.[0];
|
|
313
|
+
if (!next)
|
|
314
|
+
break;
|
|
315
|
+
processed.add(next.id);
|
|
316
|
+
results.push(await handle(next));
|
|
317
|
+
}
|
|
318
|
+
const complete = results.every((result) => result.outcome.status === "authored" || result.outcome.status === "kept");
|
|
319
|
+
return {
|
|
320
|
+
programId: options.programId,
|
|
321
|
+
complete,
|
|
322
|
+
results,
|
|
323
|
+
borrowedImplementer,
|
|
324
|
+
};
|
|
325
|
+
async function handle(workstream) {
|
|
326
|
+
const base = {
|
|
327
|
+
id: workstream.id,
|
|
328
|
+
name: workstream.name,
|
|
329
|
+
outcome: { status: "kept" },
|
|
330
|
+
decisionIds: [],
|
|
331
|
+
decisionErrors: [],
|
|
332
|
+
mergedDependencies: [],
|
|
333
|
+
unknownDependencyIds: [],
|
|
334
|
+
demotedDependencies: [],
|
|
335
|
+
reauthored: false,
|
|
336
|
+
};
|
|
337
|
+
if (blockedCone.has(workstream.id)) {
|
|
338
|
+
workstream.status = "parked";
|
|
339
|
+
await saveManifest(root, options.programId, manifest);
|
|
340
|
+
base.outcome = {
|
|
341
|
+
status: "parked",
|
|
342
|
+
reason: "an upstream dependency's authoring failed; parked, not attempted",
|
|
343
|
+
};
|
|
344
|
+
return base;
|
|
345
|
+
}
|
|
346
|
+
const existing = await readFinishedSpec(root, workstream);
|
|
347
|
+
const shouldAuthor = existing === undefined || (force && only !== undefined && only.includes(workstream.id));
|
|
348
|
+
if (!shouldAuthor)
|
|
349
|
+
return base;
|
|
350
|
+
log(`${workstream.id} ${workstream.name}: authoring`);
|
|
351
|
+
const rosterById = new Map(manifest.workstreams.map((w) => [w.id, w]));
|
|
352
|
+
const rosterIds = new Set(rosterById.keys());
|
|
353
|
+
const baseCommit = isRepository ? await git.currentCommit(root) : undefined;
|
|
354
|
+
const allDecisions = [];
|
|
355
|
+
const first = await authorBrief(root, manifest, workstream, rosterById);
|
|
356
|
+
base.demotedDependencies = first.demoted;
|
|
357
|
+
let invocation = await invokeAgent(agentRunner, author, first.brief, root);
|
|
358
|
+
base.summary = resolveSummary(invocation.output).text;
|
|
359
|
+
let parsed = extractDecisions(invocation.output);
|
|
360
|
+
base.decisionErrors.push(...parsed.errors);
|
|
361
|
+
allDecisions.push(...parsed.decisions);
|
|
362
|
+
await journalDecisions(workstream, parsed.decisions, baseCommit);
|
|
363
|
+
base.decisionIds.push(...parsed.decisions.map((decision) => decisionFingerprint(workstream.id, decision)));
|
|
364
|
+
const declaration = extractDependenciesDeclaration(invocation.output);
|
|
365
|
+
if (declaration.error)
|
|
366
|
+
log(`${workstream.id}: ${declaration.error}`);
|
|
367
|
+
const merge = mergeDependencies(workstream, rosterIds, declaration.ids);
|
|
368
|
+
base.unknownDependencyIds = merge.unknown;
|
|
369
|
+
if (merge.unknown.length > 0) {
|
|
370
|
+
log(`${workstream.id}: unknown dependency id(s) declared, ignored: ${merge.unknown.join(", ")}`);
|
|
371
|
+
}
|
|
372
|
+
if (merge.merged.length > 0) {
|
|
373
|
+
const originalDependencies = workstream.dependencies.filter((id) => !merge.merged.includes(id));
|
|
374
|
+
base.mergedDependencies = merge.merged;
|
|
375
|
+
await saveManifest(root, options.programId, manifest);
|
|
376
|
+
log(`${workstream.id}: merged new dependency edge(s): ${merge.merged.join(", ")}`);
|
|
377
|
+
const cyclesNow = findCycles(manifest.workstreams);
|
|
378
|
+
if (cyclesNow.length > 0) {
|
|
379
|
+
workstream.dependencies = originalDependencies;
|
|
380
|
+
await saveManifest(root, options.programId, manifest);
|
|
381
|
+
throw new Error(`Dependency cycle(s) created by a discovered edge from ${workstream.id}: ` +
|
|
382
|
+
`${cyclesNow.map((cycle) => cycle.join(" -> ")).join("; ")}. Re-plan with /plan-program.`);
|
|
383
|
+
}
|
|
384
|
+
const needsReauthor = [];
|
|
385
|
+
for (const id of merge.merged) {
|
|
386
|
+
const dep = rosterById.get(id);
|
|
387
|
+
if (!dep)
|
|
388
|
+
continue;
|
|
389
|
+
if ((await readFinishedSpec(root, dep)) !== undefined)
|
|
390
|
+
needsReauthor.push(id);
|
|
391
|
+
}
|
|
392
|
+
if (needsReauthor.length > 0) {
|
|
393
|
+
base.reauthored = true;
|
|
394
|
+
log(`${workstream.id}: re-authoring once with newly discovered dependency spec(s): ` +
|
|
395
|
+
needsReauthor.join(", "));
|
|
396
|
+
const note = [
|
|
397
|
+
"## You are being re-authored",
|
|
398
|
+
"",
|
|
399
|
+
"Your previous pass declared a new dependency whose finished spec is",
|
|
400
|
+
"now included below, in the dependency specs section. Revise your",
|
|
401
|
+
"spec to account for it. Any further dependency declaration in this",
|
|
402
|
+
"pass will be logged but not acted on — this workstream gets one",
|
|
403
|
+
"re-author pass.",
|
|
404
|
+
"",
|
|
405
|
+
].join("\n");
|
|
406
|
+
const second = await authorBrief(root, manifest, workstream, rosterById, note);
|
|
407
|
+
base.demotedDependencies = second.demoted;
|
|
408
|
+
invocation = await invokeAgent(agentRunner, author, second.brief, root);
|
|
409
|
+
base.summary = resolveSummary(invocation.output).text;
|
|
410
|
+
parsed = extractDecisions(invocation.output);
|
|
411
|
+
base.decisionErrors.push(...parsed.errors);
|
|
412
|
+
allDecisions.push(...parsed.decisions);
|
|
413
|
+
await journalDecisions(workstream, parsed.decisions, baseCommit);
|
|
414
|
+
base.decisionIds.push(...parsed.decisions.map((decision) => decisionFingerprint(workstream.id, decision)));
|
|
415
|
+
const secondDeclaration = extractDependenciesDeclaration(invocation.output);
|
|
416
|
+
if (secondDeclaration.ids.length > 0) {
|
|
417
|
+
log(`${workstream.id}: additional dependency declaration after the ` +
|
|
418
|
+
`re-author pass was not honored: ${secondDeclaration.ids.join(", ")}`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const final = await readFinishedSpec(root, workstream);
|
|
423
|
+
if (final === undefined) {
|
|
424
|
+
workstream.status = "parked";
|
|
425
|
+
await saveManifest(root, options.programId, manifest);
|
|
426
|
+
for (const id of downstreamCone(manifest.workstreams, [workstream.id])) {
|
|
427
|
+
blockedCone.add(id);
|
|
428
|
+
}
|
|
429
|
+
base.outcome = {
|
|
430
|
+
status: "failed",
|
|
431
|
+
reason: `no spec was written to ${workstream.taskFile} (or it was left empty)`,
|
|
432
|
+
};
|
|
433
|
+
await reviewWorkstreamDecisions(workstream.id, allDecisions, baseCommit);
|
|
434
|
+
return base;
|
|
435
|
+
}
|
|
436
|
+
let commit;
|
|
437
|
+
if (isRepository) {
|
|
438
|
+
commit = await git.commitAll(root, `nightshift(${options.programId}): author ${workstream.id} ${workstream.name}`);
|
|
439
|
+
}
|
|
440
|
+
await reviewWorkstreamDecisions(workstream.id, allDecisions, baseCommit);
|
|
441
|
+
base.outcome = { status: "authored", ...(commit === undefined ? {} : { commit }) };
|
|
442
|
+
return base;
|
|
443
|
+
}
|
|
444
|
+
async function journalDecisions(workstream, decisions, baseCommit) {
|
|
445
|
+
const events = decisions.map((decision) => ({
|
|
446
|
+
kind: "decision-recorded",
|
|
447
|
+
at: now().toISOString(),
|
|
448
|
+
id: decisionFingerprint(workstream.id, decision),
|
|
449
|
+
workstream: workstream.id,
|
|
450
|
+
decision,
|
|
451
|
+
...(baseCommit === undefined ? {} : { baseCommit }),
|
|
452
|
+
decidedBy: "implementer",
|
|
453
|
+
}));
|
|
454
|
+
await appendLedgerEvents(root, options.programId, events);
|
|
455
|
+
for (const decision of decisions) {
|
|
456
|
+
log(`${workstream.id} decision: ${decision.title} -> ${decision.chosen}`);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
function reviewWorkstreamDecisions(workstreamId, decisions, baseCommit) {
|
|
460
|
+
return reviewDecisions({
|
|
461
|
+
root,
|
|
462
|
+
programId: options.programId,
|
|
463
|
+
manifest,
|
|
464
|
+
workstreamId,
|
|
465
|
+
decisions,
|
|
466
|
+
baseCommit,
|
|
467
|
+
decider,
|
|
468
|
+
agentRunner,
|
|
469
|
+
git,
|
|
470
|
+
isRepository,
|
|
471
|
+
now,
|
|
472
|
+
log,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
//# sourceMappingURL=author.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author.js","sourceRoot":"","sources":["../src/author.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -9,7 +9,9 @@ import { ALL_TARGETS, DEFAULT_TARGETS, detectTargets, doctor, installSkills, ove
|
|
|
9
9
|
import { installArgv, planSkillInstall } from "./install-wizard.js";
|
|
10
10
|
import { packageVersion } from "./package-assets.js";
|
|
11
11
|
import { createProjectManifest } from "./project-manifest.js";
|
|
12
|
+
import { authorProgram } from "./author.js";
|
|
12
13
|
import { loadConfig } from "./config.js";
|
|
14
|
+
import { decide } from "./decide.js";
|
|
13
15
|
import { runProgram } from "./run-program.js";
|
|
14
16
|
const SCOPES = ["user", "project", "both"];
|
|
15
17
|
function parseScope(value) {
|
|
@@ -232,6 +234,102 @@ program
|
|
|
232
234
|
if (!result.complete)
|
|
233
235
|
process.exitCode = 1;
|
|
234
236
|
});
|
|
237
|
+
function renderAuthorResult(result) {
|
|
238
|
+
console.log(`${result.id} ${result.name}: ${result.outcome.status}`);
|
|
239
|
+
if (result.outcome.status === "failed" || result.outcome.status === "parked") {
|
|
240
|
+
console.log(` ${result.outcome.reason}`);
|
|
241
|
+
}
|
|
242
|
+
if (result.mergedDependencies.length > 0) {
|
|
243
|
+
console.log(` merged dependencies: ${result.mergedDependencies.join(", ")}`);
|
|
244
|
+
}
|
|
245
|
+
if (result.unknownDependencyIds.length > 0) {
|
|
246
|
+
console.log(` unknown dependency id(s) ignored: ${result.unknownDependencyIds.join(", ")}`);
|
|
247
|
+
}
|
|
248
|
+
if (result.demotedDependencies.length > 0) {
|
|
249
|
+
console.log(` dependency spec(s) too large, demoted: ${result.demotedDependencies.join(", ")}`);
|
|
250
|
+
}
|
|
251
|
+
if (result.reauthored) {
|
|
252
|
+
console.log(" re-authored once after discovering a new dependency");
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
program
|
|
256
|
+
.command("author")
|
|
257
|
+
.description("Write every missing workstream spec with a clean agent, in dependency-level order")
|
|
258
|
+
.argument("<program-id>", "Program ID from /plan-program")
|
|
259
|
+
.option("--only <ids>", "Comma-separated workstream ids eligible for --force re-authoring")
|
|
260
|
+
.option("--force", "Re-author specs named in --only even though they already exist", false)
|
|
261
|
+
.option("--cwd <path>", "Project directory", process.cwd())
|
|
262
|
+
.action(async (programId, options) => {
|
|
263
|
+
const { config } = await loadConfig(resolve(options.cwd));
|
|
264
|
+
const only = options.only
|
|
265
|
+
?.split(",")
|
|
266
|
+
.map((id) => id.trim())
|
|
267
|
+
.filter((id) => id !== "");
|
|
268
|
+
const result = await authorProgram({
|
|
269
|
+
cwd: options.cwd,
|
|
270
|
+
programId,
|
|
271
|
+
config,
|
|
272
|
+
...(only === undefined ? {} : { only }),
|
|
273
|
+
force: options.force,
|
|
274
|
+
});
|
|
275
|
+
if (result.borrowedImplementer) {
|
|
276
|
+
console.log("note: no authorAgent configured; the implementer agent authored specs instead");
|
|
277
|
+
}
|
|
278
|
+
for (const entry of result.results)
|
|
279
|
+
renderAuthorResult(entry);
|
|
280
|
+
const authored = result.results.filter((entry) => entry.outcome.status === "authored").length;
|
|
281
|
+
const kept = result.results.filter((entry) => entry.outcome.status === "kept").length;
|
|
282
|
+
const failed = result.results.filter((entry) => entry.outcome.status === "failed" || entry.outcome.status === "parked").length;
|
|
283
|
+
console.log(`\n${authored} authored, ${kept} kept, ${failed} failed/parked.`);
|
|
284
|
+
if (!result.complete)
|
|
285
|
+
process.exitCode = 1;
|
|
286
|
+
});
|
|
287
|
+
function renderDecideResult(result) {
|
|
288
|
+
switch (result.kind) {
|
|
289
|
+
case "confirmed":
|
|
290
|
+
console.log("no replay needed; the human ruling matches what was built");
|
|
291
|
+
break;
|
|
292
|
+
case "replay-unavailable":
|
|
293
|
+
console.log(`replay unavailable: ${result.reason}`);
|
|
294
|
+
break;
|
|
295
|
+
case "replay-preview":
|
|
296
|
+
console.log(`the choice differs from what was built.`);
|
|
297
|
+
console.log(`anchor commit: ${result.anchor}`);
|
|
298
|
+
console.log(`replay would reset ${result.resetWorkstreams.length} workstream(s): ` +
|
|
299
|
+
`${result.resetWorkstreams.join(", ") || "(none)"}`);
|
|
300
|
+
console.log("re-run with --replay to roll back and rebuild them");
|
|
301
|
+
break;
|
|
302
|
+
case "replayed":
|
|
303
|
+
console.log(`anchor commit: ${result.anchor}`);
|
|
304
|
+
console.log(`pre-replay HEAD preserved at ${result.preReplayRef} (${result.preReplayCommit})`);
|
|
305
|
+
console.log(`reset ${result.resetWorkstreams.length} workstream(s) to not_started: ` +
|
|
306
|
+
`${result.resetWorkstreams.join(", ") || "(none)"}`);
|
|
307
|
+
console.log(`next: ${result.nextCommand}`);
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
program
|
|
312
|
+
.command("decide")
|
|
313
|
+
.description("Record a human ruling on a ledgered decision, and optionally replay to " +
|
|
314
|
+
"rebuild the workstreams it affects")
|
|
315
|
+
.argument("<program-id>", "Program ID from /plan-program")
|
|
316
|
+
.argument("<decision-id>", "Decision ledger id shown in the run report")
|
|
317
|
+
.requiredOption("--choose <label>", "The option label the human is ruling on")
|
|
318
|
+
.requiredOption("--reason <text>", "Why, for the human record")
|
|
319
|
+
.option("--replay", "When the choice differs from what was built, roll back to the anchor " +
|
|
320
|
+
"commit and reset the affected workstreams", false)
|
|
321
|
+
.option("--cwd <path>", "Project directory", process.cwd())
|
|
322
|
+
.action(async (programId, decisionId, options) => {
|
|
323
|
+
const result = await decide({
|
|
324
|
+
cwd: options.cwd,
|
|
325
|
+
programId,
|
|
326
|
+
decisionId,
|
|
327
|
+
choose: options.choose,
|
|
328
|
+
reason: options.reason,
|
|
329
|
+
replay: options.replay,
|
|
330
|
+
});
|
|
331
|
+
renderDecideResult(result);
|
|
332
|
+
});
|
|
235
333
|
program
|
|
236
334
|
.command("doctor")
|
|
237
335
|
.description("Verify packaged assets and print the resolved skills root for each target")
|
|
@@ -256,5 +354,16 @@ program
|
|
|
256
354
|
console.error(problem);
|
|
257
355
|
process.exitCode = 1;
|
|
258
356
|
});
|
|
259
|
-
|
|
357
|
+
try {
|
|
358
|
+
await program.parseAsync();
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
// Guard refusals and validation failures are guidance for a human, not
|
|
362
|
+
// crashes: print the message, not a stack trace. The stack is available
|
|
363
|
+
// under NIGHTSHIFT_DEBUG for actual bug hunts.
|
|
364
|
+
if (process.env.NIGHTSHIFT_DEBUG)
|
|
365
|
+
throw error;
|
|
366
|
+
console.error(error.message);
|
|
367
|
+
process.exitCode = 1;
|
|
368
|
+
}
|
|
260
369
|
//# sourceMappingURL=cli.js.map
|