@jakkrichm/create-nexus-devflow 2.9.4 → 2.10.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 +3 -3
- package/dist/lib/dashboard-page.d.ts +1 -1
- package/dist/lib/dashboard-page.js +5 -1
- package/dist/lib/dashboard-page.js.map +1 -1
- package/dist/lib/project-config.d.ts +2 -0
- package/dist/lib/project-config.js +5 -2
- package/dist/lib/project-config.js.map +1 -1
- package/dist/lib/review.d.ts +38 -0
- package/dist/lib/review.js +429 -0
- package/dist/lib/review.js.map +1 -0
- package/dist/lib/status.d.ts +19 -2
- package/dist/lib/status.js +83 -15
- package/dist/lib/status.js.map +1 -1
- package/package.json +1 -1
- package/template/.agents/skills/audit/SKILL.md +119 -144
- package/template/.agents/skills/audit/reference/independent-review.md +128 -0
- package/template/.agents/skills/autopilot/SKILL.md +22 -1
- package/template/.agents/skills/browser-tests/SKILL.md +163 -0
- package/template/.agents/skills/check/SKILL.md +32 -23
- package/template/.agents/skills/complete/SKILL.md +28 -39
- package/template/.agents/skills/continuous/SKILL.md +12 -0
- package/template/.agents/skills/doctor/SKILL.md +8 -4
- package/template/.agents/skills/feature/SKILL.md +22 -1
- package/template/.agents/skills/implement/SKILL.md +21 -1
- package/template/.agents/skills/onboard/SKILL.md +17 -1
- package/template/.agents/skills/status/SKILL.md +12 -1
- package/template/.agents/skills/tests/SKILL.md +1 -1
- package/template/.agents/skills/try/SKILL.md +9 -24
- package/template/.claude/skills/audit/SKILL.md +119 -144
- package/template/.claude/skills/audit/reference/independent-review.md +128 -0
- package/template/.claude/skills/autopilot/SKILL.md +22 -1
- package/template/.claude/skills/browser-tests/SKILL.md +163 -0
- package/template/.claude/skills/check/SKILL.md +32 -23
- package/template/.claude/skills/complete/SKILL.md +28 -39
- package/template/.claude/skills/continuous/SKILL.md +12 -0
- package/template/.claude/skills/doctor/SKILL.md +9 -4
- package/template/.claude/skills/feature/SKILL.md +22 -1
- package/template/.claude/skills/implement/SKILL.md +21 -1
- package/template/.claude/skills/onboard/SKILL.md +17 -1
- package/template/.claude/skills/status/SKILL.md +12 -1
- package/template/.claude/skills/tests/SKILL.md +1 -1
- package/template/.claude/skills/try/SKILL.md +9 -24
- package/template/AGENTS.md +4 -4
- package/template/devflow/build-plan.md +6 -0
- package/template/devflow/config.json +2 -0
- package/template/devflow/context/coding-standards.md +8 -1
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
const DEFAULT_REVIEW_PATH = path.join("devflow", "context", "review.md");
|
|
7
|
+
const RESET_MARKER = "_No independent review requested.";
|
|
8
|
+
const FULL_SHA_PATTERN = /^[0-9a-f]{40}$/;
|
|
9
|
+
const HASH_PATTERN = /^[0-9a-f]{64}$/;
|
|
10
|
+
const BASE_REF_PATTERN = /^(?!.*(?:\.\.|\/\/|@\{))[A-Za-z0-9](?:[A-Za-z0-9._/-]*[A-Za-z0-9])?$/;
|
|
11
|
+
const FIELD_PATTERN = /^\*\*([^*]+):\*\*\s*(.*?)\s*$/;
|
|
12
|
+
const RUNTIME_DEFAULT_MODEL = "runtime default (exact model not known until reviewer starts)";
|
|
13
|
+
const execFileAsync = promisify(execFile);
|
|
14
|
+
async function resolveReviewPaths(projectRoot, taskSlug) {
|
|
15
|
+
if (taskSlug) {
|
|
16
|
+
const taskDir = path.join(projectRoot, "devflow", "context", taskSlug);
|
|
17
|
+
return {
|
|
18
|
+
reviewPath: path.join(taskDir, "review.md"),
|
|
19
|
+
specPath: path.join(taskDir, "spec.md"),
|
|
20
|
+
findingsPath: path.join(taskDir, "findings.md")
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// Check if there are active task directories in devflow/context/{xxx-slug}/
|
|
24
|
+
const contextDir = path.join(projectRoot, "devflow", "context");
|
|
25
|
+
try {
|
|
26
|
+
const entries = await fs.readdir(contextDir, { withFileTypes: true });
|
|
27
|
+
const taskDirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith("."));
|
|
28
|
+
if (taskDirs.length === 1 && taskDirs[0]) {
|
|
29
|
+
const taskDir = path.join(contextDir, taskDirs[0].name);
|
|
30
|
+
return {
|
|
31
|
+
reviewPath: path.join(taskDir, "review.md"),
|
|
32
|
+
specPath: path.join(taskDir, "spec.md"),
|
|
33
|
+
findingsPath: path.join(taskDir, "findings.md")
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Ignore and fallback
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
reviewPath: path.join(projectRoot, DEFAULT_REVIEW_PATH),
|
|
42
|
+
specPath: path.join(projectRoot, "devflow", "context", "current-feature.md"),
|
|
43
|
+
findingsPath: path.join(projectRoot, "devflow", "context", "findings.md")
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function readIndependentReview(projectRoot, taskSlug) {
|
|
47
|
+
const { reviewPath, specPath, findingsPath } = await resolveReviewPaths(projectRoot, taskSlug);
|
|
48
|
+
try {
|
|
49
|
+
const stats = await fs.lstat(reviewPath);
|
|
50
|
+
if (stats.isSymbolicLink()) {
|
|
51
|
+
return malformedSummary({
|
|
52
|
+
code: "unsafe_review_path",
|
|
53
|
+
message: "Independent review file is a symbolic link and was not read."
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (!stats.isFile()) {
|
|
57
|
+
return malformedSummary({
|
|
58
|
+
code: "invalid_review_path",
|
|
59
|
+
message: "Independent review path is not a regular file."
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
const parsed = parseIndependentReview(await fs.readFile(reviewPath, "utf8"));
|
|
63
|
+
if (parsed.state === "none" || parsed.state === "malformed") {
|
|
64
|
+
return parsed;
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
...parsed,
|
|
68
|
+
freshness: await determineFreshness(projectRoot, parsed, specPath, reviewPath, findingsPath)
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
if (getErrorCode(error) === "ENOENT") {
|
|
73
|
+
return emptySummary();
|
|
74
|
+
}
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function parseIndependentReview(markdown) {
|
|
79
|
+
if (markdown.includes(RESET_MARKER) && !/^\*\*Status:\*\*/m.test(markdown)) {
|
|
80
|
+
return emptySummary();
|
|
81
|
+
}
|
|
82
|
+
const fields = new Map();
|
|
83
|
+
for (const line of markdown.split(/\r?\n/)) {
|
|
84
|
+
const match = line.match(FIELD_PATTERN);
|
|
85
|
+
if (match?.[1]) {
|
|
86
|
+
fields.set(normalizeLabel(match[1]), (match[2] || "").trim());
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const state = normalizeState(fields.get("status"));
|
|
90
|
+
const targetCommit = normalizeHash(fields.get("target commit"), FULL_SHA_PATTERN);
|
|
91
|
+
const baseCommit = normalizeHash(fields.get("base commit"), FULL_SHA_PATTERN);
|
|
92
|
+
const baseRef = normalizeBaseRef(fields.get("base ref"));
|
|
93
|
+
const specHash = normalizeHash(fields.get("spec hash"), HASH_PATTERN);
|
|
94
|
+
const preparedBy = normalizeAdapter(fields.get("prepared by"));
|
|
95
|
+
const builderModel = normalizeText(fields.get("builder model"));
|
|
96
|
+
const requestedReviewer = normalizeAdapter(fields.get("requested reviewer"));
|
|
97
|
+
const requestedModel = normalizeText(fields.get("requested model"));
|
|
98
|
+
const requestedAt = normalizeTimestamp(fields.get("requested at"));
|
|
99
|
+
const workflow = normalizeWorkflow(fields.get("workflow"));
|
|
100
|
+
const checkRequired = normalizeBoolean(fields.get("check required"));
|
|
101
|
+
const reviewerAdapter = normalizeAdapter(fields.get("reviewer adapter"));
|
|
102
|
+
const reviewerModel = normalizeReviewerModel(fields.get("reviewer model"));
|
|
103
|
+
const reviewerContext = normalizeText(fields.get("reviewer context"));
|
|
104
|
+
const reviewedAt = normalizeText(fields.get("reviewed at"));
|
|
105
|
+
const scope = normalizeText(fields.get("scope"));
|
|
106
|
+
const lenses = normalizeLenses(fields.get("lenses"));
|
|
107
|
+
const verdict = normalizeVerdict(fields.get("verdict"));
|
|
108
|
+
const checkResult = normalizeCheckResult(fields.get("check result"));
|
|
109
|
+
const completedSectionsValid = [
|
|
110
|
+
"commands",
|
|
111
|
+
"evidence",
|
|
112
|
+
"findings",
|
|
113
|
+
"remaining risk"
|
|
114
|
+
].every((heading) => readSection(markdown, heading) !== null);
|
|
115
|
+
const commonFieldsValid = state !== null &&
|
|
116
|
+
targetCommit !== null &&
|
|
117
|
+
baseCommit !== null &&
|
|
118
|
+
baseRef !== null &&
|
|
119
|
+
specHash !== null &&
|
|
120
|
+
preparedBy !== null &&
|
|
121
|
+
builderModel !== null &&
|
|
122
|
+
requestedReviewer !== null &&
|
|
123
|
+
requestedModel !== null &&
|
|
124
|
+
requestedAt !== null &&
|
|
125
|
+
workflow !== null &&
|
|
126
|
+
checkRequired !== null;
|
|
127
|
+
const completedFieldsValid = reviewerAdapter !== null &&
|
|
128
|
+
reviewerModel !== null &&
|
|
129
|
+
reviewerContext?.toLowerCase() === "fresh session" &&
|
|
130
|
+
normalizeTimestamp(reviewedAt || undefined) !== null &&
|
|
131
|
+
(scope?.toLowerCase() === "current" || scope?.toLowerCase() === "current-feature") &&
|
|
132
|
+
["quality", "security", "performance", "tests"].every((lens) => lenses.includes(lens)) &&
|
|
133
|
+
verdict === state &&
|
|
134
|
+
checkResult !== null &&
|
|
135
|
+
completedSectionsValid &&
|
|
136
|
+
(state !== "passed" || !checkRequired || checkResult === "passed") &&
|
|
137
|
+
(state !== "passed" || checkRequired || checkResult === "not-required" || checkResult === "passed");
|
|
138
|
+
if (!commonFieldsValid ||
|
|
139
|
+
((state === "passed" || state === "changes-requested") && !completedFieldsValid)) {
|
|
140
|
+
return malformedSummary({
|
|
141
|
+
code: "malformed_review",
|
|
142
|
+
message: "Independent review record is missing or has invalid required fields."
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
state,
|
|
147
|
+
freshness: "unknown",
|
|
148
|
+
targetCommit,
|
|
149
|
+
baseCommit,
|
|
150
|
+
baseRef,
|
|
151
|
+
specHash,
|
|
152
|
+
preparedBy,
|
|
153
|
+
builderModel,
|
|
154
|
+
requestedReviewer,
|
|
155
|
+
requestedModel,
|
|
156
|
+
requestedAt,
|
|
157
|
+
workflow,
|
|
158
|
+
checkRequired,
|
|
159
|
+
reviewerAdapter,
|
|
160
|
+
reviewerModel,
|
|
161
|
+
reviewerContext,
|
|
162
|
+
reviewedAt,
|
|
163
|
+
scope,
|
|
164
|
+
lenses,
|
|
165
|
+
verdict,
|
|
166
|
+
checkResult,
|
|
167
|
+
warnings: []
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
async function determineFreshness(projectRoot, review, specPath, reviewPath, findingsPath) {
|
|
171
|
+
if (!review.targetCommit || !review.baseCommit || !review.baseRef || !review.specHash) {
|
|
172
|
+
return "unknown";
|
|
173
|
+
}
|
|
174
|
+
if (review.reviewerAdapter &&
|
|
175
|
+
review.requestedReviewer &&
|
|
176
|
+
review.reviewerAdapter !== review.requestedReviewer) {
|
|
177
|
+
return "stale";
|
|
178
|
+
}
|
|
179
|
+
if (review.reviewerModel &&
|
|
180
|
+
review.requestedModel &&
|
|
181
|
+
review.requestedModel !== RUNTIME_DEFAULT_MODEL &&
|
|
182
|
+
review.reviewerModel !== review.requestedModel) {
|
|
183
|
+
return "stale";
|
|
184
|
+
}
|
|
185
|
+
const [head, currentWork, mergeBase, permittedBaseRefs] = await Promise.all([
|
|
186
|
+
runOptionalGit(projectRoot, ["rev-parse", "HEAD"]),
|
|
187
|
+
readOptionalRegularFile(specPath),
|
|
188
|
+
runOptionalGit(projectRoot, [
|
|
189
|
+
"merge-base",
|
|
190
|
+
review.baseRef,
|
|
191
|
+
review.targetCommit
|
|
192
|
+
]),
|
|
193
|
+
readPermittedBaseRefs(projectRoot)
|
|
194
|
+
]);
|
|
195
|
+
if (!head || currentWork === null) {
|
|
196
|
+
return "unknown";
|
|
197
|
+
}
|
|
198
|
+
if (review.baseCommit === review.targetCommit ||
|
|
199
|
+
!permittedBaseRefs.has(review.baseRef) ||
|
|
200
|
+
mergeBase !== review.baseCommit) {
|
|
201
|
+
return "stale";
|
|
202
|
+
}
|
|
203
|
+
const currentSpecHash = createHash("sha256").update(currentWork).digest("hex");
|
|
204
|
+
if (head !== review.targetCommit || currentSpecHash !== review.specHash) {
|
|
205
|
+
return "stale";
|
|
206
|
+
}
|
|
207
|
+
const relReviewPath = path.relative(projectRoot, reviewPath).replace(/\\/g, "/");
|
|
208
|
+
const relFindingsPath = path.relative(projectRoot, findingsPath).replace(/\\/g, "/");
|
|
209
|
+
const relevantDiff = await hasRelevantDiff(projectRoot, review.targetCommit, relReviewPath, relFindingsPath);
|
|
210
|
+
return relevantDiff === null ? "unknown" : relevantDiff ? "stale" : "current";
|
|
211
|
+
}
|
|
212
|
+
async function hasRelevantDiff(projectRoot, targetCommit, relReviewPath, relFindingsPath) {
|
|
213
|
+
try {
|
|
214
|
+
await execFileAsync("git", [
|
|
215
|
+
"-C",
|
|
216
|
+
projectRoot,
|
|
217
|
+
"diff",
|
|
218
|
+
"--quiet",
|
|
219
|
+
targetCommit,
|
|
220
|
+
"--",
|
|
221
|
+
".",
|
|
222
|
+
`:(exclude)${relReviewPath}`,
|
|
223
|
+
`:(exclude)${relFindingsPath}`
|
|
224
|
+
], { encoding: "utf8", maxBuffer: 1024 * 1024 });
|
|
225
|
+
}
|
|
226
|
+
catch (error) {
|
|
227
|
+
if (getErrorCode(error) === "1") {
|
|
228
|
+
return true;
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
const untracked = await runOptionalGit(projectRoot, [
|
|
233
|
+
"ls-files",
|
|
234
|
+
"--others",
|
|
235
|
+
"--exclude-standard",
|
|
236
|
+
"-z"
|
|
237
|
+
]);
|
|
238
|
+
if (untracked === null) {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
return untracked
|
|
242
|
+
.split("\0")
|
|
243
|
+
.filter(Boolean)
|
|
244
|
+
.some((file) => file !== relReviewPath && file !== relFindingsPath);
|
|
245
|
+
}
|
|
246
|
+
async function readOptionalRegularFile(filePath) {
|
|
247
|
+
try {
|
|
248
|
+
const stats = await fs.lstat(filePath);
|
|
249
|
+
if (stats.isSymbolicLink() || !stats.isFile()) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
return await fs.readFile(filePath, "utf8");
|
|
253
|
+
}
|
|
254
|
+
catch (error) {
|
|
255
|
+
if (getErrorCode(error) === "ENOENT") {
|
|
256
|
+
return null;
|
|
257
|
+
}
|
|
258
|
+
throw error;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
async function runOptionalGit(projectRoot, args) {
|
|
262
|
+
try {
|
|
263
|
+
const result = await execFileAsync("git", ["-C", projectRoot, ...args], {
|
|
264
|
+
encoding: "utf8",
|
|
265
|
+
maxBuffer: 1024 * 1024
|
|
266
|
+
});
|
|
267
|
+
return result.stdout.trim();
|
|
268
|
+
}
|
|
269
|
+
catch {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async function readPermittedBaseRefs(projectRoot) {
|
|
274
|
+
const refs = new Set();
|
|
275
|
+
const remotes = await runOptionalGit(projectRoot, ["remote"]);
|
|
276
|
+
for (const remote of remotes?.split(/\r?\n/).filter(Boolean) || []) {
|
|
277
|
+
const remoteDefault = await runOptionalGit(projectRoot, [
|
|
278
|
+
"symbolic-ref",
|
|
279
|
+
"--quiet",
|
|
280
|
+
"--short",
|
|
281
|
+
`refs/remotes/${remote}/HEAD`
|
|
282
|
+
]);
|
|
283
|
+
if (remoteDefault) {
|
|
284
|
+
refs.add(remoteDefault);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
for (const localDefault of ["main", "master"]) {
|
|
288
|
+
if (await runOptionalGit(projectRoot, [
|
|
289
|
+
"rev-parse",
|
|
290
|
+
"--verify",
|
|
291
|
+
`${localDefault}^{commit}`
|
|
292
|
+
])) {
|
|
293
|
+
refs.add(localDefault);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return refs;
|
|
297
|
+
}
|
|
298
|
+
function normalizeLabel(value) {
|
|
299
|
+
return value.trim().toLowerCase();
|
|
300
|
+
}
|
|
301
|
+
function normalizeState(value) {
|
|
302
|
+
const normalized = value?.trim().toLowerCase();
|
|
303
|
+
return normalized === "pending" ||
|
|
304
|
+
normalized === "passed" ||
|
|
305
|
+
normalized === "changes-requested"
|
|
306
|
+
? normalized
|
|
307
|
+
: null;
|
|
308
|
+
}
|
|
309
|
+
function normalizeAdapter(value) {
|
|
310
|
+
const normalized = value?.trim().toLowerCase();
|
|
311
|
+
return normalized === "antigravity" ||
|
|
312
|
+
normalized === "claude" ||
|
|
313
|
+
normalized === "codex" ||
|
|
314
|
+
normalized === "copilot" ||
|
|
315
|
+
normalized === "opencode"
|
|
316
|
+
? normalized
|
|
317
|
+
: null;
|
|
318
|
+
}
|
|
319
|
+
function normalizeHash(value, pattern) {
|
|
320
|
+
const normalized = value?.trim().toLowerCase() || "";
|
|
321
|
+
return pattern.test(normalized) ? normalized : null;
|
|
322
|
+
}
|
|
323
|
+
function normalizeBaseRef(value) {
|
|
324
|
+
const normalized = value?.trim() || "";
|
|
325
|
+
return BASE_REF_PATTERN.test(normalized) ? normalized : null;
|
|
326
|
+
}
|
|
327
|
+
function normalizeText(value) {
|
|
328
|
+
const normalized = value?.trim();
|
|
329
|
+
return normalized ? normalized : null;
|
|
330
|
+
}
|
|
331
|
+
function normalizeReviewerModel(value) {
|
|
332
|
+
const normalized = normalizeText(value);
|
|
333
|
+
return normalized === RUNTIME_DEFAULT_MODEL ? null : normalized;
|
|
334
|
+
}
|
|
335
|
+
function normalizeTimestamp(value) {
|
|
336
|
+
const normalized = normalizeText(value);
|
|
337
|
+
return normalized && !Number.isNaN(Date.parse(normalized)) ? normalized : null;
|
|
338
|
+
}
|
|
339
|
+
function normalizeWorkflow(value) {
|
|
340
|
+
const normalized = value?.trim().toLowerCase();
|
|
341
|
+
return normalized === "continuous" || normalized === "regular"
|
|
342
|
+
? normalized
|
|
343
|
+
: null;
|
|
344
|
+
}
|
|
345
|
+
function normalizeBoolean(value) {
|
|
346
|
+
const normalized = value?.trim().toLowerCase();
|
|
347
|
+
return normalized === "yes" ? true : normalized === "no" ? false : null;
|
|
348
|
+
}
|
|
349
|
+
function normalizeLenses(value) {
|
|
350
|
+
return value
|
|
351
|
+
? value.split(",").map((lens) => lens.trim().toLowerCase()).filter(Boolean)
|
|
352
|
+
: [];
|
|
353
|
+
}
|
|
354
|
+
function normalizeVerdict(value) {
|
|
355
|
+
const normalized = value?.trim().toLowerCase();
|
|
356
|
+
return normalized === "changes-requested" || normalized === "passed"
|
|
357
|
+
? normalized
|
|
358
|
+
: null;
|
|
359
|
+
}
|
|
360
|
+
function normalizeCheckResult(value) {
|
|
361
|
+
const normalized = value?.trim().toLowerCase();
|
|
362
|
+
return normalized === "failed" ||
|
|
363
|
+
normalized === "not-required" ||
|
|
364
|
+
normalized === "passed" ||
|
|
365
|
+
normalized === "unavailable"
|
|
366
|
+
? normalized
|
|
367
|
+
: null;
|
|
368
|
+
}
|
|
369
|
+
function readSection(markdown, heading) {
|
|
370
|
+
const lines = markdown.split(/\r?\n/);
|
|
371
|
+
const start = lines.findIndex((line) => line.trim().toLowerCase() === `## ${heading}`);
|
|
372
|
+
if (start === -1) {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
const content = [];
|
|
376
|
+
for (let index = start + 1; index < lines.length; index += 1) {
|
|
377
|
+
const line = lines[index] || "";
|
|
378
|
+
if (/^##\s+/.test(line)) {
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
content.push(line);
|
|
382
|
+
}
|
|
383
|
+
const normalized = content.join("\n").trim();
|
|
384
|
+
return normalized ? normalized : null;
|
|
385
|
+
}
|
|
386
|
+
function emptySummary() {
|
|
387
|
+
return {
|
|
388
|
+
state: "none",
|
|
389
|
+
freshness: "not-applicable",
|
|
390
|
+
targetCommit: null,
|
|
391
|
+
baseCommit: null,
|
|
392
|
+
baseRef: null,
|
|
393
|
+
specHash: null,
|
|
394
|
+
preparedBy: null,
|
|
395
|
+
builderModel: null,
|
|
396
|
+
requestedReviewer: null,
|
|
397
|
+
requestedModel: null,
|
|
398
|
+
requestedAt: null,
|
|
399
|
+
workflow: null,
|
|
400
|
+
checkRequired: null,
|
|
401
|
+
reviewerAdapter: null,
|
|
402
|
+
reviewerModel: null,
|
|
403
|
+
reviewerContext: null,
|
|
404
|
+
reviewedAt: null,
|
|
405
|
+
scope: null,
|
|
406
|
+
lenses: [],
|
|
407
|
+
verdict: null,
|
|
408
|
+
checkResult: null,
|
|
409
|
+
warnings: []
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function malformedSummary(warning) {
|
|
413
|
+
return {
|
|
414
|
+
...emptySummary(),
|
|
415
|
+
state: "malformed",
|
|
416
|
+
freshness: "unknown",
|
|
417
|
+
warnings: [warning]
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
function getErrorCode(error) {
|
|
421
|
+
return typeof error === "object" &&
|
|
422
|
+
error !== null &&
|
|
423
|
+
"code" in error &&
|
|
424
|
+
(typeof error.code === "string" || typeof error.code === "number")
|
|
425
|
+
? String(error.code)
|
|
426
|
+
: undefined;
|
|
427
|
+
}
|
|
428
|
+
export { DEFAULT_REVIEW_PATH, parseIndependentReview, readIndependentReview };
|
|
429
|
+
//# sourceMappingURL=review.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"review.js","sourceRoot":"","sources":["../../lib/review.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/status.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { ProjectAdapter } from "./project-metadata.js";
|
|
|
6
6
|
import type { IdeasSummary } from "./ideas.js";
|
|
7
7
|
import type { ProjectConfig, ProjectConfigState } from "./project-config.js";
|
|
8
8
|
import type { RunStateSummary } from "./run-state.js";
|
|
9
|
+
import type { ReviewCheckResult, ReviewFreshness, ReviewState } from "./review.js";
|
|
9
10
|
type CompletionState = "blocked" | "needs_verification" | "ready";
|
|
10
11
|
interface StatusWarning {
|
|
11
12
|
code: string;
|
|
@@ -36,6 +37,21 @@ interface StatusFindings {
|
|
|
36
37
|
active: Array<Pick<Finding, "id" | "severity" | "status" | "title">>;
|
|
37
38
|
blockers: Array<Pick<Finding, "id" | "severity" | "status" | "title">>;
|
|
38
39
|
}
|
|
40
|
+
interface StatusReview {
|
|
41
|
+
state: ReviewState;
|
|
42
|
+
freshness: ReviewFreshness;
|
|
43
|
+
verdict: "changes-requested" | "passed" | null;
|
|
44
|
+
checkResult: ReviewCheckResult | null;
|
|
45
|
+
targetCommit: string | null;
|
|
46
|
+
requestedReviewer: string | null;
|
|
47
|
+
requestedModel: string | null;
|
|
48
|
+
reviewerAdapter: string | null;
|
|
49
|
+
reviewerModel: string | null;
|
|
50
|
+
warnings: StatusWarning[];
|
|
51
|
+
}
|
|
52
|
+
interface StatusActiveRun extends ActiveRunSummary {
|
|
53
|
+
review: StatusReview;
|
|
54
|
+
}
|
|
39
55
|
interface StatusNextAction {
|
|
40
56
|
command: string | null;
|
|
41
57
|
reason: string;
|
|
@@ -61,8 +77,9 @@ interface ProjectStatus {
|
|
|
61
77
|
configuration: StatusConfiguration;
|
|
62
78
|
activity: StatusActivity;
|
|
63
79
|
currentWork: StatusCurrentWork;
|
|
64
|
-
activeRuns:
|
|
80
|
+
activeRuns: StatusActiveRun[];
|
|
65
81
|
findings: StatusFindings;
|
|
82
|
+
review: StatusReview;
|
|
66
83
|
ideas: IdeasSummary;
|
|
67
84
|
git: GitStatusSummary;
|
|
68
85
|
completion: StatusCompletion;
|
|
@@ -73,4 +90,4 @@ declare function readProjectStatus(startPath?: string): Promise<ProjectStatus>;
|
|
|
73
90
|
declare function formatHumanStatus(status: ProjectStatus, options?: HumanStatusOptions): string;
|
|
74
91
|
declare function shouldUseColor(isTTY?: boolean | undefined, environment?: NodeJS.ProcessEnv): boolean;
|
|
75
92
|
export { formatHumanStatus, readProjectStatus, shouldUseColor };
|
|
76
|
-
export type { CompletionState, HumanStatusOptions, ProjectStatus, StatusActivity, StatusCompletion, StatusCurrentWork, StatusFindings, StatusNextAction, StatusWarning };
|
|
93
|
+
export type { CompletionState, HumanStatusOptions, ProjectStatus, StatusActivity, StatusActiveRun, StatusCompletion, StatusCurrentWork, StatusFindings, StatusNextAction, StatusWarning };
|
package/dist/lib/status.js
CHANGED
|
@@ -7,6 +7,7 @@ import { readProjectMetadata } from "./project-metadata.js";
|
|
|
7
7
|
import { readIdeas } from "./ideas.js";
|
|
8
8
|
import { readProjectConfig } from "./project-config.js";
|
|
9
9
|
import { readRunState } from "./run-state.js";
|
|
10
|
+
import { readIndependentReview } from "./review.js";
|
|
10
11
|
async function readProjectStatus(startPath = process.cwd()) {
|
|
11
12
|
const metadata = await readProjectMetadata(startPath);
|
|
12
13
|
const [contextPaths, config, currentWork, activeRuns, findings, git, ideas, runState] = await Promise.all([
|
|
@@ -19,6 +20,16 @@ async function readProjectStatus(startPath = process.cwd()) {
|
|
|
19
20
|
readIdeas(metadata.project.root),
|
|
20
21
|
readRunState(metadata.project.root)
|
|
21
22
|
]);
|
|
23
|
+
const primaryRunId = currentWork.runId || (activeRuns.length === 1 ? activeRuns[0]?.runId : undefined);
|
|
24
|
+
const [review, activeRunReviews] = await Promise.all([
|
|
25
|
+
readIndependentReview(metadata.project.root, primaryRunId || undefined),
|
|
26
|
+
Promise.all(activeRuns.map((run) => readIndependentReview(metadata.project.root, run.runId)))
|
|
27
|
+
]);
|
|
28
|
+
const statusReview = formatReview(review);
|
|
29
|
+
const statusActiveRuns = activeRuns.map((run, index) => ({
|
|
30
|
+
...run,
|
|
31
|
+
review: formatReview(activeRunReviews[index] || review)
|
|
32
|
+
}));
|
|
22
33
|
let stageMarkdown = "";
|
|
23
34
|
try {
|
|
24
35
|
stageMarkdown = await fs.readFile(contextPaths.stagePath, "utf8");
|
|
@@ -30,9 +41,10 @@ async function readProjectStatus(startPath = process.cwd()) {
|
|
|
30
41
|
...currentWork.warnings,
|
|
31
42
|
...findings.warnings,
|
|
32
43
|
...runState.warnings,
|
|
44
|
+
...review.warnings,
|
|
33
45
|
...findDrift(currentWork, git)
|
|
34
46
|
];
|
|
35
|
-
const completion = selectCompletion(currentWork, findings, git, stageMarkdown);
|
|
47
|
+
const completion = selectCompletion(currentWork, findings, git, stageMarkdown, review, config.values);
|
|
36
48
|
const nextAction = selectNextAction(currentWork, findings, stageMarkdown);
|
|
37
49
|
return {
|
|
38
50
|
schemaVersion: metadata.schemaVersion,
|
|
@@ -62,8 +74,9 @@ async function readProjectStatus(startPath = process.cwd()) {
|
|
|
62
74
|
feature: runState.feature
|
|
63
75
|
},
|
|
64
76
|
currentWork: formatCurrentWork(currentWork),
|
|
65
|
-
activeRuns,
|
|
77
|
+
activeRuns: statusActiveRuns,
|
|
66
78
|
findings: formatFindings(findings),
|
|
79
|
+
review: statusReview,
|
|
67
80
|
ideas,
|
|
68
81
|
git,
|
|
69
82
|
completion,
|
|
@@ -101,7 +114,11 @@ function formatHumanStatus(status, options = {}) {
|
|
|
101
114
|
if (status.activeRuns && status.activeRuns.length > 0) {
|
|
102
115
|
lines.push(formatRow("Spec Queue", `${status.activeRuns.length} active (${status.activeRuns.map((r) => r.runId).join(", ")})`, style));
|
|
103
116
|
}
|
|
104
|
-
lines.push(formatRow("Findings", formatFindingsValue(status.findings, style), style)
|
|
117
|
+
lines.push(formatRow("Findings", formatFindingsValue(status.findings, style), style));
|
|
118
|
+
if (status.review && status.review.state !== "none") {
|
|
119
|
+
lines.push(formatRow("Review", formatReviewValue(status.review, style), style));
|
|
120
|
+
}
|
|
121
|
+
lines.push(formatRow("Completion", formatCompletionValue(status.completion, style), style), "", formatSection("Git", style));
|
|
105
122
|
appendGitLines(lines, status.git, style);
|
|
106
123
|
if (status.warnings.length > 0) {
|
|
107
124
|
lines.push("", formatSection("Attention", style));
|
|
@@ -126,7 +143,7 @@ function formatConfigValue(state) {
|
|
|
126
143
|
return "built-in defaults";
|
|
127
144
|
}
|
|
128
145
|
function formatQualityGates(gates) {
|
|
129
|
-
return `audit ${gates.audit}, check ${gates.check}, try guide ${gates.tryGuide}`;
|
|
146
|
+
return `audit ${gates.audit}, review ${gates.independentReview}, check ${gates.check}, try guide ${gates.tryGuide}`;
|
|
130
147
|
}
|
|
131
148
|
function shouldUseColor(isTTY = process.stdout.isTTY, environment = process.env) {
|
|
132
149
|
return isTTY === true && !Object.hasOwn(environment, "NO_COLOR");
|
|
@@ -137,6 +154,39 @@ function formatSection(label, style) {
|
|
|
137
154
|
function formatRow(label, value, style) {
|
|
138
155
|
return ` ${style.cyan(label.padEnd(14))}${value}`;
|
|
139
156
|
}
|
|
157
|
+
function formatReviewValue(review, style) {
|
|
158
|
+
const parts = [review.state];
|
|
159
|
+
if (review.verdict) {
|
|
160
|
+
parts.push(`verdict ${review.verdict}`);
|
|
161
|
+
}
|
|
162
|
+
if (review.checkResult) {
|
|
163
|
+
parts.push(`check ${review.checkResult}`);
|
|
164
|
+
}
|
|
165
|
+
parts.push(`freshness ${review.freshness}`);
|
|
166
|
+
if (review.reviewerModel) {
|
|
167
|
+
parts.push(`(${review.reviewerModel})`);
|
|
168
|
+
}
|
|
169
|
+
return review.freshness === "stale"
|
|
170
|
+
? style.yellow(parts.join(", "))
|
|
171
|
+
: parts.join(", ");
|
|
172
|
+
}
|
|
173
|
+
function formatReview(review) {
|
|
174
|
+
return {
|
|
175
|
+
state: review.state,
|
|
176
|
+
freshness: review.freshness,
|
|
177
|
+
verdict: review.verdict,
|
|
178
|
+
checkResult: review.checkResult,
|
|
179
|
+
targetCommit: review.targetCommit,
|
|
180
|
+
requestedReviewer: review.requestedReviewer,
|
|
181
|
+
requestedModel: review.requestedModel,
|
|
182
|
+
reviewerAdapter: review.reviewerAdapter,
|
|
183
|
+
reviewerModel: review.reviewerModel,
|
|
184
|
+
warnings: review.warnings.map((warning) => ({
|
|
185
|
+
code: warning.code,
|
|
186
|
+
message: warning.message
|
|
187
|
+
}))
|
|
188
|
+
};
|
|
189
|
+
}
|
|
140
190
|
function formatActivityValue(activity, style) {
|
|
141
191
|
if (activity.state !== "recorded" || !activity.command) {
|
|
142
192
|
return style.dim("none");
|
|
@@ -186,22 +236,22 @@ function formatFindingsValue(findings, style) {
|
|
|
186
236
|
}
|
|
187
237
|
const activeCounts = [...activeGroups.entries()].map(([label, ids]) => `${ids.length} ${label} (${ids.join(", ")})`);
|
|
188
238
|
const resolvedCounts = ["closed", "accepted", "invalid"]
|
|
189
|
-
.
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return
|
|
239
|
+
.map((status) => {
|
|
240
|
+
const count = findings.byStatus[status] || 0;
|
|
241
|
+
return count > 0 ? `${count} ${status}` : null;
|
|
242
|
+
})
|
|
243
|
+
.filter(Boolean);
|
|
244
|
+
const parts = [...activeCounts, ...resolvedCounts];
|
|
245
|
+
return parts.join(", ");
|
|
196
246
|
}
|
|
197
247
|
function formatCompletionValue(completion, style) {
|
|
198
248
|
if (completion.state === "ready") {
|
|
199
|
-
return style.green("ready");
|
|
249
|
+
return style.green("ready to complete");
|
|
200
250
|
}
|
|
201
251
|
if (completion.state === "needs_verification") {
|
|
202
|
-
return style.yellow(
|
|
252
|
+
return style.yellow(`needs verification (${completion.blockers.join("; ")})`);
|
|
203
253
|
}
|
|
204
|
-
return style.red(`blocked
|
|
254
|
+
return style.red(`blocked (${completion.blockers.join("; ")})`);
|
|
205
255
|
}
|
|
206
256
|
function appendGitLines(lines, git, style) {
|
|
207
257
|
if (!git.available) {
|
|
@@ -267,7 +317,7 @@ function formatFindings(findings) {
|
|
|
267
317
|
blockers: findings.blockers.map(selectFinding)
|
|
268
318
|
};
|
|
269
319
|
}
|
|
270
|
-
function selectCompletion(currentWork, findings, git, stageMarkdown) {
|
|
320
|
+
function selectCompletion(currentWork, findings, git, stageMarkdown, review, config) {
|
|
271
321
|
const blockers = [];
|
|
272
322
|
if (currentWork.state !== "active") {
|
|
273
323
|
blockers.push("no active delivery run or living spec");
|
|
@@ -281,6 +331,24 @@ function selectCompletion(currentWork, findings, git, stageMarkdown) {
|
|
|
281
331
|
if (!git.available) {
|
|
282
332
|
blockers.push("Git repository is unavailable");
|
|
283
333
|
}
|
|
334
|
+
if (review && config) {
|
|
335
|
+
const isGateActive = config.qualityGates.regular.independentReview !== "manual";
|
|
336
|
+
if (review.state === "malformed") {
|
|
337
|
+
blockers.push("independent review record is malformed");
|
|
338
|
+
}
|
|
339
|
+
else if (review.state === "changes-requested") {
|
|
340
|
+
blockers.push("independent review requested changes");
|
|
341
|
+
}
|
|
342
|
+
else if (review.state === "pending") {
|
|
343
|
+
blockers.push("independent review is pending");
|
|
344
|
+
}
|
|
345
|
+
else if (isGateActive && review.state === "none") {
|
|
346
|
+
blockers.push("independent review is required");
|
|
347
|
+
}
|
|
348
|
+
else if (review.state === "passed" && review.freshness !== "current") {
|
|
349
|
+
blockers.push("independent review receipt is stale");
|
|
350
|
+
}
|
|
351
|
+
}
|
|
284
352
|
if (blockers.length > 0) {
|
|
285
353
|
return { state: "blocked", blockers };
|
|
286
354
|
}
|