@pourkit/cli 0.0.0-next-20260531183322 → 0.0.0-next-20260601025244
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 +85 -33
- package/dist/cli.js.map +1 -1
- package/dist/e2e/run-live-e2e.js +76 -29
- package/dist/e2e/run-live-e2e.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -745,8 +745,7 @@ function getVerificationCommands(target) {
|
|
|
745
745
|
}
|
|
746
746
|
async function loadRepoConfig(repoRoot2, configFileName = "pourkit.config.ts") {
|
|
747
747
|
const { existsSync: existsSync10 } = await import("fs");
|
|
748
|
-
const {
|
|
749
|
-
const { tmpdir } = await import("os");
|
|
748
|
+
const { mkdir: mkdir5, writeFile: writeFile3, rm } = await import("fs/promises");
|
|
750
749
|
const { join: pjoin, basename } = await import("path");
|
|
751
750
|
const { pathToFileURL: pathToFileURL2 } = await import("url");
|
|
752
751
|
const { build } = await import("esbuild");
|
|
@@ -756,8 +755,10 @@ async function loadRepoConfig(repoRoot2, configFileName = "pourkit.config.ts") {
|
|
|
756
755
|
`No config file found at ${configPath}. Create a ${configFileName} that exports a default PourkitConfig.`
|
|
757
756
|
);
|
|
758
757
|
}
|
|
758
|
+
const tmpDir = pjoin(repoRoot2, ".pourkit", ".tmp", "config");
|
|
759
|
+
await mkdir5(tmpDir, { recursive: true });
|
|
759
760
|
const tmpFile = pjoin(
|
|
760
|
-
|
|
761
|
+
tmpDir,
|
|
761
762
|
`pourkit-config-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.mjs`
|
|
762
763
|
);
|
|
763
764
|
try {
|
|
@@ -1261,7 +1262,23 @@ function invalidateAfterBaseRefresh(state) {
|
|
|
1261
1262
|
}
|
|
1262
1263
|
|
|
1263
1264
|
// failure-resolution/effect-runtime.ts
|
|
1265
|
+
import { Effect as Effect2 } from "effect";
|
|
1266
|
+
|
|
1267
|
+
// shared/effect-runtime.ts
|
|
1264
1268
|
import { Effect } from "effect";
|
|
1269
|
+
var initialized = false;
|
|
1270
|
+
function initializeEffectRuntime() {
|
|
1271
|
+
if (initialized) return;
|
|
1272
|
+
initialized = true;
|
|
1273
|
+
}
|
|
1274
|
+
function runEffect(program) {
|
|
1275
|
+
if (!initialized) {
|
|
1276
|
+
throw new Error(
|
|
1277
|
+
"Effect runtime not initialized. Call initializeEffectRuntime() at CLI startup."
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
return Effect.runPromiseExit(program);
|
|
1281
|
+
}
|
|
1265
1282
|
|
|
1266
1283
|
// failure-resolution/types.ts
|
|
1267
1284
|
var RebaseConflict = class extends Error {
|
|
@@ -1295,6 +1312,30 @@ var RecoveryArtifactInvalid = class extends Error {
|
|
|
1295
1312
|
this.reason = args.reason;
|
|
1296
1313
|
}
|
|
1297
1314
|
};
|
|
1315
|
+
var ConfigFailure = class extends Error {
|
|
1316
|
+
_tag = "ConfigFailure";
|
|
1317
|
+
configKey;
|
|
1318
|
+
expectedType;
|
|
1319
|
+
message;
|
|
1320
|
+
constructor(args) {
|
|
1321
|
+
super(args.message);
|
|
1322
|
+
this.name = "ConfigFailure";
|
|
1323
|
+
this.configKey = args.configKey;
|
|
1324
|
+
this.expectedType = args.expectedType;
|
|
1325
|
+
this.message = args.message;
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
var SafetyFailure = class extends Error {
|
|
1329
|
+
_tag = "SafetyFailure";
|
|
1330
|
+
sensitivityKind;
|
|
1331
|
+
message;
|
|
1332
|
+
constructor(args) {
|
|
1333
|
+
super(args.message);
|
|
1334
|
+
this.name = "SafetyFailure";
|
|
1335
|
+
this.sensitivityKind = args.sensitivityKind;
|
|
1336
|
+
this.message = args.message;
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1298
1339
|
var SUPPORTED_DECISIONS = /* @__PURE__ */ new Set([
|
|
1299
1340
|
"RETRY_STAGE",
|
|
1300
1341
|
"HANDOFF_TO_HUMAN",
|
|
@@ -1470,23 +1511,23 @@ function recordStageAttempt(worktreePath, record) {
|
|
|
1470
1511
|
|
|
1471
1512
|
// failure-resolution/effect-runtime.ts
|
|
1472
1513
|
function baseRefreshEffect(options) {
|
|
1473
|
-
return
|
|
1474
|
-
|
|
1514
|
+
return Effect2.promise(() => refreshStaleIssueBranch(options)).pipe(
|
|
1515
|
+
Effect2.flatMap(
|
|
1475
1516
|
(result) => {
|
|
1476
1517
|
switch (result.status) {
|
|
1477
1518
|
case "refreshed":
|
|
1478
|
-
return
|
|
1519
|
+
return Effect2.succeed({ status: "refreshed" });
|
|
1479
1520
|
case "skipped-current":
|
|
1480
|
-
return
|
|
1521
|
+
return Effect2.succeed({ status: "skipped-current" });
|
|
1481
1522
|
case "conflicted":
|
|
1482
|
-
return
|
|
1523
|
+
return Effect2.fail(
|
|
1483
1524
|
new RebaseConflict({
|
|
1484
1525
|
conflictedPaths: result.conflictedPaths,
|
|
1485
1526
|
message: result.message
|
|
1486
1527
|
})
|
|
1487
1528
|
);
|
|
1488
1529
|
case "refused-published-history":
|
|
1489
|
-
return
|
|
1530
|
+
return Effect2.fail(
|
|
1490
1531
|
new PublishedHistoryRisk({
|
|
1491
1532
|
prNumber: result.prNumber,
|
|
1492
1533
|
prState: result.prState
|
|
@@ -1501,8 +1542,8 @@ async function runBaseRefreshAttempt(options) {
|
|
|
1501
1542
|
const attemptId = createStageAttemptId();
|
|
1502
1543
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1503
1544
|
const program = baseRefreshEffect(options).pipe(
|
|
1504
|
-
|
|
1505
|
-
onSuccess: (success) =>
|
|
1545
|
+
Effect2.tapBoth({
|
|
1546
|
+
onSuccess: (success) => Effect2.sync(() => {
|
|
1506
1547
|
recordStageAttempt(options.worktreePath, {
|
|
1507
1548
|
id: attemptId,
|
|
1508
1549
|
stage: "baseRefresh",
|
|
@@ -1511,7 +1552,7 @@ async function runBaseRefreshAttempt(options) {
|
|
|
1511
1552
|
outcome: "success"
|
|
1512
1553
|
});
|
|
1513
1554
|
}),
|
|
1514
|
-
onFailure: (failure) =>
|
|
1555
|
+
onFailure: (failure) => Effect2.sync(() => {
|
|
1515
1556
|
recordStageAttempt(options.worktreePath, {
|
|
1516
1557
|
id: attemptId,
|
|
1517
1558
|
stage: "baseRefresh",
|
|
@@ -1527,7 +1568,7 @@ async function runBaseRefreshAttempt(options) {
|
|
|
1527
1568
|
})
|
|
1528
1569
|
})
|
|
1529
1570
|
);
|
|
1530
|
-
return
|
|
1571
|
+
return runEffect(program);
|
|
1531
1572
|
}
|
|
1532
1573
|
|
|
1533
1574
|
// commands/conflict-resolution.ts
|
|
@@ -1550,7 +1591,7 @@ async function hasUnresolvedConflictMarkers(worktreePath, files) {
|
|
|
1550
1591
|
}
|
|
1551
1592
|
|
|
1552
1593
|
// commands/issue-run.ts
|
|
1553
|
-
import { Exit as
|
|
1594
|
+
import { Exit as Exit3 } from "effect";
|
|
1554
1595
|
|
|
1555
1596
|
// serena/baseline.ts
|
|
1556
1597
|
init_common();
|
|
@@ -1875,7 +1916,7 @@ import { join as join6 } from "path";
|
|
|
1875
1916
|
|
|
1876
1917
|
// failure-resolution/recovery-policy.ts
|
|
1877
1918
|
function isSecuritySensitiveFailure(failure) {
|
|
1878
|
-
return failure instanceof PublishedHistoryRisk;
|
|
1919
|
+
return failure instanceof PublishedHistoryRisk || failure instanceof SafetyFailure;
|
|
1879
1920
|
}
|
|
1880
1921
|
async function evaluateRecoveryPolicy(params) {
|
|
1881
1922
|
if (isSecuritySensitiveFailure(params.failure)) {
|
|
@@ -1884,6 +1925,14 @@ async function evaluateRecoveryPolicy(params) {
|
|
|
1884
1925
|
reason: "Security-sensitive failure \u2014 AI recovery bypassed"
|
|
1885
1926
|
};
|
|
1886
1927
|
}
|
|
1928
|
+
if (params.failure instanceof ConfigFailure) {
|
|
1929
|
+
if (params.agentRecommendedDecision !== "FAIL_RUN" && params.agentRecommendedDecision !== "HANDOFF_TO_HUMAN") {
|
|
1930
|
+
return {
|
|
1931
|
+
decision: "HANDOFF_TO_HUMAN",
|
|
1932
|
+
reason: `ConfigFailure \u2014 agent recommended ${params.agentRecommendedDecision} but config errors are not AI-repairable`
|
|
1933
|
+
};
|
|
1934
|
+
}
|
|
1935
|
+
}
|
|
1887
1936
|
const budget = recoveryBudgetForFailure(
|
|
1888
1937
|
params.worktreePath,
|
|
1889
1938
|
params.fingerprint,
|
|
@@ -1913,13 +1962,13 @@ async function evaluateRecoveryPolicy(params) {
|
|
|
1913
1962
|
// failure-resolution/failure-resolution-agent.ts
|
|
1914
1963
|
function constructFailureResolutionPacket(failure, context) {
|
|
1915
1964
|
return {
|
|
1916
|
-
failureType:
|
|
1965
|
+
failureType: failure._tag,
|
|
1917
1966
|
stageName: context.stageName,
|
|
1918
1967
|
attemptNumber: context.attemptNumber,
|
|
1919
1968
|
worktreePath: context.worktreePath,
|
|
1920
1969
|
branchName: context.branchName,
|
|
1921
1970
|
baseBranch: context.baseBranch,
|
|
1922
|
-
conflictedPaths: failure.conflictedPaths,
|
|
1971
|
+
conflictedPaths: failure instanceof RebaseConflict ? failure.conflictedPaths : void 0,
|
|
1923
1972
|
failureSummary: failure.message,
|
|
1924
1973
|
maxAttempts: context.maxAttempts,
|
|
1925
1974
|
allowedDecisions: context.allowedDecisions,
|
|
@@ -1940,10 +1989,7 @@ async function runFailureResolutionAgent(options) {
|
|
|
1940
1989
|
const frConfig = target.strategy.failureResolution;
|
|
1941
1990
|
const artifactPath = packet.artifactTarget;
|
|
1942
1991
|
const fullArtifactPath = join6(worktreePath, artifactPath);
|
|
1943
|
-
const fingerprint = computeFailureFingerprint(
|
|
1944
|
-
"baseRefresh",
|
|
1945
|
-
"RebaseConflict"
|
|
1946
|
-
);
|
|
1992
|
+
const fingerprint = computeFailureFingerprint(packet.stageName, failure._tag);
|
|
1947
1993
|
const prompt = [
|
|
1948
1994
|
`# Failure Resolution: ${packet.failureType}`,
|
|
1949
1995
|
"",
|
|
@@ -1982,7 +2028,8 @@ async function runFailureResolutionAgent(options) {
|
|
|
1982
2028
|
fingerprint,
|
|
1983
2029
|
`Agent execution failed: ${executionResult.error}`,
|
|
1984
2030
|
void 0,
|
|
1985
|
-
"HANDOFF_TO_HUMAN"
|
|
2031
|
+
"HANDOFF_TO_HUMAN",
|
|
2032
|
+
packet.stageName
|
|
1986
2033
|
);
|
|
1987
2034
|
return {
|
|
1988
2035
|
status: "handoff",
|
|
@@ -1997,7 +2044,8 @@ async function runFailureResolutionAgent(options) {
|
|
|
1997
2044
|
fingerprint,
|
|
1998
2045
|
"Agent did not write artifact",
|
|
1999
2046
|
void 0,
|
|
2000
|
-
"HANDOFF_TO_HUMAN"
|
|
2047
|
+
"HANDOFF_TO_HUMAN",
|
|
2048
|
+
packet.stageName
|
|
2001
2049
|
);
|
|
2002
2050
|
return {
|
|
2003
2051
|
status: "handoff",
|
|
@@ -2017,7 +2065,8 @@ async function runFailureResolutionAgent(options) {
|
|
|
2017
2065
|
fingerprint,
|
|
2018
2066
|
reason,
|
|
2019
2067
|
void 0,
|
|
2020
|
-
"HANDOFF_TO_HUMAN"
|
|
2068
|
+
"HANDOFF_TO_HUMAN",
|
|
2069
|
+
packet.stageName
|
|
2021
2070
|
);
|
|
2022
2071
|
return { status: "handoff", decision: "HANDOFF_TO_HUMAN", reason };
|
|
2023
2072
|
}
|
|
@@ -2032,7 +2081,8 @@ async function runFailureResolutionAgent(options) {
|
|
|
2032
2081
|
fingerprint,
|
|
2033
2082
|
validation.reason,
|
|
2034
2083
|
void 0,
|
|
2035
|
-
"HANDOFF_TO_HUMAN"
|
|
2084
|
+
"HANDOFF_TO_HUMAN",
|
|
2085
|
+
packet.stageName
|
|
2036
2086
|
);
|
|
2037
2087
|
return {
|
|
2038
2088
|
status: "handoff",
|
|
@@ -2054,7 +2104,8 @@ async function runFailureResolutionAgent(options) {
|
|
|
2054
2104
|
fingerprint,
|
|
2055
2105
|
policyResult.reason,
|
|
2056
2106
|
artifactPath,
|
|
2057
|
-
policyResult.decision
|
|
2107
|
+
policyResult.decision,
|
|
2108
|
+
packet.stageName
|
|
2058
2109
|
);
|
|
2059
2110
|
if (policyResult.decision === "HANDOFF_TO_HUMAN") {
|
|
2060
2111
|
return {
|
|
@@ -2076,12 +2127,12 @@ async function runFailureResolutionAgent(options) {
|
|
|
2076
2127
|
artifact
|
|
2077
2128
|
};
|
|
2078
2129
|
}
|
|
2079
|
-
async function writeRecoveryAttempt(worktreePath, outcome, fingerprint, summary, artifactRef, decision) {
|
|
2130
|
+
async function writeRecoveryAttempt(worktreePath, outcome, fingerprint, summary, artifactRef, decision, stageName = "baseRefresh") {
|
|
2080
2131
|
writeAttemptLog(worktreePath, {
|
|
2081
2132
|
attemptType: "recovery",
|
|
2082
2133
|
fingerprint,
|
|
2083
2134
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2084
|
-
stage:
|
|
2135
|
+
stage: stageName,
|
|
2085
2136
|
outcome,
|
|
2086
2137
|
artifactRef,
|
|
2087
2138
|
decision: decision ?? (outcome === "handoff" ? "HANDOFF_TO_HUMAN" : outcome === "success" ? "RETRY_STAGE" : void 0)
|
|
@@ -3671,7 +3722,7 @@ async function startIssueRun(options) {
|
|
|
3671
3722
|
prNumber: existingPr?.number,
|
|
3672
3723
|
prState: existingPr?.state
|
|
3673
3724
|
});
|
|
3674
|
-
if (
|
|
3725
|
+
if (Exit3.isSuccess(exit)) {
|
|
3675
3726
|
const refreshResult = exit.value;
|
|
3676
3727
|
if (refreshResult.status === "refreshed") {
|
|
3677
3728
|
if (worktreeState?.completedStages.builder) {
|
|
@@ -9041,11 +9092,11 @@ function createCliProgram(version) {
|
|
|
9041
9092
|
return program;
|
|
9042
9093
|
}
|
|
9043
9094
|
async function resolveCliVersion() {
|
|
9044
|
-
if (isPackageVersion("0.0.0-next-
|
|
9045
|
-
return "0.0.0-next-
|
|
9095
|
+
if (isPackageVersion("0.0.0-next-20260601025244")) {
|
|
9096
|
+
return "0.0.0-next-20260601025244";
|
|
9046
9097
|
}
|
|
9047
|
-
if (isReleaseVersion("0.0.0-next-
|
|
9048
|
-
return "0.0.0-next-
|
|
9098
|
+
if (isReleaseVersion("0.0.0-next-20260601025244")) {
|
|
9099
|
+
return "0.0.0-next-20260601025244";
|
|
9049
9100
|
}
|
|
9050
9101
|
try {
|
|
9051
9102
|
const root = repoRoot();
|
|
@@ -9071,6 +9122,7 @@ async function resolveCliVersion() {
|
|
|
9071
9122
|
return DEVELOPMENT_VERSION;
|
|
9072
9123
|
}
|
|
9073
9124
|
async function main(argv = process.argv.slice(2)) {
|
|
9125
|
+
initializeEffectRuntime();
|
|
9074
9126
|
const version = await resolveCliVersion();
|
|
9075
9127
|
const program = createCliProgram(version);
|
|
9076
9128
|
if (argv.length === 0) {
|