omnius 1.0.455 → 1.0.457

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/index.js CHANGED
@@ -14238,6 +14238,66 @@ function findMatchOffsets(haystack, needle) {
14238
14238
  function replaceAllOccurrences(haystack, needle, replacement) {
14239
14239
  return haystack.split(needle).join(replacement);
14240
14240
  }
14241
+ function buildMissingOldStringLlmContent(input) {
14242
+ const lines = [
14243
+ "[FILE_EDIT_OLD_STRING_NOT_FOUND]",
14244
+ `path=${input.path}`,
14245
+ "The attempted old_string was absent from the current file.",
14246
+ "Do not copy diagnostic gutters into old_string. Ignore line numbers, leading '>' markers, and the '|' separator.",
14247
+ "",
14248
+ "attempted_old_string:",
14249
+ fencedText(input.attemptedOldString)
14250
+ ];
14251
+ if (input.snippetContent) {
14252
+ const range = input.snippetStartLine && input.snippetEndLine && input.totalLines ? `lines ${input.snippetStartLine}-${input.snippetEndLine} of ${input.totalLines}` : "closest current text";
14253
+ lines.push("", `copyable_current_text_without_gutters (${range}):`, fencedText(stripDiagnosticGutters(input.snippetContent)), "", "Next action: build a new file_edit old_string only from the copyable_current_text_without_gutters block, or file_read the target if more context is needed.");
14254
+ } else {
14255
+ lines.push("", "Next action: file_read the target, then build old_string from exact current file content.");
14256
+ }
14257
+ lines.push("", "Do not use shell text-rewrite commands as a workaround for this edit failure; keep the change tracked through file_edit, batch_edit, file_patch, or file_write.");
14258
+ if (input.newString.length > 0) {
14259
+ lines.push("", "desired_new_string:", fencedText(input.newString));
14260
+ }
14261
+ return lines.join("\n");
14262
+ }
14263
+ function buildAmbiguousOldStringLlmContent(input) {
14264
+ const replaceAllArgs = {
14265
+ path: input.path,
14266
+ old_string: input.oldString,
14267
+ new_string: input.newString,
14268
+ replace_all: true
14269
+ };
14270
+ return [
14271
+ "[FILE_EDIT_AMBIGUOUS_OLD_STRING]",
14272
+ `path=${input.path}`,
14273
+ `old_string matched ${input.occurrences} locations at lines ${input.matchLines.join(", ")}.`,
14274
+ "Do not retry the same old_string without either replace_all=true or additional unique surrounding context.",
14275
+ "Do not copy diagnostic gutters into old_string. Ignore line numbers, leading '>' markers, and the '|' separator.",
14276
+ "",
14277
+ "valid_next_action_replace_all_if_every_match_should_change_identically:",
14278
+ fencedJson(replaceAllArgs),
14279
+ "",
14280
+ "valid_next_action_single_location:",
14281
+ "Use file_edit with an old_string that includes unique surrounding current file text from exactly one match below.",
14282
+ "",
14283
+ "copyable_match_contexts_without_gutters:",
14284
+ fencedText(stripDiagnosticGutters(input.snippets).trim()),
14285
+ "",
14286
+ "Do not use shell text-rewrite commands as a workaround for this ambiguity; keep the change tracked through file_edit, batch_edit, file_patch, or file_write."
14287
+ ].join("\n");
14288
+ }
14289
+ function stripDiagnosticGutters(text2) {
14290
+ return text2.split("\n").map((line) => {
14291
+ const match = line.match(/^[ >]\s*\d+\s\|\s?(.*)$/);
14292
+ return match ? match[1] ?? "" : line;
14293
+ }).join("\n");
14294
+ }
14295
+ function fencedText(value2) {
14296
+ return ["```text", value2, "```"].join("\n");
14297
+ }
14298
+ function fencedJson(value2) {
14299
+ return ["```json", JSON.stringify(value2, null, 2), "```"].join("\n");
14300
+ }
14241
14301
  var FileEditTool;
14242
14302
  var init_file_edit = __esm({
14243
14303
  "packages/execution/dist/tools/file-edit.js"() {
@@ -14394,6 +14454,15 @@ Use the EXACT current content above to construct a working old_string. Do not re
14394
14454
  success: false,
14395
14455
  output: "",
14396
14456
  error: errorMsg,
14457
+ llmContent: buildMissingOldStringLlmContent({
14458
+ path: filePath,
14459
+ attemptedOldString: oldString,
14460
+ newString,
14461
+ snippetContent: snippet?.content ?? null,
14462
+ snippetStartLine: snippet?.startLine ?? null,
14463
+ snippetEndLine: snippet?.endLine ?? null,
14464
+ totalLines: snippet?.totalLines ?? null
14465
+ }),
14397
14466
  durationMs: performance.now() - start2,
14398
14467
  mutated: false,
14399
14468
  mutatedFiles: [],
@@ -14417,6 +14486,14 @@ ${s2.content}`;
14417
14486
  ${snippets}
14418
14487
 
14419
14488
  Add UNIQUE surrounding context (a function name, distinctive comment, or unique line above/below) to disambiguate. Or set replace_all=true if you want all ${occurrences} occurrences replaced identically.`,
14489
+ llmContent: buildAmbiguousOldStringLlmContent({
14490
+ path: filePath,
14491
+ oldString,
14492
+ newString,
14493
+ occurrences,
14494
+ matchLines,
14495
+ snippets
14496
+ }),
14420
14497
  durationMs: performance.now() - start2,
14421
14498
  mutated: false,
14422
14499
  mutatedFiles: [],
@@ -566026,12 +566103,12 @@ function buildCriticGuidanceMessage(call, hits, opts = {}) {
566026
566103
  const cached = opts.cachedResult ? `
566027
566104
  Prior evidence preview:
566028
566105
  ${opts.cachedResult.slice(0, 700)}` : "";
566029
- const source = opts.adversaryFlag ? "The adversary recognized this exact tool call as already observed earlier." : `This is exact repeat #${hits} for the same ${call.tool} arguments.`;
566030
- return `[ADVERSARY GUIDANCE — non-blocking]
566106
+ const source = opts.adversaryFlag ? "The runtime recognized this exact tool call as already observed earlier." : `This is exact repeat #${hits} for the same ${call.tool} arguments.`;
566107
+ return `[RUNTIME EVIDENCE CACHE — non-blocking]
566031
566108
  Observation: ${source}
566032
566109
  Call: ${call.tool}(${argPreview})
566033
- Root cause hypothesis: the run is losing track of already-observed evidence, usually after path confusion, compaction, or an over-broad discovery loop.
566034
- Corrective action: let this call's result inform the next step once, then pivot to a concrete action.
566110
+ State: exact prior evidence exists for these arguments in the current state version.
566111
+ Next action contract: let this result inform the next step once, then pivot to a concrete action.
566035
566112
  Suggested next actions: edit/write the implicated file, run verification, read a different specific file, or complete with evidence. Prefer not to repeat this exact call again unless the filesystem, browser, or page state changed.${cached}`;
566036
566113
  }
566037
566114
  function buildCachedResultEnvelope(result) {
@@ -570813,7 +570890,7 @@ ${fileLines}`);
570813
570890
  const counts = { ok: 0, failed: 0, blocked: 0 };
570814
570891
  for (const ev of events) {
570815
570892
  const preview = ev.outputPreview ?? "";
570816
- if (preview.includes("[FOCUS SUPERVISOR BLOCK]") || preview.includes("[STOP RE-RUNNING") || preview.includes("[REPEAT GATE")) {
570893
+ if (preview.includes("[FOCUS SUPERVISOR BLOCK]") || preview.includes("[STOP RE-RUNNING") || preview.includes("[CACHED VERIFIER FAILURE") || preview.includes("[REPEAT GATE")) {
570817
570894
  counts.blocked++;
570818
570895
  } else if (ev.success === false) {
570819
570896
  counts.failed++;
@@ -573775,6 +573852,10 @@ function adversarySystemPrompt() {
573775
573852
  ].join("\n");
573776
573853
  }
573777
573854
  function buildObservationPrompt(obs, recentLedger) {
573855
+ const stateDigest = obs.stateDigest ? `
573856
+ Runner world/progress digest:
573857
+ ${obs.stateDigest.slice(0, 1800)}
573858
+ ` : "";
573778
573859
  const outcomes = obs.recentToolOutcomes.slice(-8).map((o2) => {
573779
573860
  const target = o2.path ? ` path=${o2.path}` : "";
573780
573861
  const evidence = o2.evidence ? ` | evidence: ${o2.evidence.slice(0, 220)}` : "";
@@ -573788,6 +573869,8 @@ function buildObservationPrompt(obs, recentLedger) {
573788
573869
  `This is a loop. Reason about WHY — for THIS specific call, not generically.`,
573789
573870
  ls2.alreadyHave ? `Evidence the agent ALREADY obtained from a prior identical call:
573790
573871
  ${ls2.alreadyHave.slice(0, 900)}` : `(No cached result available for the repeated call.)`,
573872
+ "",
573873
+ stateDigest.trim(),
573791
573874
  "",
573792
573875
  "Agent's latest message:",
573793
573876
  obs.assistantText.slice(0, 1200) || "(empty)",
@@ -573809,6 +573892,8 @@ ${ls2.alreadyHave.slice(0, 900)}` : `(No cached result available for the repeate
573809
573892
  "",
573810
573893
  "A repeating identical error means the CHANGE ITSELF is wrong — an unsupported attribute/option, a wrong API/signature, or a missing prerequisite — NOT a value the agent hasn't guessed yet.",
573811
573894
  "",
573895
+ stateDigest.trim(),
573896
+ "",
573812
573897
  "Agent's latest message:",
573813
573898
  obs.assistantText.slice(0, 900) || "(empty)",
573814
573899
  "",
@@ -573819,12 +573904,32 @@ ${ls2.alreadyHave.slice(0, 900)}` : `(No cached result available for the repeate
573819
573904
  "Return ONLY the JSON object."
573820
573905
  ].join("\n");
573821
573906
  }
573907
+ if (obs.diagnosticSignal) {
573908
+ return [
573909
+ `The runtime queued a diagnostic trigger: ${obs.diagnosticSignal}.`,
573910
+ "This trigger is only a routing signal. Do NOT trust it as a verdict; classify from the world/progress digest and tool evidence.",
573911
+ stateDigest.trim(),
573912
+ "",
573913
+ "Agent's latest message:",
573914
+ obs.assistantText.slice(0, 1600) || "(empty)",
573915
+ "",
573916
+ "Recent tool outcomes:",
573917
+ outcomes || " (none)",
573918
+ priorDoubts ? `
573919
+ Unresolved doubts you raised earlier:
573920
+ ${priorDoubts}` : "",
573921
+ "",
573922
+ "Decide whether there is a real contradiction, stale-state action, unproven claim, or no issue. Return ONLY the JSON object."
573923
+ ].filter((line) => line !== "").join("\n");
573924
+ }
573822
573925
  return [
573823
573926
  obs.claimsCompletion ? "The agent is asserting COMPLETION this turn." : "The agent produced a progress/success-flavored claim this turn.",
573824
573927
  "",
573825
573928
  "Agent's latest message:",
573826
573929
  obs.assistantText.slice(0, 1800) || "(empty)",
573827
573930
  "",
573931
+ stateDigest.trim(),
573932
+ "",
573828
573933
  "Recent tool outcomes (evidence available):",
573829
573934
  outcomes || " (none)",
573830
573935
  priorDoubts ? `
@@ -573959,14 +574064,16 @@ var init_adversaryStream = __esm({
573959
574064
  return true;
573960
574065
  if (obs.failingApproach)
573961
574066
  return true;
574067
+ if (obs.diagnosticSignal)
574068
+ return true;
573962
574069
  return SUCCESS_LANGUAGE.test(obs.assistantText);
573963
574070
  }
573964
574071
  /** Ingest an observation. Replaces any prior un-audited pending observation. */
573965
574072
  observe(obs) {
573966
574073
  if (!this.shouldAudit(obs))
573967
574074
  return;
573968
- const loopKey = obs.loopSignal ? `loop:${obs.loopSignal.tool}:${obs.loopSignal.target}:${obs.loopSignal.count}` : obs.failingApproach ? `fail:${obs.failingApproach.count}:${obs.failingApproach.sample.slice(0, 60)}` : "";
573969
- const sig = `${obs.turn}:${loopKey}:${obs.assistantText.slice(0, 200)}`;
574075
+ const loopKey = obs.loopSignal ? `loop:${obs.loopSignal.tool}:${obs.loopSignal.target}:${obs.loopSignal.count}` : obs.failingApproach ? `fail:${obs.failingApproach.count}:${obs.failingApproach.sample.slice(0, 60)}` : obs.diagnosticSignal ? `diag:${obs.diagnosticSignal}` : "";
574076
+ const sig = `${obs.turn}:${loopKey}:${obs.assistantText.slice(0, 200)}:${obs.stateDigest?.slice(0, 120) ?? ""}`;
573970
574077
  if (sig === this.lastAuditedSignature)
573971
574078
  return;
573972
574079
  this.pending = obs;
@@ -574802,6 +574909,12 @@ function violatesDirective(directive, input) {
574802
574909
  return !(input.toolName === "todo_write" || isEditTool(input.toolName));
574803
574910
  case "read_authoritative_target":
574804
574911
  return !(isEvidenceGatheringTool(input.toolName) || input.isReadLike);
574912
+ case "disambiguate_edit_match":
574913
+ if (isEditTool(input.toolName))
574914
+ return false;
574915
+ if (isEvidenceGatheringTool(input.toolName) || input.isReadLike)
574916
+ return false;
574917
+ return true;
574805
574918
  case "run_verification":
574806
574919
  return input.toolName !== "shell";
574807
574920
  case "report_blocked":
@@ -574818,9 +574931,6 @@ function violatesDirective(directive, input) {
574818
574931
  }
574819
574932
  }
574820
574933
  function forbiddenCachedEvidenceFamilies(input, family) {
574821
- if (input.cachedResultFailed && input.toolName === "shell") {
574822
- return uniqueLimited([family, "shell"]);
574823
- }
574824
574934
  return [family];
574825
574935
  }
574826
574936
  function normalizeCompletionStatus(value2) {
@@ -574885,7 +574995,7 @@ function cleanFailureSample(text2) {
574885
574995
  }
574886
574996
  function failureErrorClass(text2) {
574887
574997
  const normalized = String(text2 || "").toLowerCase();
574888
- if (/ambiguous|multiple occurrences|matches more than once/.test(normalized)) {
574998
+ if (/ambiguous|not unique|multiple occurrences|matches more than once|found \d+ occurrences|has \d+ matches/.test(normalized)) {
574889
574999
  return "stale_ambiguous_target";
574890
575000
  }
574891
575001
  if (/expected[_ -]?hash|hash mismatch|stale hash|beforehash|afterhash/.test(normalized)) {
@@ -574939,13 +575049,15 @@ function editTargetDescriptor(toolName, args) {
574939
575049
  "expected_old_string",
574940
575050
  "expectedHash",
574941
575051
  "expected_hash",
575052
+ "replace_all",
575053
+ "replaceAll",
574942
575054
  "mode",
574943
575055
  "offset",
574944
575056
  "limit",
574945
575057
  "start_line"
574946
575058
  ]) {
574947
575059
  const value2 = args[key];
574948
- if (typeof value2 === "string" || typeof value2 === "number") {
575060
+ if (typeof value2 === "string" || typeof value2 === "number" || typeof value2 === "boolean") {
574949
575061
  parts.push(`${key}=${String(value2)}`);
574950
575062
  }
574951
575063
  }
@@ -574957,7 +575069,8 @@ function editTargetDescriptor(toolName, args) {
574957
575069
  const rec = edit;
574958
575070
  const editPath = rec["path"] ?? rec["file"] ?? rec["filePath"] ?? rec["file_path"];
574959
575071
  const target = rec["old_string"] ?? rec["oldString"] ?? rec["oldText"] ?? rec["search"] ?? rec["expected_old_string"] ?? rec["offset"] ?? rec["start_line"] ?? "";
574960
- parts.push(`${String(editPath ?? "")}=${String(target ?? "")}`);
575072
+ const replaceAll = rec["replace_all"] === true || rec["replaceAll"] === true;
575073
+ parts.push(`${String(editPath ?? "")}=${String(target ?? "")}${replaceAll ? ":replace_all=true" : ""}`);
574961
575074
  }
574962
575075
  }
574963
575076
  if (parts.length === 0 && toolName === "file_patch") {
@@ -575192,6 +575305,10 @@ var init_focusSupervisor = __esm({
575192
575305
  this.clearSatisfiedDirective("requested edit already applied", input.turn);
575193
575306
  return;
575194
575307
  }
575308
+ if (input.success && input.noop && input.isReadLike && (this.directive?.requiredNextAction === "use_cached_evidence" || this.directive?.requiredNextAction === "read_authoritative_target")) {
575309
+ this.clearSatisfiedDirective(input.runtimeAuthored ? "cached authoritative evidence reused" : "authoritative evidence already available", input.turn);
575310
+ return;
575311
+ }
575195
575312
  if (input.runtimeAuthored) {
575196
575313
  this.lastDecision = "runtime_authored_not_satisfied";
575197
575314
  this.lastReason = "runtime-authored control result did not execute the requested tool";
@@ -575212,7 +575329,7 @@ var init_focusSupervisor = __esm({
575212
575329
  return;
575213
575330
  }
575214
575331
  if (input.toolName === "file_read" && input.success) {
575215
- if (this.directive?.requiredNextAction === "read_authoritative_target" || this.directive?.requiredNextAction === "use_cached_evidence") {
575332
+ if (this.directive?.requiredNextAction === "read_authoritative_target") {
575216
575333
  this.clearSatisfiedDirective("authoritative evidence refreshed", input.turn);
575217
575334
  }
575218
575335
  return;
@@ -575220,8 +575337,10 @@ var init_focusSupervisor = __esm({
575220
575337
  if (input.toolName === "shell" && input.success) {
575221
575338
  if (this.directive?.requiredNextAction === "run_verification") {
575222
575339
  this.clearSatisfiedDirective("verification ran successfully", input.turn);
575223
- } else if (input.isReadLike && (this.directive?.requiredNextAction === "read_authoritative_target" || this.directive?.requiredNextAction === "use_cached_evidence")) {
575340
+ } else if (input.isReadLike && this.directive?.requiredNextAction === "read_authoritative_target") {
575224
575341
  this.clearSatisfiedDirective("authoritative evidence read via shell", input.turn);
575342
+ } else if (!input.isReadLike && this.directive?.requiredNextAction === "use_cached_evidence") {
575343
+ this.clearSatisfiedDirective("distinct shell action executed after cached evidence", input.turn);
575225
575344
  }
575226
575345
  return;
575227
575346
  }
@@ -575237,27 +575356,29 @@ var init_focusSupervisor = __esm({
575237
575356
  };
575238
575357
  this.failureFamilies.set(family, next);
575239
575358
  if (next.count >= 2) {
575359
+ const ambiguousEditFailure = isEditTool(input.toolName) && next.errorClass === "stale_ambiguous_target";
575240
575360
  const staleEditFailure = isEditTool(input.toolName) && next.errorClass.startsWith("stale_");
575241
- const forbidden = staleEditFailure ? uniqueLimited([
575361
+ const forbidden = staleEditFailure ? ambiguousEditFailure ? [actionFamily(input.toolName, input.args)] : uniqueLimited([
575242
575362
  actionFamily(input.toolName, input.args),
575243
575363
  input.toolName
575244
- ]) : input.toolName === "shell" ? uniqueLimited([actionFamily(input.toolName, input.args), "shell"]) : [actionFamily(input.toolName, input.args)];
575364
+ ]) : input.toolName === "shell" ? [actionFamily(input.toolName, input.args)] : [actionFamily(input.toolName, input.args)];
575245
575365
  this.setDirective({
575246
575366
  turn: input.turn,
575247
575367
  state: "forced_replan",
575248
575368
  reason: `same ${input.toolName} failure family repeated ${next.count} times: ${next.sample}`,
575249
- requiredNextAction: staleEditFailure ? "read_authoritative_target" : input.toolName === "shell" ? "use_cached_evidence" : "update_todos",
575369
+ requiredNextAction: ambiguousEditFailure ? "disambiguate_edit_match" : staleEditFailure ? "read_authoritative_target" : input.toolName === "shell" ? "use_cached_evidence" : "update_todos",
575250
575370
  forbiddenActionFamilies: forbidden
575251
575371
  });
575252
575372
  } else if (next.count === 1 && !this.directive) {
575373
+ const ambiguousEditFailure = isEditTool(input.toolName) && next.errorClass === "stale_ambiguous_target";
575253
575374
  const staleEditFailure = isEditTool(input.toolName) && next.errorClass.startsWith("stale_");
575254
575375
  const shellFailure = input.toolName === "shell";
575255
575376
  this.setDirective({
575256
575377
  turn: input.turn,
575257
575378
  state: shellFailure ? "cached_evidence" : "warn",
575258
575379
  reason: `first ${input.toolName} failure (${next.errorClass}): ${next.sample}`,
575259
- requiredNextAction: staleEditFailure ? "read_authoritative_target" : shellFailure ? "use_cached_evidence" : "update_todos",
575260
- forbiddenActionFamilies: shellFailure ? uniqueLimited([actionFamily(input.toolName, input.args), "shell"]) : [actionFamily(input.toolName, input.args)]
575380
+ requiredNextAction: ambiguousEditFailure ? "disambiguate_edit_match" : staleEditFailure ? "read_authoritative_target" : shellFailure ? "use_cached_evidence" : "update_todos",
575381
+ forbiddenActionFamilies: shellFailure ? [actionFamily(input.toolName, input.args)] : [actionFamily(input.toolName, input.args)]
575261
575382
  });
575262
575383
  }
575263
575384
  }
@@ -578939,8 +579060,11 @@ ${parts.join("\n")}
578939
579060
  case "update_todos":
578940
579061
  return "todo_write with a changed plan/status, or a real file edit if that is the active work";
578941
579062
  case "read_authoritative_target":
578942
- case "use_cached_evidence":
578943
579063
  return "use cached evidence or one authoritative file_read/read-only shell, then act";
579064
+ case "use_cached_evidence":
579065
+ return "do not rerun the blocked family; use the cached result to make a concrete edit, run a genuinely different diagnostic/verification command, or report incomplete";
579066
+ case "disambiguate_edit_match":
579067
+ return "file_edit or batch_edit with replace_all=true for identical global changes, or with a more unique old_string copied from current file context";
578944
579068
  case "edit_different_target":
578945
579069
  return "file_write, file_edit, batch_edit, or file_patch on a different supported target";
578946
579070
  case "run_verification":
@@ -585514,16 +585638,14 @@ TASK: ${scrubbedTask}` : scrubbedTask;
585514
585638
  cwd: this._workingDirectory || process.cwd(),
585515
585639
  model: this._backendModelLabel(this.backend),
585516
585640
  onCritique: (critique2, sourceTurn) => {
585517
- if (completed || this._completionIncompleteVerification || this.aborted) {
585518
- return;
585519
- }
585520
- if (this._adversaryMode === "skillcoach" || this._adversaryMode === "both") {
585641
+ const runClosed = completed || this._completionIncompleteVerification || this.aborted;
585642
+ if (!runClosed && (this._adversaryMode === "skillcoach" || this._adversaryMode === "both")) {
585521
585643
  this.pendingUserMessages.push(AdversaryStream.formatInjection(critique2));
585522
585644
  }
585523
585645
  this.emit({
585524
585646
  type: "adversary_reaction",
585525
585647
  adversary: {
585526
- class: critique2.class === "false_failure" ? "false_failure" : critique2.class === "false_success" ? "false_success" : "guidance",
585648
+ class: critique2.class === "ok" ? "guidance" : critique2.class,
585527
585649
  shortText: critique2.shortText,
585528
585650
  confidence: critique2.confidence,
585529
585651
  details: AdversaryStream.formatInjection(critique2)
@@ -585544,6 +585666,7 @@ TASK: ${scrubbedTask}` : scrubbedTask;
585544
585666
  this._argCohorts.clear();
585545
585667
  this._adversaryRedundantSignals.clear();
585546
585668
  this._adversaryRecentFlags.clear();
585669
+ this._adversaryStateVersion = 0;
585547
585670
  this._lastTodoWriteTurn = -1;
585548
585671
  this._lastTodoReminderTurn = -1;
585549
585672
  let pendingConstraintWarnings = [];
@@ -588481,13 +588604,10 @@ Read the current file if needed, make a different concrete edit, or move to veri
588481
588604
  }
588482
588605
  criticGuidance = criticDecision.guidanceMessage;
588483
588606
  this.emit({
588484
- type: "adversary_reaction",
588485
- adversary: {
588486
- class: "guidance",
588487
- shortText: `Adversary guidance for repeated ${tc.name} call`,
588488
- confidence: 0.9,
588489
- details: criticDecision.reason
588490
- },
588607
+ type: "status",
588608
+ content: `Runtime cache guidance for repeated ${tc.name} call: ${criticDecision.reason}`,
588609
+ toolName: tc.name,
588610
+ turn,
588491
588611
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
588492
588612
  });
588493
588613
  if (this._adversaryStream && criticDecision.hitNumber >= 2) {
@@ -588517,6 +588637,9 @@ Read the current file if needed, make a different concrete edit, or move to veri
588517
588637
  const _repeatGateMax = this._resolveRepeatGateMax();
588518
588638
  const isFailedShellRepeat = tc.name === "shell" && typeof _existingFp?.result === "string" && _existingFp.result.includes("status: failure");
588519
588639
  const repeatGateEligible = isReadLike || tc.name === "memory_write" || isFailedShellRepeat;
588640
+ const suppressSuccessfulShellCacheGuidance = tc.name === "shell" && !isFailedShellRepeat;
588641
+ if (suppressSuccessfulShellCacheGuidance)
588642
+ criticGuidance = null;
588520
588643
  if (isReadLike && this._evidenceLedger) {
588521
588644
  const readArgs = tc.arguments;
588522
588645
  const readPath2 = String(readArgs?.["path"] ?? readArgs?.["file"] ?? "");
@@ -588562,10 +588685,10 @@ Read the current file if needed, make a different concrete edit, or move to veri
588562
588685
  const cachedResult = this.sanitizeCachedToolResult(tc.name, _existingFp.result);
588563
588686
  repeatShortCircuit = isFailedShellRepeat ? {
588564
588687
  success: false,
588565
- output: `[STOP RE-RUNNING FAILED COMMAND — this exact shell command already failed and no real file mutation has invalidated that evidence. It was NOT executed again. Use the cached failure below to change approach, inspect a different target, or report incomplete.]
588688
+ output: `[CACHED VERIFIER FAILURE — this same shell command already produced debugging evidence and was not re-executed unchanged. Treat the cached transcript below as the current failure signal. Change the code/config, run a genuinely different verifier/diagnostic command, or report the blocker with this evidence.]
588566
588689
 
588567
588690
  ${cachedResult}`,
588568
- error: "Repeated failing shell command was not re-executed.",
588691
+ error: "Cached verifier failure reused; command was not re-executed unchanged.",
588569
588692
  runtimeAuthored: true
588570
588693
  } : {
588571
588694
  success: true,
@@ -588578,7 +588701,7 @@ ${cachedResult}`,
588578
588701
  this.emit({
588579
588702
  type: "status",
588580
588703
  toolName: tc.name,
588581
- content: repeatShortCircuit ? repeatShortCircuit.success ? `Exact repeat of ${tc.name} served from cache (hit #${criticDecision.hitNumber}); not re-executed` : `Exact repeat of ${tc.name} blocked after ${criticDecision.hitNumber} repeats; re-plan required` : `Adversary guidance emitted for ${tc.name}; tool call will still execute`,
588704
+ content: repeatShortCircuit ? repeatShortCircuit.success ? `Exact repeat of ${tc.name} served from cache (hit #${criticDecision.hitNumber}); not re-executed` : `Exact repeat of ${tc.name} blocked after ${criticDecision.hitNumber} repeats; re-plan required` : suppressSuccessfulShellCacheGuidance ? `Repeated successful shell command observed; re-executing because no state-independent verdict was made` : `Runtime cache guidance emitted for ${tc.name}; tool call will still execute`,
588582
588705
  turn,
588583
588706
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
588584
588707
  });
@@ -588860,7 +588983,11 @@ Respond with EXACTLY this structure before your next tool call:
588860
588983
  }
588861
588984
  const shellFilesystemMutation = tc.name === "shell" && result.success === true && this._shellCommandLikelyMutatesFilesystem(String(tc.arguments?.["command"] ?? tc.arguments?.["cmd"] ?? ""));
588862
588985
  const realFileMutation = this._isRealProjectMutation(tc.name, result);
588986
+ const observedStateMutation = realFileMutation || shellFilesystemMutation || result.success === true && result.mutated === true;
588863
588987
  const realMutationPaths = realFileMutation ? this._extractToolTargetPaths(tc.name, tc.arguments, result) : [];
588988
+ if (observedStateMutation) {
588989
+ this._markAdversaryObservedStateMutation();
588990
+ }
588864
588991
  if (realFileMutation && this._reg61PerpetualGateActive) {
588865
588992
  this._reg61PerpetualGateActive = false;
588866
588993
  this.emit({
@@ -589700,8 +589827,10 @@ Respond with EXACTLY this structure before your next tool call:
589700
589827
  }
589701
589828
  if (isFileMutation && recentToolResults.size > 0) {
589702
589829
  for (const key of Array.from(recentToolResults.keys())) {
589703
- if (key.startsWith("shell:"))
589830
+ if (key.startsWith("shell:")) {
589704
589831
  recentToolResults.delete(key);
589832
+ dedupHitCount.delete(key);
589833
+ }
589705
589834
  }
589706
589835
  }
589707
589836
  if (isFileMutation) {
@@ -593110,7 +593239,18 @@ ${folded}`);
593110
593239
  buildRecoveryGuidance(toolName, error, args) {
593111
593240
  const errLower = error.toLowerCase();
593112
593241
  if (toolName === "file_edit" || toolName === "batch_edit") {
593113
- if (errLower.includes("not found") || errLower.includes("old_string") || errLower.includes("no match")) {
593242
+ if (/ambiguous|not unique|multiple occurrences|matches more than once|found \d+ occurrences|has \d+ matches/.test(errLower)) {
593243
+ if (toolName === "batch_edit") {
593244
+ return `[RECOVERY] batch_edit failed because at least one old_string matched multiple locations.
593245
+ ACTION: retry the affected edit with replace_all=true if every match should change identically, or add unique surrounding current file text to that edit's old_string if only one location should change. Do not switch to shell sed/perl/python rewrites.`;
593246
+ }
593247
+ const filePath = String(args["path"] ?? "the file");
593248
+ const oldStr = String(args["old_string"] ?? "").slice(0, 120);
593249
+ return `[RECOVERY] file_edit failed because old_string is ambiguous in ${filePath}.
593250
+ Attempted old_string preview: "${oldStr}".
593251
+ ACTION: retry file_edit with replace_all=true if every match should change identically, or use an old_string containing unique surrounding current file text for exactly one location. Do not retry the same old_string without replace_all, and do not switch to shell sed/perl/python rewrites.`;
593252
+ }
593253
+ if (errLower.includes("not found") || errLower.includes("no match") || errLower.includes("no occurrences") || errLower.includes("0 occurrences") || errLower.includes("could not find")) {
593114
593254
  if (toolName === "batch_edit") {
593115
593255
  const edits = Array.isArray(args["edits"]) ? args["edits"] : [];
593116
593256
  const filePaths = [
@@ -594383,6 +594523,10 @@ ${trimmedNew}`;
594383
594523
  // we add a second analysis path that catches mismatches in real-time.
594384
594524
  /** Track recent tool outcomes for the adversary */
594385
594525
  _adversaryToolOutcomes = [];
594526
+ /** Monotonic counter for observed local state changes.
594527
+ * Redundant-action classification is only valid within the same state
594528
+ * version; a repeated verifier after an edit is fresh evidence. */
594529
+ _adversaryStateVersion = 0;
594386
594530
  /** WO-FIX-C: Tool fingerprints the adversary has flagged as redundant.
594387
594531
  * Checked in executeSingle to attach advisory guidance before dispatch. */
594388
594532
  _adversaryRedundantSignals = /* @__PURE__ */ new Set();
@@ -594397,6 +594541,59 @@ ${trimmedNew}`;
594397
594541
  * Generates typed self-reflections on task failure and injects them
594398
594542
  * into the next attempt's context for active learning. */
594399
594543
  _reflectionBuffer = null;
594544
+ _markAdversaryObservedStateMutation() {
594545
+ this._adversaryStateVersion++;
594546
+ this._adversaryRedundantSignals.clear();
594547
+ for (const key of Array.from(this._adversaryRecentFlags.keys())) {
594548
+ if (key.startsWith("redundant_action:")) {
594549
+ this._adversaryRecentFlags.delete(key);
594550
+ }
594551
+ }
594552
+ }
594553
+ _buildAdversaryStateDigest(turn) {
594554
+ const ts = this._taskState;
594555
+ let todos = [];
594556
+ try {
594557
+ todos = this.readSessionTodos() ?? [];
594558
+ } catch {
594559
+ todos = [];
594560
+ }
594561
+ const todoCounts = {
594562
+ completed: todos.filter((t2) => t2.status === "completed").length,
594563
+ inProgress: todos.filter((t2) => t2.status === "in_progress").length,
594564
+ pending: todos.filter((t2) => t2.status === "pending").length,
594565
+ blocked: todos.filter((t2) => t2.status === "blocked").length
594566
+ };
594567
+ const activeTodos = todos.filter((t2) => t2.status === "in_progress" || t2.status === "blocked").slice(0, 4).map((t2) => `[${t2.status}] ${String(t2.content ?? "").slice(0, 120)}`);
594568
+ const modifiedFiles = [...ts.modifiedFiles.entries()].slice(-10).map(([path12, action]) => `${action}:${path12}`);
594569
+ const worldFiles = [...this._worldFacts.files.entries()].sort((a2, b) => (b[1].lastSeenTurn ?? 0) - (a2[1].lastSeenTurn ?? 0)).slice(0, 8).map(([path12, fact]) => {
594570
+ const write2 = fact.lastWriteTurn ? ` write@${fact.lastWriteTurn}` : "";
594571
+ const seen = `seen@${fact.lastSeenTurn}`;
594572
+ const wc = fact.writeCount ? ` writes=${fact.writeCount}` : "";
594573
+ return `${path12} (${seen}${write2}${wc})`;
594574
+ });
594575
+ const recentFailures = this._recentFailures.slice(-5).map((failure) => {
594576
+ const text2 = (failure.error || failure.output || "").replace(/\s+/g, " ").trim().slice(0, 180);
594577
+ return `${failure.tool}: ${text2}`;
594578
+ });
594579
+ const focus = this._focusSupervisor?.snapshot().directive;
594580
+ const lines = [
594581
+ `[WORLD STATE SUMMARY] turn=${turn} state_version=${this._adversaryStateVersion}`,
594582
+ `goal=${(ts.originalGoal || ts.goal || "").slice(0, 260)}`,
594583
+ `phase=${ts.phase ?? "unknown"} current_step=${(ts.currentStep || "none").slice(0, 180)}`,
594584
+ ts.nextAction ? `next_action=${ts.nextAction.slice(0, 180)}` : "",
594585
+ `progress=todos completed:${todoCounts.completed} in_progress:${todoCounts.inProgress} pending:${todoCounts.pending} blocked:${todoCounts.blocked}; completed_steps:${ts.completedSteps.length}; failed_approaches:${ts.failedApproaches.length}; modified_files:${ts.modifiedFiles.size}; tool_calls:${ts.toolCallCount}`,
594586
+ activeTodos.length ? `active_todos=${activeTodos.join(" | ")}` : "",
594587
+ ts.completedSteps.length ? `recent_completed=${ts.completedSteps.slice(-5).join(" | ").slice(0, 500)}` : "",
594588
+ ts.failedApproaches.length ? `recent_failed_approaches=${ts.failedApproaches.slice(-4).join(" | ").slice(0, 500)}` : "",
594589
+ modifiedFiles.length ? `modified_files_recent=${modifiedFiles.join(" | ").slice(0, 700)}` : "",
594590
+ worldFiles.length ? `world_files_recent=${worldFiles.join(" | ").slice(0, 700)}` : "",
594591
+ this._worldFacts.lastTest.summary ? `last_verification=${this._worldFacts.lastTest.passed ? "passed" : "failed"} turn=${this._worldFacts.lastTest.turn ?? "?"}: ${this._worldFacts.lastTest.summary.slice(0, 260)}` : "",
594592
+ recentFailures.length ? `recent_failures=${recentFailures.join(" | ").slice(0, 700)}` : "",
594593
+ focus ? `focus=${focus.requiredNextAction}: ${focus.reason.slice(0, 240)}` : ""
594594
+ ].filter(Boolean);
594595
+ return lines.join("\n").slice(0, 2600);
594596
+ }
594400
594597
  buildAdversaryToolOutcomeEvidence(toolName, toolArgs, content, succeeded) {
594401
594598
  const pathValue = toolArgs?.["path"] ?? toolArgs?.["file"] ?? toolArgs?.["filePath"] ?? toolArgs?.["file_path"];
594402
594599
  const path12 = typeof pathValue === "string" && pathValue.trim() ? pathValue.trim() : void 0;
@@ -594480,6 +594677,7 @@ ${trimmedNew}`;
594480
594677
  toolCallId: msg.tool_call_id,
594481
594678
  argsKey,
594482
594679
  fingerprint,
594680
+ stateVersion: this._adversaryStateVersion,
594483
594681
  succeeded,
594484
594682
  ...outcomeEvidence
594485
594683
  });
@@ -594488,136 +594686,66 @@ ${trimmedNew}`;
594488
594686
  }
594489
594687
  while (this._adversaryToolOutcomes.length > 20)
594490
594688
  this._adversaryToolOutcomes.shift();
594491
- if (this._adversaryStream && !this._completionIncompleteVerification) {
594492
- const lastAssistantMsg = [...recent].reverse().find((m2) => m2.role === "assistant" && typeof m2.content === "string");
594493
- const assistantText = typeof lastAssistantMsg?.content === "string" ? lastAssistantMsg.content.replace(/<think>[\s\S]*?<\/think>/g, "").trim() : "";
594494
- if (assistantText) {
594495
- const claimsCompletion = /task.?complete|all tests pass|\bdone\b|\bcomplete(d)?\b/i.test(assistantText);
594496
- this._adversaryStream.observe({
594497
- turn,
594498
- assistantText,
594499
- recentToolOutcomes: this._adversaryToolOutcomes.slice(-8).map((o2) => ({
594500
- tool: o2.tool,
594501
- succeeded: o2.succeeded,
594502
- preview: o2.preview,
594503
- path: o2.path,
594504
- evidence: o2.evidence
594505
- })),
594506
- claimsCompletion
594507
- });
594508
- void this._adversaryStream.tick().catch(() => {
594509
- });
594510
- }
594511
- }
594512
- for (const [key, val] of this._adversaryRecentFlags) {
594513
- if (turn - val.lastTurn > _AgenticRunner.ADVERSARY_FLAG_TTL)
594514
- this._adversaryRecentFlags.delete(key);
594515
- }
594516
- const adversaryFlag = (flagKey, messages3) => {
594517
- const existing = this._adversaryRecentFlags.get(flagKey);
594518
- if (existing) {
594519
- existing.count++;
594520
- existing.lastTurn = turn;
594521
- if (existing.count >= _AgenticRunner.ADVERSARY_ESCALATE_THRESHOLD) {
594522
- return "escalate";
594523
- }
594524
- return "suppress";
594525
- }
594526
- this._adversaryRecentFlags.set(flagKey, { count: 1, lastTurn: turn });
594527
- return "proceed";
594528
- };
594529
- const emitReaction = (cls, shortText, confidence2, details2) => {
594689
+ const stateDigest = this._buildAdversaryStateDigest(turn);
594690
+ const recentToolOutcomes = this._adversaryToolOutcomes.slice(-8).map((o2) => ({
594691
+ tool: o2.tool,
594692
+ succeeded: o2.succeeded,
594693
+ preview: o2.preview,
594694
+ path: o2.path,
594695
+ evidence: o2.evidence
594696
+ }));
594697
+ const queueAdversaryAudit = (input, reason) => {
594698
+ if (!this._adversaryStream || this._completionIncompleteVerification)
594699
+ return;
594700
+ const observation = {
594701
+ turn,
594702
+ recentToolOutcomes,
594703
+ stateDigest,
594704
+ ...input
594705
+ };
594706
+ if (!this._adversaryStream.shouldAudit(observation))
594707
+ return;
594708
+ this._adversaryStream.observe(observation);
594709
+ void this._adversaryStream.tick().catch(() => {
594710
+ });
594530
594711
  this.emit({
594531
- type: "adversary_reaction",
594532
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
594533
- adversary: { class: cls, shortText, confidence: confidence2, details: details2 }
594712
+ type: "status",
594713
+ content: `Adversary inference queued: ${reason}`,
594714
+ turn,
594715
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
594534
594716
  });
594535
594717
  };
594536
- const buildAdversaryCritique = (input) => {
594537
- const alternatives = input.alternatives && input.alternatives.length > 0 ? `
594538
- Alternatives:
594539
- ${input.alternatives.map((item) => `- ${item}`).join("\n")}` : "";
594540
- return [
594541
- `[ADVERSARY CRITIQUE — non-blocking]`,
594542
- `Evidence: ${input.evidence}`,
594543
- `Root cause hypothesis: ${input.hypothesis}`,
594544
- `Corrective action: ${input.correctiveAction}${alternatives}`
594545
- ].join("\n");
594546
- };
594547
594718
  const lastAssistant = [...recent].reverse().find((m2) => m2.role === "assistant" && typeof m2.content === "string");
594548
594719
  if (lastAssistant && typeof lastAssistant.content === "string") {
594549
- const text2 = lastAssistant.content.toLowerCase();
594720
+ const assistantText = lastAssistant.content.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
594721
+ const text2 = assistantText.toLowerCase();
594722
+ const claimsCompletion = /task.?complete|all tests pass|\bdone\b|\bcomplete(d)?\b/i.test(text2);
594723
+ queueAdversaryAudit({
594724
+ assistantText,
594725
+ claimsCompletion
594726
+ }, claimsCompletion ? "completion/progress claim" : "success-language audit");
594550
594727
  const claimsFailure = /(?:fail|error|didn't work|not working|unable to|cannot|couldn't|both .* fail|tools? (?:have |has )?been fail)/i.test(text2);
594551
594728
  if (claimsFailure) {
594552
594729
  const recentOutcomes = this._adversaryToolOutcomes.slice(-4);
594553
594730
  const successes = recentOutcomes.filter((o2) => o2.succeeded);
594554
594731
  if (successes.length >= 1) {
594555
- const successList = successes.map((o2) => `${o2.tool}: ${o2.preview.slice(0, 60)}`).join("; ");
594556
- const ffFlag = adversaryFlag("false_failure", messages2);
594557
- if (ffFlag !== "suppress") {
594558
- const critiqueText = buildAdversaryCritique({
594559
- evidence: `Recent tools succeeded: ${successList}.`,
594560
- hypothesis: "The main loop is interpreting uncertainty or partial progress as failure and may be about to discard usable evidence.",
594561
- correctiveAction: "Use the successful results to advance the task, then verify the next concrete step.",
594562
- alternatives: [
594563
- "Edit or run the next verification step that follows from the successful output.",
594564
- "Read a different targeted file if the successful result exposed a new path or symbol.",
594565
- "Complete only if the successful output is sufficient evidence for the user's request."
594566
- ]
594567
- });
594568
- emitReaction("false_failure", `Claimed failure, but recent tools succeeded (${successes.length})`, 0.9, successList);
594569
- if (this._adversaryMode === "skillcoach" || this._adversaryMode === "both") {
594570
- if (ffFlag === "escalate") {
594571
- messages2.push({
594572
- role: "system",
594573
- content: critiqueText + "\n[ESCALATED: This warning was previously issued without effect.]"
594574
- });
594575
- } else {
594576
- this.pendingUserMessages.push(critiqueText);
594577
- }
594578
- }
594579
- this.emit({
594580
- type: "status",
594581
- content: `\x1B[38;5;178m⚠ Corrected false failure claim (${successes.length} tools succeeded)\x1B[0m`,
594582
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
594583
- });
594584
- }
594732
+ queueAdversaryAudit({
594733
+ assistantText,
594734
+ claimsCompletion: false,
594735
+ diagnosticSignal: "possible_false_failure"
594736
+ }, `possible false-failure claim after ${successes.length} successful tool outcome(s)`);
594585
594737
  }
594586
594738
  }
594587
- }
594588
- if (lastAssistant && typeof lastAssistant.content === "string") {
594589
- const text2 = lastAssistant.content.toLowerCase();
594590
594739
  const claimsSuccess = /(done|fixed|success|passed|complete)/i.test(text2);
594591
594740
  if (claimsSuccess) {
594592
594741
  const recentOutcomes = this._adversaryToolOutcomes.slice(-4);
594593
594742
  const failures = recentOutcomes.filter((o2) => !o2.succeeded);
594594
- const successes = recentOutcomes.filter((o2) => o2.succeeded);
594595
- if (failures.length > 0 && successes.length === 0) {
594596
- const failList = failures.map((o2) => `${o2.tool}: ${o2.preview.slice(0, 60)}`).join("; ");
594597
- const fsFlag = adversaryFlag("false_success", messages2);
594598
- if (fsFlag !== "suppress") {
594599
- const critiqueText = buildAdversaryCritique({
594600
- evidence: `Recent tools show errors (${failures.length}): ${failList}.`,
594601
- hypothesis: "The main loop is prematurely compressing intent into success language before the verifier produced evidence.",
594602
- correctiveAction: "Inspect the failed output, identify the implicated path/symbol/command, and run one focused corrective step before claiming success.",
594603
- alternatives: [
594604
- "Read the smallest relevant source region around the failed symbol.",
594605
- "Patch the implicated code or configuration.",
594606
- "Run the same verifier only after a state-changing fix."
594607
- ]
594608
- });
594609
- emitReaction("false_success", `Claimed success, but recent tools failed (${failures.length})`, 0.9, failList);
594610
- if (this._adversaryMode === "skillcoach" || this._adversaryMode === "both") {
594611
- if (fsFlag === "escalate") {
594612
- messages2.push({
594613
- role: "system",
594614
- content: critiqueText + "\n[ESCALATED: This warning was previously issued without effect.]"
594615
- });
594616
- } else {
594617
- this.pendingUserMessages.push(critiqueText);
594618
- }
594619
- }
594620
- }
594743
+ if (failures.length > 0) {
594744
+ queueAdversaryAudit({
594745
+ assistantText,
594746
+ claimsCompletion,
594747
+ diagnosticSignal: "possible_false_success"
594748
+ }, `possible false-success claim near ${failures.length} recent failure(s)`);
594621
594749
  }
594622
594750
  }
594623
594751
  }
@@ -594635,38 +594763,20 @@ ${input.alternatives.map((item) => `- ${item}`).join("\n")}` : "";
594635
594763
  }
594636
594764
  const argsKey = this._buildExactArgsKey(args);
594637
594765
  const fingerprint = this._buildToolFingerprint(name10, args);
594638
- const prior = this._adversaryToolOutcomes.find((o2) => o2.succeeded && o2.tool === name10 && o2.fingerprint === fingerprint && o2.turn < turn);
594766
+ const prior = this._adversaryToolOutcomes.find((o2) => o2.succeeded && o2.tool === name10 && o2.fingerprint === fingerprint && o2.stateVersion === this._adversaryStateVersion && o2.turn < turn);
594639
594767
  if (prior) {
594640
- this._adversaryRedundantSignals.add(fingerprint);
594641
- const raFlag = adversaryFlag(`redundant_action:${fingerprint}`, messages2);
594642
- if (raFlag !== "suppress") {
594643
- const critiqueText = buildAdversaryCritique({
594644
- evidence: `${name10} already succeeded on turn ${prior.turn} with exact arguments (${argsKey.slice(0, 120)}). Prior preview: ${prior.preview}`,
594645
- hypothesis: "The main loop may have lost track of previously observed evidence because of context pressure, path confusion, or repeated discovery.",
594646
- correctiveAction: "Let this duplicate run execute if needed, but treat the prior result as evidence and pivot afterward unless state has changed.",
594647
- alternatives: [
594648
- "Use the prior result to edit/write, verify, or finish with evidence.",
594649
- "Read a different specific file or selector if the current evidence is insufficient.",
594650
- "Repeat exact arguments only when filesystem, browser, or page state changed."
594651
- ]
594652
- });
594653
- emitReaction("redundant_action", `Already ran ${name10} successfully on turn ${prior.turn}`, 0.8, prior.preview);
594654
- if (this._adversaryMode === "skillcoach" || this._adversaryMode === "both") {
594655
- if (raFlag === "escalate") {
594656
- messages2.push({
594657
- role: "system",
594658
- content: critiqueText + "\n[ESCALATED: This redundant-action warning was issued 3+ times as a user message without effect.]"
594659
- });
594660
- } else {
594661
- this.pendingUserMessages.push(critiqueText);
594662
- }
594663
- }
594664
- this.emit({
594665
- type: "status",
594666
- content: `\x1B[38;5;178m⚠ Adversary noted redundant ${name10} call (succeeded on turn ${prior.turn}); action remains allowed\x1B[0m`,
594667
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
594668
- });
594669
- }
594768
+ const repeatCount = this._adversaryToolOutcomes.filter((o2) => o2.tool === name10 && o2.fingerprint === fingerprint && o2.stateVersion === this._adversaryStateVersion && o2.turn < turn).length + 1;
594769
+ queueAdversaryAudit({
594770
+ assistantText: "",
594771
+ claimsCompletion: false,
594772
+ diagnosticSignal: "possible_repeated_action",
594773
+ loopSignal: {
594774
+ tool: name10,
594775
+ target: argsKey.slice(0, 180),
594776
+ count: repeatCount,
594777
+ alreadyHave: prior.preview
594778
+ }
594779
+ }, `possible repeated action ${name10} after prior same-state success`);
594670
594780
  break;
594671
594781
  }
594672
594782
  }
@@ -594684,35 +594794,11 @@ ${input.alternatives.map((item) => `- ${item}`).join("\n")}` : "";
594684
594794
  }
594685
594795
  }
594686
594796
  if (consecutiveShortResults >= 3) {
594687
- const itFlag = adversaryFlag("idle_think", messages2);
594688
- if (itFlag !== "suppress") {
594689
- const critiqueText = buildAdversaryCritique({
594690
- evidence: `${consecutiveShortResults} consecutive output-like calls occurred without an input-like observation.`,
594691
- hypothesis: "The loop may be acting from stale state instead of re-observing the environment.",
594692
- correctiveAction: "Take one input/observation step before another output step.",
594693
- alternatives: [
594694
- "Call the input/listen/poll tool for the current environment.",
594695
- "Read the current UI/page state before clicking or typing again.",
594696
- "If the task is already complete, finish with the concrete evidence already observed."
594697
- ]
594698
- });
594699
- emitReaction("idle_think", `Consecutive output without input: ${consecutiveShortResults}`, 0.7);
594700
- if (this._adversaryMode === "skillcoach" || this._adversaryMode === "both") {
594701
- if (itFlag === "escalate") {
594702
- messages2.push({
594703
- role: "system",
594704
- content: critiqueText + "\n[ESCALATED: This warning was previously issued without effect.]"
594705
- });
594706
- } else {
594707
- this.pendingUserMessages.push(critiqueText);
594708
- }
594709
- }
594710
- this.emit({
594711
- type: "status",
594712
- content: `\x1B[38;5;178m⚠ Adversary flagged runaway-output risk (${consecutiveShortResults} consecutive sends without receive); action remains allowed\x1B[0m`,
594713
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
594714
- });
594715
- }
594797
+ queueAdversaryAudit({
594798
+ assistantText: "",
594799
+ claimsCompletion: false,
594800
+ diagnosticSignal: "possible_stale_output"
594801
+ }, `possible stale-output loop (${consecutiveShortResults} short successful outcomes)`);
594716
594802
  }
594717
594803
  }
594718
594804
  }
@@ -594720,6 +594806,8 @@ ${input.alternatives.map((item) => `- ${item}`).join("\n")}` : "";
594720
594806
  const failCount = this._adversaryToolOutcomes.filter((o2) => !o2.succeeded).length;
594721
594807
  const lastFour = this._adversaryToolOutcomes.slice(-4);
594722
594808
  const details = [
594809
+ stateDigest,
594810
+ ``,
594723
594811
  `Recent tool outcomes:`,
594724
594812
  ...lastFour.map((o2) => `- ${o2.tool}: ${o2.succeeded ? "OK" : "ERR"} — ${o2.preview}`)
594725
594813
  ].join("\n");
@@ -630964,6 +631052,7 @@ var init_status_bar = __esm({
630964
631052
  this._contentScrollOffset = 0;
630965
631053
  if (this.active) {
630966
631054
  this.repaintContent();
631055
+ this.refreshDynamicBlocks();
630967
631056
  this._contentCursorNeedsReplay = true;
630968
631057
  if (this.writeDepth > 0) this._contentCursorReplayActive = true;
630969
631058
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.455",
3
+ "version": "1.0.457",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.455",
9
+ "version": "1.0.457",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.455",
3
+ "version": "1.0.457",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",