@pourkit/cli 0.0.0-next-20260614074434 → 0.0.0-next-20260614201555
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +183 -428
- package/dist/cli.js.map +1 -1
- package/dist/e2e/run-live-e2e.js +72 -278
- package/dist/e2e/run-live-e2e.js.map +1 -1
- package/dist/issues/close-issues-on-merge.js +19 -1
- package/dist/issues/close-issues-on-merge.js.map +1 -1
- package/dist/issues/unblock.js +19 -1
- package/dist/issues/unblock.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -153,6 +153,7 @@ __export(common_exports, {
|
|
|
153
153
|
execJson: () => execJson,
|
|
154
154
|
parseWorktreeListPorcelain: () => parseWorktreeListPorcelain,
|
|
155
155
|
readMaybeEnvInt: () => readMaybeEnvInt,
|
|
156
|
+
redactSensitiveValues: () => redactSensitiveValues,
|
|
156
157
|
repoRelative: () => repoRelative,
|
|
157
158
|
repoRoot: () => repoRoot,
|
|
158
159
|
sleep: () => sleep,
|
|
@@ -311,7 +312,14 @@ function parseWorktreeListPorcelain(text2, branch) {
|
|
|
311
312
|
}
|
|
312
313
|
return null;
|
|
313
314
|
}
|
|
314
|
-
|
|
315
|
+
function redactSensitiveValues(input) {
|
|
316
|
+
let redacted = input;
|
|
317
|
+
for (const pattern of TOKEN_LIKE_PATTERNS) {
|
|
318
|
+
redacted = redacted.replace(pattern, "[REDACTED]");
|
|
319
|
+
}
|
|
320
|
+
return redacted;
|
|
321
|
+
}
|
|
322
|
+
var execFileAsync, TRANSIENT_GH_ERROR, TYPE_LABELS, TOKEN_LIKE_PATTERNS;
|
|
315
323
|
var init_common = __esm({
|
|
316
324
|
"shared/common.ts"() {
|
|
317
325
|
"use strict";
|
|
@@ -325,6 +333,16 @@ var init_common = __esm({
|
|
|
325
333
|
"type:polish",
|
|
326
334
|
"type:refactor"
|
|
327
335
|
];
|
|
336
|
+
TOKEN_LIKE_PATTERNS = [
|
|
337
|
+
/gh[ps]_[A-Za-z0-9]{20,}/g,
|
|
338
|
+
/token[=:_\s][A-Za-z0-9_-]{20,}/gi,
|
|
339
|
+
/secret[=:_\s][A-Za-z0-9_-]{20,}/gi,
|
|
340
|
+
/credential[=:_\s][A-Za-z0-9_-]{20,}/gi,
|
|
341
|
+
/key[=:_\s][A-Za-z0-9_-]{20,}/gi,
|
|
342
|
+
/bearer\s+[A-Za-z0-9_-]{20,}/gi,
|
|
343
|
+
/authorization:\s*Bearer\s+[A-Za-z0-9_-]{20,}/gi,
|
|
344
|
+
/xox[baprs]-[A-Za-z0-9_-]{10,}/g
|
|
345
|
+
];
|
|
328
346
|
}
|
|
329
347
|
});
|
|
330
348
|
|
|
@@ -335,13 +353,20 @@ import { pathToFileURL } from "url";
|
|
|
335
353
|
import { Command, Option, CommanderError } from "commander";
|
|
336
354
|
|
|
337
355
|
// shared/config.ts
|
|
338
|
-
import { readFileSync } from "fs";
|
|
356
|
+
import { existsSync, readFileSync } from "fs";
|
|
339
357
|
import { fileURLToPath } from "url";
|
|
340
358
|
import { dirname, isAbsolute, join, normalize, sep, resolve } from "path";
|
|
341
359
|
import Ajv from "ajv";
|
|
342
360
|
var __filename = fileURLToPath(import.meta.url);
|
|
343
361
|
var __dirname = dirname(__filename);
|
|
344
|
-
|
|
362
|
+
function resolvePackagedAssetPath(fileName) {
|
|
363
|
+
const candidates = [
|
|
364
|
+
resolve(__dirname, "schema", fileName),
|
|
365
|
+
resolve(__dirname, "../schema", fileName)
|
|
366
|
+
];
|
|
367
|
+
return candidates.find((candidate) => existsSync(candidate)) ?? candidates[0];
|
|
368
|
+
}
|
|
369
|
+
var SCHEMA_PATH = resolvePackagedAssetPath("pourkit.schema.json");
|
|
345
370
|
var _schema = null;
|
|
346
371
|
var _validate = null;
|
|
347
372
|
var _ajvErrors = null;
|
|
@@ -929,12 +954,12 @@ function resolveTarget(config, explicitTarget) {
|
|
|
929
954
|
init_common();
|
|
930
955
|
|
|
931
956
|
// shared/worktree-run-state.ts
|
|
932
|
-
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
957
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
933
958
|
import { dirname as dirname2, join as join2 } from "path";
|
|
934
959
|
var WORKTREE_RUN_STATE_PATH = ".pourkit/state.json";
|
|
935
960
|
function readWorktreeRunState(worktreePath) {
|
|
936
961
|
const statePath = join2(worktreePath, WORKTREE_RUN_STATE_PATH);
|
|
937
|
-
if (!
|
|
962
|
+
if (!existsSync2(statePath)) {
|
|
938
963
|
return null;
|
|
939
964
|
}
|
|
940
965
|
try {
|
|
@@ -1106,7 +1131,7 @@ async function cleanupRepository(options) {
|
|
|
1106
1131
|
// commands/artifact-validation.ts
|
|
1107
1132
|
import { createHash } from "crypto";
|
|
1108
1133
|
import { execSync } from "child_process";
|
|
1109
|
-
import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as
|
|
1134
|
+
import { existsSync as existsSync7, readdirSync as readdirSync3, readFileSync as readFileSync7 } from "fs";
|
|
1110
1135
|
import { isAbsolute as isAbsolute3, join as join7, resolve as resolve3 } from "path";
|
|
1111
1136
|
|
|
1112
1137
|
// pr/review-verdict.ts
|
|
@@ -1140,7 +1165,7 @@ function parseReviewVerdict(output) {
|
|
|
1140
1165
|
|
|
1141
1166
|
// commands/review.ts
|
|
1142
1167
|
import {
|
|
1143
|
-
existsSync as
|
|
1168
|
+
existsSync as existsSync6,
|
|
1144
1169
|
mkdirSync as mkdirSync5,
|
|
1145
1170
|
readFileSync as readFileSync6,
|
|
1146
1171
|
readdirSync as readdirSync2,
|
|
@@ -1149,7 +1174,7 @@ import {
|
|
|
1149
1174
|
import { join as join6 } from "path";
|
|
1150
1175
|
|
|
1151
1176
|
// execution/agent-output-retry.ts
|
|
1152
|
-
import { existsSync as
|
|
1177
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, rmSync } from "fs";
|
|
1153
1178
|
import { dirname as dirname3, join as join4 } from "path";
|
|
1154
1179
|
async function executeWithMissingOrEmptyArtifactRetry({
|
|
1155
1180
|
executionProvider,
|
|
@@ -1207,7 +1232,7 @@ async function executeWithMissingOrEmptyArtifactRetry({
|
|
|
1207
1232
|
};
|
|
1208
1233
|
}
|
|
1209
1234
|
function readArtifactOutput(artifactPath) {
|
|
1210
|
-
if (!
|
|
1235
|
+
if (!existsSync3(artifactPath)) {
|
|
1211
1236
|
return { _tag: "missing", path: artifactPath };
|
|
1212
1237
|
}
|
|
1213
1238
|
const output = readFileSync3(artifactPath, "utf-8");
|
|
@@ -1222,7 +1247,7 @@ function prepareArtifactPath(artifactPath) {
|
|
|
1222
1247
|
}
|
|
1223
1248
|
|
|
1224
1249
|
// shared/run-context.ts
|
|
1225
|
-
import { existsSync as
|
|
1250
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, readdirSync } from "fs";
|
|
1226
1251
|
import { isAbsolute as isAbsolute2, join as join5, relative, resolve as resolve2 } from "path";
|
|
1227
1252
|
|
|
1228
1253
|
// commands/run-verification.ts
|
|
@@ -1371,13 +1396,6 @@ var STAGE_SECTIONS = {
|
|
|
1371
1396
|
"branch",
|
|
1372
1397
|
"verification-commands",
|
|
1373
1398
|
"artifacts"
|
|
1374
|
-
],
|
|
1375
|
-
prdReconciliation: [
|
|
1376
|
-
"issue",
|
|
1377
|
-
"comments",
|
|
1378
|
-
"branch",
|
|
1379
|
-
"verification-commands",
|
|
1380
|
-
"artifacts"
|
|
1381
1399
|
]
|
|
1382
1400
|
};
|
|
1383
1401
|
function buildRunContextArtifact(options) {
|
|
@@ -1524,7 +1542,7 @@ function renderPrdContext(issue, parentPrdIssue, repoRoot2) {
|
|
|
1524
1542
|
}
|
|
1525
1543
|
for (const documentPath of documentPaths) {
|
|
1526
1544
|
const absolutePath = resolveRepoPath(repoRoot2, documentPath);
|
|
1527
|
-
if (!absolutePath || !
|
|
1545
|
+
if (!absolutePath || !existsSync4(absolutePath)) continue;
|
|
1528
1546
|
parts.push(
|
|
1529
1547
|
`### Document Content: \`${documentPath}\``,
|
|
1530
1548
|
"",
|
|
@@ -1561,27 +1579,20 @@ function resolveRepoPath(repoRoot2, path9) {
|
|
|
1561
1579
|
return resolved;
|
|
1562
1580
|
}
|
|
1563
1581
|
function findParentPrdPath(repoRoot2, parentRef) {
|
|
1564
|
-
const
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
"architecture",
|
|
1568
|
-
parentRef,
|
|
1569
|
-
"PRD.md"
|
|
1570
|
-
);
|
|
1571
|
-
if (existsSync3(directPath)) return directPath;
|
|
1572
|
-
const architectureRoot = join5(repoRoot2, ".pourkit", "architecture");
|
|
1573
|
-
if (!existsSync3(architectureRoot)) return null;
|
|
1574
|
-
return findPrdMirror(architectureRoot, parentRef);
|
|
1582
|
+
const plansRoot = join5(repoRoot2, ".pourkit", "plans");
|
|
1583
|
+
if (!existsSync4(plansRoot)) return null;
|
|
1584
|
+
return findPrdInPlans(plansRoot, parentRef);
|
|
1575
1585
|
}
|
|
1576
|
-
function
|
|
1586
|
+
function findPrdInPlans(directory, parentRef) {
|
|
1577
1587
|
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
1578
1588
|
const entryPath = join5(directory, entry.name);
|
|
1579
1589
|
if (entry.isDirectory()) {
|
|
1580
|
-
|
|
1590
|
+
const prdNumber = parentRef.match(/^PRD-(\d+)$/)?.[1];
|
|
1591
|
+
if (entry.name.startsWith(parentRef) || prdNumber && entry.name.startsWith(`${prdNumber}-`)) {
|
|
1581
1592
|
const prdPath = join5(entryPath, "PRD.md");
|
|
1582
|
-
if (
|
|
1593
|
+
if (existsSync4(prdPath)) return prdPath;
|
|
1583
1594
|
}
|
|
1584
|
-
const nested =
|
|
1595
|
+
const nested = findPrdInPlans(entryPath, parentRef);
|
|
1585
1596
|
if (nested) return nested;
|
|
1586
1597
|
}
|
|
1587
1598
|
}
|
|
@@ -1613,7 +1624,7 @@ function appendProtectedWorkGuidance(promptBody) {
|
|
|
1613
1624
|
|
|
1614
1625
|
// shared/effect-services.ts
|
|
1615
1626
|
import { Context, Effect, Layer } from "effect";
|
|
1616
|
-
import { existsSync as
|
|
1627
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync2, rmSync as rmSync2 } from "fs";
|
|
1617
1628
|
var GitExecutionError = class extends Error {
|
|
1618
1629
|
_tag = "GitExecutionError";
|
|
1619
1630
|
message;
|
|
@@ -1641,7 +1652,7 @@ var FileSystemDefault = Layer.succeed(
|
|
|
1641
1652
|
)
|
|
1642
1653
|
}),
|
|
1643
1654
|
exists: (path9) => Effect.try({
|
|
1644
|
-
try: () =>
|
|
1655
|
+
try: () => existsSync5(path9),
|
|
1645
1656
|
catch: (error) => new Error(
|
|
1646
1657
|
`Failed to check existence of ${path9}: ${error instanceof Error ? error.message : String(error)}`
|
|
1647
1658
|
)
|
|
@@ -2025,7 +2036,7 @@ function extractLatestFindingIds(reviewOutput, iteration) {
|
|
|
2025
2036
|
return ids;
|
|
2026
2037
|
}
|
|
2027
2038
|
function validateRefactorArtifact(artifactPath, findingIds) {
|
|
2028
|
-
if (!
|
|
2039
|
+
if (!existsSync6(artifactPath)) {
|
|
2029
2040
|
throw new RefactorArtifactValidationError(
|
|
2030
2041
|
`Refactor artifact missing at ${artifactPath}`
|
|
2031
2042
|
);
|
|
@@ -2516,14 +2527,14 @@ function recoverReviewOutputFromString(logContent) {
|
|
|
2516
2527
|
return recoveredOutput.length > 0 ? recoveredOutput : null;
|
|
2517
2528
|
}
|
|
2518
2529
|
function recoverReviewOutputFromLog(logPath) {
|
|
2519
|
-
if (!
|
|
2530
|
+
if (!existsSync6(logPath)) {
|
|
2520
2531
|
return null;
|
|
2521
2532
|
}
|
|
2522
2533
|
const logContent = readFileSync6(logPath, "utf-8");
|
|
2523
2534
|
return recoverReviewOutputFromString(logContent);
|
|
2524
2535
|
}
|
|
2525
2536
|
function readReviewArtifact(artifactPath, logPath) {
|
|
2526
|
-
if (
|
|
2537
|
+
if (existsSync6(artifactPath)) {
|
|
2527
2538
|
const output = readFileSync6(artifactPath, "utf-8");
|
|
2528
2539
|
if (output.trim()) {
|
|
2529
2540
|
return output;
|
|
@@ -2534,7 +2545,7 @@ function readReviewArtifact(artifactPath, logPath) {
|
|
|
2534
2545
|
writeFileSync3(artifactPath, recoveredOutput, "utf-8");
|
|
2535
2546
|
return recoveredOutput;
|
|
2536
2547
|
}
|
|
2537
|
-
if (!
|
|
2548
|
+
if (!existsSync6(artifactPath)) {
|
|
2538
2549
|
throw new Error(`Reviewer did not produce output at ${artifactPath}`);
|
|
2539
2550
|
}
|
|
2540
2551
|
throw new Error(`Reviewer produced empty output at ${artifactPath}`);
|
|
@@ -3173,194 +3184,6 @@ function parseConflictResolutionArtifact(output) {
|
|
|
3173
3184
|
};
|
|
3174
3185
|
}
|
|
3175
3186
|
|
|
3176
|
-
// prd-run/final-review-validation.ts
|
|
3177
|
-
import { existsSync as existsSync6, readFileSync as readFileSync7 } from "fs";
|
|
3178
|
-
function parseFinalReviewArtifact(artifactPath) {
|
|
3179
|
-
if (!existsSync6(artifactPath)) {
|
|
3180
|
-
return {
|
|
3181
|
-
ok: false,
|
|
3182
|
-
reason: "Final Review artifact not found.",
|
|
3183
|
-
diagnostics: [`Artifact path: ${artifactPath}`]
|
|
3184
|
-
};
|
|
3185
|
-
}
|
|
3186
|
-
let content;
|
|
3187
|
-
try {
|
|
3188
|
-
content = readFileSync7(artifactPath, "utf-8");
|
|
3189
|
-
} catch (error) {
|
|
3190
|
-
return {
|
|
3191
|
-
ok: false,
|
|
3192
|
-
reason: "Final Review artifact could not be read.",
|
|
3193
|
-
diagnostics: [
|
|
3194
|
-
error instanceof Error ? error.message : String(error),
|
|
3195
|
-
`Artifact path: ${artifactPath}`
|
|
3196
|
-
]
|
|
3197
|
-
};
|
|
3198
|
-
}
|
|
3199
|
-
let parsed;
|
|
3200
|
-
try {
|
|
3201
|
-
parsed = JSON.parse(content);
|
|
3202
|
-
} catch {
|
|
3203
|
-
return {
|
|
3204
|
-
ok: false,
|
|
3205
|
-
reason: "Final Review artifact is not valid JSON.",
|
|
3206
|
-
diagnostics: [`Artifact path: ${artifactPath}`]
|
|
3207
|
-
};
|
|
3208
|
-
}
|
|
3209
|
-
const verdict = parsed.verdict;
|
|
3210
|
-
if (!verdict || typeof verdict !== "string") {
|
|
3211
|
-
return {
|
|
3212
|
-
ok: false,
|
|
3213
|
-
reason: "Final Review artifact is missing a verdict field.",
|
|
3214
|
-
diagnostics: [`Artifact content preview: ${content.slice(0, 300)}`]
|
|
3215
|
-
};
|
|
3216
|
-
}
|
|
3217
|
-
const allowedVerdicts = [
|
|
3218
|
-
"pass_no_changes",
|
|
3219
|
-
"pass_with_retouch",
|
|
3220
|
-
"needs_human_review",
|
|
3221
|
-
"blocked"
|
|
3222
|
-
];
|
|
3223
|
-
if (!allowedVerdicts.includes(verdict)) {
|
|
3224
|
-
return {
|
|
3225
|
-
ok: false,
|
|
3226
|
-
reason: `Final Review artifact has unsupported verdict "${verdict}".`,
|
|
3227
|
-
diagnostics: [`Allowed verdicts: ${allowedVerdicts.join(", ")}`]
|
|
3228
|
-
};
|
|
3229
|
-
}
|
|
3230
|
-
const summary = typeof parsed.summary === "string" ? parsed.summary : typeof parsed.reason === "string" ? parsed.reason : String(verdict);
|
|
3231
|
-
const diagnostics = Array.isArray(parsed.diagnostics) ? parsed.diagnostics : [];
|
|
3232
|
-
const changedPaths = Array.isArray(parsed.changedPaths) ? parsed.changedPaths : void 0;
|
|
3233
|
-
const isAutoSummary = !parsed.summary && !parsed.reason;
|
|
3234
|
-
if (verdict === "pass_with_retouch" && (!changedPaths || changedPaths.length === 0) && isAutoSummary) {
|
|
3235
|
-
return {
|
|
3236
|
-
ok: false,
|
|
3237
|
-
reason: 'Final Review artifact with "pass_with_retouch" verdict requires changed paths.',
|
|
3238
|
-
diagnostics: [
|
|
3239
|
-
"pass_with_retouch verdict must include a changedPaths array in the artifact or provide a summary/reason with enough context for git diff fallback.",
|
|
3240
|
-
"Provide changedPaths or a descriptive summary in the artifact."
|
|
3241
|
-
]
|
|
3242
|
-
};
|
|
3243
|
-
}
|
|
3244
|
-
const prdRef = typeof parsed.prdRef === "string" && parsed.prdRef.trim() ? parsed.prdRef.trim() : void 0;
|
|
3245
|
-
const stage = typeof parsed.stage === "string" && parsed.stage.trim() ? parsed.stage.trim() : void 0;
|
|
3246
|
-
const checkoutBase = typeof parsed.checkoutBase === "string" && parsed.checkoutBase.trim() ? parsed.checkoutBase.trim() : void 0;
|
|
3247
|
-
const reviewBase = typeof parsed.reviewBase === "string" && parsed.reviewBase.trim() ? parsed.reviewBase.trim() : void 0;
|
|
3248
|
-
return {
|
|
3249
|
-
ok: true,
|
|
3250
|
-
verdict,
|
|
3251
|
-
summary,
|
|
3252
|
-
diagnostics,
|
|
3253
|
-
changedPaths,
|
|
3254
|
-
prdRef,
|
|
3255
|
-
stage,
|
|
3256
|
-
checkoutBase,
|
|
3257
|
-
reviewBase
|
|
3258
|
-
};
|
|
3259
|
-
}
|
|
3260
|
-
function validateFinalReviewArtifactSemanticIds(artifact, context) {
|
|
3261
|
-
const errors = [];
|
|
3262
|
-
if (!artifact.prdRef) {
|
|
3263
|
-
errors.push("Final Review artifact is missing prdRef.");
|
|
3264
|
-
} else if (artifact.prdRef !== context.prdRef) {
|
|
3265
|
-
errors.push(
|
|
3266
|
-
`Final Review artifact prdRef "${artifact.prdRef}" does not match active PRD Run "${context.prdRef}".`
|
|
3267
|
-
);
|
|
3268
|
-
}
|
|
3269
|
-
if (!artifact.stage) {
|
|
3270
|
-
errors.push("Final Review artifact is missing stage field.");
|
|
3271
|
-
} else if (artifact.stage !== "prdFinalReview") {
|
|
3272
|
-
errors.push(
|
|
3273
|
-
`Final Review artifact stage "${artifact.stage}" is not "prdFinalReview".`
|
|
3274
|
-
);
|
|
3275
|
-
}
|
|
3276
|
-
if (!artifact.checkoutBase) {
|
|
3277
|
-
errors.push("Final Review artifact is missing checkoutBase.");
|
|
3278
|
-
} else if (artifact.checkoutBase !== context.prdBranch) {
|
|
3279
|
-
errors.push(
|
|
3280
|
-
`Final Review artifact checkoutBase "${artifact.checkoutBase}" does not match active PRD Branch "${context.prdBranch}".`
|
|
3281
|
-
);
|
|
3282
|
-
}
|
|
3283
|
-
if (!artifact.reviewBase) {
|
|
3284
|
-
errors.push("Final Review artifact is missing reviewBase.");
|
|
3285
|
-
} else if (artifact.reviewBase !== context.mergeBase) {
|
|
3286
|
-
errors.push(
|
|
3287
|
-
`Final Review artifact reviewBase "${artifact.reviewBase}" does not match active merge base "${context.mergeBase}".`
|
|
3288
|
-
);
|
|
3289
|
-
}
|
|
3290
|
-
if (errors.length > 0) {
|
|
3291
|
-
return { ok: false, errors, blockedGate: "final-review" };
|
|
3292
|
-
}
|
|
3293
|
-
return { ok: true };
|
|
3294
|
-
}
|
|
3295
|
-
function validateFinalReviewRetouchScope(changedPaths) {
|
|
3296
|
-
if (!changedPaths || changedPaths.length === 0) {
|
|
3297
|
-
return {
|
|
3298
|
-
ok: false,
|
|
3299
|
-
reason: "Final Review retouch scope validation failed. No changed paths available. Provide changed paths or run Final Review with a summary that includes changed paths.",
|
|
3300
|
-
diagnostics: ["Changed paths list is empty or undefined."],
|
|
3301
|
-
offendingPaths: []
|
|
3302
|
-
};
|
|
3303
|
-
}
|
|
3304
|
-
const offendingPaths = changedPaths.filter((p) => !isRetouchScopePath(p));
|
|
3305
|
-
const allowedPaths = changedPaths.filter((p) => isRetouchScopePath(p));
|
|
3306
|
-
if (allowedPaths.length === 0) {
|
|
3307
|
-
return {
|
|
3308
|
-
ok: false,
|
|
3309
|
-
reason: "Final Review retouch scope validation failed. No implementation, test, or Changeset paths found for retouch.",
|
|
3310
|
-
diagnostics: [
|
|
3311
|
-
"All changed paths are prohibited for retouch.",
|
|
3312
|
-
...changedPaths.map((p) => ` - ${p}`)
|
|
3313
|
-
],
|
|
3314
|
-
offendingPaths
|
|
3315
|
-
};
|
|
3316
|
-
}
|
|
3317
|
-
if (offendingPaths.length > 0) {
|
|
3318
|
-
return {
|
|
3319
|
-
ok: false,
|
|
3320
|
-
reason: "Final Review retouch scope validation failed. Prohibited paths cannot be included in retouch PR.",
|
|
3321
|
-
diagnostics: [
|
|
3322
|
-
"Prohibited paths found:",
|
|
3323
|
-
...offendingPaths.map((p) => ` - ${p}`)
|
|
3324
|
-
],
|
|
3325
|
-
offendingPaths
|
|
3326
|
-
};
|
|
3327
|
-
}
|
|
3328
|
-
return { ok: true, changedPaths };
|
|
3329
|
-
}
|
|
3330
|
-
function validateFinalReviewAgentOutputs(options) {
|
|
3331
|
-
const artifact = parseFinalReviewArtifact(options.artifactPath);
|
|
3332
|
-
if (!artifact.ok) {
|
|
3333
|
-
return { ...artifact, offendingPaths: [] };
|
|
3334
|
-
}
|
|
3335
|
-
const semanticResult = validateFinalReviewArtifactSemanticIds(
|
|
3336
|
-
artifact,
|
|
3337
|
-
options.context
|
|
3338
|
-
);
|
|
3339
|
-
if (!semanticResult.ok) {
|
|
3340
|
-
return {
|
|
3341
|
-
ok: false,
|
|
3342
|
-
reason: "Final Review artifact has mismatched semantic IDs.",
|
|
3343
|
-
diagnostics: semanticResult.errors,
|
|
3344
|
-
offendingPaths: []
|
|
3345
|
-
};
|
|
3346
|
-
}
|
|
3347
|
-
if (artifact.verdict !== "pass_with_retouch") {
|
|
3348
|
-
return { ok: true, artifact };
|
|
3349
|
-
}
|
|
3350
|
-
const changedPaths = options.changedPaths && options.changedPaths.length > 0 ? options.changedPaths : artifact.changedPaths;
|
|
3351
|
-
const retouch = validateFinalReviewRetouchScope(changedPaths ?? []);
|
|
3352
|
-
if (!retouch.ok) {
|
|
3353
|
-
return retouch;
|
|
3354
|
-
}
|
|
3355
|
-
return { ok: true, artifact, retouch };
|
|
3356
|
-
}
|
|
3357
|
-
function isRetouchScopePath(path9) {
|
|
3358
|
-
if (path9.startsWith(".pourkit/plans/") || path9 === ".pourkit/CONTEXT.md" || path9.startsWith(".pourkit/docs/") || /^\.pourkit\/prd-runs\/[^/]+\.json$/.test(path9)) {
|
|
3359
|
-
return false;
|
|
3360
|
-
}
|
|
3361
|
-
return true;
|
|
3362
|
-
}
|
|
3363
|
-
|
|
3364
3187
|
// commands/artifact-validation.ts
|
|
3365
3188
|
var CONFLICT_MARKER_PATTERN = /<<<<<<<|=======|>>>>>>>/m;
|
|
3366
3189
|
function invalid(options, reason, diagnostics = []) {
|
|
@@ -3388,7 +3211,7 @@ function readArtifact(options) {
|
|
|
3388
3211
|
};
|
|
3389
3212
|
}
|
|
3390
3213
|
try {
|
|
3391
|
-
const content =
|
|
3214
|
+
const content = readFileSync7(options.artifactPath, "utf-8");
|
|
3392
3215
|
if (!content.trim()) {
|
|
3393
3216
|
return { ok: false, result: invalid(options, "Artifact is empty") };
|
|
3394
3217
|
}
|
|
@@ -3559,7 +3382,7 @@ function validateAgentArtifact(options) {
|
|
|
3559
3382
|
case "refactor": {
|
|
3560
3383
|
let findingIds = options.findingIds ?? [];
|
|
3561
3384
|
if (findingIds.length === 0 && options.latestReviewArtifactPath) {
|
|
3562
|
-
const latestReview =
|
|
3385
|
+
const latestReview = readFileSync7(
|
|
3563
3386
|
options.latestReviewArtifactPath,
|
|
3564
3387
|
"utf-8"
|
|
3565
3388
|
);
|
|
@@ -3585,7 +3408,7 @@ function validateAgentArtifact(options) {
|
|
|
3585
3408
|
const filePath = resolve3(base, file);
|
|
3586
3409
|
try {
|
|
3587
3410
|
return CONFLICT_MARKER_PATTERN.test(
|
|
3588
|
-
|
|
3411
|
+
readFileSync7(filePath, "utf-8")
|
|
3589
3412
|
);
|
|
3590
3413
|
} catch {
|
|
3591
3414
|
return false;
|
|
@@ -3601,29 +3424,6 @@ function validateAgentArtifact(options) {
|
|
|
3601
3424
|
}
|
|
3602
3425
|
return valid(options, [`status: ${parsed.status}`]);
|
|
3603
3426
|
}
|
|
3604
|
-
// QUARANTINED: Retained for Issue Final Review artifact validation via
|
|
3605
|
-
// `runPrdRunValidateFinalReviewCommand`. Remove when Issue Final Review
|
|
3606
|
-
// is migrated to its own dedicated validator kind.
|
|
3607
|
-
case "final-review": {
|
|
3608
|
-
if (!options.prdRef || !options.checkoutBase || !options.reviewBase) {
|
|
3609
|
-
return invalid(
|
|
3610
|
-
options,
|
|
3611
|
-
"Final Review artifact validation requires --prd-ref, --checkout-base, and --review-base."
|
|
3612
|
-
);
|
|
3613
|
-
}
|
|
3614
|
-
const result = validateFinalReviewAgentOutputs({
|
|
3615
|
-
artifactPath: options.artifactPath,
|
|
3616
|
-
context: {
|
|
3617
|
-
prdRef: options.prdRef,
|
|
3618
|
-
prdBranch: options.checkoutBase,
|
|
3619
|
-
mergeBase: options.reviewBase
|
|
3620
|
-
}
|
|
3621
|
-
});
|
|
3622
|
-
if (!result.ok) {
|
|
3623
|
-
return invalid(options, result.reason, result.diagnostics);
|
|
3624
|
-
}
|
|
3625
|
-
return valid(options, [`verdict: ${result.artifact.verdict}`]);
|
|
3626
|
-
}
|
|
3627
3427
|
case "issue-final-review": {
|
|
3628
3428
|
if (options.issueNumber === void 0 || !options.branchName) {
|
|
3629
3429
|
return invalid(
|
|
@@ -3663,12 +3463,6 @@ function validateAgentArtifact(options) {
|
|
|
3663
3463
|
}
|
|
3664
3464
|
return valid(options, [`decision: ${parsed.json.recoveryDecision}`]);
|
|
3665
3465
|
}
|
|
3666
|
-
case "reconciliation":
|
|
3667
|
-
case "planning-manifest":
|
|
3668
|
-
return invalid(
|
|
3669
|
-
options,
|
|
3670
|
-
`Artifact kind "${options.kind}" has been removed from PRD Run validation`
|
|
3671
|
-
);
|
|
3672
3466
|
case "local-prd":
|
|
3673
3467
|
case "local-issue":
|
|
3674
3468
|
case "local-triage":
|
|
@@ -3749,7 +3543,7 @@ function runLocalValidateArtifactCommand(options) {
|
|
|
3749
3543
|
}
|
|
3750
3544
|
function readLocalArtifact(path9, failureCode) {
|
|
3751
3545
|
try {
|
|
3752
|
-
const raw =
|
|
3546
|
+
const raw = readFileSync7(path9, "utf-8");
|
|
3753
3547
|
const parsed = JSON.parse(raw);
|
|
3754
3548
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
3755
3549
|
return {
|
|
@@ -4448,7 +4242,7 @@ function validateLocalTriage(prdPath, issuePaths) {
|
|
|
4448
4242
|
}
|
|
4449
4243
|
|
|
4450
4244
|
// commands/issue-run.ts
|
|
4451
|
-
import { existsSync as existsSync12, readFileSync as
|
|
4245
|
+
import { existsSync as existsSync12, readFileSync as readFileSync14 } from "fs";
|
|
4452
4246
|
import { isAbsolute as isAbsolute4, join as join15 } from "path";
|
|
4453
4247
|
|
|
4454
4248
|
// pr/templates.ts
|
|
@@ -4584,7 +4378,7 @@ function runEffectAndMapExit(program) {
|
|
|
4584
4378
|
}
|
|
4585
4379
|
|
|
4586
4380
|
// shared/attempt-log.ts
|
|
4587
|
-
import { appendFileSync, existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as
|
|
4381
|
+
import { appendFileSync, existsSync as existsSync8, mkdirSync as mkdirSync6, readFileSync as readFileSync8 } from "fs";
|
|
4588
4382
|
import { dirname as dirname4, join as join8 } from "path";
|
|
4589
4383
|
var ATTEMPT_LOG_PATH = ".pourkit/attempt-log.jsonl";
|
|
4590
4384
|
function writeAttemptLog(worktreePath, entry) {
|
|
@@ -4597,7 +4391,7 @@ function readAttemptLog(worktreePath) {
|
|
|
4597
4391
|
if (!existsSync8(logPath)) {
|
|
4598
4392
|
return [];
|
|
4599
4393
|
}
|
|
4600
|
-
const raw =
|
|
4394
|
+
const raw = readFileSync8(logPath, "utf-8");
|
|
4601
4395
|
const lines = raw.split("\n").filter((l) => l.length > 0);
|
|
4602
4396
|
const entries = [];
|
|
4603
4397
|
for (const line of lines) {
|
|
@@ -4716,7 +4510,7 @@ async function runBaseRefreshAttempt(options) {
|
|
|
4716
4510
|
}
|
|
4717
4511
|
|
|
4718
4512
|
// commands/conflict-resolution.ts
|
|
4719
|
-
import { existsSync as existsSync9, readFileSync as
|
|
4513
|
+
import { existsSync as existsSync9, readFileSync as readFileSync9 } from "fs";
|
|
4720
4514
|
import { join as join9 } from "path";
|
|
4721
4515
|
init_common();
|
|
4722
4516
|
var CONFLICT_MARKER_PATTERN2 = /<<<<<<<|=======|>>>>>>>/m;
|
|
@@ -4724,7 +4518,7 @@ async function hasUnresolvedConflictMarkers(worktreePath, files) {
|
|
|
4724
4518
|
for (const file of files) {
|
|
4725
4519
|
const filePath = join9(worktreePath, file);
|
|
4726
4520
|
try {
|
|
4727
|
-
const content =
|
|
4521
|
+
const content = readFileSync9(filePath, "utf-8");
|
|
4728
4522
|
if (CONFLICT_MARKER_PATTERN2.test(content)) {
|
|
4729
4523
|
return true;
|
|
4730
4524
|
}
|
|
@@ -5055,7 +4849,7 @@ async function prepareSerenaForTarget(options) {
|
|
|
5055
4849
|
}
|
|
5056
4850
|
|
|
5057
4851
|
// failure-resolution/failure-resolution-agent.ts
|
|
5058
|
-
import { readFileSync as
|
|
4852
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
5059
4853
|
import { join as join10 } from "path";
|
|
5060
4854
|
|
|
5061
4855
|
// failure-resolution/recovery-policy.ts
|
|
@@ -5209,7 +5003,7 @@ async function runFailureResolutionAgent(options) {
|
|
|
5209
5003
|
}
|
|
5210
5004
|
let artifact;
|
|
5211
5005
|
try {
|
|
5212
|
-
const md =
|
|
5006
|
+
const md = readFileSync10(fullArtifactPath, "utf-8");
|
|
5213
5007
|
const validation2 = validateAgentArtifact({
|
|
5214
5008
|
kind: "failure-resolution",
|
|
5215
5009
|
artifactPath: fullArtifactPath,
|
|
@@ -5303,7 +5097,7 @@ async function writeRecoveryAttempt(worktreePath, outcome, fingerprint, summary,
|
|
|
5303
5097
|
|
|
5304
5098
|
// commands/pr-description-agent.ts
|
|
5305
5099
|
import { join as join12 } from "path";
|
|
5306
|
-
import { readFileSync as
|
|
5100
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
5307
5101
|
|
|
5308
5102
|
// pr/pr-description-context.ts
|
|
5309
5103
|
init_common();
|
|
@@ -5497,7 +5291,7 @@ function runFinalizerAgent(options) {
|
|
|
5497
5291
|
],
|
|
5498
5292
|
logger: options.logger
|
|
5499
5293
|
});
|
|
5500
|
-
const output =
|
|
5294
|
+
const output = readFileSync11(artifactPath, "utf-8");
|
|
5501
5295
|
yield* persistGeneratedArtifactEffect(options.worktreePath, output, fs);
|
|
5502
5296
|
return result;
|
|
5503
5297
|
});
|
|
@@ -5625,7 +5419,7 @@ function persistGeneratedArtifactEffect(worktreePath, output, fs) {
|
|
|
5625
5419
|
|
|
5626
5420
|
// prd-run/local-merge-coordinator.ts
|
|
5627
5421
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
5628
|
-
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as
|
|
5422
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync12, writeFileSync as writeFileSync4 } from "fs";
|
|
5629
5423
|
import { join as join13 } from "path";
|
|
5630
5424
|
|
|
5631
5425
|
// prd-run/local-branches.ts
|
|
@@ -5728,7 +5522,7 @@ function readIssueBranchName(repoRoot2, prdId, issueId) {
|
|
|
5728
5522
|
const issuePath = getIssueArtifactPath(repoRoot2, prdId, issueId);
|
|
5729
5523
|
if (!existsSync10(issuePath)) return null;
|
|
5730
5524
|
try {
|
|
5731
|
-
const content =
|
|
5525
|
+
const content = readFileSync12(issuePath, "utf-8");
|
|
5732
5526
|
const parsed = JSON.parse(content);
|
|
5733
5527
|
return typeof parsed.branchName === "string" && parsed.branchName ? parsed.branchName : null;
|
|
5734
5528
|
} catch {
|
|
@@ -5740,7 +5534,7 @@ async function hasLocalIssueMergeReceipt(prdId, issueId, repoRoot2) {
|
|
|
5740
5534
|
const receiptPath = getMergeReceiptPath(root, prdId, issueId);
|
|
5741
5535
|
if (!existsSync10(receiptPath)) return null;
|
|
5742
5536
|
try {
|
|
5743
|
-
const content =
|
|
5537
|
+
const content = readFileSync12(receiptPath, "utf-8");
|
|
5744
5538
|
const parsed = JSON.parse(content);
|
|
5745
5539
|
if (typeof parsed.prdId === "string" && typeof parsed.issueId === "string" && typeof parsed.stage === "string" && typeof parsed.sourceBranch === "string" && typeof parsed.localPrdBranch === "string" && typeof parsed.mergeCommit === "string" && typeof parsed.completedAt === "string") {
|
|
5746
5540
|
return parsed;
|
|
@@ -5756,7 +5550,7 @@ async function squashMergeLocalIssue(prdId, issueId, input, repoRoot2) {
|
|
|
5756
5550
|
if (existsSync10(receiptPath)) {
|
|
5757
5551
|
try {
|
|
5758
5552
|
const existing = JSON.parse(
|
|
5759
|
-
|
|
5553
|
+
readFileSync12(receiptPath, "utf-8")
|
|
5760
5554
|
);
|
|
5761
5555
|
if (existing.prdId === prdId && existing.issueId === issueId && existing.mergeCommit) {
|
|
5762
5556
|
return {
|
|
@@ -6165,7 +5959,7 @@ function runMergeCoordinator(options) {
|
|
|
6165
5959
|
}
|
|
6166
5960
|
|
|
6167
5961
|
// commands/issue-final-review-agent.ts
|
|
6168
|
-
import { existsSync as existsSync11, readFileSync as
|
|
5962
|
+
import { existsSync as existsSync11, readFileSync as readFileSync13 } from "fs";
|
|
6169
5963
|
import { join as join14 } from "path";
|
|
6170
5964
|
var ISSUE_FINAL_REVIEW_ARTIFACT_PATH = join14(
|
|
6171
5965
|
".pourkit",
|
|
@@ -6279,7 +6073,7 @@ async function runIssueFinalReviewAgent(options) {
|
|
|
6279
6073
|
}
|
|
6280
6074
|
function loadIssueFinalReviewPrompt(repoRoot2, promptTemplate) {
|
|
6281
6075
|
const promptPath = resolvePromptTemplatePath(repoRoot2, promptTemplate);
|
|
6282
|
-
const promptBody = existsSync11(promptPath) ?
|
|
6076
|
+
const promptBody = existsSync11(promptPath) ? readFileSync13(promptPath, "utf-8") : promptTemplate;
|
|
6283
6077
|
return appendProtectedWorkGuidance(`${promptBody}
|
|
6284
6078
|
|
|
6285
6079
|
## Shared Run Context
|
|
@@ -6901,7 +6695,7 @@ async function completeIssueRun(options) {
|
|
|
6901
6695
|
message: `Finalizer artifact missing at ${finalizerFromState.artifactPath}`
|
|
6902
6696
|
});
|
|
6903
6697
|
}
|
|
6904
|
-
const artifactContent =
|
|
6698
|
+
const artifactContent = readFileSync14(
|
|
6905
6699
|
finalizerFromState.artifactPath,
|
|
6906
6700
|
"utf-8"
|
|
6907
6701
|
);
|
|
@@ -7615,7 +7409,7 @@ async function syncTargetBranch(root, baseBranch, logger) {
|
|
|
7615
7409
|
}
|
|
7616
7410
|
function loadBuilderPrompt(repoRoot2, promptTemplate) {
|
|
7617
7411
|
const promptPath = resolvePromptTemplatePath(repoRoot2, promptTemplate);
|
|
7618
|
-
const promptBody = existsSync12(promptPath) ?
|
|
7412
|
+
const promptBody = existsSync12(promptPath) ? readFileSync14(promptPath, "utf-8") : promptTemplate;
|
|
7619
7413
|
return appendProtectedWorkGuidance(`${promptBody}
|
|
7620
7414
|
|
|
7621
7415
|
## Shared Run Context
|
|
@@ -8106,26 +7900,16 @@ async function runIssueCreateCommand(args, issueProvider, logger) {
|
|
|
8106
7900
|
}
|
|
8107
7901
|
|
|
8108
7902
|
// commands/prd-run.ts
|
|
8109
|
-
import {
|
|
8110
|
-
cpSync,
|
|
8111
|
-
existsSync as existsSync16,
|
|
8112
|
-
lstatSync,
|
|
8113
|
-
mkdirSync as mkdirSync10,
|
|
8114
|
-
mkdtempSync,
|
|
8115
|
-
readFileSync as readFileSync18,
|
|
8116
|
-
realpathSync,
|
|
8117
|
-
rmSync as rmSync3
|
|
8118
|
-
} from "fs";
|
|
7903
|
+
import { existsSync as existsSync16, lstatSync, readFileSync as readFileSync18, realpathSync } from "fs";
|
|
8119
7904
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
8120
|
-
import {
|
|
8121
|
-
import { tmpdir } from "os";
|
|
7905
|
+
import { join as join19, relative as relative2 } from "path";
|
|
8122
7906
|
import { Match, pipe } from "effect";
|
|
8123
7907
|
|
|
8124
7908
|
// prd-run/state.ts
|
|
8125
7909
|
import {
|
|
8126
7910
|
existsSync as existsSync13,
|
|
8127
7911
|
mkdirSync as mkdirSync8,
|
|
8128
|
-
readFileSync as
|
|
7912
|
+
readFileSync as readFileSync15,
|
|
8129
7913
|
readdirSync as readdirSync4,
|
|
8130
7914
|
writeFileSync as writeFileSync5
|
|
8131
7915
|
} from "fs";
|
|
@@ -8225,12 +8009,12 @@ function readPrdRun(repoRoot2, prdRef) {
|
|
|
8225
8009
|
return { record: null, diagnostics: [] };
|
|
8226
8010
|
}
|
|
8227
8011
|
try {
|
|
8228
|
-
const raw = JSON.parse(
|
|
8012
|
+
const raw = JSON.parse(readFileSync15(recordPath, "utf-8"));
|
|
8229
8013
|
const parsed = normalizeLegacyPrdRunRecord(PrdRunRecordSchema.parse(raw));
|
|
8230
8014
|
return { record: parsed, diagnostics: [] };
|
|
8231
8015
|
} catch (error) {
|
|
8232
8016
|
try {
|
|
8233
|
-
const raw = JSON.parse(
|
|
8017
|
+
const raw = JSON.parse(readFileSync15(recordPath, "utf-8"));
|
|
8234
8018
|
if (raw && typeof raw === "object" && raw.start && typeof raw.start === "object" && raw.start.startBaseBranch === void 0) {
|
|
8235
8019
|
return {
|
|
8236
8020
|
record: raw,
|
|
@@ -8264,7 +8048,7 @@ function listPrdRuns(repoRoot2) {
|
|
|
8264
8048
|
const recordPath = join16(stateDir, entry.name);
|
|
8265
8049
|
try {
|
|
8266
8050
|
const record = normalizeLegacyPrdRunRecord(
|
|
8267
|
-
PrdRunRecordSchema.parse(JSON.parse(
|
|
8051
|
+
PrdRunRecordSchema.parse(JSON.parse(readFileSync15(recordPath, "utf-8")))
|
|
8268
8052
|
);
|
|
8269
8053
|
records.push(record);
|
|
8270
8054
|
} catch (error) {
|
|
@@ -8339,26 +8123,9 @@ function getRecordPath(repoRoot2, prdRef) {
|
|
|
8339
8123
|
);
|
|
8340
8124
|
}
|
|
8341
8125
|
|
|
8342
|
-
// prd-run/
|
|
8343
|
-
import {
|
|
8344
|
-
import {
|
|
8345
|
-
var PRD_REF_REGEX2 = /^PRD-\d{3,4}$/;
|
|
8346
|
-
var StageSchema = z2.enum(["prdFinalReview", "prdReconciliation"]);
|
|
8347
|
-
var EvidencePacketSchema = z2.object({
|
|
8348
|
-
prdRef: z2.string().regex(PRD_REF_REGEX2),
|
|
8349
|
-
prdBranch: z2.string().min(1),
|
|
8350
|
-
mergeBase: z2.string().min(6),
|
|
8351
|
-
planningManifestPath: z2.string().min(1),
|
|
8352
|
-
planningManifestFacts: z2.object({
|
|
8353
|
-
parentPrdIssueUrl: z2.string().min(1),
|
|
8354
|
-
childIssueCount: z2.number().int().nonnegative()
|
|
8355
|
-
}),
|
|
8356
|
-
stage: StageSchema,
|
|
8357
|
-
stageReceipts: z2.record(z2.string(), z2.unknown())
|
|
8358
|
-
}).strict();
|
|
8359
|
-
|
|
8360
|
-
// commands/prd-run.ts
|
|
8361
|
-
init_common();
|
|
8126
|
+
// prd-run/local-queue-loop.ts
|
|
8127
|
+
import { readFileSync as readFileSync16, writeFileSync as writeFileSync6 } from "fs";
|
|
8128
|
+
import { join as join18 } from "path";
|
|
8362
8129
|
|
|
8363
8130
|
// prd-run/local-artifacts.ts
|
|
8364
8131
|
import { existsSync as existsSync14 } from "fs";
|
|
@@ -8501,75 +8268,8 @@ async function resolveLocalIssueArtifacts(prdId, repoRoot2) {
|
|
|
8501
8268
|
return { ok: true, data: issues };
|
|
8502
8269
|
}
|
|
8503
8270
|
|
|
8504
|
-
// prd-run/local-issue-adapter.ts
|
|
8505
|
-
var VALID_TRIAGE_LABELS = /* @__PURE__ */ new Set([
|
|
8506
|
-
"needs-triage",
|
|
8507
|
-
"ready-for-agent",
|
|
8508
|
-
"blocked",
|
|
8509
|
-
"ready-for-human",
|
|
8510
|
-
"wontfix"
|
|
8511
|
-
]);
|
|
8512
|
-
function countTypeLabels(labels) {
|
|
8513
|
-
return labels.filter((l) => l.startsWith("type:")).length;
|
|
8514
|
-
}
|
|
8515
|
-
function countTriageLabels(labels) {
|
|
8516
|
-
return labels.filter((l) => VALID_TRIAGE_LABELS.has(l)).length;
|
|
8517
|
-
}
|
|
8518
|
-
function countCategoryLabels(labels) {
|
|
8519
|
-
const triageCount = countTriageLabels(labels);
|
|
8520
|
-
const typeCount = countTypeLabels(labels);
|
|
8521
|
-
return labels.length - triageCount - typeCount;
|
|
8522
|
-
}
|
|
8523
|
-
function hasValidLabels(labels) {
|
|
8524
|
-
if (countTriageLabels(labels) !== 1) return false;
|
|
8525
|
-
if (!labels.includes("ready-for-agent")) return false;
|
|
8526
|
-
if (countTypeLabels(labels) !== 1) return false;
|
|
8527
|
-
if (countCategoryLabels(labels) !== 1) return false;
|
|
8528
|
-
return true;
|
|
8529
|
-
}
|
|
8530
|
-
function isIssueBlockedByDependencies(issue, issues) {
|
|
8531
|
-
const blockers = [];
|
|
8532
|
-
for (const depId of issue.dependencyIssueIds) {
|
|
8533
|
-
const dep = issues.find((i) => i.id === depId);
|
|
8534
|
-
if (!dep || dep.receipts.completedAt === null) {
|
|
8535
|
-
blockers.push(depId);
|
|
8536
|
-
}
|
|
8537
|
-
}
|
|
8538
|
-
return blockers;
|
|
8539
|
-
}
|
|
8540
|
-
async function getRunnableLocalIssues(prdId, repoRoot2) {
|
|
8541
|
-
const issuesResult = await resolveLocalIssueArtifacts(prdId, repoRoot2);
|
|
8542
|
-
if (!issuesResult.ok) return [];
|
|
8543
|
-
const issues = issuesResult.data;
|
|
8544
|
-
const runnable = [];
|
|
8545
|
-
for (const issue of issues) {
|
|
8546
|
-
if (!hasValidLabels(issue.labels)) continue;
|
|
8547
|
-
if (issue.status !== "ready-for-agent") continue;
|
|
8548
|
-
const blockers = isIssueBlockedByDependencies(issue, issues);
|
|
8549
|
-
runnable.push({
|
|
8550
|
-
id: issue.id,
|
|
8551
|
-
title: issue.title,
|
|
8552
|
-
labels: issue.labels,
|
|
8553
|
-
blockedBy: blockers.length > 0 ? blockers : void 0
|
|
8554
|
-
});
|
|
8555
|
-
}
|
|
8556
|
-
const filtered = runnable.filter(
|
|
8557
|
-
(i) => !i.blockedBy || i.blockedBy.length === 0
|
|
8558
|
-
);
|
|
8559
|
-
return filtered;
|
|
8560
|
-
}
|
|
8561
|
-
|
|
8562
|
-
// prd-run/local-final-review.ts
|
|
8563
|
-
import { execFileSync as execFileSync3, execSync as execSync2 } from "child_process";
|
|
8564
|
-
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync6 } from "fs";
|
|
8565
|
-
import { join as join18 } from "path";
|
|
8566
|
-
|
|
8567
|
-
// prd-run/local-queue-loop.ts
|
|
8568
|
-
import { readFileSync as readFileSync17, writeFileSync as writeFileSync7 } from "fs";
|
|
8569
|
-
import { join as join19 } from "path";
|
|
8570
|
-
|
|
8571
8271
|
// prd-run/local-issue-run.ts
|
|
8572
|
-
import { execFileSync as
|
|
8272
|
+
import { execFileSync as execFileSync3 } from "child_process";
|
|
8573
8273
|
init_common();
|
|
8574
8274
|
async function createLocalIssueBranch(prdId, issueId, repoRoot2) {
|
|
8575
8275
|
const root = repoRoot2 ?? process.cwd();
|
|
@@ -8593,7 +8293,7 @@ async function createLocalIssueBranch(prdId, issueId, repoRoot2) {
|
|
|
8593
8293
|
}
|
|
8594
8294
|
const localPrdBranch = `local/${prdId}`;
|
|
8595
8295
|
try {
|
|
8596
|
-
|
|
8296
|
+
execFileSync3(
|
|
8597
8297
|
"git",
|
|
8598
8298
|
["show-ref", "--verify", "--quiet", `refs/heads/${localPrdBranch}`],
|
|
8599
8299
|
{
|
|
@@ -8609,7 +8309,7 @@ async function createLocalIssueBranch(prdId, issueId, repoRoot2) {
|
|
|
8609
8309
|
}
|
|
8610
8310
|
let branchExists = false;
|
|
8611
8311
|
try {
|
|
8612
|
-
|
|
8312
|
+
execFileSync3(
|
|
8613
8313
|
"git",
|
|
8614
8314
|
["show-ref", "--verify", "--quiet", `refs/heads/${branchName}`],
|
|
8615
8315
|
{
|
|
@@ -8622,7 +8322,7 @@ async function createLocalIssueBranch(prdId, issueId, repoRoot2) {
|
|
|
8622
8322
|
} catch {
|
|
8623
8323
|
}
|
|
8624
8324
|
if (!branchExists) {
|
|
8625
|
-
|
|
8325
|
+
execFileSync3("git", ["checkout", "-b", branchName, localPrdBranch], {
|
|
8626
8326
|
cwd: root,
|
|
8627
8327
|
encoding: "utf8",
|
|
8628
8328
|
stdio: "pipe"
|
|
@@ -8687,11 +8387,69 @@ async function runLocalIssue(prdId, issueId, builder, repoRoot2) {
|
|
|
8687
8387
|
}
|
|
8688
8388
|
}
|
|
8689
8389
|
|
|
8390
|
+
// prd-run/local-issue-adapter.ts
|
|
8391
|
+
var VALID_TRIAGE_LABELS = /* @__PURE__ */ new Set([
|
|
8392
|
+
"needs-triage",
|
|
8393
|
+
"ready-for-agent",
|
|
8394
|
+
"blocked",
|
|
8395
|
+
"ready-for-human",
|
|
8396
|
+
"wontfix"
|
|
8397
|
+
]);
|
|
8398
|
+
function countTypeLabels(labels) {
|
|
8399
|
+
return labels.filter((l) => l.startsWith("type:")).length;
|
|
8400
|
+
}
|
|
8401
|
+
function countTriageLabels(labels) {
|
|
8402
|
+
return labels.filter((l) => VALID_TRIAGE_LABELS.has(l)).length;
|
|
8403
|
+
}
|
|
8404
|
+
function countCategoryLabels(labels) {
|
|
8405
|
+
const triageCount = countTriageLabels(labels);
|
|
8406
|
+
const typeCount = countTypeLabels(labels);
|
|
8407
|
+
return labels.length - triageCount - typeCount;
|
|
8408
|
+
}
|
|
8409
|
+
function hasValidLabels(labels) {
|
|
8410
|
+
if (countTriageLabels(labels) !== 1) return false;
|
|
8411
|
+
if (!labels.includes("ready-for-agent")) return false;
|
|
8412
|
+
if (countTypeLabels(labels) !== 1) return false;
|
|
8413
|
+
if (countCategoryLabels(labels) !== 1) return false;
|
|
8414
|
+
return true;
|
|
8415
|
+
}
|
|
8416
|
+
function isIssueBlockedByDependencies(issue, issues) {
|
|
8417
|
+
const blockers = [];
|
|
8418
|
+
for (const depId of issue.dependencyIssueIds) {
|
|
8419
|
+
const dep = issues.find((i) => i.id === depId);
|
|
8420
|
+
if (!dep || dep.receipts.completedAt === null) {
|
|
8421
|
+
blockers.push(depId);
|
|
8422
|
+
}
|
|
8423
|
+
}
|
|
8424
|
+
return blockers;
|
|
8425
|
+
}
|
|
8426
|
+
async function getRunnableLocalIssues(prdId, repoRoot2) {
|
|
8427
|
+
const issuesResult = await resolveLocalIssueArtifacts(prdId, repoRoot2);
|
|
8428
|
+
if (!issuesResult.ok) return [];
|
|
8429
|
+
const issues = issuesResult.data;
|
|
8430
|
+
const runnable = [];
|
|
8431
|
+
for (const issue of issues) {
|
|
8432
|
+
if (!hasValidLabels(issue.labels)) continue;
|
|
8433
|
+
if (issue.status !== "ready-for-agent") continue;
|
|
8434
|
+
const blockers = isIssueBlockedByDependencies(issue, issues);
|
|
8435
|
+
runnable.push({
|
|
8436
|
+
id: issue.id,
|
|
8437
|
+
title: issue.title,
|
|
8438
|
+
labels: issue.labels,
|
|
8439
|
+
blockedBy: blockers.length > 0 ? blockers : void 0
|
|
8440
|
+
});
|
|
8441
|
+
}
|
|
8442
|
+
const filtered = runnable.filter(
|
|
8443
|
+
(i) => !i.blockedBy || i.blockedBy.length === 0
|
|
8444
|
+
);
|
|
8445
|
+
return filtered;
|
|
8446
|
+
}
|
|
8447
|
+
|
|
8690
8448
|
// prd-run/local-queue-loop.ts
|
|
8691
8449
|
var CHILD_CLEANUP_LABELS = ["agent-in-progress", "pr-open-awaiting-merge"];
|
|
8692
8450
|
var LOCAL_ISSUE_ID_REGEX = /^I-(\d+)$/i;
|
|
8693
8451
|
function getIssueArtifactPath2(repoRoot2, prdId, issueId) {
|
|
8694
|
-
return
|
|
8452
|
+
return join18(
|
|
8695
8453
|
repoRoot2,
|
|
8696
8454
|
".pourkit",
|
|
8697
8455
|
"local-prd-runs",
|
|
@@ -8702,7 +8460,7 @@ function getIssueArtifactPath2(repoRoot2, prdId, issueId) {
|
|
|
8702
8460
|
}
|
|
8703
8461
|
function readIssueArtifact(repoRoot2, prdId, issueId) {
|
|
8704
8462
|
try {
|
|
8705
|
-
const content =
|
|
8463
|
+
const content = readFileSync16(
|
|
8706
8464
|
getIssueArtifactPath2(repoRoot2, prdId, issueId),
|
|
8707
8465
|
"utf-8"
|
|
8708
8466
|
);
|
|
@@ -8712,7 +8470,7 @@ function readIssueArtifact(repoRoot2, prdId, issueId) {
|
|
|
8712
8470
|
}
|
|
8713
8471
|
}
|
|
8714
8472
|
function writeIssueArtifact(repoRoot2, prdId, issue) {
|
|
8715
|
-
|
|
8473
|
+
writeFileSync6(
|
|
8716
8474
|
getIssueArtifactPath2(repoRoot2, prdId, issue.id),
|
|
8717
8475
|
JSON.stringify(issue, null, 2),
|
|
8718
8476
|
"utf-8"
|
|
@@ -9378,6 +9136,9 @@ async function runQueueCommand(options) {
|
|
|
9378
9136
|
return runEffectAndMapExit(runQueueLoop(queueOptions));
|
|
9379
9137
|
}
|
|
9380
9138
|
|
|
9139
|
+
// prd-run/final-review-validation.ts
|
|
9140
|
+
import { existsSync as existsSync15, readFileSync as readFileSync17 } from "fs";
|
|
9141
|
+
|
|
9381
9142
|
// commands/prd-run.ts
|
|
9382
9143
|
function planLaunchResume(record) {
|
|
9383
9144
|
if (!record) return { attempted: [], skipped: [], resumed: [] };
|
|
@@ -9439,10 +9200,10 @@ function planLaunchResume(record) {
|
|
|
9439
9200
|
);
|
|
9440
9201
|
}
|
|
9441
9202
|
function validateLocalStartStore(repoRoot2, prdRef) {
|
|
9442
|
-
const localStoreDir =
|
|
9203
|
+
const localStoreDir = join19(repoRoot2, ".pourkit", "local-prd-runs", prdRef);
|
|
9443
9204
|
let localStoreReady = false;
|
|
9444
9205
|
if (existsSync16(localStoreDir)) {
|
|
9445
|
-
const localStorePath =
|
|
9206
|
+
const localStorePath = join19(localStoreDir, "prd.json");
|
|
9446
9207
|
try {
|
|
9447
9208
|
const content = JSON.parse(readFileSync18(localStorePath, "utf8"));
|
|
9448
9209
|
localStoreReady = content?.id === prdRef && content?.kind === "prd";
|
|
@@ -9614,7 +9375,7 @@ async function runPrdRunLaunchCommand(options) {
|
|
|
9614
9375
|
attempted.push("queue");
|
|
9615
9376
|
}
|
|
9616
9377
|
const currentRecord = readPrdRun(options.repoRoot, prdRef).record;
|
|
9617
|
-
const localStorePath =
|
|
9378
|
+
const localStorePath = join19(
|
|
9618
9379
|
options.repoRoot,
|
|
9619
9380
|
".pourkit",
|
|
9620
9381
|
"local-prd-runs",
|
|
@@ -10131,7 +9892,7 @@ async function processStartResult(startResult, options) {
|
|
|
10131
9892
|
start,
|
|
10132
9893
|
mode: modeForRecord
|
|
10133
9894
|
});
|
|
10134
|
-
const localStorePath =
|
|
9895
|
+
const localStorePath = join19(repoRoot2, ".pourkit", "local-prd-runs", prdRef);
|
|
10135
9896
|
if (existsSync16(localStorePath)) {
|
|
10136
9897
|
const queueResult = await runLocalQueueLoop(
|
|
10137
9898
|
prdRef,
|
|
@@ -11029,7 +10790,7 @@ import {
|
|
|
11029
10790
|
rename,
|
|
11030
10791
|
writeFile as writeFile2
|
|
11031
10792
|
} from "fs/promises";
|
|
11032
|
-
import { createHash as
|
|
10793
|
+
import { createHash as createHash2, randomUUID } from "crypto";
|
|
11033
10794
|
import path5 from "path";
|
|
11034
10795
|
import { execFile as execFile2 } from "child_process";
|
|
11035
10796
|
import { promisify as promisify2 } from "util";
|
|
@@ -11505,7 +11266,7 @@ async function walkDir(dir) {
|
|
|
11505
11266
|
}
|
|
11506
11267
|
async function computeFileChecksum(filePath) {
|
|
11507
11268
|
const content = await readFile5(filePath);
|
|
11508
|
-
return
|
|
11269
|
+
return createHash2("sha256").update(content).digest("hex");
|
|
11509
11270
|
}
|
|
11510
11271
|
function lockfileExists(root, name) {
|
|
11511
11272
|
return existsSync17(path5.join(root, name));
|
|
@@ -13180,16 +12941,20 @@ async function runSerenaStatusCommand(options) {
|
|
|
13180
12941
|
// commands/config-schema.ts
|
|
13181
12942
|
import { readFileSync as readFileSync19, existsSync as existsSync18 } from "fs";
|
|
13182
12943
|
import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile3 } from "fs/promises";
|
|
13183
|
-
import { resolve as resolve4, dirname as
|
|
12944
|
+
import { resolve as resolve4, dirname as dirname5 } from "path";
|
|
13184
12945
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
13185
12946
|
import Ajv2 from "ajv";
|
|
13186
12947
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
13187
|
-
var __dirname2 =
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
)
|
|
13192
|
-
|
|
12948
|
+
var __dirname2 = dirname5(__filename2);
|
|
12949
|
+
function resolvePackagedAssetPath2(fileName) {
|
|
12950
|
+
const candidates = [
|
|
12951
|
+
resolve4(__dirname2, "schema", fileName),
|
|
12952
|
+
resolve4(__dirname2, "../schema", fileName)
|
|
12953
|
+
];
|
|
12954
|
+
return candidates.find((candidate) => existsSync18(candidate)) ?? candidates[0];
|
|
12955
|
+
}
|
|
12956
|
+
var PACKAGED_SCHEMA_PATH = resolvePackagedAssetPath2("pourkit.schema.json");
|
|
12957
|
+
var PACKAGED_HASH_PATH = resolvePackagedAssetPath2("pourkit.schema.hash");
|
|
13193
12958
|
var _schemaValidator = null;
|
|
13194
12959
|
var _schemaErrors = null;
|
|
13195
12960
|
function getSchemaValidator() {
|
|
@@ -13865,21 +13630,21 @@ function formatChecks2(checks) {
|
|
|
13865
13630
|
init_common();
|
|
13866
13631
|
|
|
13867
13632
|
// execution/sandcastle-execution.ts
|
|
13868
|
-
import { mkdirSync as
|
|
13869
|
-
import { join as
|
|
13633
|
+
import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync7 } from "fs";
|
|
13634
|
+
import { join as join21 } from "path";
|
|
13870
13635
|
import { createWorktree, opencode } from "@ai-hero/sandcastle";
|
|
13871
13636
|
import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
|
|
13872
13637
|
|
|
13873
13638
|
// execution/execution-provider.ts
|
|
13874
13639
|
init_common();
|
|
13875
|
-
import { mkdtempSync
|
|
13640
|
+
import { mkdtempSync } from "fs";
|
|
13876
13641
|
import { writeFile as writeFile4 } from "fs/promises";
|
|
13877
|
-
import { tmpdir
|
|
13878
|
-
import { dirname as
|
|
13642
|
+
import { tmpdir } from "os";
|
|
13643
|
+
import { dirname as dirname6, join as join20 } from "path";
|
|
13879
13644
|
async function writeExecutionArtifacts(worktreePath, artifacts) {
|
|
13880
13645
|
for (const artifact of artifacts) {
|
|
13881
|
-
const filePath =
|
|
13882
|
-
await ensureDir(
|
|
13646
|
+
const filePath = join20(worktreePath, artifact.path);
|
|
13647
|
+
await ensureDir(dirname6(filePath));
|
|
13883
13648
|
await writeFile4(filePath, artifact.content, "utf-8");
|
|
13884
13649
|
}
|
|
13885
13650
|
}
|
|
@@ -13889,7 +13654,7 @@ init_common();
|
|
|
13889
13654
|
import path7 from "path";
|
|
13890
13655
|
|
|
13891
13656
|
// execution/sandbox-image.ts
|
|
13892
|
-
import { createHash as
|
|
13657
|
+
import { createHash as createHash3 } from "crypto";
|
|
13893
13658
|
import { existsSync as existsSync19, readFileSync as readFileSync20 } from "fs";
|
|
13894
13659
|
import path6 from "path";
|
|
13895
13660
|
function sandboxImageName(repoRoot2) {
|
|
@@ -13900,7 +13665,7 @@ function sandboxImageName(repoRoot2) {
|
|
|
13900
13665
|
if (!existsSync19(dockerfilePath)) {
|
|
13901
13666
|
return `sandcastle:${baseName}`;
|
|
13902
13667
|
}
|
|
13903
|
-
const fingerprint =
|
|
13668
|
+
const fingerprint = createHash3("sha256").update(readFileSync20(dockerfilePath)).digest("hex").slice(0, 8);
|
|
13904
13669
|
return `sandcastle:${baseName}-${fingerprint}`;
|
|
13905
13670
|
}
|
|
13906
13671
|
|
|
@@ -14196,13 +13961,13 @@ function isPlainObject(value) {
|
|
|
14196
13961
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14197
13962
|
}
|
|
14198
13963
|
function savePromptToFile(repoRoot2, stage, iteration, prompt) {
|
|
14199
|
-
const promptsDir =
|
|
14200
|
-
|
|
13964
|
+
const promptsDir = join21(repoRoot2, ".pourkit", ".tmp", "prompts");
|
|
13965
|
+
mkdirSync9(promptsDir, { recursive: true });
|
|
14201
13966
|
const timestamp2 = Date.now();
|
|
14202
13967
|
const iterationSuffix = iteration !== void 0 ? `-iteration-${iteration}` : "";
|
|
14203
13968
|
const filename = `${stage}${iterationSuffix}-${timestamp2}.md`;
|
|
14204
|
-
const filePath =
|
|
14205
|
-
|
|
13969
|
+
const filePath = join21(promptsDir, filename);
|
|
13970
|
+
writeFileSync7(filePath, prompt, "utf-8");
|
|
14206
13971
|
}
|
|
14207
13972
|
|
|
14208
13973
|
// cli.ts
|
|
@@ -14302,7 +14067,7 @@ function createCliProgram(version) {
|
|
|
14302
14067
|
});
|
|
14303
14068
|
program.command("validate-artifact").description("Validate an agent handoff artifact").argument(
|
|
14304
14069
|
"<kind>",
|
|
14305
|
-
"artifact kind: reviewer, refactor, finalizer, conflict-resolution,
|
|
14070
|
+
"artifact kind: reviewer, refactor, finalizer, conflict-resolution, failure-resolution, local-prd, local-issue, local-triage, or issue-final-review"
|
|
14306
14071
|
).argument("<artifactPath>", "artifact path to validate").argument("[extraPaths...]", "additional artifact paths (for local-triage)").option("--iteration <number>", "review/refactor iteration", (value) => {
|
|
14307
14072
|
const parsed = Number.parseInt(value, 10);
|
|
14308
14073
|
if (!Number.isInteger(parsed) || parsed < 1) {
|
|
@@ -14335,12 +14100,6 @@ function createCliProgram(version) {
|
|
|
14335
14100
|
return previous;
|
|
14336
14101
|
},
|
|
14337
14102
|
[]
|
|
14338
|
-
).option("--prd-ref <ref>", "PRD ref for final-review artifacts").option(
|
|
14339
|
-
"--checkout-base <ref>",
|
|
14340
|
-
"checkout base / PRD branch for final-review artifacts"
|
|
14341
|
-
).option(
|
|
14342
|
-
"--review-base <ref>",
|
|
14343
|
-
"review merge base for final-review artifacts"
|
|
14344
14103
|
).option(
|
|
14345
14104
|
"--issue-number <number>",
|
|
14346
14105
|
"issue number for issue-final-review artifacts",
|
|
@@ -14365,7 +14124,6 @@ function createCliProgram(version) {
|
|
|
14365
14124
|
"refactor",
|
|
14366
14125
|
"finalizer",
|
|
14367
14126
|
"conflict-resolution",
|
|
14368
|
-
"final-review",
|
|
14369
14127
|
"failure-resolution",
|
|
14370
14128
|
"local-prd",
|
|
14371
14129
|
"local-issue",
|
|
@@ -14399,9 +14157,6 @@ function createCliProgram(version) {
|
|
|
14399
14157
|
findingIds: options.findingId,
|
|
14400
14158
|
latestReviewArtifactPath: options.latestReviewArtifact,
|
|
14401
14159
|
allowedDecisions: options.allowedDecision,
|
|
14402
|
-
prdRef: options.prdRef,
|
|
14403
|
-
checkoutBase: options.checkoutBase,
|
|
14404
|
-
reviewBase: options.reviewBase,
|
|
14405
14160
|
issueNumber: options.issueNumber,
|
|
14406
14161
|
branchName: options.branchName,
|
|
14407
14162
|
checkConflictMarkers: options.checkConflictMarkers
|
|
@@ -14905,11 +14660,11 @@ function createCliProgram(version) {
|
|
|
14905
14660
|
return program;
|
|
14906
14661
|
}
|
|
14907
14662
|
async function resolveCliVersion() {
|
|
14908
|
-
if (isPackageVersion("0.0.0-next-
|
|
14909
|
-
return "0.0.0-next-
|
|
14663
|
+
if (isPackageVersion("0.0.0-next-20260614201555")) {
|
|
14664
|
+
return "0.0.0-next-20260614201555";
|
|
14910
14665
|
}
|
|
14911
|
-
if (isReleaseVersion("0.0.0-next-
|
|
14912
|
-
return "0.0.0-next-
|
|
14666
|
+
if (isReleaseVersion("0.0.0-next-20260614201555")) {
|
|
14667
|
+
return "0.0.0-next-20260614201555";
|
|
14913
14668
|
}
|
|
14914
14669
|
try {
|
|
14915
14670
|
const root = repoRoot();
|