@pourkit/cli 0.0.0-next-20260622055621 → 0.0.0-next-20260622201317
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 +171 -201
- package/dist/cli.js.map +1 -1
- package/dist/e2e/run-live-e2e.js +148 -178
- package/dist/e2e/run-live-e2e.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3742,7 +3742,6 @@ function shellQuote(value) {
|
|
|
3742
3742
|
|
|
3743
3743
|
// commands/issue-run.ts
|
|
3744
3744
|
import { existsSync as existsSync13, readFileSync as readFileSync15 } from "fs";
|
|
3745
|
-
import { isAbsolute as isAbsolute4, join as join15 } from "path";
|
|
3746
3745
|
|
|
3747
3746
|
// pr/templates.ts
|
|
3748
3747
|
init_common();
|
|
@@ -6091,16 +6090,17 @@ function isAllowedDocumentationTokenReference(value) {
|
|
|
6091
6090
|
return /^token\s*:\s*["']?<verdict>/i.test(value);
|
|
6092
6091
|
}
|
|
6093
6092
|
|
|
6094
|
-
//
|
|
6093
|
+
// issues/issue-final-review.ts
|
|
6095
6094
|
import { existsSync as existsSync12, readFileSync as readFileSync14 } from "fs";
|
|
6096
|
-
import { join as join13 } from "path";
|
|
6095
|
+
import { isAbsolute as isAbsolute4, join as join13 } from "path";
|
|
6096
|
+
init_common();
|
|
6097
6097
|
var ISSUE_FINAL_REVIEW_ARTIFACT_PATH = join13(
|
|
6098
6098
|
".pourkit",
|
|
6099
6099
|
".tmp",
|
|
6100
6100
|
"issue-final-review",
|
|
6101
6101
|
"agent-output.json"
|
|
6102
6102
|
);
|
|
6103
|
-
async function
|
|
6103
|
+
async function runIssueFinalReview(options) {
|
|
6104
6104
|
const {
|
|
6105
6105
|
executionProvider,
|
|
6106
6106
|
target,
|
|
@@ -6113,6 +6113,34 @@ async function runIssueFinalReviewAgent(options) {
|
|
|
6113
6113
|
} = options;
|
|
6114
6114
|
const artifactPathInWorktree = ISSUE_FINAL_REVIEW_ARTIFACT_PATH;
|
|
6115
6115
|
const artifactPath = join13(worktreePath, artifactPathInWorktree);
|
|
6116
|
+
const ifrFromState = options.worktreeState?.issueFinalReview;
|
|
6117
|
+
if (ifrFromState?.completed && ifrFromState.verdict === "pass") {
|
|
6118
|
+
if (!ifrFromState.artifactPath) {
|
|
6119
|
+
throw new Error(
|
|
6120
|
+
"Issue Final Review state is incomplete: missing artifactPath"
|
|
6121
|
+
);
|
|
6122
|
+
}
|
|
6123
|
+
const cachedArtifactPath = isAbsolute4(ifrFromState.artifactPath) ? ifrFromState.artifactPath : join13(worktreePath, ifrFromState.artifactPath);
|
|
6124
|
+
const validation2 = validateAgentArtifact({
|
|
6125
|
+
kind: "issue-final-review",
|
|
6126
|
+
artifactPath: cachedArtifactPath,
|
|
6127
|
+
issueNumber: issue.number,
|
|
6128
|
+
branchName: builderBranch
|
|
6129
|
+
});
|
|
6130
|
+
if (!validation2.ok) {
|
|
6131
|
+
throw new Error(
|
|
6132
|
+
`Issue Final Review state artifact is invalid: ${validation2.reason}`
|
|
6133
|
+
);
|
|
6134
|
+
}
|
|
6135
|
+
return {
|
|
6136
|
+
status: "skipped",
|
|
6137
|
+
verdict: "pass",
|
|
6138
|
+
artifactPath: cachedArtifactPath,
|
|
6139
|
+
selfRetouched: ifrFromState.selfRetouched ?? false,
|
|
6140
|
+
changedPaths: ifrFromState.changedPaths ?? [],
|
|
6141
|
+
verificationPassed: ifrFromState.verificationPassed ?? false
|
|
6142
|
+
};
|
|
6143
|
+
}
|
|
6116
6144
|
const strategy = target.strategy;
|
|
6117
6145
|
const issueFinalReview = strategy.issueFinalReview;
|
|
6118
6146
|
const agent = issueFinalReview;
|
|
@@ -6189,17 +6217,42 @@ async function runIssueFinalReviewAgent(options) {
|
|
|
6189
6217
|
}
|
|
6190
6218
|
const parsed = JSON.parse(content);
|
|
6191
6219
|
const verdict = parsed.verdict;
|
|
6220
|
+
const baseRef = `origin/${target.baseBranch}`;
|
|
6221
|
+
await assertCanonicalBaseAncestor2({
|
|
6222
|
+
worktreePath,
|
|
6223
|
+
baseRef,
|
|
6224
|
+
stageName: "Issue Final Review",
|
|
6225
|
+
logger
|
|
6226
|
+
});
|
|
6192
6227
|
if (verdict === "pass") {
|
|
6228
|
+
const changedPaths = await completeIssueFinalReviewChangedPaths({
|
|
6229
|
+
worktreePath,
|
|
6230
|
+
baseRef,
|
|
6231
|
+
declaredChangedPaths: extractChangedPaths(parsed),
|
|
6232
|
+
logger
|
|
6233
|
+
});
|
|
6234
|
+
updateWorktreeRunState(worktreePath, {
|
|
6235
|
+
issueFinalReview: {
|
|
6236
|
+
completed: true,
|
|
6237
|
+
verdict: "pass",
|
|
6238
|
+
artifactPath,
|
|
6239
|
+
selfRetouched: parsed.selfRetouched === true,
|
|
6240
|
+
changedPaths,
|
|
6241
|
+
verificationPassed: parsed.verification?.passed === true
|
|
6242
|
+
}
|
|
6243
|
+
});
|
|
6193
6244
|
return {
|
|
6245
|
+
status: "passed",
|
|
6194
6246
|
verdict: "pass",
|
|
6195
6247
|
artifactPath,
|
|
6196
6248
|
selfRetouched: parsed.selfRetouched === true,
|
|
6197
|
-
changedPaths
|
|
6249
|
+
changedPaths,
|
|
6198
6250
|
verificationPassed: parsed.verification?.passed === true
|
|
6199
6251
|
};
|
|
6200
6252
|
}
|
|
6201
6253
|
if (verdict === "needs_human_review") {
|
|
6202
6254
|
return {
|
|
6255
|
+
status: "needs_human_review",
|
|
6203
6256
|
verdict: "needs_human_review",
|
|
6204
6257
|
artifactPath,
|
|
6205
6258
|
needsHumanReason: parsed.needsHumanReason,
|
|
@@ -6211,6 +6264,89 @@ async function runIssueFinalReviewAgent(options) {
|
|
|
6211
6264
|
`Unknown Issue Final Review verdict: ${JSON.stringify(verdict)}`
|
|
6212
6265
|
);
|
|
6213
6266
|
}
|
|
6267
|
+
async function assertCanonicalBaseAncestor2(options) {
|
|
6268
|
+
const { worktreePath, baseRef, stageName, logger } = options;
|
|
6269
|
+
await syncRemoteBaseRef2(worktreePath, baseRef, logger);
|
|
6270
|
+
try {
|
|
6271
|
+
await execCapture("git", ["merge-base", "--is-ancestor", baseRef, "HEAD"], {
|
|
6272
|
+
cwd: worktreePath,
|
|
6273
|
+
logger,
|
|
6274
|
+
label: "git merge-base --is-ancestor"
|
|
6275
|
+
});
|
|
6276
|
+
} catch {
|
|
6277
|
+
throw new Error(
|
|
6278
|
+
`Cannot continue after ${stageName}: ${baseRef} is not an ancestor of HEAD. An agent may have moved the issue branch behind the canonical base; refresh the branch onto the latest target base before continuing.`
|
|
6279
|
+
);
|
|
6280
|
+
}
|
|
6281
|
+
}
|
|
6282
|
+
async function syncRemoteBaseRef2(worktreePath, baseRef, logger) {
|
|
6283
|
+
const remoteBase = parseRemoteBaseRef2(baseRef);
|
|
6284
|
+
if (!remoteBase) {
|
|
6285
|
+
return;
|
|
6286
|
+
}
|
|
6287
|
+
await execCapture("git", ["fetch", remoteBase.remote, remoteBase.branch], {
|
|
6288
|
+
cwd: worktreePath,
|
|
6289
|
+
logger,
|
|
6290
|
+
label: "git fetch target"
|
|
6291
|
+
});
|
|
6292
|
+
}
|
|
6293
|
+
function parseRemoteBaseRef2(baseRef) {
|
|
6294
|
+
const [remote, ...branchParts] = baseRef.split("/");
|
|
6295
|
+
const branch = branchParts.join("/");
|
|
6296
|
+
if (!remote || !branch) {
|
|
6297
|
+
return null;
|
|
6298
|
+
}
|
|
6299
|
+
return { remote, branch };
|
|
6300
|
+
}
|
|
6301
|
+
async function completeIssueFinalReviewChangedPaths(options) {
|
|
6302
|
+
const actualChangedPaths = await listIssueFinalReviewChangedPaths2(options);
|
|
6303
|
+
const declared = new Set(options.declaredChangedPaths.map(normalizeGitPath2));
|
|
6304
|
+
const missing = actualChangedPaths.filter((path9) => !declared.has(path9));
|
|
6305
|
+
if (missing.length === 0) {
|
|
6306
|
+
return actualChangedPaths;
|
|
6307
|
+
}
|
|
6308
|
+
options.logger.step(
|
|
6309
|
+
"warn",
|
|
6310
|
+
`Issue Final Review pass omitted ${missing.length} changed file(s) from changedFiles; using git inventory for finalization state.`
|
|
6311
|
+
);
|
|
6312
|
+
options.logger.kv("MISSING_CHANGED_FILES", missing.join(", "));
|
|
6313
|
+
return actualChangedPaths;
|
|
6314
|
+
}
|
|
6315
|
+
async function listIssueFinalReviewChangedPaths2(options) {
|
|
6316
|
+
const trackedDiff = await execCapture(
|
|
6317
|
+
"git",
|
|
6318
|
+
["diff-index", "--name-only", options.baseRef, "--"],
|
|
6319
|
+
{
|
|
6320
|
+
cwd: options.worktreePath,
|
|
6321
|
+
logger: options.logger,
|
|
6322
|
+
label: "git diff-index Issue Final Review paths"
|
|
6323
|
+
}
|
|
6324
|
+
);
|
|
6325
|
+
const untrackedFiles = await execCapture(
|
|
6326
|
+
"git",
|
|
6327
|
+
["ls-files", "--others", "--exclude-standard"],
|
|
6328
|
+
{
|
|
6329
|
+
cwd: options.worktreePath,
|
|
6330
|
+
logger: options.logger,
|
|
6331
|
+
label: "git ls-files Issue Final Review paths"
|
|
6332
|
+
}
|
|
6333
|
+
);
|
|
6334
|
+
return Array.from(
|
|
6335
|
+
/* @__PURE__ */ new Set([
|
|
6336
|
+
...parseGitPathList2(trackedDiff.stdout),
|
|
6337
|
+
...parseGitPathList2(untrackedFiles.stdout)
|
|
6338
|
+
])
|
|
6339
|
+
).filter(isIssueFinalReviewAuditedPath2);
|
|
6340
|
+
}
|
|
6341
|
+
function parseGitPathList2(output) {
|
|
6342
|
+
return output.split(/\r?\n/).map(normalizeGitPath2).filter((path9) => path9.length > 0);
|
|
6343
|
+
}
|
|
6344
|
+
function normalizeGitPath2(path9) {
|
|
6345
|
+
return path9.replace(/^"|"$/g, "").replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/\/+$/, "");
|
|
6346
|
+
}
|
|
6347
|
+
function isIssueFinalReviewAuditedPath2(path9) {
|
|
6348
|
+
return path9 !== "" && path9 !== WORKTREE_RUN_STATE_PATH && !path9.startsWith(".pourkit/.tmp/") && !path9.startsWith(".pourkit/logs/");
|
|
6349
|
+
}
|
|
6214
6350
|
function extractChangedPaths(parsed) {
|
|
6215
6351
|
return Array.isArray(parsed.changedFiles) ? parsed.changedFiles.map(
|
|
6216
6352
|
(file) => file && typeof file === "object" ? file.path : void 0
|
|
@@ -6449,90 +6585,7 @@ function assertIssueFinalReviewPassed(worktreeState) {
|
|
|
6449
6585
|
}
|
|
6450
6586
|
}
|
|
6451
6587
|
async function advanceIssueFinalReview(options) {
|
|
6452
|
-
|
|
6453
|
-
executionProvider,
|
|
6454
|
-
config,
|
|
6455
|
-
target,
|
|
6456
|
-
issue,
|
|
6457
|
-
parentPrdIssue,
|
|
6458
|
-
builderBranch,
|
|
6459
|
-
worktreePath,
|
|
6460
|
-
repoRoot: repoRoot2,
|
|
6461
|
-
logger,
|
|
6462
|
-
reviewArtifactPath,
|
|
6463
|
-
reviewVerdict,
|
|
6464
|
-
worktreeState
|
|
6465
|
-
} = options;
|
|
6466
|
-
const ifrFromState = worktreeState?.issueFinalReview;
|
|
6467
|
-
if (ifrFromState?.completed && ifrFromState.verdict === "pass") {
|
|
6468
|
-
if (!ifrFromState.artifactPath) {
|
|
6469
|
-
throw new Error(
|
|
6470
|
-
"Issue Final Review state is incomplete: missing artifactPath"
|
|
6471
|
-
);
|
|
6472
|
-
}
|
|
6473
|
-
const artifactPath = isAbsolute4(ifrFromState.artifactPath) ? ifrFromState.artifactPath : join15(worktreePath, ifrFromState.artifactPath);
|
|
6474
|
-
const validation = validateAgentArtifact({
|
|
6475
|
-
kind: "issue-final-review",
|
|
6476
|
-
artifactPath,
|
|
6477
|
-
issueNumber: issue.number,
|
|
6478
|
-
branchName: builderBranch
|
|
6479
|
-
});
|
|
6480
|
-
if (!validation.ok) {
|
|
6481
|
-
throw new Error(
|
|
6482
|
-
`Issue Final Review state artifact is invalid: ${validation.reason}`
|
|
6483
|
-
);
|
|
6484
|
-
}
|
|
6485
|
-
return {
|
|
6486
|
-
verdict: "pass",
|
|
6487
|
-
artifactPath,
|
|
6488
|
-
selfRetouched: ifrFromState.selfRetouched ?? false,
|
|
6489
|
-
changedPaths: ifrFromState.changedPaths ?? [],
|
|
6490
|
-
verificationPassed: ifrFromState.verificationPassed ?? false
|
|
6491
|
-
};
|
|
6492
|
-
}
|
|
6493
|
-
const result = await runIssueFinalReviewAgent({
|
|
6494
|
-
executionProvider,
|
|
6495
|
-
config,
|
|
6496
|
-
target,
|
|
6497
|
-
issue,
|
|
6498
|
-
parentPrdIssue,
|
|
6499
|
-
builderBranch,
|
|
6500
|
-
worktreePath,
|
|
6501
|
-
repoRoot: repoRoot2,
|
|
6502
|
-
logger,
|
|
6503
|
-
reviewArtifactPath,
|
|
6504
|
-
reviewVerdict,
|
|
6505
|
-
...options.memory ? { memory: options.memory } : {}
|
|
6506
|
-
});
|
|
6507
|
-
await assertCanonicalBaseAncestor2({
|
|
6508
|
-
worktreePath,
|
|
6509
|
-
baseRef: `origin/${target.baseBranch}`,
|
|
6510
|
-
stageName: "Issue Final Review",
|
|
6511
|
-
logger
|
|
6512
|
-
});
|
|
6513
|
-
if (result.verdict === "pass") {
|
|
6514
|
-
const changedPaths = await completeIssueFinalReviewChangedPaths({
|
|
6515
|
-
worktreePath,
|
|
6516
|
-
baseRef: `origin/${target.baseBranch}`,
|
|
6517
|
-
declaredChangedPaths: result.changedPaths,
|
|
6518
|
-
logger
|
|
6519
|
-
});
|
|
6520
|
-
updateWorktreeRunState(worktreePath, {
|
|
6521
|
-
issueFinalReview: {
|
|
6522
|
-
completed: true,
|
|
6523
|
-
verdict: "pass",
|
|
6524
|
-
artifactPath: result.artifactPath,
|
|
6525
|
-
selfRetouched: result.selfRetouched,
|
|
6526
|
-
changedPaths,
|
|
6527
|
-
verificationPassed: result.verificationPassed
|
|
6528
|
-
}
|
|
6529
|
-
});
|
|
6530
|
-
return {
|
|
6531
|
-
...result,
|
|
6532
|
-
changedPaths
|
|
6533
|
-
};
|
|
6534
|
-
}
|
|
6535
|
-
return result;
|
|
6588
|
+
return runIssueFinalReview(options);
|
|
6536
6589
|
}
|
|
6537
6590
|
async function startIssueRun(options) {
|
|
6538
6591
|
const {
|
|
@@ -6968,89 +7021,6 @@ async function finalizeWorktreeCommit(options) {
|
|
|
6968
7021
|
label: "git commit"
|
|
6969
7022
|
});
|
|
6970
7023
|
}
|
|
6971
|
-
async function assertCanonicalBaseAncestor2(options) {
|
|
6972
|
-
const { worktreePath, baseRef, stageName, logger } = options;
|
|
6973
|
-
await syncRemoteBaseRef2(worktreePath, baseRef, logger);
|
|
6974
|
-
try {
|
|
6975
|
-
await execCapture("git", ["merge-base", "--is-ancestor", baseRef, "HEAD"], {
|
|
6976
|
-
cwd: worktreePath,
|
|
6977
|
-
logger,
|
|
6978
|
-
label: "git merge-base --is-ancestor"
|
|
6979
|
-
});
|
|
6980
|
-
} catch {
|
|
6981
|
-
throw new Error(
|
|
6982
|
-
`Cannot continue after ${stageName}: ${baseRef} is not an ancestor of HEAD. An agent may have moved the issue branch behind the canonical base; refresh the branch onto the latest target base before continuing.`
|
|
6983
|
-
);
|
|
6984
|
-
}
|
|
6985
|
-
}
|
|
6986
|
-
async function completeIssueFinalReviewChangedPaths(options) {
|
|
6987
|
-
const actualChangedPaths = await listIssueFinalReviewChangedPaths2(options);
|
|
6988
|
-
const declared = new Set(options.declaredChangedPaths.map(normalizeGitPath2));
|
|
6989
|
-
const missing = actualChangedPaths.filter((path9) => !declared.has(path9));
|
|
6990
|
-
if (missing.length === 0) {
|
|
6991
|
-
return actualChangedPaths;
|
|
6992
|
-
}
|
|
6993
|
-
options.logger.step(
|
|
6994
|
-
"warn",
|
|
6995
|
-
`Issue Final Review pass omitted ${missing.length} changed file(s) from changedFiles; using git inventory for finalization state.`
|
|
6996
|
-
);
|
|
6997
|
-
options.logger.kv("MISSING_CHANGED_FILES", missing.join(", "));
|
|
6998
|
-
return actualChangedPaths;
|
|
6999
|
-
}
|
|
7000
|
-
async function listIssueFinalReviewChangedPaths2(options) {
|
|
7001
|
-
const trackedDiff = await execCapture(
|
|
7002
|
-
"git",
|
|
7003
|
-
["diff-index", "--name-only", options.baseRef, "--"],
|
|
7004
|
-
{
|
|
7005
|
-
cwd: options.worktreePath,
|
|
7006
|
-
logger: options.logger,
|
|
7007
|
-
label: "git diff-index Issue Final Review paths"
|
|
7008
|
-
}
|
|
7009
|
-
);
|
|
7010
|
-
const untrackedFiles = await execCapture(
|
|
7011
|
-
"git",
|
|
7012
|
-
["ls-files", "--others", "--exclude-standard"],
|
|
7013
|
-
{
|
|
7014
|
-
cwd: options.worktreePath,
|
|
7015
|
-
logger: options.logger,
|
|
7016
|
-
label: "git ls-files Issue Final Review paths"
|
|
7017
|
-
}
|
|
7018
|
-
);
|
|
7019
|
-
return Array.from(
|
|
7020
|
-
/* @__PURE__ */ new Set([
|
|
7021
|
-
...parseGitPathList2(trackedDiff.stdout),
|
|
7022
|
-
...parseGitPathList2(untrackedFiles.stdout)
|
|
7023
|
-
])
|
|
7024
|
-
).filter(isIssueFinalReviewAuditedPath2);
|
|
7025
|
-
}
|
|
7026
|
-
function parseGitPathList2(output) {
|
|
7027
|
-
return output.split(/\r?\n/).map(normalizeGitPath2).filter((path9) => path9.length > 0);
|
|
7028
|
-
}
|
|
7029
|
-
function normalizeGitPath2(path9) {
|
|
7030
|
-
return path9.replace(/^"|"$/g, "").replace(/\\/g, "/").replace(/^\.\/+/, "").replace(/\/+$/, "");
|
|
7031
|
-
}
|
|
7032
|
-
function isIssueFinalReviewAuditedPath2(path9) {
|
|
7033
|
-
return path9 !== "" && path9 !== WORKTREE_RUN_STATE_PATH && !path9.startsWith(".pourkit/.tmp/") && !path9.startsWith(".pourkit/logs/");
|
|
7034
|
-
}
|
|
7035
|
-
async function syncRemoteBaseRef2(worktreePath, baseRef, logger) {
|
|
7036
|
-
const remoteBase = parseRemoteBaseRef2(baseRef);
|
|
7037
|
-
if (!remoteBase) {
|
|
7038
|
-
return;
|
|
7039
|
-
}
|
|
7040
|
-
await execCapture("git", ["fetch", remoteBase.remote, remoteBase.branch], {
|
|
7041
|
-
cwd: worktreePath,
|
|
7042
|
-
logger,
|
|
7043
|
-
label: "git fetch target"
|
|
7044
|
-
});
|
|
7045
|
-
}
|
|
7046
|
-
function parseRemoteBaseRef2(baseRef) {
|
|
7047
|
-
const [remote, ...branchParts] = baseRef.split("/");
|
|
7048
|
-
const branch = branchParts.join("/");
|
|
7049
|
-
if (!remote || !branch) {
|
|
7050
|
-
return null;
|
|
7051
|
-
}
|
|
7052
|
-
return { remote, branch };
|
|
7053
|
-
}
|
|
7054
7024
|
function makeIssueTransitions2(provider, config) {
|
|
7055
7025
|
return createIssueTransitions(
|
|
7056
7026
|
{
|
|
@@ -7199,7 +7169,7 @@ async function runIssueLifecycle(options) {
|
|
|
7199
7169
|
worktreeState: startResult.worktreeState,
|
|
7200
7170
|
memory: startResult.memory
|
|
7201
7171
|
});
|
|
7202
|
-
if (finalReviewResult.
|
|
7172
|
+
if (finalReviewResult.status === "needs_human_review") {
|
|
7203
7173
|
await options.deps.transitionIssueFinalReviewNeedsHumanToHandoff({
|
|
7204
7174
|
issueNumber: options.issueNumber,
|
|
7205
7175
|
finalReviewResult
|
|
@@ -7393,7 +7363,7 @@ async function runIssueCreateCommand(args, issueProvider, logger) {
|
|
|
7393
7363
|
|
|
7394
7364
|
// commands/prd-run.ts
|
|
7395
7365
|
import { lstatSync, realpathSync } from "fs";
|
|
7396
|
-
import { join as
|
|
7366
|
+
import { join as join16 } from "path";
|
|
7397
7367
|
|
|
7398
7368
|
// prd-run/state.ts
|
|
7399
7369
|
import {
|
|
@@ -7403,7 +7373,7 @@ import {
|
|
|
7403
7373
|
readdirSync as readdirSync3,
|
|
7404
7374
|
writeFileSync as writeFileSync4
|
|
7405
7375
|
} from "fs";
|
|
7406
|
-
import { join as
|
|
7376
|
+
import { join as join15 } from "path";
|
|
7407
7377
|
import { z } from "zod";
|
|
7408
7378
|
var PRD_RUN_STATE_DIR = ".pourkit/prd-runs";
|
|
7409
7379
|
var PrdRunRecordSchema = z.object({
|
|
@@ -7518,7 +7488,7 @@ function readPrdRun(repoRoot2, prdRef) {
|
|
|
7518
7488
|
}
|
|
7519
7489
|
}
|
|
7520
7490
|
function listPrdRuns(repoRoot2) {
|
|
7521
|
-
const stateDir =
|
|
7491
|
+
const stateDir = join15(repoRoot2, PRD_RUN_STATE_DIR);
|
|
7522
7492
|
if (!existsSync14(stateDir)) {
|
|
7523
7493
|
return { records: [], diagnostics: [] };
|
|
7524
7494
|
}
|
|
@@ -7528,7 +7498,7 @@ function listPrdRuns(repoRoot2) {
|
|
|
7528
7498
|
(left, right) => left.name.localeCompare(right.name)
|
|
7529
7499
|
)) {
|
|
7530
7500
|
if (!entry.isFile() || !entry.name.endsWith(".json")) continue;
|
|
7531
|
-
const recordPath =
|
|
7501
|
+
const recordPath = join15(stateDir, entry.name);
|
|
7532
7502
|
try {
|
|
7533
7503
|
const record = PrdRunRecordSchema.parse(
|
|
7534
7504
|
JSON.parse(readFileSync16(recordPath, "utf-8"))
|
|
@@ -7544,7 +7514,7 @@ function listPrdRuns(repoRoot2) {
|
|
|
7544
7514
|
}
|
|
7545
7515
|
function writePrdRunRecord(repoRoot2, record) {
|
|
7546
7516
|
const normalized = normalizePrdRunRef(record.prdRef);
|
|
7547
|
-
const stateDir =
|
|
7517
|
+
const stateDir = join15(repoRoot2, PRD_RUN_STATE_DIR);
|
|
7548
7518
|
const recordPath = getRecordPath(repoRoot2, normalized);
|
|
7549
7519
|
mkdirSync7(stateDir, { recursive: true });
|
|
7550
7520
|
writeFileSync4(
|
|
@@ -7554,7 +7524,7 @@ function writePrdRunRecord(repoRoot2, record) {
|
|
|
7554
7524
|
);
|
|
7555
7525
|
}
|
|
7556
7526
|
function getRecordPath(repoRoot2, prdRef) {
|
|
7557
|
-
return
|
|
7527
|
+
return join15(
|
|
7558
7528
|
repoRoot2,
|
|
7559
7529
|
PRD_RUN_STATE_DIR,
|
|
7560
7530
|
`${normalizePrdRunRef(prdRef)}.json`
|
|
@@ -12325,10 +12295,10 @@ Init applied: ${result.applied} operations applied, ${result.skipped} skipped.`
|
|
|
12325
12295
|
|
|
12326
12296
|
// commands/memory-init.ts
|
|
12327
12297
|
import { existsSync as existsSync17, mkdirSync as mkdirSync8, readFileSync as readFileSync18, writeFileSync as writeFileSync5 } from "fs";
|
|
12328
|
-
import { join as
|
|
12298
|
+
import { join as join17 } from "path";
|
|
12329
12299
|
async function runMemoryInitCommand(options) {
|
|
12330
12300
|
const cwd = options.cwd ?? process.cwd();
|
|
12331
|
-
const configPath =
|
|
12301
|
+
const configPath = join17(cwd, ".pourkit", "config.json");
|
|
12332
12302
|
if (!existsSync17(configPath)) {
|
|
12333
12303
|
return {
|
|
12334
12304
|
ok: false,
|
|
@@ -12360,8 +12330,8 @@ async function runMemoryInitCommand(options) {
|
|
|
12360
12330
|
const next = { ...raw, memory };
|
|
12361
12331
|
writeFileSync5(configPath, JSON.stringify(next, null, 2) + "\n");
|
|
12362
12332
|
}
|
|
12363
|
-
mkdirSync8(
|
|
12364
|
-
const gitignorePath =
|
|
12333
|
+
mkdirSync8(join17(cwd, ".pourkit", "icm"), { recursive: true });
|
|
12334
|
+
const gitignorePath = join17(cwd, ".gitignore");
|
|
12365
12335
|
updateManagedBlockSync(gitignorePath, generateGitignoreBlock());
|
|
12366
12336
|
const managed = await generateManagedAgentInstructions({
|
|
12367
12337
|
sourceRoot: cwd,
|
|
@@ -12369,14 +12339,14 @@ async function runMemoryInitCommand(options) {
|
|
|
12369
12339
|
});
|
|
12370
12340
|
let updatedAgentFile = false;
|
|
12371
12341
|
for (const fileName of ["AGENTS.md", "CLAUDE.md"]) {
|
|
12372
|
-
const agentPath =
|
|
12342
|
+
const agentPath = join17(cwd, fileName);
|
|
12373
12343
|
if (existsSync17(agentPath)) {
|
|
12374
12344
|
updateManagedBlockSync(agentPath, managed);
|
|
12375
12345
|
updatedAgentFile = true;
|
|
12376
12346
|
}
|
|
12377
12347
|
}
|
|
12378
12348
|
if (!updatedAgentFile) {
|
|
12379
|
-
updateManagedBlockSync(
|
|
12349
|
+
updateManagedBlockSync(join17(cwd, "AGENTS.md"), managed);
|
|
12380
12350
|
}
|
|
12381
12351
|
return {
|
|
12382
12352
|
ok: true,
|
|
@@ -14373,7 +14343,7 @@ init_common();
|
|
|
14373
14343
|
|
|
14374
14344
|
// execution/sandcastle-execution.ts
|
|
14375
14345
|
import { existsSync as existsSync21, mkdirSync as mkdirSync9, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
14376
|
-
import { join as
|
|
14346
|
+
import { join as join20 } from "path";
|
|
14377
14347
|
import { createWorktree, opencode } from "@ai-hero/sandcastle";
|
|
14378
14348
|
import { docker } from "@ai-hero/sandcastle/sandboxes/docker";
|
|
14379
14349
|
|
|
@@ -14382,10 +14352,10 @@ init_common();
|
|
|
14382
14352
|
import { mkdtempSync } from "fs";
|
|
14383
14353
|
import { writeFile as writeFile4 } from "fs/promises";
|
|
14384
14354
|
import { tmpdir } from "os";
|
|
14385
|
-
import { dirname as dirname7, join as
|
|
14355
|
+
import { dirname as dirname7, join as join18 } from "path";
|
|
14386
14356
|
async function writeExecutionArtifacts(worktreePath, artifacts) {
|
|
14387
14357
|
for (const artifact of artifacts) {
|
|
14388
|
-
const filePath =
|
|
14358
|
+
const filePath = join18(worktreePath, artifact.path);
|
|
14389
14359
|
await ensureDir(dirname7(filePath));
|
|
14390
14360
|
await writeFile4(filePath, artifact.content, "utf-8");
|
|
14391
14361
|
}
|
|
@@ -14447,7 +14417,7 @@ async function createSandboxFromExistingWorktree(options) {
|
|
|
14447
14417
|
}
|
|
14448
14418
|
|
|
14449
14419
|
// execution/sandbox-options.ts
|
|
14450
|
-
import { join as
|
|
14420
|
+
import { join as join19 } from "path";
|
|
14451
14421
|
var POURKIT_ICM_CONTAINER_DIR = "/home/agent/.pourkit/icm";
|
|
14452
14422
|
function buildSandboxOptions(repoRoot2, sandbox, memory) {
|
|
14453
14423
|
const mounts = [];
|
|
@@ -14456,12 +14426,12 @@ function buildSandboxOptions(repoRoot2, sandbox, memory) {
|
|
|
14456
14426
|
}
|
|
14457
14427
|
if (memory?.available) {
|
|
14458
14428
|
mounts.push({
|
|
14459
|
-
hostPath:
|
|
14429
|
+
hostPath: join19(repoRoot2, ".pourkit", "icm"),
|
|
14460
14430
|
sandboxPath: POURKIT_ICM_CONTAINER_DIR,
|
|
14461
14431
|
readonly: false
|
|
14462
14432
|
});
|
|
14463
14433
|
mounts.push({
|
|
14464
|
-
hostPath:
|
|
14434
|
+
hostPath: join19(repoRoot2, ".pourkit", "icm", "cache"),
|
|
14465
14435
|
sandboxPath: "/home/agent/.cache/icm",
|
|
14466
14436
|
readonly: false
|
|
14467
14437
|
});
|
|
@@ -14595,13 +14565,13 @@ var SandcastleExecutionSession = class {
|
|
|
14595
14565
|
"Memory enabled but memory context is invalid. Run `pourkit memory init` or install ICM for host planning use."
|
|
14596
14566
|
);
|
|
14597
14567
|
}
|
|
14598
|
-
const hostMemoryDir =
|
|
14568
|
+
const hostMemoryDir = join20(repoRoot2, ".pourkit", "icm");
|
|
14599
14569
|
if (!existsSync21(hostMemoryDir) || !statSync2(hostMemoryDir).isDirectory()) {
|
|
14600
14570
|
throw new MissingHostMemoryDirError(
|
|
14601
14571
|
"Memory enabled but host .pourkit/icm/ directory is missing. Run `pourkit memory init` to create the repo-scoped memory store."
|
|
14602
14572
|
);
|
|
14603
14573
|
}
|
|
14604
|
-
mkdirSync9(
|
|
14574
|
+
mkdirSync9(join20(hostMemoryDir, "cache"), { recursive: true });
|
|
14605
14575
|
}
|
|
14606
14576
|
const sandboxOptions = buildSandboxOptions(
|
|
14607
14577
|
repoRoot2,
|
|
@@ -14760,7 +14730,7 @@ function sanitizeBranch(branchName) {
|
|
|
14760
14730
|
}
|
|
14761
14731
|
function safeCopyToWorktreePaths(paths, repoRoot2, worktreePath) {
|
|
14762
14732
|
return paths.filter((relativePath) => {
|
|
14763
|
-
const source =
|
|
14733
|
+
const source = join20(repoRoot2, relativePath);
|
|
14764
14734
|
if (!existsSync21(source)) {
|
|
14765
14735
|
return true;
|
|
14766
14736
|
}
|
|
@@ -14771,7 +14741,7 @@ function safeCopyToWorktreePaths(paths, repoRoot2, worktreePath) {
|
|
|
14771
14741
|
} catch {
|
|
14772
14742
|
return true;
|
|
14773
14743
|
}
|
|
14774
|
-
const destination =
|
|
14744
|
+
const destination = join20(worktreePath, relativePath);
|
|
14775
14745
|
return !existsSync21(destination);
|
|
14776
14746
|
});
|
|
14777
14747
|
}
|
|
@@ -14836,12 +14806,12 @@ function isPlainObject(value) {
|
|
|
14836
14806
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
14837
14807
|
}
|
|
14838
14808
|
function savePromptToFile(repoRoot2, stage, iteration, prompt) {
|
|
14839
|
-
const promptsDir =
|
|
14809
|
+
const promptsDir = join20(repoRoot2, ".pourkit", ".tmp", "prompts");
|
|
14840
14810
|
mkdirSync9(promptsDir, { recursive: true });
|
|
14841
14811
|
const timestamp2 = Date.now();
|
|
14842
14812
|
const iterationSuffix = iteration !== void 0 ? `-iteration-${iteration}` : "";
|
|
14843
14813
|
const filename = `${stage}${iterationSuffix}-${timestamp2}.md`;
|
|
14844
|
-
const filePath =
|
|
14814
|
+
const filePath = join20(promptsDir, filename);
|
|
14845
14815
|
writeFileSync6(filePath, prompt, "utf-8");
|
|
14846
14816
|
}
|
|
14847
14817
|
|
|
@@ -15562,11 +15532,11 @@ function createCliProgram(version) {
|
|
|
15562
15532
|
return program;
|
|
15563
15533
|
}
|
|
15564
15534
|
async function resolveCliVersion() {
|
|
15565
|
-
if (isPackageVersion("0.0.0-next-
|
|
15566
|
-
return "0.0.0-next-
|
|
15535
|
+
if (isPackageVersion("0.0.0-next-20260622201317")) {
|
|
15536
|
+
return "0.0.0-next-20260622201317";
|
|
15567
15537
|
}
|
|
15568
|
-
if (isReleaseVersion("0.0.0-next-
|
|
15569
|
-
return "0.0.0-next-
|
|
15538
|
+
if (isReleaseVersion("0.0.0-next-20260622201317")) {
|
|
15539
|
+
return "0.0.0-next-20260622201317";
|
|
15570
15540
|
}
|
|
15571
15541
|
try {
|
|
15572
15542
|
const root = repoRoot();
|