@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 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 { readFile: readFile5, writeFile: writeFile3, rm } = await import("fs/promises");
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
- tmpdir(),
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 Effect.promise(() => refreshStaleIssueBranch(options)).pipe(
1474
- Effect.flatMap(
1514
+ return Effect2.promise(() => refreshStaleIssueBranch(options)).pipe(
1515
+ Effect2.flatMap(
1475
1516
  (result) => {
1476
1517
  switch (result.status) {
1477
1518
  case "refreshed":
1478
- return Effect.succeed({ status: "refreshed" });
1519
+ return Effect2.succeed({ status: "refreshed" });
1479
1520
  case "skipped-current":
1480
- return Effect.succeed({ status: "skipped-current" });
1521
+ return Effect2.succeed({ status: "skipped-current" });
1481
1522
  case "conflicted":
1482
- return Effect.fail(
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 Effect.fail(
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
- Effect.tapBoth({
1505
- onSuccess: (success) => Effect.sync(() => {
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) => Effect.sync(() => {
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 Effect.runPromiseExit(program);
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 Exit2 } from "effect";
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: "RebaseConflict",
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: "baseRefresh",
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 (Exit2.isSuccess(exit)) {
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-20260531183322")) {
9045
- return "0.0.0-next-20260531183322";
9095
+ if (isPackageVersion("0.0.0-next-20260601025244")) {
9096
+ return "0.0.0-next-20260601025244";
9046
9097
  }
9047
- if (isReleaseVersion("0.0.0-next-20260531183322")) {
9048
- return "0.0.0-next-20260531183322";
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) {