@wildorder/nightshift 0.5.0 → 0.7.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/LICENSE +21 -21
- package/dist/author.d.ts +13 -0
- package/dist/author.d.ts.map +1 -1
- package/dist/author.js +46 -13
- 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 +13 -5
- package/dist/decide.d.ts.map +1 -1
- package/dist/decide.js +50 -35
- package/dist/decide.js.map +1 -1
- package/dist/decider-review.d.ts +68 -1
- package/dist/decider-review.d.ts.map +1 -1
- package/dist/decider-review.js +211 -3
- package/dist/decider-review.js.map +1 -1
- package/dist/decision-ledger.d.ts +79 -1
- package/dist/decision-ledger.d.ts.map +1 -1
- package/dist/decision-ledger.js +118 -11
- package/dist/decision-ledger.js.map +1 -1
- package/dist/decision-view.d.ts +41 -0
- package/dist/decision-view.d.ts.map +1 -0
- package/dist/decision-view.js +264 -0
- package/dist/decision-view.js.map +1 -0
- 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 -0
- package/dist/findings.d.ts.map +1 -1
- package/dist/findings.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +2 -2
- 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/programs-dir.d.ts +27 -0
- package/dist/programs-dir.d.ts.map +1 -0
- package/dist/programs-dir.js +52 -0
- package/dist/programs-dir.js.map +1 -0
- package/dist/publish.d.ts +105 -0
- package/dist/publish.d.ts.map +1 -0
- package/dist/publish.js +528 -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 +33 -1
- package/dist/review-pass.d.ts.map +1 -1
- package/dist/review-pass.js +94 -42
- package/dist/review-pass.js.map +1 -1
- package/dist/run-program.d.ts +29 -3
- package/dist/run-program.d.ts.map +1 -1
- package/dist/run-program.js +431 -47
- 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 +5 -4
- package/skills/plan-program/SKILL.md +14 -0
- package/templates/AGENTS.md +29 -29
- package/templates/CLAUDE.md +7 -7
- package/templates/vision.md +46 -46
package/dist/decider-review.js
CHANGED
|
@@ -7,12 +7,22 @@ import { appendLedgerEvents } from "./decision-ledger.js";
|
|
|
7
7
|
* decision, one invocation, one verdict — a judgment, not a dialogue. No
|
|
8
8
|
* decider configured means defaults stand unratified, which the run report
|
|
9
9
|
* says plainly.
|
|
10
|
+
*
|
|
11
|
+
* A routed finding is a different kind of subject — raised by an
|
|
12
|
+
* independent reviewer, not a judgment call an agent stands behind — and
|
|
13
|
+
* gets its own triage path (`triageFindings`) with its own three-disposition
|
|
14
|
+
* vocabulary. The two paths are kept physically separate on purpose: an
|
|
15
|
+
* agent's own decision must stay on its untouched `ratify`/`escalate`
|
|
16
|
+
* contract.
|
|
10
17
|
*/
|
|
11
18
|
const DIFF_LIMIT = 20_000;
|
|
12
|
-
function
|
|
13
|
-
|
|
19
|
+
function clipDiff(diff) {
|
|
20
|
+
return diff.length > DIFF_LIMIT
|
|
14
21
|
? `${diff.slice(0, DIFF_LIMIT)}\n… (diff clipped at ${DIFF_LIMIT} characters)`
|
|
15
22
|
: diff;
|
|
23
|
+
}
|
|
24
|
+
function deciderBrief(manifest, record, diff) {
|
|
25
|
+
const clippedDiff = clipDiff(diff);
|
|
16
26
|
return [
|
|
17
27
|
"# Review one decision",
|
|
18
28
|
"",
|
|
@@ -66,7 +76,7 @@ function extractVerdict(output) {
|
|
|
66
76
|
return undefined;
|
|
67
77
|
}
|
|
68
78
|
export async function reviewDecisions(options) {
|
|
69
|
-
const { root, programId, manifest, workstreamId, decisions, baseCommit, decider, agentRunner, git, isRepository, now, log, } = options;
|
|
79
|
+
const { root, programId, manifest, workstreamId, decisions, baseCommit, decider, agentRunner, git, isRepository, reviewed, triaged, now, log, } = options;
|
|
70
80
|
if (!decider || decisions.length === 0)
|
|
71
81
|
return;
|
|
72
82
|
const diff = isRepository && baseCommit !== undefined
|
|
@@ -74,6 +84,9 @@ export async function reviewDecisions(options) {
|
|
|
74
84
|
: "";
|
|
75
85
|
for (const decision of decisions) {
|
|
76
86
|
const id = decisionFingerprint(workstreamId, decision);
|
|
87
|
+
if (reviewed.has(id))
|
|
88
|
+
continue;
|
|
89
|
+
reviewed.add(id);
|
|
77
90
|
const brief = deciderBrief(manifest, { workstream: workstreamId, decision }, diff);
|
|
78
91
|
const invocation = await invokeAgent(agentRunner, decider, brief, root);
|
|
79
92
|
const verdict = extractVerdict(invocation.output);
|
|
@@ -92,7 +105,202 @@ export async function reviewDecisions(options) {
|
|
|
92
105
|
reviewedBy: "decider",
|
|
93
106
|
};
|
|
94
107
|
await appendLedgerEvents(root, programId, [event]);
|
|
108
|
+
triaged.add(id);
|
|
95
109
|
log(`${workstreamId} decision ${id}: ${verdict.verdict}`);
|
|
96
110
|
}
|
|
97
111
|
}
|
|
112
|
+
function findingEvidenceLines(evidence) {
|
|
113
|
+
return evidence.map((item) => {
|
|
114
|
+
if (item.kind === "location") {
|
|
115
|
+
const range = item.endLine === undefined ? `${item.startLine}` : `${item.startLine}-${item.endLine}`;
|
|
116
|
+
const location = `${item.file}:${range}${item.unverifiable ? " (unverifiable path)" : ""}`;
|
|
117
|
+
return item.excerpt ? `- ${location} — ${item.excerpt}` : `- ${location}`;
|
|
118
|
+
}
|
|
119
|
+
if (item.kind === "concern") {
|
|
120
|
+
return item.detail ? `- ${item.named} — ${item.detail}` : `- ${item.named}`;
|
|
121
|
+
}
|
|
122
|
+
return `- ${item.metric}: ${item.value}`;
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The origin-aware finding brief (SC-11): states plainly that the subject is
|
|
127
|
+
* a finding routed from a review pass, never framed as an agent's own
|
|
128
|
+
* judgment call, renders the finding as the structured data it is, offers
|
|
129
|
+
* the three dispositions with honest definitions, and — for a finding the
|
|
130
|
+
* reviewer itself declined to rate a blocker — states in prose (never a
|
|
131
|
+
* numeric cap) that escalation is reserved for the genuinely unsettleable.
|
|
132
|
+
*/
|
|
133
|
+
function findingTriageBrief(manifest, workstreamId, event, diff) {
|
|
134
|
+
const clippedDiff = clipDiff(diff);
|
|
135
|
+
const evidenceLines = findingEvidenceLines(event.evidence);
|
|
136
|
+
const higherBar = event.severity === "major"
|
|
137
|
+
? [
|
|
138
|
+
"This finding's severity is **major** — the reviewer itself",
|
|
139
|
+
"declined to rate it a blocker. That is itself evidence: reserve",
|
|
140
|
+
"`escalate` for what is genuinely unsettleable here, and lean on",
|
|
141
|
+
"`fix-now` or `accept` — a reviewer that stopped short of blocker",
|
|
142
|
+
"is usually right that the crew can settle this on its own.",
|
|
143
|
+
"",
|
|
144
|
+
]
|
|
145
|
+
: [];
|
|
146
|
+
return [
|
|
147
|
+
"# Triage a finding",
|
|
148
|
+
"",
|
|
149
|
+
`Program: ${manifest.program.id} — ${manifest.program.name}`,
|
|
150
|
+
`Workstream: ${workstreamId}`,
|
|
151
|
+
"",
|
|
152
|
+
"This is a **finding routed from a review pass** — raised by an",
|
|
153
|
+
"independent reviewer, not a judgment call an implementing agent made",
|
|
154
|
+
"and stands behind. Your job is to triage it: fix it now, accept it as",
|
|
155
|
+
"a known limitation, or escalate it to the human. You never edit",
|
|
156
|
+
"anything.",
|
|
157
|
+
"",
|
|
158
|
+
`- **Severity:** ${event.severity}`,
|
|
159
|
+
`- **Category:** ${event.category}`,
|
|
160
|
+
`- **Subject:** ${event.subject}`,
|
|
161
|
+
`- **Message:** ${event.message}`,
|
|
162
|
+
...(evidenceLines.length > 0 ? ["- **Evidence:**", ...evidenceLines] : []),
|
|
163
|
+
"",
|
|
164
|
+
...higherBar,
|
|
165
|
+
"The work this finding concerns:",
|
|
166
|
+
"",
|
|
167
|
+
"```diff",
|
|
168
|
+
clippedDiff.trim() === "" ? "(no diff available)" : clippedDiff,
|
|
169
|
+
"```",
|
|
170
|
+
"",
|
|
171
|
+
"Reply with exactly one verdict block:",
|
|
172
|
+
"",
|
|
173
|
+
"```verdict",
|
|
174
|
+
"{",
|
|
175
|
+
' "disposition": "fix-now" | "accept" | "escalate",',
|
|
176
|
+
' "rationale": "One or two sentences, written for the human who reads the run report.",',
|
|
177
|
+
' "question": "…",',
|
|
178
|
+
' "alternatives": [',
|
|
179
|
+
' { "label": "…", "description": "…" }',
|
|
180
|
+
" ]",
|
|
181
|
+
"}",
|
|
182
|
+
"```",
|
|
183
|
+
"",
|
|
184
|
+
"`question` and `alternatives` apply only to `escalate` — omit them for",
|
|
185
|
+
"`fix-now` or `accept`.",
|
|
186
|
+
"",
|
|
187
|
+
"`fix-now`: the finding is worth one bounded fix attempt in this run",
|
|
188
|
+
"before proceeding. `accept`: a real but tolerable limitation, recorded",
|
|
189
|
+
"for the human and not worth stopping for. `escalate`: the crew cannot",
|
|
190
|
+
"settle this and the human should rule — compose the question and the",
|
|
191
|
+
"real alternatives yourself, in your own words. One triage, one",
|
|
192
|
+
"verdict: this is a judgment, not a dialogue.",
|
|
193
|
+
].join("\n");
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* A well-formed escalation alternative, per SC-12 and the verdict contract:
|
|
197
|
+
* a *real* `{ label, description }` composed by the decider, not a bare
|
|
198
|
+
* label. Unlike `DecisionOption` (where `description` is optional for an
|
|
199
|
+
* agent's own decision options), an escalation alternative requires a
|
|
200
|
+
* non-blank description — a hollow `{ "label": "fix" }` is not an
|
|
201
|
+
* alternative the human can rule on.
|
|
202
|
+
*/
|
|
203
|
+
function isWellFormedAlternative(value) {
|
|
204
|
+
if (typeof value !== "object" || value === null)
|
|
205
|
+
return false;
|
|
206
|
+
const candidate = value;
|
|
207
|
+
if (typeof candidate.label !== "string" || candidate.label.trim() === "")
|
|
208
|
+
return false;
|
|
209
|
+
if (typeof candidate.description !== "string" || candidate.description.trim() === "") {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Parses the finding-triage verdict block, last-block-wins, fail-closed to
|
|
216
|
+
* `undefined` — mirroring `extractVerdict`. An `escalate` verdict missing a
|
|
217
|
+
* real, non-blank question or a non-empty array of well-formed alternatives
|
|
218
|
+
* is rejected here rather than written: the invariant that a ledgered
|
|
219
|
+
* `escalate` always carries both holds at this boundary (SC-12).
|
|
220
|
+
*/
|
|
221
|
+
export function extractTriageVerdict(output) {
|
|
222
|
+
const matches = [...output.matchAll(/```verdict[^\S\r\n]*\r?\n([\s\S]*?)```/gu)];
|
|
223
|
+
for (const match of matches.reverse()) {
|
|
224
|
+
try {
|
|
225
|
+
const parsed = JSON.parse(match[1] ?? "");
|
|
226
|
+
if (typeof parsed.rationale !== "string")
|
|
227
|
+
continue;
|
|
228
|
+
if (parsed.disposition === "fix-now" || parsed.disposition === "accept") {
|
|
229
|
+
return { disposition: parsed.disposition, rationale: parsed.rationale };
|
|
230
|
+
}
|
|
231
|
+
if (parsed.disposition === "escalate") {
|
|
232
|
+
const question = parsed.question;
|
|
233
|
+
const alternatives = parsed.alternatives;
|
|
234
|
+
if (typeof question === "string" &&
|
|
235
|
+
question.trim() !== "" &&
|
|
236
|
+
Array.isArray(alternatives) &&
|
|
237
|
+
alternatives.length > 0 &&
|
|
238
|
+
alternatives.every(isWellFormedAlternative)) {
|
|
239
|
+
return {
|
|
240
|
+
disposition: "escalate",
|
|
241
|
+
rationale: parsed.rationale,
|
|
242
|
+
question,
|
|
243
|
+
alternatives,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
// A hollow escalation (missing question/alternatives) is rejected at
|
|
247
|
+
// this boundary — try an earlier block rather than writing it.
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
// Try an earlier block.
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return undefined;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Triages each routed finding with the charter's three dispositions. This
|
|
258
|
+
* only records a `fix-now` triage — WS-06 acts on it. Fails open throughout:
|
|
259
|
+
* no decider, a non-zero exit, an unparseable verdict, or a hollow
|
|
260
|
+
* escalation leaves the finding `open` and never blocks the run.
|
|
261
|
+
*/
|
|
262
|
+
export async function triageFindings(options) {
|
|
263
|
+
const { root, programId, manifest, workstreamId, findings, baseCommit, decider, agentRunner, git, isRepository, reviewed, triaged, now, log, } = options;
|
|
264
|
+
if (!decider || findings.length === 0)
|
|
265
|
+
return;
|
|
266
|
+
const diff = isRepository && baseCommit !== undefined
|
|
267
|
+
? await git.diffSince(root, baseCommit)
|
|
268
|
+
: "";
|
|
269
|
+
for (const event of findings) {
|
|
270
|
+
if (reviewed.has(event.id))
|
|
271
|
+
continue;
|
|
272
|
+
reviewed.add(event.id);
|
|
273
|
+
const brief = findingTriageBrief(manifest, workstreamId, event, diff);
|
|
274
|
+
const invocation = await invokeAgent(agentRunner, decider, brief, root);
|
|
275
|
+
const verdict = extractTriageVerdict(invocation.output);
|
|
276
|
+
if (invocation.exitCode !== 0 || verdict === undefined) {
|
|
277
|
+
// Fail open: an untriaged finding stays open and the report says so;
|
|
278
|
+
// it never blocks the run.
|
|
279
|
+
log(`${workstreamId} finding ${event.id}: decider produced no verdict; left untriaged`);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
const triageEvent = verdict.disposition === "escalate"
|
|
283
|
+
? {
|
|
284
|
+
kind: "finding-triaged",
|
|
285
|
+
at: now().toISOString(),
|
|
286
|
+
id: event.id,
|
|
287
|
+
disposition: "escalate",
|
|
288
|
+
rationale: verdict.rationale,
|
|
289
|
+
question: verdict.question,
|
|
290
|
+
alternatives: verdict.alternatives,
|
|
291
|
+
reviewedBy: "decider",
|
|
292
|
+
}
|
|
293
|
+
: {
|
|
294
|
+
kind: "finding-triaged",
|
|
295
|
+
at: now().toISOString(),
|
|
296
|
+
id: event.id,
|
|
297
|
+
disposition: verdict.disposition,
|
|
298
|
+
rationale: verdict.rationale,
|
|
299
|
+
reviewedBy: "decider",
|
|
300
|
+
};
|
|
301
|
+
await appendLedgerEvents(root, programId, [triageEvent]);
|
|
302
|
+
triaged.add(event.id);
|
|
303
|
+
log(`${workstreamId} finding ${event.id}: ${verdict.disposition}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
98
306
|
//# sourceMappingURL=decider-review.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decider-review.js","sourceRoot":"","sources":["../src/decider-review.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAoB,MAAM,mBAAmB,CAAC;AAElE,OAAO,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"decider-review.js","sourceRoot":"","sources":["../src/decider-review.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { DecisionBlock } from "./decision.js";
|
|
1
|
+
import type { DecisionBlock, DecisionOption } from "./decision.js";
|
|
2
|
+
import type { Evidence, FindingCategory, Severity } from "./findings.js";
|
|
2
3
|
/**
|
|
3
4
|
* The decision ledger: an append-only JSONL journal per program, the durable
|
|
4
5
|
* record of every judgment call a run made, who reviewed it, and what a
|
|
@@ -34,6 +35,46 @@ export type LedgerEvent = (EventBase & {
|
|
|
34
35
|
/** The option label the human settled on. */
|
|
35
36
|
chosen: string;
|
|
36
37
|
reason: string;
|
|
38
|
+
}) | (EventBase & {
|
|
39
|
+
kind: "finding-recorded";
|
|
40
|
+
workstream: string;
|
|
41
|
+
severity: Severity;
|
|
42
|
+
category: FindingCategory;
|
|
43
|
+
subject: string;
|
|
44
|
+
message: string;
|
|
45
|
+
evidence: Evidence[];
|
|
46
|
+
/** The finding's optional machine code. */
|
|
47
|
+
code?: string;
|
|
48
|
+
/** The green pre-critique commit — the anchor. */
|
|
49
|
+
baseCommit?: string;
|
|
50
|
+
/** Attribution — never "implementer": a finding is the reviewer's. */
|
|
51
|
+
foundBy: "reviewer";
|
|
52
|
+
}) | (EventBase & ({
|
|
53
|
+
kind: "finding-triaged";
|
|
54
|
+
disposition: "fix-now" | "accept";
|
|
55
|
+
rationale: string;
|
|
56
|
+
reviewedBy: "decider";
|
|
57
|
+
} | {
|
|
58
|
+
kind: "finding-triaged";
|
|
59
|
+
disposition: "escalate";
|
|
60
|
+
rationale: string;
|
|
61
|
+
/** Composed by the decider. */
|
|
62
|
+
question: string;
|
|
63
|
+
/** The real alternatives, in the decider's words. */
|
|
64
|
+
alternatives: DecisionOption[];
|
|
65
|
+
reviewedBy: "decider";
|
|
66
|
+
})) | (EventBase & {
|
|
67
|
+
kind: "finding-fix-attempted";
|
|
68
|
+
/** "kept" only when a fix verified clean AND landed a commit; "failed"
|
|
69
|
+
* for a failed verification or a clean attempt that produced no
|
|
70
|
+
* commit. */
|
|
71
|
+
outcome: "kept" | "failed";
|
|
72
|
+
/** The implementer's verbatim summary, plus (on failure) the
|
|
73
|
+
* verification diagnosis or the no-change fact. */
|
|
74
|
+
note: string;
|
|
75
|
+
/** The fix commit, present only on a kept fix that landed one. */
|
|
76
|
+
commit?: string;
|
|
77
|
+
attemptedBy: "implementer";
|
|
37
78
|
});
|
|
38
79
|
export type DecisionStatus = "unratified" | "ratified" | "escalated" | "human-decided";
|
|
39
80
|
export interface DecisionRecord {
|
|
@@ -50,8 +91,45 @@ export interface DecisionRecord {
|
|
|
50
91
|
/** True when the agent claimed the choice is costly to undo. */
|
|
51
92
|
oneWay: boolean;
|
|
52
93
|
}
|
|
94
|
+
export type FindingStatus = "open" | "fix-now" | "accepted" | "escalated" | "human-decided";
|
|
95
|
+
export interface FindingRecord {
|
|
96
|
+
id: string;
|
|
97
|
+
workstream: string;
|
|
98
|
+
severity: Severity;
|
|
99
|
+
category: FindingCategory;
|
|
100
|
+
subject: string;
|
|
101
|
+
message: string;
|
|
102
|
+
evidence: Evidence[];
|
|
103
|
+
code?: string;
|
|
104
|
+
baseCommit?: string;
|
|
105
|
+
status: FindingStatus;
|
|
106
|
+
/** Present when a decider triaged it. */
|
|
107
|
+
triageRationale?: string;
|
|
108
|
+
/** Present when the decider escalated; the composed question. */
|
|
109
|
+
escalationQuestion?: string;
|
|
110
|
+
escalationAlternatives?: DecisionOption[];
|
|
111
|
+
/** Present when a human decided; overrides the decider's triage. */
|
|
112
|
+
humanChosen?: string;
|
|
113
|
+
humanReason?: string;
|
|
114
|
+
foundBy: "reviewer";
|
|
115
|
+
/** Discriminates from a DecisionRecord where a union of both is handled. */
|
|
116
|
+
origin: "finding";
|
|
117
|
+
/**
|
|
118
|
+
* Present once a `fix-now` triage has driven a bounded fix attempt
|
|
119
|
+
* (WS-06). "kept" leaves `status` at `"fix-now"` — a fix-attempt-and-verify
|
|
120
|
+
* fact, not a per-finding proof of correction; "failed" moves `status` to
|
|
121
|
+
* `"escalated"` while `triageRationale` (the decider's original reason)
|
|
122
|
+
* stays untouched.
|
|
123
|
+
*/
|
|
124
|
+
fixAttempt?: {
|
|
125
|
+
outcome: "kept" | "failed";
|
|
126
|
+
note: string;
|
|
127
|
+
commit?: string;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
53
130
|
export interface DecisionLedgerView {
|
|
54
131
|
decisions: DecisionRecord[];
|
|
132
|
+
findings: FindingRecord[];
|
|
55
133
|
/** Journal lines that could not be read; reported, never fatal. */
|
|
56
134
|
corrupt: number;
|
|
57
135
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decision-ledger.d.ts","sourceRoot":"","sources":["../src/decision-ledger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"decision-ledger.d.ts","sourceRoot":"","sources":["../src/decision-ledger.ts"],"names":[],"mappings":"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"}
|
package/dist/decision-ledger.js
CHANGED
|
@@ -13,6 +13,11 @@ import { dirname, join, resolve } from "node:path";
|
|
|
13
13
|
* blocked run — because the ledger explains work, it does not gate it.
|
|
14
14
|
*/
|
|
15
15
|
export const LEDGER_SCHEMA_VERSION = 1;
|
|
16
|
+
const FINDING_STATUS_BY_DISPOSITION = {
|
|
17
|
+
"fix-now": "fix-now",
|
|
18
|
+
accept: "accepted",
|
|
19
|
+
escalate: "escalated",
|
|
20
|
+
};
|
|
16
21
|
export function ledgerPath(root, programId) {
|
|
17
22
|
return join(resolve(root), "docs", "programs", `${programId}-decisions.jsonl`);
|
|
18
23
|
}
|
|
@@ -27,13 +32,14 @@ export async function appendLedgerEvents(root, programId, events) {
|
|
|
27
32
|
await appendFile(path, `${lines}\n`, "utf8");
|
|
28
33
|
}
|
|
29
34
|
export function reduceLedgerEvents(events) {
|
|
30
|
-
const
|
|
35
|
+
const decisionsById = new Map();
|
|
36
|
+
const findingsById = new Map();
|
|
31
37
|
for (const event of events) {
|
|
32
38
|
if (event.kind === "decision-recorded") {
|
|
33
|
-
const existing =
|
|
39
|
+
const existing = decisionsById.get(event.id);
|
|
34
40
|
// A re-recorded decision (retry, resumed run) refreshes the block but
|
|
35
41
|
// keeps any higher-authority outcome already on the record.
|
|
36
|
-
|
|
42
|
+
decisionsById.set(event.id, {
|
|
37
43
|
id: event.id,
|
|
38
44
|
workstream: event.workstream,
|
|
39
45
|
decision: event.decision,
|
|
@@ -54,23 +60,124 @@ export function reduceLedgerEvents(events) {
|
|
|
54
60
|
});
|
|
55
61
|
continue;
|
|
56
62
|
}
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
if (event.kind === "finding-recorded") {
|
|
64
|
+
const existing = findingsById.get(event.id);
|
|
65
|
+
// Mirrors the decision-recorded re-record rule: refresh the finding's
|
|
66
|
+
// own fields, keep any higher-authority outcome already on it.
|
|
67
|
+
findingsById.set(event.id, {
|
|
68
|
+
id: event.id,
|
|
69
|
+
workstream: event.workstream,
|
|
70
|
+
severity: event.severity,
|
|
71
|
+
category: event.category,
|
|
72
|
+
subject: event.subject,
|
|
73
|
+
message: event.message,
|
|
74
|
+
evidence: event.evidence,
|
|
75
|
+
...(event.code === undefined ? {} : { code: event.code }),
|
|
76
|
+
...(event.baseCommit === undefined
|
|
77
|
+
? {}
|
|
78
|
+
: { baseCommit: event.baseCommit }),
|
|
79
|
+
status: existing?.status ?? "open",
|
|
80
|
+
...(existing?.triageRationale === undefined
|
|
81
|
+
? {}
|
|
82
|
+
: { triageRationale: existing.triageRationale }),
|
|
83
|
+
...(existing?.escalationQuestion === undefined
|
|
84
|
+
? {}
|
|
85
|
+
: { escalationQuestion: existing.escalationQuestion }),
|
|
86
|
+
...(existing?.escalationAlternatives === undefined
|
|
87
|
+
? {}
|
|
88
|
+
: { escalationAlternatives: existing.escalationAlternatives }),
|
|
89
|
+
...(existing?.humanChosen === undefined
|
|
90
|
+
? {}
|
|
91
|
+
: { humanChosen: existing.humanChosen }),
|
|
92
|
+
...(existing?.humanReason === undefined
|
|
93
|
+
? {}
|
|
94
|
+
: { humanReason: existing.humanReason }),
|
|
95
|
+
...(existing?.fixAttempt === undefined
|
|
96
|
+
? {}
|
|
97
|
+
: { fixAttempt: existing.fixAttempt }),
|
|
98
|
+
foundBy: "reviewer",
|
|
99
|
+
origin: "finding",
|
|
100
|
+
});
|
|
59
101
|
continue;
|
|
102
|
+
}
|
|
103
|
+
if (event.kind === "finding-triaged") {
|
|
104
|
+
const record = findingsById.get(event.id);
|
|
105
|
+
if (!record)
|
|
106
|
+
continue;
|
|
107
|
+
// Human authority already on the record outranks a decider triage.
|
|
108
|
+
if (record.status === "human-decided")
|
|
109
|
+
continue;
|
|
110
|
+
record.status = FINDING_STATUS_BY_DISPOSITION[event.disposition];
|
|
111
|
+
record.triageRationale = event.rationale;
|
|
112
|
+
if (event.disposition === "escalate") {
|
|
113
|
+
record.escalationQuestion = event.question;
|
|
114
|
+
record.escalationAlternatives = event.alternatives;
|
|
115
|
+
}
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (event.kind === "finding-fix-attempted") {
|
|
119
|
+
const record = findingsById.get(event.id);
|
|
120
|
+
if (!record)
|
|
121
|
+
continue;
|
|
122
|
+
// Human authority already on the record outranks a fix attempt — the
|
|
123
|
+
// fix-now driver never selects a human-decided finding in the first
|
|
124
|
+
// place (it reads the same projection), but an older run's ledger can
|
|
125
|
+
// still contain the event, so the reducer stays harmless either way.
|
|
126
|
+
if (record.status === "human-decided")
|
|
127
|
+
continue;
|
|
128
|
+
record.fixAttempt = {
|
|
129
|
+
outcome: event.outcome,
|
|
130
|
+
note: event.note,
|
|
131
|
+
...(event.commit === undefined ? {} : { commit: event.commit }),
|
|
132
|
+
};
|
|
133
|
+
// A kept fix leaves status at "fix-now" — the presence of a "kept"
|
|
134
|
+
// fixAttempt is what distinguishes it from a still-pending fix-now
|
|
135
|
+
// finding. A failed fix — a failed verification or a clean attempt
|
|
136
|
+
// that landed no commit — is promoted to escalation: this is the
|
|
137
|
+
// *only* place that promotion happens, a projection, not a re-triage.
|
|
138
|
+
if (event.outcome === "failed") {
|
|
139
|
+
record.status = "escalated";
|
|
140
|
+
}
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
60
143
|
if (event.kind === "decision-reviewed") {
|
|
144
|
+
const record = decisionsById.get(event.id);
|
|
145
|
+
if (!record)
|
|
146
|
+
continue;
|
|
61
147
|
// Human authority already on the record outranks a decider review.
|
|
62
148
|
if (record.status === "human-decided")
|
|
63
149
|
continue;
|
|
64
150
|
record.status = event.verdict === "ratify" ? "ratified" : "escalated";
|
|
65
151
|
record.reviewRationale = event.rationale;
|
|
152
|
+
continue;
|
|
66
153
|
}
|
|
67
|
-
|
|
68
|
-
record
|
|
69
|
-
|
|
70
|
-
|
|
154
|
+
if (event.kind === "decision-human") {
|
|
155
|
+
// A human ruling settles whichever record matches the id — a decision
|
|
156
|
+
// or a finding — never both, since ids never collide across the two.
|
|
157
|
+
const decision = decisionsById.get(event.id);
|
|
158
|
+
if (decision) {
|
|
159
|
+
decision.status = "human-decided";
|
|
160
|
+
decision.humanChosen = event.chosen;
|
|
161
|
+
decision.humanReason = event.reason;
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
const finding = findingsById.get(event.id);
|
|
165
|
+
if (finding) {
|
|
166
|
+
finding.status = "human-decided";
|
|
167
|
+
finding.humanChosen = event.chosen;
|
|
168
|
+
finding.humanReason = event.reason;
|
|
169
|
+
}
|
|
170
|
+
continue;
|
|
71
171
|
}
|
|
172
|
+
// A genuinely unknown or future event kind is ignored, never
|
|
173
|
+
// mis-handled — reads stay fail-open regardless of what a hand-edited
|
|
174
|
+
// or newer ledger presents.
|
|
72
175
|
}
|
|
73
|
-
return {
|
|
176
|
+
return {
|
|
177
|
+
decisions: [...decisionsById.values()],
|
|
178
|
+
findings: [...findingsById.values()],
|
|
179
|
+
corrupt: 0,
|
|
180
|
+
};
|
|
74
181
|
}
|
|
75
182
|
/**
|
|
76
183
|
* Read and reduce the journal. Fail-open: a missing file is an empty ledger,
|
|
@@ -83,7 +190,7 @@ export async function readDecisionLedger(root, programId) {
|
|
|
83
190
|
raw = await readFile(ledgerPath(root, programId), "utf8");
|
|
84
191
|
}
|
|
85
192
|
catch {
|
|
86
|
-
return { decisions: [], corrupt: 0 };
|
|
193
|
+
return { decisions: [], findings: [], corrupt: 0 };
|
|
87
194
|
}
|
|
88
195
|
const events = [];
|
|
89
196
|
let corrupt = 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decision-ledger.js","sourceRoot":"","sources":["../src/decision-ledger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"decision-ledger.js","sourceRoot":"","sources":["../src/decision-ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { DecisionLedgerView, DecisionRecord, FindingRecord } from "./decision-ledger.js";
|
|
2
|
+
/**
|
|
3
|
+
* The canonical human view of a decision or a finding — the single module
|
|
4
|
+
* every surface renders through (SC-04). Two densities, both kinds of
|
|
5
|
+
* record, and the one implementation of the `nightshift decide` flip
|
|
6
|
+
* command. Nothing here calls a forge or writes a file: it returns markdown
|
|
7
|
+
* `string[]`, matching `renderPassReport`'s convention — the caller splices
|
|
8
|
+
* the lines under its own heading.
|
|
9
|
+
*
|
|
10
|
+
* This module renders and nothing else: it never calls a forge, spawns an
|
|
11
|
+
* agent, or writes a file. Both surfaces render through it — the run report
|
|
12
|
+
* (`run-program.ts`) and the pull request's escalation comments
|
|
13
|
+
* (`publish.ts`) — and the hand-rolled renderers they each used to carry are
|
|
14
|
+
* gone, which is what keeps one decision from reading three ways (SC-04).
|
|
15
|
+
*/
|
|
16
|
+
export type Density = "compact" | "full";
|
|
17
|
+
export interface RenderOptions {
|
|
18
|
+
density: Density;
|
|
19
|
+
programId: string;
|
|
20
|
+
}
|
|
21
|
+
export type RenderableRecord = DecisionRecord | FindingRecord;
|
|
22
|
+
/**
|
|
23
|
+
* Everything the decider escalated — an agent's decision and a routed
|
|
24
|
+
* finding alike. The one definition of "needs your attention", shared by the
|
|
25
|
+
* run report's section, the pull request's escalation comments, and the
|
|
26
|
+
* count the CLI prints when a run ends, so the three can never disagree
|
|
27
|
+
* about how many things are waiting for the human.
|
|
28
|
+
*/
|
|
29
|
+
export declare function escalatedRecords(ledger: DecisionLedgerView): RenderableRecord[];
|
|
30
|
+
/** A `DecisionRecord` written by a pre-decision-legibility conversion of a finding. */
|
|
31
|
+
export declare function isLegacyFinding(record: DecisionRecord): boolean;
|
|
32
|
+
/** The single implementation of the `nightshift decide` flip command. */
|
|
33
|
+
export declare function flipCommand(programId: string, decisionId: string, chooseLabel: string, reason: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Dispatches: a `FindingRecord` renders as a finding; a legacy synthetic
|
|
36
|
+
* finding (a `DecisionRecord` whose title is `"Reviewer finding: …"`) renders
|
|
37
|
+
* as the history it is; any other `DecisionRecord` renders as an agent
|
|
38
|
+
* decision.
|
|
39
|
+
*/
|
|
40
|
+
export declare function renderRecord(record: RenderableRecord, opts: RenderOptions): string[];
|
|
41
|
+
//# sourceMappingURL=decision-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decision-view.d.ts","sourceRoot":"","sources":["../src/decision-view.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,kBAAkB,EAClB,cAAc,EACd,aAAa,EACd,MAAM,sBAAsB,CAAC;AAG9B;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEzC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,aAAa,CAAC;AAE9D;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,kBAAkB,GAAG,gBAAgB,EAAE,CAK/E;AAID,uFAAuF;AACvF,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAE/D;AAWD,yEAAyE;AACzE,wBAAgB,WAAW,CACzB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,GACb,MAAM,CAKR;AAsQD;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,gBAAgB,EACxB,IAAI,EAAE,aAAa,GAClB,MAAM,EAAE,CAgBV"}
|