@pentoshi/clai 3.8.1 → 3.8.3

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.
@@ -779,6 +779,8 @@ export async function runAgentTurn(prompt, options = {}) {
779
779
  // normal continuation is governed by evidence and resource deltas above.
780
780
  const maxIterations = Math.max(210, computeMaxIterations(stepBudget));
781
781
  let productiveSteps = 0;
782
+ /** Successful file mutation this turn — kills false "error diagnosed but not fixed". */
783
+ let sawSuccessfulMutation = false;
782
784
  let step = -1;
783
785
  let nextToolEventId = 0;
784
786
  const alreadyPrintedIds = new Set();
@@ -2575,12 +2577,17 @@ export async function runAgentTurn(prompt, options = {}) {
2575
2577
  const planNarrated = (buildLikeTurn || pentestLikeTurn) &&
2576
2578
  !activePlan &&
2577
2579
  looksLikePlanNarration(cleaned);
2578
- const errorFixNarration = looksLikeErrorDiagnosisWithFixIntent(cleaned);
2580
+ // Only force "diagnosed but not fixed" when the model is still
2581
+ // narrating a fix without having applied one this turn. Post-fix
2582
+ // summaries ("I've fixed…", build passed) must never re-enter.
2583
+ const errorFixNarration = !sawSuccessfulMutation &&
2584
+ looksLikeErrorDiagnosisWithFixIntent(cleaned);
2579
2585
  const shouldRetryBeforeFinalizing = productiveSteps === 0 ||
2580
2586
  planNarrated ||
2581
2587
  (session.planApproved.value &&
2582
2588
  planHasOpenWorkNow &&
2583
2589
  (narratedAction || errorFixNarration)) ||
2590
+ // errorFix only when no mutation yet (gate is in errorFixNarration)
2584
2591
  (session.planApproved.value && errorFixNarration) ||
2585
2592
  (buildLikeTurn && errorFixNarration);
2586
2593
  if (wantsAction &&
@@ -2933,6 +2940,22 @@ export async function runAgentTurn(prompt, options = {}) {
2933
2940
  truncatedToolRetries = 0;
2934
2941
  malformedFenceRetries = 0;
2935
2942
  bareToolJsonRetries = 0;
2943
+ if (res.ok &&
2944
+ (res.call.name === "fs.edit" ||
2945
+ res.call.name === "fs.write" ||
2946
+ res.call.name === "fs.writeMany" ||
2947
+ res.call.name === "fs.replaceLines" ||
2948
+ res.call.name === "fs.append")) {
2949
+ // Mutation landed — post-fix summaries must not re-force tools.
2950
+ sawSuccessfulMutation = true;
2951
+ }
2952
+ // A fresh failed localhost probe re-opens the diagnosis→fix gate.
2953
+ if ((res.call.name === "http.fetch" ||
2954
+ res.call.name === "web.fetch" ||
2955
+ res.call.name === "shell.exec") &&
2956
+ localHttpProbeIsFailure(res.result.output ?? res.contextOutput ?? "")) {
2957
+ sawSuccessfulMutation = false;
2958
+ }
2936
2959
  if (res.ok && isEvidenceWorkTool(res.call.name)) {
2937
2960
  recovery.prematureComplete = 0;
2938
2961
  recovery.actionIntent = 0;