omnius 1.0.458 → 1.0.460

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
@@ -572346,6 +572346,20 @@ var init_streaming_executor = __esm({
572346
572346
  setExecutor(fn) {
572347
572347
  this.executeFn = fn;
572348
572348
  }
572349
+ /** Rename a queued streaming tool entry when the provider reveals its real id late. */
572350
+ rename(oldId, newId) {
572351
+ if (!oldId || !newId || oldId === newId)
572352
+ return;
572353
+ const entry = this.tools.get(oldId);
572354
+ if (!entry || this.tools.has(newId))
572355
+ return;
572356
+ this.tools.delete(oldId);
572357
+ entry.id = newId;
572358
+ this.tools.set(newId, entry);
572359
+ const idx = this.insertionOrder.indexOf(oldId);
572360
+ if (idx >= 0)
572361
+ this.insertionOrder[idx] = newId;
572362
+ }
572349
572363
  /** Update the parsed-input concurrency classifier. */
572350
572364
  setConcurrencyResolver(fn) {
572351
572365
  this.config.concurrencyResolver = fn;
@@ -572583,7 +572597,7 @@ var init_streaming_executor = __esm({
572583
572597
  entry.state = "executing";
572584
572598
  entry.startedAt = Date.now();
572585
572599
  const exec7 = this.executeFn;
572586
- entry.promise = exec7(entry.name, entry.args).then((result) => {
572600
+ entry.promise = exec7(entry.id, entry.name, entry.args).then((result) => {
572587
572601
  entry.state = "completed";
572588
572602
  entry.result = result;
572589
572603
  entry.completedAt = Date.now();
@@ -573206,6 +573220,7 @@ var init_context_fabric = __esm({
573206
573220
  GOAL: 100,
573207
573221
  ACTION_CONTRACT: 98,
573208
573222
  USER_STEERING: 95,
573223
+ RUNTIME_GUIDANCE: 94,
573209
573224
  TASK_STATE: 80,
573210
573225
  KNOWN_FILES: 70,
573211
573226
  RECENT_FAILURE: 65,
@@ -573222,6 +573237,7 @@ var init_context_fabric = __esm({
573222
573237
  KIND_ORDER = [
573223
573238
  "goal",
573224
573239
  "user_steering",
573240
+ "runtime_guidance",
573225
573241
  "action_contract",
573226
573242
  "task_state",
573227
573243
  "known_files",
@@ -573239,6 +573255,7 @@ var init_context_fabric = __esm({
573239
573255
  KIND_LABELS = {
573240
573256
  goal: "Goal",
573241
573257
  user_steering: "User Steering",
573258
+ runtime_guidance: "Runtime Guidance",
573242
573259
  action_contract: "Next Action Contract",
573243
573260
  task_state: "Task State",
573244
573261
  known_files: "Known Files",
@@ -573256,6 +573273,7 @@ var init_context_fabric = __esm({
573256
573273
  DEFAULT_KIND_CHAR_BUDGET = {
573257
573274
  goal: 900,
573258
573275
  user_steering: 1400,
573276
+ runtime_guidance: 1800,
573259
573277
  action_contract: 1800,
573260
573278
  task_state: 1800,
573261
573279
  known_files: 2400,
@@ -574740,8 +574758,87 @@ function diagnoseContextDump(record) {
574740
574758
  if (record.metrics.estimatedTokens > 1e5) {
574741
574759
  diagnoses.add("large-context-window");
574742
574760
  }
574761
+ if (hasToolResultBindingMismatch(record)) {
574762
+ diagnoses.add("tool-result-binding-mismatch");
574763
+ }
574743
574764
  return [...diagnoses].sort();
574744
574765
  }
574766
+ function hasToolResultBindingMismatch(record) {
574767
+ const messages2 = Array.isArray(record.request?.["messages"]) ? record.request["messages"] : [];
574768
+ if (messages2.length === 0)
574769
+ return false;
574770
+ const callsById = /* @__PURE__ */ new Map();
574771
+ for (const message2 of messages2) {
574772
+ if (message2["role"] !== "assistant")
574773
+ continue;
574774
+ const calls = Array.isArray(message2["tool_calls"]) ? message2["tool_calls"] : [];
574775
+ for (const call of calls) {
574776
+ const id2 = typeof call["id"] === "string" ? call["id"] : "";
574777
+ const fn = call["function"] && typeof call["function"] === "object" ? call["function"] : {};
574778
+ const name10 = typeof fn["name"] === "string" ? fn["name"] : "";
574779
+ const argsRaw = typeof fn["arguments"] === "string" ? fn["arguments"] : "{}";
574780
+ let args = {};
574781
+ try {
574782
+ args = JSON.parse(argsRaw);
574783
+ } catch {
574784
+ args = {};
574785
+ }
574786
+ if (id2)
574787
+ callsById.set(id2, { name: name10, args });
574788
+ }
574789
+ }
574790
+ for (const message2 of messages2) {
574791
+ if (message2["role"] !== "tool")
574792
+ continue;
574793
+ const id2 = typeof message2["tool_call_id"] === "string" ? message2["tool_call_id"] : "";
574794
+ const call = id2 ? callsById.get(id2) : void 0;
574795
+ if (!call)
574796
+ continue;
574797
+ const requested = extractToolTarget(call.args);
574798
+ if (!requested)
574799
+ continue;
574800
+ const content = typeof message2["content"] === "string" ? message2["content"] : "";
574801
+ const reported = extractReportedToolTarget(content);
574802
+ if (!reported)
574803
+ continue;
574804
+ if (!targetsCompatible(requested, reported))
574805
+ return true;
574806
+ }
574807
+ return false;
574808
+ }
574809
+ function extractToolTarget(args) {
574810
+ const value2 = args["path"] ?? args["file"] ?? args["file_path"] ?? args["filepath"] ?? args["directory"] ?? args["cwd"];
574811
+ return typeof value2 === "string" ? value2.trim() : "";
574812
+ }
574813
+ function extractReportedToolTarget(content) {
574814
+ const patterns = [
574815
+ /^target=([^\n\r]+)/m,
574816
+ /^path=([^\n\r]+)/m,
574817
+ /\bfile\s+([^\s]+)\s+already contains/i,
574818
+ /\bEdited\s+([^\s]+)\s+at line/i,
574819
+ /\bat\s+([^\s]+)\s+\(sha256\b/i,
574820
+ /\bRefusing to (?:edit|overwrite existing file)\s+([^\s]+)/i
574821
+ ];
574822
+ for (const pattern of patterns) {
574823
+ const match = content.match(pattern);
574824
+ const raw = match?.[1]?.trim();
574825
+ if (raw)
574826
+ return raw.replace(/[),.;:]+$/, "");
574827
+ }
574828
+ return "";
574829
+ }
574830
+ function targetsCompatible(requested, reported) {
574831
+ const left = normalizeTargetForCompare(requested);
574832
+ const right = normalizeTargetForCompare(reported);
574833
+ if (!left || !right)
574834
+ return true;
574835
+ if (left === right)
574836
+ return true;
574837
+ return left.endsWith(`/${right}`) || right.endsWith(`/${left}`);
574838
+ }
574839
+ function normalizeTargetForCompare(value2) {
574840
+ return value2.trim().replace(/^["']|["']$/g, "").replace(/\\/g, "/").replace(/\/+/g, "/").replace(/\/$/, "");
574841
+ }
574745
574842
  function summarizeToolEvent(toolName, success, diagnoses, command) {
574746
574843
  const status = success ? "success" : "failure";
574747
574844
  const parts = [`${toolName} ${status}`];
@@ -574853,6 +574950,7 @@ function writeContract(contractPath) {
574853
574950
  "- `focus-supervisor-cached-evidence`: the focus supervisor short-circuited a call successfully by reusing current cached evidence.",
574854
574951
  "- `background-task-id-missing`: task status lookup could not find the spawned task id.",
574855
574952
  "- `raw-discovery-dominates-context`: context-window metrics show low signal/noise around raw discovery output.",
574953
+ "- `tool-result-binding-mismatch`: the outbound model transcript contains a tool result whose reported target does not match the assistant tool call it is attached to.",
574856
574954
  ""
574857
574955
  ].join("\n");
574858
574956
  writeFileSync49(contractPath, body, "utf-8");
@@ -578125,32 +578223,75 @@ function sanitizeHistoryThink(messages2) {
578125
578223
  const stripped = messages2.map((m2) => {
578126
578224
  if (m2.role !== "assistant" || typeof m2.content !== "string")
578127
578225
  return m2;
578128
- return { ...m2, content: stripThinkBlocks(m2.content) };
578226
+ const withoutThink = stripThinkBlocks(m2.content);
578227
+ const collapsed = collapseDegenerateAssistantRepetition(withoutThink);
578228
+ return { ...m2, content: collapsed ?? withoutThink };
578129
578229
  });
578130
578230
  const sanitized = [];
578131
578231
  for (let i2 = 0; i2 < stripped.length; i2++) {
578132
578232
  const current = stripped[i2];
578133
- const next = stripped[i2 + 1];
578134
- if (isOrphanDuplicateAssistantToolAnchor(current, next, referencedToolCallIds)) {
578233
+ if (isOrphanDuplicateAssistantToolAnchor(stripped, i2, referencedToolCallIds)) {
578135
578234
  continue;
578136
578235
  }
578137
578236
  sanitized.push(current);
578138
578237
  }
578139
578238
  return sanitized;
578140
578239
  }
578141
- function isOrphanDuplicateAssistantToolAnchor(current, next, referencedToolCallIds) {
578142
- if (!next)
578240
+ function collapseDegenerateAssistantRepetition(content) {
578241
+ const trimmed = content.trim();
578242
+ if (trimmed.length < 160)
578243
+ return null;
578244
+ const lineUnits = trimmed.split(/\n+/).map((line) => line.trim()).filter((line) => line.length >= 12);
578245
+ const sentenceUnits = lineUnits.length >= 3 ? lineUnits : trimmed.split(/(?<=[.!?])\s+/).map((part) => part.trim()).filter((part) => part.length >= 12);
578246
+ if (sentenceUnits.length < 3)
578247
+ return null;
578248
+ const counts = /* @__PURE__ */ new Map();
578249
+ for (const unit of sentenceUnits) {
578250
+ const key = unit.toLowerCase().replace(/\s+/g, " ").slice(0, 220);
578251
+ const current = counts.get(key) ?? { count: 0, chars: 0, sample: unit };
578252
+ current.count++;
578253
+ current.chars += unit.length;
578254
+ counts.set(key, current);
578255
+ }
578256
+ let best = null;
578257
+ for (const value2 of counts.values()) {
578258
+ if (!best || value2.count > best.count || value2.count === best.count && value2.chars > best.chars) {
578259
+ best = value2;
578260
+ }
578261
+ }
578262
+ if (!best || best.count < 3)
578263
+ return null;
578264
+ const repeatedRatio = best.chars / Math.max(1, trimmed.length);
578265
+ if (repeatedRatio < 0.55)
578266
+ return null;
578267
+ return `[assistant repetitive text suppressed: repeated ${best.count}x "${best.sample.slice(0, 180)}"]`;
578268
+ }
578269
+ function isOrphanDuplicateAssistantToolAnchor(messages2, index, referencedToolCallIds) {
578270
+ const current = messages2[index];
578271
+ if (!current)
578143
578272
  return false;
578144
- if (current.role !== "assistant" || next.role !== "assistant")
578273
+ if (current.role !== "assistant")
578145
578274
  return false;
578146
- if (!Array.isArray(current.tool_calls) || !Array.isArray(next.tool_calls)) {
578275
+ if (!Array.isArray(current.tool_calls) || current.tool_calls.length === 0) {
578147
578276
  return false;
578148
578277
  }
578149
- if (current.tool_calls.length === 0 || next.tool_calls.length === 0) {
578278
+ if (assistantVisibleText(current).length > 0)
578150
578279
  return false;
578280
+ let next;
578281
+ for (let i2 = index + 1; i2 < Math.min(messages2.length, index + 8); i2++) {
578282
+ const candidate = messages2[i2];
578283
+ if (candidate.role === "system")
578284
+ continue;
578285
+ if (candidate.role !== "assistant")
578286
+ return false;
578287
+ next = candidate;
578288
+ break;
578151
578289
  }
578152
- if (assistantVisibleText(current).length > 0)
578290
+ if (!next)
578291
+ return false;
578292
+ if (!Array.isArray(next.tool_calls) || next.tool_calls.length === 0) {
578153
578293
  return false;
578294
+ }
578154
578295
  if (toolCallsFingerprint(current.tool_calls) !== toolCallsFingerprint(next.tool_calls)) {
578155
578296
  return false;
578156
578297
  }
@@ -578423,6 +578564,7 @@ var init_agenticRunner = __esm({
578423
578564
  _onTypedEvent;
578424
578565
  handlers = [];
578425
578566
  pendingUserMessages = [];
578567
+ pendingRuntimeGuidanceMessages = [];
578426
578568
  aborted = false;
578427
578569
  _abortController = new AbortController();
578428
578570
  _paused = false;
@@ -578802,6 +578944,7 @@ var init_agenticRunner = __esm({
578802
578944
  //
578803
578945
  // Kill switch: OMNIUS_DISABLE_REG61_COERCE=1 disables BOTH set and enforce.
578804
578946
  _reg61PerpetualGateActive = false;
578947
+ _reg61DeferredFocusDirectiveId = null;
578805
578948
  // DECOMP-2 (root-cause from batch531-midi-decomp, 2026-05-03): compelling
578806
578949
  // sub_agent delegation. DECOMP-1's informational directive was ignored
578807
578950
  // (0 sub_agent calls in 466 tool-call run despite directive at turn 1).
@@ -578921,28 +579064,58 @@ var init_agenticRunner = __esm({
578921
579064
  return this.options.workboardDir || this._workingDirectory || process.cwd();
578922
579065
  }
578923
579066
  getOrCreateWorkboard() {
578924
- if (this._workboard)
579067
+ const goal = this._taskState.originalGoal || this._taskState.goal || "";
579068
+ if (this._workboard) {
579069
+ this._workboard = this._seedWorkboardCardsIfNeeded(this._workboard, goal);
578925
579070
  return this._workboard;
579071
+ }
578926
579072
  const dir = this._workboardDir();
578927
579073
  const runId = this._sessionId;
578928
579074
  const existing = loadWorkboardSnapshot(dir, runId);
578929
579075
  if (existing) {
578930
- this._workboard = existing;
578931
- return existing;
579076
+ this._workboard = this._seedWorkboardCardsIfNeeded(existing, goal);
579077
+ return this._workboard;
578932
579078
  }
578933
579079
  try {
578934
579080
  this._workboard = createWorkboard(dir, {
578935
579081
  runId,
578936
579082
  owner: this.options.subAgent ? "sub-agent" : "agent",
578937
- goal: this._taskState.originalGoal || this._taskState.goal || void 0,
579083
+ goal: goal || void 0,
578938
579084
  title: (this._taskState.goal || "").slice(0, 120) || void 0,
578939
- cards: this._initialWorkboardCardsForGoal(this._taskState.originalGoal || this._taskState.goal || "")
579085
+ cards: this._initialWorkboardCardsForGoal(goal)
578940
579086
  });
578941
579087
  } catch {
578942
579088
  this._workboard = loadWorkboardSnapshot(dir, runId);
578943
579089
  }
579090
+ if (this._workboard) {
579091
+ this._workboard = this._seedWorkboardCardsIfNeeded(this._workboard, goal);
579092
+ }
578944
579093
  return this._workboard;
578945
579094
  }
579095
+ _seedWorkboardCardsIfNeeded(snapshot, goal) {
579096
+ if (snapshot.cards.length > 0)
579097
+ return snapshot;
579098
+ const cards = this._initialWorkboardCardsForGoal(goal);
579099
+ if (cards.length === 0)
579100
+ return snapshot;
579101
+ let current = snapshot;
579102
+ const dir = this._workboardDir();
579103
+ for (const card of cards) {
579104
+ try {
579105
+ current = addWorkboardCard(dir, {
579106
+ ...card,
579107
+ runId: snapshot.runId,
579108
+ actor: this.options.subAgent ? "sub-agent" : "agent",
579109
+ decisionReason: "Seeded missing workboard card after an empty persisted board was detected for an active user task."
579110
+ });
579111
+ } catch {
579112
+ const refreshed = readActiveWorkboardSnapshot(dir, snapshot.runId);
579113
+ if (refreshed)
579114
+ current = refreshed;
579115
+ }
579116
+ }
579117
+ return readActiveWorkboardSnapshot(dir, snapshot.runId) ?? current;
579118
+ }
578946
579119
  _initialWorkboardCardsForGoal(goal) {
578947
579120
  if (!this.writesUserTaskArtifacts())
578948
579121
  return [];
@@ -579060,9 +579233,11 @@ var init_agenticRunner = __esm({
579060
579233
  injectWorkboardContext() {
579061
579234
  if (this._workboard || this.options.subAgent) {
579062
579235
  const dir = this._workboardDir();
579063
- const snapshot = readActiveWorkboardSnapshot(dir, this._sessionId);
579236
+ let snapshot = readActiveWorkboardSnapshot(dir, this._sessionId);
579064
579237
  if (!snapshot)
579065
579238
  return null;
579239
+ snapshot = this._seedWorkboardCardsIfNeeded(snapshot, this._taskState.originalGoal || this._taskState.goal || "");
579240
+ this._workboard = snapshot;
579066
579241
  const activeCards = snapshot.cards.filter((c9) => c9.status === "in_progress" || c9.status === "open" || c9.status === "needs_changes");
579067
579242
  if (activeCards.length === 0 && snapshot.cards.every((c9) => c9.status === "verified" || c9.status === "completed"))
579068
579243
  return null;
@@ -579092,11 +579267,13 @@ ${parts.join("\n")}
579092
579267
  const dir = this._workboardDir();
579093
579268
  const fromDisk = readActiveWorkboardSnapshot(dir, this._sessionId);
579094
579269
  if (fromDisk) {
579095
- this._workboard = fromDisk;
579096
- return fromDisk;
579270
+ this._workboard = this._seedWorkboardCardsIfNeeded(fromDisk, this._taskState.originalGoal || this._taskState.goal || "");
579271
+ return this._workboard;
579097
579272
  }
579098
- if (this._workboard)
579273
+ if (this._workboard) {
579274
+ this._workboard = this._seedWorkboardCardsIfNeeded(this._workboard, this._taskState.originalGoal || this._taskState.goal || "");
579099
579275
  return this._workboard;
579276
+ }
579100
579277
  const goal = this._taskState.originalGoal || this._taskState.goal || "";
579101
579278
  if (this._initialWorkboardCardsForGoal(goal).length === 0)
579102
579279
  return null;
@@ -580445,6 +580622,25 @@ Your hypotheses MUST address this specific error, not generic causes.
580445
580622
  const fa = this._detectFailingApproachSignal(turn);
580446
580623
  return fa ? this._failingApproachDirective(fa) : null;
580447
580624
  }
580625
+ _focusDirectiveSuppressesEditPressure() {
580626
+ return this._focusSupervisor?.currentDirective ?? null;
580627
+ }
580628
+ _deferReg61ToFocusDirective(input) {
580629
+ if (this._reg61PerpetualGateActive) {
580630
+ this._reg61PerpetualGateActive = false;
580631
+ }
580632
+ if (this._reg61DeferredFocusDirectiveId === input.directive.id)
580633
+ return;
580634
+ this._reg61DeferredFocusDirectiveId = input.directive.id;
580635
+ const _cyclePart = input.cycleLabel ? ` (${input.cycleLabel})` : "";
580636
+ const _detail = input.detail ? `; ${input.detail}` : "";
580637
+ this.emit({
580638
+ type: "status",
580639
+ content: `REG-61 deferred to focus supervisor at turn ${input.turn}${_cyclePart}; source=${input.source}; directive_id=${input.directive.id}; required_next_action=${input.directive.requiredNextAction}${_detail}`,
580640
+ turn: input.turn,
580641
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
580642
+ });
580643
+ }
580448
580644
  /**
580449
580645
  * REG-61 sliding-window first-edit / sustained-edit nudge.
580450
580646
  *
@@ -580536,11 +580732,23 @@ Your hypotheses MUST address this specific error, not generic causes.
580536
580732
  }
580537
580733
  if (_readsInWindow < REG61_MIN_READS)
580538
580734
  return;
580735
+ const _gapDesc = this._lastFileWriteTurn < 0 ? `no creative edits yet this run` : `${turn - this._lastFileWriteTurn} turns since last creative edit (turn ${this._lastFileWriteTurn})`;
580736
+ const focusDirective = this._focusDirectiveSuppressesEditPressure();
580737
+ if (focusDirective) {
580738
+ this._deferReg61ToFocusDirective({
580739
+ directive: focusDirective,
580740
+ turn,
580741
+ cycleLabel,
580742
+ source: "trigger",
580743
+ detail: `reads_in_window=${_readsInWindow}; ${_gapDesc}`
580744
+ });
580745
+ return;
580746
+ }
580747
+ this._reg61DeferredFocusDirectiveId = null;
580539
580748
  this._reg61CooldownUntilTurn = turn + REG61_COOLDOWN;
580540
580749
  if (process.env["OMNIUS_DISABLE_REG61_COERCE"] !== "1") {
580541
580750
  this._reg61PerpetualGateActive = true;
580542
580751
  }
580543
- const _gapDesc = this._lastFileWriteTurn < 0 ? `no creative edits yet this run` : `${turn - this._lastFileWriteTurn} turns since last creative edit (turn ${this._lastFileWriteTurn})`;
580544
580752
  const reg61Msg = `[FIRST-EDIT NUDGE — REG-61]
580545
580753
  You have made ${_readsInWindow} read/exploration calls in the trailing window — ${_gapDesc}. Reading is preparation; writing is progress. Runs that stay in pure-read mode produce zero deliverables.
580546
580754
 
@@ -581463,7 +581671,7 @@ ${context2 ?? ""}`;
581463
581671
  }
581464
581672
  if (critique2) {
581465
581673
  this._visualNudgesEmitted.add(nudgeKey);
581466
- this.pendingUserMessages.push(critique2);
581674
+ this.enqueueRuntimeGuidance(critique2);
581467
581675
  }
581468
581676
  }
581469
581677
  }
@@ -584312,7 +584520,7 @@ ${blob}
584312
584520
  });
584313
584521
  if (!this._microcompactHintEmitted && this.tools.has("memory_write")) {
584314
584522
  this._microcompactHintEmitted = true;
584315
- this.pendingUserMessages.push(`[SYSTEM] Older tool results have been cleared to save context. If you discovered important patterns or facts, use memory_write to persist them before they are lost from context.`);
584523
+ this.enqueueRuntimeGuidance(`[SYSTEM] Older tool results have been cleared to save context. If you discovered important patterns or facts, use memory_write to persist them before they are lost from context.`);
584316
584524
  }
584317
584525
  }
584318
584526
  }
@@ -585045,6 +585253,11 @@ ${notice}`;
585045
585253
  injectUserMessage(content) {
585046
585254
  this.pendingUserMessages.push(this.scrubUserInput(content, "injected-user-message"));
585047
585255
  }
585256
+ enqueueRuntimeGuidance(content) {
585257
+ const cleaned = this.scrubUserInput(content, "runtime-guidance").trim();
585258
+ if (cleaned)
585259
+ this.pendingRuntimeGuidanceMessages.push(cleaned);
585260
+ }
585048
585261
  /** Retract the last pending user message (Esc cancel).
585049
585262
  * Returns the retracted text, or null if queue is empty or already consumed. */
585050
585263
  retractLastPendingMessage() {
@@ -585892,7 +586105,7 @@ TASK: ${scrubbedTask}` : scrubbedTask;
585892
586105
  onCritique: (critique2, sourceTurn) => {
585893
586106
  const runClosed = completed || this._completionIncompleteVerification || this.aborted;
585894
586107
  if (!runClosed && (this._adversaryMode === "skillcoach" || this._adversaryMode === "both")) {
585895
- this.pendingUserMessages.push(AdversaryStream.formatInjection(critique2));
586108
+ this.enqueueRuntimeGuidance(AdversaryStream.formatInjection(critique2));
585896
586109
  }
585897
586110
  this.emit({
585898
586111
  type: "adversary_reaction",
@@ -587292,7 +587505,7 @@ ${_staleSamples.join("\n")}` : ``,
587292
587505
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
587293
587506
  });
587294
587507
  messages2.push({
587295
- role: "user",
587508
+ role: "system",
587296
587509
  content: this.buildHealthCheckPrompt(elapsed, toolCallCount, repetitionScore, selfEvalCount)
587297
587510
  });
587298
587511
  nextSelfEval = now2 + selfEvalInterval;
@@ -587327,6 +587540,7 @@ ${_staleSamples.join("\n")}` : ``,
587327
587540
  });
587328
587541
  }
587329
587542
  }
587543
+ this.drainPendingRuntimeGuidance(turn);
587330
587544
  while (this.pendingUserMessages.length > 0) {
587331
587545
  const userMsg = this.pendingUserMessages.shift();
587332
587546
  await this.appendInjectedUserMessage(userMsg, messages2, turn);
@@ -587334,7 +587548,7 @@ ${_staleSamples.join("\n")}` : ``,
587334
587548
  if (!this.options.disableTodoPlanningNudges) {
587335
587549
  const maybeReminder = this.getTodoReminderContent(turn);
587336
587550
  if (maybeReminder) {
587337
- messages2.push({ role: "user", content: maybeReminder });
587551
+ messages2.push({ role: "system", content: maybeReminder });
587338
587552
  this.emit({
587339
587553
  type: "status",
587340
587554
  content: `todo_reminder injected (turn ${turn}, last todo_write turn ${this._lastTodoWriteTurn})`,
@@ -587353,7 +587567,7 @@ ${_staleSamples.join("\n")}` : ``,
587353
587567
  const isComplex = !explicitSingleTool && (wordCount2 > 40 || hasMultipleActions || hasMultipleFiles);
587354
587568
  if (isComplex) {
587355
587569
  messages2.push({
587356
- role: "user",
587570
+ role: "system",
587357
587571
  content: `[TASK DECOMPOSITION — Multi-step task detected]
587358
587572
 
587359
587573
  MANDATORY FIRST ACTION: Call todo_write NOW with the complete plan.
@@ -587379,7 +587593,7 @@ Call todo_write FIRST, then start with step 1.`
587379
587593
  const isGreenfield = /\bcreate\b.*\bnew\b|\bimplement\b.*\bclass\b|\bwrite\b.*\bfrom scratch\b|\bbuild\b.*\bmodule\b/i.test(goal);
587380
587594
  if (isGreenfield && !isComplex) {
587381
587595
  messages2.push({
587382
- role: "user",
587596
+ role: "system",
587383
587597
  content: `[GREENFIELD TASK — Write code immediately]
587384
587598
 
587385
587599
  MANDATORY: Your FIRST tool call MUST be file_write.
@@ -587505,7 +587719,7 @@ ${hints.join("\n")}`);
587505
587719
  const isLooping = repetitionRatio > 0.4;
587506
587720
  const highArousal = errorRatio > 0.5 || isLooping;
587507
587721
  if (highArousal && !isLooping && !noProgress) {
587508
- this.pendingUserMessages.push(`[COGNITIVE STATE: HIGH AROUSAL] Recent error rate is ${Math.round(errorRatio * 100)}%. Your current approach may be hitting a wall. Consider:
587722
+ this.enqueueRuntimeGuidance(`[COGNITIVE STATE: HIGH AROUSAL] Recent error rate is ${Math.round(errorRatio * 100)}%. Your current approach may be hitting a wall. Consider:
587509
587723
  1. Read related files you haven't examined yet
587510
587724
  2. Search for similar patterns in the codebase
587511
587725
  3. Check if your assumptions about the API/framework are correct
@@ -587515,7 +587729,7 @@ State what you've learned from the errors before trying again.`);
587515
587729
  const progress = this._taskState.completedSteps.slice(-3).join("; ");
587516
587730
  const failures = this._taskState.failedApproaches.slice(-2).join("; ");
587517
587731
  messages2.push({
587518
- role: "user",
587732
+ role: "system",
587519
587733
  content: `[PROGRESS CHECK — Turn ${turn}]
587520
587734
  **Goal:** ${this._taskState.goal}
587521
587735
  ` + (progress ? `**Done so far:** ${progress}
@@ -587926,7 +588140,7 @@ ${memoryLines.join("\n")}`
587926
588140
  const result = this.applyRegisteredToolResultTriage(rawResult, resolvedParsedTool.name, tool);
587927
588141
  messages2.push({ role: "assistant", content });
587928
588142
  messages2.push({
587929
- role: "user",
588143
+ role: "system",
587930
588144
  content: `Tool result (${parsed.tool}): ${result.output.slice(0, 2e3)}`
587931
588145
  });
587932
588146
  if (resolvedParsedTool.name === "task_complete") {
@@ -588115,7 +588329,7 @@ ${memoryLines.join("\n")}`
588115
588329
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
588116
588330
  });
588117
588331
  messages2.push({
588118
- role: "user",
588332
+ role: "system",
588119
588333
  content: `[SYSTEM] You produced ${consecutiveEmptyResponses} empty responses in a row. You MUST take action now. Your task: ${this._taskState.goal}
588120
588334
 
588121
588335
  ` + (this._taskState.nextAction ? `**DO THIS NOW:** ${this._taskState.nextAction}
@@ -588213,7 +588427,7 @@ ${memoryLines.join("\n")}`
588213
588427
  }
588214
588428
  });
588215
588429
  if (this._adversaryMode === "skillcoach" || this._adversaryMode === "both") {
588216
- this.pendingUserMessages.push(`[ADVERSARY CRITIQUE — non-blocking]
588430
+ this.enqueueRuntimeGuidance(`[ADVERSARY CRITIQUE — non-blocking]
588217
588431
  Evidence: ${tc.name} with similar arguments has failed ${cohort.failure}× recently.
588218
588432
  Root cause hypothesis: the argument family may be wrong, a prerequisite may be missing, or the tool is being used before enough state is known.
588219
588433
  Corrective action: try a different approach first: read relevant files, adjust arguments, or verify prerequisites.`);
@@ -588226,7 +588440,7 @@ Corrective action: try a different approach first: read relevant files, adjust a
588226
588440
  const _injKey = `resfix:${_sug.fix.from.join(" ")}=>${_sug.fix.to.join(" ")}`;
588227
588441
  if (!this._errorGuidanceInjected.has(_injKey)) {
588228
588442
  this._errorGuidanceInjected.add(_injKey);
588229
- this.pendingUserMessages.push(_sug.message);
588443
+ this.enqueueRuntimeGuidance(_sug.message);
588230
588444
  this.emit({
588231
588445
  type: "status",
588232
588446
  content: `Resolution memory: suggested \`${_sug.fix.from.join(" ")}\`→\`${_sug.fix.to.join(" ")}\` before shell call`,
@@ -588449,7 +588663,16 @@ Corrective action: try a different approach first: read relevant files, adjust a
588449
588663
  "priority_delegate",
588450
588664
  "background_run"
588451
588665
  ]);
588452
- if (this._reg61PerpetualGateActive && !REG61_BYPASS_TOOLS.has(tc.name) && process.env["OMNIUS_DISABLE_REG61_COERCE"] !== "1") {
588666
+ const focusDirectiveForEditPressure = this._focusDirectiveSuppressesEditPressure();
588667
+ if (this._reg61PerpetualGateActive && focusDirectiveForEditPressure) {
588668
+ this._deferReg61ToFocusDirective({
588669
+ directive: focusDirectiveForEditPressure,
588670
+ turn,
588671
+ source: "latched_steer",
588672
+ detail: `attempted_tool=${tc.name}`
588673
+ });
588674
+ }
588675
+ if (this._reg61PerpetualGateActive && !focusDirectiveForEditPressure && !REG61_BYPASS_TOOLS.has(tc.name) && process.env["OMNIUS_DISABLE_REG61_COERCE"] !== "1") {
588453
588676
  const _dbgLoop = this._detectDebugLoop([
588454
588677
  ...toolCallLog,
588455
588678
  { name: tc.name, argsKey }
@@ -589107,7 +589330,7 @@ ${cachedResult}`,
589107
589330
  });
589108
589331
  if (this._hookDenyHintCount < 3 && this.tools.has("memory_write")) {
589109
589332
  this._hookDenyHintCount++;
589110
- this.pendingUserMessages.push(`[SYSTEM] Tool "${tc.name}" was blocked: ${hookCheck.reason}. If this constraint should persist across sessions, use memory_write to save it (e.g., memory_write(topic="constraints", key="${tc.name}_blocked", value="${(hookCheck.reason ?? "hook").slice(0, 80)}")).`);
589333
+ this.enqueueRuntimeGuidance(`[SYSTEM] Tool "${tc.name}" was blocked: ${hookCheck.reason}. If this constraint should persist across sessions, use memory_write to save it (e.g., memory_write(topic="constraints", key="${tc.name}_blocked", value="${(hookCheck.reason ?? "hook").slice(0, 80)}")).`);
589111
589334
  }
589112
589335
  } else {
589113
589336
  const finalArgs = hookCheck.modifiedArgs ?? tc.arguments;
@@ -590345,7 +590568,7 @@ ${bookkeepingGuidance}` : bookkeepingGuidance;
590345
590568
  }
590346
590569
  if (this._isAtomicBatchEditAbort(tc.name, result)) {
590347
590570
  editFeedbackRequiredBeforeMoreEdits = this._buildBatchEditAtomicAbortGuidance(tc.arguments);
590348
- this.pendingUserMessages.push(editFeedbackRequiredBeforeMoreEdits);
590571
+ this.enqueueRuntimeGuidance(editFeedbackRequiredBeforeMoreEdits);
590349
590572
  }
590350
590573
  const currentLogEntry = toolCallLog[_toolLogTailIdx];
590351
590574
  if (currentLogEntry) {
@@ -590594,7 +590817,7 @@ Evidence: ${evidencePreview}`.slice(0, 500);
590594
590817
  }
590595
590818
  const consecutiveSameTool = Math.max(sameToolFailStreak, this._taskState.failedApproaches.slice(-2).filter((f2) => f2.startsWith(`${tc.name}(`)).length);
590596
590819
  if (sameToolFailStreak >= 5 && (this.options.modelTier === "small" || this.options.modelTier === "medium")) {
590597
- this.pendingUserMessages.push(`[BRANCH — evaluate alternatives before acting]
590820
+ this.enqueueRuntimeGuidance(`[BRANCH — evaluate alternatives before acting]
590598
590821
  Tool "${tc.name}" has failed ${sameToolFailStreak} times. STOP and enumerate:
590599
590822
  Option A: [describe a completely different approach]
590600
590823
  Option B: [describe another alternative]
@@ -590604,7 +590827,7 @@ Pick the BEST option and explain why, then execute it. Do NOT retry ${tc.name} w
590604
590827
  sameToolFailName = null;
590605
590828
  }
590606
590829
  if (consecutiveSameTool >= 2 && (this.options.modelTier === "small" || this.options.modelTier === "medium")) {
590607
- this.pendingUserMessages.push(`[PIVOT REQUIRED] You have failed ${consecutiveSameTool + 1} times in a row with ${tc.name}. Your current approach is not working. You MUST try something fundamentally different:
590830
+ this.enqueueRuntimeGuidance(`[PIVOT REQUIRED] You have failed ${consecutiveSameTool + 1} times in a row with ${tc.name}. Your current approach is not working. You MUST try something fundamentally different:
590608
590831
  - If file_edit keeps failing: re-read the file first, then use the EXACT text from the file
590609
590832
  - If shell keeps failing: try a different command or check prerequisites
590610
590833
  - If grep_search finds nothing: try broader patterns or list_directory
@@ -590617,7 +590840,7 @@ Do NOT retry ${tc.name} with similar arguments.`);
590617
590840
  this._taskState.failedApproaches.shift();
590618
590841
  }
590619
590842
  if (this._taskState.failedApproaches.length === 3 && this.tools.has("memory_write")) {
590620
- this.pendingUserMessages.push(`[SYSTEM] You have ${this._taskState.failedApproaches.length} failed approaches this session. Consider using memory_write to save these failure patterns so you avoid them in future sessions:
590843
+ this.enqueueRuntimeGuidance(`[SYSTEM] You have ${this._taskState.failedApproaches.length} failed approaches this session. Consider using memory_write to save these failure patterns so you avoid them in future sessions:
590621
590844
  ` + this._taskState.failedApproaches.map((f2) => `- ${f2}`).join("\n"));
590622
590845
  }
590623
590846
  }
@@ -590625,7 +590848,7 @@ Do NOT retry ${tc.name} with similar arguments.`);
590625
590848
  sameToolFailStreak = 0;
590626
590849
  sameToolFailName = null;
590627
590850
  if (isGenerationArtifactSuccess(tc.name, result.output ?? "")) {
590628
- this.pendingUserMessages.push(`[GENERATION COMPLETE] ${tc.name} succeeded. Do not call the same generation tool again for the same request. Use the artifact/path from the tool result; if delivery is needed, send it, otherwise call task_complete.`);
590851
+ this.enqueueRuntimeGuidance(`[GENERATION COMPLETE] ${tc.name} succeeded. Do not call the same generation tool again for the same request. Use the artifact/path from the tool result; if delivery is needed, send it, otherwise call task_complete.`);
590629
590852
  }
590630
590853
  }
590631
590854
  if (filePath && (tc.name === "file_read" || tc.name === "file_write" || tc.name === "file_edit" || tc.name === "batch_edit" || tc.name === "file_patch")) {
@@ -590653,7 +590876,7 @@ Do NOT retry ${tc.name} with similar arguments.`);
590653
590876
  if (isModify && (turnTier === "small" || turnTier === "medium")) {
590654
590877
  const modCount = this._taskState.modifiedFiles.size;
590655
590878
  if (modCount >= 2 && modCount % 2 === 0) {
590656
- this.pendingUserMessages.push(`[Test reminder] You've modified ${modCount} files. Run relevant tests NOW to verify: shell(command="npm test") or the project's test command. Fix any failures before continuing.`);
590879
+ this.enqueueRuntimeGuidance(`[Test reminder] You've modified ${modCount} files. Run relevant tests NOW to verify: shell(command="npm test") or the project's test command. Fix any failures before continuing.`);
590657
590880
  }
590658
590881
  }
590659
590882
  }
@@ -590697,7 +590920,7 @@ Do NOT retry ${tc.name} with similar arguments.`);
590697
590920
  }
590698
590921
  if (isEisdir) {
590699
590922
  const failedPath = String(tc.arguments?.["path"] ?? tc.arguments?.["file"] ?? "unknown");
590700
- this.pendingUserMessages.push(`[SYSTEM] "${failedPath}" is a DIRECTORY, not a file. You CANNOT use file_read on directories.
590923
+ this.enqueueRuntimeGuidance(`[SYSTEM] "${failedPath}" is a DIRECTORY, not a file. You CANNOT use file_read on directories.
590701
590924
  Use list_directory("${failedPath}") to see its contents instead.
590702
590925
  Then use file_read on individual FILES inside it.`);
590703
590926
  this._taskState.failedApproaches.push(`file_read("${failedPath}"): EISDIR — this is a directory, use list_directory`);
@@ -590708,7 +590931,7 @@ Then use file_read on individual FILES inside it.`);
590708
590931
  if (this._consecutiveEnoent >= 2 || windowEnoents >= 4) {
590709
590932
  const failedPath = String(tc.arguments?.["path"] ?? tc.arguments?.["file"] ?? "unknown");
590710
590933
  const triggerReason = this._consecutiveEnoent >= 2 ? `${this._consecutiveEnoent} consecutive file-not-found errors` : `${windowEnoents}/8 recent file operations failed`;
590711
- this.pendingUserMessages.push(`[SYSTEM] ${triggerReason} (last: "${failedPath}"). You are repeating failed paths. CHANGE YOUR APPROACH:
590934
+ this.enqueueRuntimeGuidance(`[SYSTEM] ${triggerReason} (last: "${failedPath}"). You are repeating failed paths. CHANGE YOUR APPROACH:
590712
590935
  1. Call list_directory(".") to see what exists at the project root
590713
590936
  2. Entries in a directory listing are RELATIVE to that directory. If you listed "parent/" and saw "child", the full path is "parent/child" — NOT ".child" or just "child"
590714
590937
  3. If an entry is a directory (marked "d"), use list_directory on it, NOT file_read
@@ -590807,10 +591030,12 @@ Then use file_read on individual FILES inside it.`);
590807
591030
  const rawToolCalls = msg.toolCalls;
590808
591031
  if (this.options.streamEnabled && this._streamingExecutor.hasTools) {
590809
591032
  const streamFpInFlight = /* @__PURE__ */ new Map();
590810
- this._streamingExecutor.setExecutor(async (name10, args) => {
590811
- let matchTc = rawToolCalls.find((tc) => tc.name === name10 && JSON.stringify(tc.arguments) === JSON.stringify(args)) ?? rawToolCalls.find((tc) => tc.name === name10);
591033
+ this._streamingExecutor.setExecutor(async (id2, name10, args) => {
591034
+ const argsFingerprint = this._buildToolFingerprint(name10, args);
591035
+ const exactArgMatches = rawToolCalls.filter((tc) => tc.name === name10 && this._buildToolFingerprint(tc.name, tc.arguments ?? {}) === argsFingerprint);
591036
+ let matchTc = rawToolCalls.find((tc) => tc.id === id2) ?? (exactArgMatches.length === 1 ? exactArgMatches[0] : void 0);
590812
591037
  if (!matchTc) {
590813
- const synthId = globalThis.crypto?.randomUUID?.() || `call_${Date.now()}`;
591038
+ const synthId = id2 || globalThis.crypto?.randomUUID?.() || `call_${Date.now()}`;
590814
591039
  matchTc = { id: synthId, name: name10, arguments: args };
590815
591040
  messages2.push({
590816
591041
  role: "assistant",
@@ -591331,7 +591556,7 @@ Your most recent tool calls SUCCEEDED. If the task is complete, call task_comple
591331
591556
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
591332
591557
  });
591333
591558
  messages2.push({
591334
- role: "user",
591559
+ role: "system",
591335
591560
  content: "You have been reasoning internally for several turns without producing visible output or tool calls. Please take action now — call a tool or produce a visible response." + successHint
591336
591561
  });
591337
591562
  }
@@ -591351,7 +591576,7 @@ Your most recent tool calls SUCCEEDED. If the task is complete, call task_comple
591351
591576
  if (shellCommands.length > 0 && shellCommands.length < 2e3) {
591352
591577
  if (looksLikeShellFileWrite(shellCommands)) {
591353
591578
  messages2.push({
591354
- role: "user",
591579
+ role: "system",
591355
591580
  content: `You wrote a shell code block that appears to create or overwrite files. I did NOT auto-execute it because shell redirection bypasses file_write/file_edit/file_patch/batch_edit tracking and version checks. Use file_write/content_base64 for full-file writes, file_edit or batch_edit for exact replacements, or file_patch/new_content_base64 for line-range patches.`
591356
591581
  });
591357
591582
  this.emit({
@@ -591411,7 +591636,7 @@ Your most recent tool calls SUCCEEDED. If the task is complete, call task_comple
591411
591636
  } else {
591412
591637
  correction = `CRITICAL: You cannot use ${toolName} by writing text. After ${narratedToolCallCount} attempts, it is clear this approach will not work. Try a COMPLETELY DIFFERENT tool or approach. For example: if trying skill_execute, try shell("cat .omnius/skills/*/SKILL.md") instead. If trying file_read, try shell("cat path/to/file") instead.`;
591413
591638
  }
591414
- messages2.push({ role: "user", content: correction });
591639
+ messages2.push({ role: "system", content: correction });
591415
591640
  this.emit({
591416
591641
  type: "status",
591417
591642
  content: `Narrated tool call #${narratedToolCallCount}: model wrote ${toolName} as text`,
@@ -591420,11 +591645,12 @@ Your most recent tool calls SUCCEEDED. If the task is complete, call task_comple
591420
591645
  } else {
591421
591646
  narratedToolCallCount = 0;
591422
591647
  messages2.push({
591423
- role: "user",
591648
+ role: "system",
591424
591649
  content: "Continue working. Use tools to read files, make changes, and run validation. Call task_complete when done."
591425
591650
  });
591426
591651
  }
591427
591652
  if (adversaryAddedGuidance) {
591653
+ this.drainPendingRuntimeGuidance(turn);
591428
591654
  while (this.pendingUserMessages.length > 0) {
591429
591655
  const userMsg = this.pendingUserMessages.shift();
591430
591656
  await this.appendInjectedUserMessage(userMsg, messages2, turn);
@@ -591494,7 +591720,7 @@ Your most recent tool calls SUCCEEDED. If the task is complete, call task_comple
591494
591720
  });
591495
591721
  this._reg61CooldownUntilTurn = -1;
591496
591722
  messages2.push({
591497
- role: "user",
591723
+ role: "system",
591498
591724
  content: `[CONTINUATION — Cycle ${bruteForceCycle}]
591499
591725
 
591500
591726
  You have used ${totalTurns} turns and ${toolCallCount} tool calls so far. The task is NOT yet complete. DO NOT give up — re-evaluate and continue:
@@ -591585,11 +591811,12 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
591585
591811
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
591586
591812
  });
591587
591813
  messages2.push({
591588
- role: "user",
591814
+ role: "system",
591589
591815
  content: this.buildHealthCheckPrompt(elapsed, toolCallCount, repetitionScore, selfEvalCount)
591590
591816
  });
591591
591817
  nextSelfEval = bfNow + selfEvalInterval;
591592
591818
  }
591819
+ this.drainPendingRuntimeGuidance(turn);
591593
591820
  while (this.pendingUserMessages.length > 0) {
591594
591821
  const userMsg = this.pendingUserMessages.shift();
591595
591822
  await this.appendInjectedUserMessage(userMsg, messages2, turn);
@@ -591931,7 +592158,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
591931
592158
  this._consecutiveEnoent++;
591932
592159
  if (this._consecutiveEnoent >= 2) {
591933
592160
  const failedPath2 = String(tc.arguments?.["path"] ?? tc.arguments?.["file"] ?? "unknown");
591934
- this.pendingUserMessages.push(`[SYSTEM] ${this._consecutiveEnoent} consecutive file-not-found errors (last: "${failedPath2}"). You are repeating failed paths. CHANGE YOUR APPROACH:
592161
+ this.enqueueRuntimeGuidance(`[SYSTEM] ${this._consecutiveEnoent} consecutive file-not-found errors (last: "${failedPath2}"). You are repeating failed paths. CHANGE YOUR APPROACH:
591935
592162
  1. Call list_directory(".") to see what exists at the project root
591936
592163
  2. Entries in a directory listing are RELATIVE to that directory. If you listed "parent/" and saw "child", the full path is "parent/child" — NOT ".child" or just "child"
591937
592164
  3. If an entry is a directory (marked "d"), use list_directory on it, NOT file_read
@@ -592068,7 +592295,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
592068
592295
  const recentSucc = this._adversaryToolOutcomes.slice(-3).filter((o2) => o2.succeeded);
592069
592296
  const succHint = recentSucc.length > 0 ? "\n\nYour most recent tool calls SUCCEEDED. If the task is complete, call task_complete now with a summary." : "";
592070
592297
  messages2.push({
592071
- role: "user",
592298
+ role: "system",
592072
592299
  content: "You have been reasoning internally for several turns without producing visible output or tool calls. Please take action now — call a tool or produce a visible response." + succHint
592073
592300
  });
592074
592301
  }
@@ -592083,7 +592310,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
592083
592310
  break;
592084
592311
  }
592085
592312
  messages2.push({
592086
- role: "user",
592313
+ role: "system",
592087
592314
  content: "Continue working. Use tools to read files, make changes, and run validation. Call task_complete when done."
592088
592315
  });
592089
592316
  }
@@ -593639,11 +593866,20 @@ ${result.output}`, "utf-8");
593639
593866
  const folded = this.foldOutput(modelContent, maxLen);
593640
593867
  return this.wrapToolOutputForModel(toolName, `[Tool output truncated — ${result.output.length} chars, ${lineCount} lines]
593641
593868
  Full output saved to: ${savedPath}
593642
- To read the complete output, use file_read with path="${savedPath}".
593869
+ ${this.truncatedToolOutputAccessHint(savedPath)}
593643
593870
 
593644
593871
  Truncated preview (beginning + end):
593645
593872
  ${folded}`);
593646
593873
  }
593874
+ truncatedToolOutputAccessHint(savedPath) {
593875
+ if (this.tools.has("file_read")) {
593876
+ return `To read the complete output, use file_read with path="${savedPath}".`;
593877
+ }
593878
+ if (this.tools.has("shell")) {
593879
+ return `To inspect the complete output, use shell with a read-only command for ${JSON.stringify(savedPath)}.`;
593880
+ }
593881
+ return `No file-reading tool is available in this agent role. Do not call file_read for this saved path; use the truncated preview, or report that the full payload is archived at ${savedPath}.`;
593882
+ }
593647
593883
  wrapToolOutputForModel(toolName, output) {
593648
593884
  if (toolName === "task_complete" || output.startsWith("[trust_tier:")) {
593649
593885
  return output;
@@ -594113,6 +594349,50 @@ ${tail}`;
594113
594349
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
594114
594350
  });
594115
594351
  }
594352
+ drainPendingRuntimeGuidance(turn) {
594353
+ while (this.pendingRuntimeGuidanceMessages.length > 0) {
594354
+ const guidance = this.pendingRuntimeGuidanceMessages.shift();
594355
+ this.appendRuntimeGuidance(guidance, turn);
594356
+ }
594357
+ }
594358
+ appendRuntimeGuidance(guidance, turn) {
594359
+ const packet = this.formatRuntimeGuidance(guidance);
594360
+ const guidanceHash = _createHash("sha256").update(packet).digest("hex").slice(0, 16);
594361
+ const signal = signalFromBlock("runtime_guidance", "runtime.guidance", packet, {
594362
+ id: `runtime-guidance-${turn}-${guidanceHash}`,
594363
+ dedupeKey: `runtime.guidance:${guidanceHash}`,
594364
+ priority: 94,
594365
+ createdTurn: turn,
594366
+ ttlTurns: 8
594367
+ });
594368
+ if (signal)
594369
+ this._contextLedger.upsert(signal);
594370
+ this.emit({
594371
+ type: "status",
594372
+ content: `Runtime guidance queued: ${guidance.replace(/\s+/g, " ").slice(0, 140)}`,
594373
+ turn,
594374
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
594375
+ });
594376
+ }
594377
+ formatRuntimeGuidance(guidance) {
594378
+ if (guidance.trim().startsWith("[RUNTIME_GUIDANCE_INTAKE")) {
594379
+ return guidance;
594380
+ }
594381
+ return [
594382
+ "[RUNTIME_GUIDANCE_INTAKE v1]",
594383
+ "Source: Omnius runtime control/advisory signal, not an external user message.",
594384
+ "",
594385
+ "<<<RUNTIME_GUIDANCE>>>",
594386
+ guidance,
594387
+ "<<<END_RUNTIME_GUIDANCE>>>",
594388
+ "",
594389
+ "Contract:",
594390
+ "- Treat this as diagnostic/control-plane guidance for the next action.",
594391
+ "- Reconcile it with the user goal and fresh tool evidence.",
594392
+ "- Do not quote or summarize this wrapper to the user.",
594393
+ "[/RUNTIME_GUIDANCE_INTAKE]"
594394
+ ].join("\n");
594395
+ }
594116
594396
  formatInjectedUserMessage(userMsg) {
594117
594397
  if (userMsg.trim().startsWith("[MID_TASK_STEERING_INTAKE")) {
594118
594398
  return userMsg;
@@ -597200,14 +597480,17 @@ ${description}`
597200
597480
  }
597201
597481
  }
597202
597482
  const acc = toolCallAccumulators.get(idx);
597483
+ if (chunk.toolCallId && chunk.toolCallId !== acc.id) {
597484
+ const previousId = acc.id;
597485
+ acc.id = chunk.toolCallId;
597486
+ this._streamingExecutor.rename(previousId, acc.id);
597487
+ }
597203
597488
  if (chunk.toolCallName) {
597204
597489
  acc.name = chunk.toolCallName;
597205
597490
  if (!this._streamingExecutor.getStates().has(acc.id) && acc.name) {
597206
597491
  this._streamingExecutor.queue(acc.id, acc.name);
597207
597492
  }
597208
597493
  }
597209
- if (chunk.toolCallId)
597210
- acc.id = chunk.toolCallId;
597211
597494
  if (chunk.toolCallArgs) {
597212
597495
  acc.args += chunk.toolCallArgs;
597213
597496
  }
@@ -742968,13 +743251,15 @@ The user pasted a clipboard image saved at ${relPath}. Use the OCR, vision analy
742968
743251
  },
742969
743252
  savePendingTaskState() {
742970
743253
  if (lastSubmittedPrompt && activeTask) {
743254
+ const activeToolCallCount = activeTask.toolCallCount;
743255
+ const activeFilesTouched = Array.from(activeTask.filesTouched);
742971
743256
  savePendingTask(repoRoot, {
742972
743257
  prompt: lastSubmittedPrompt,
742973
- progressSummary: `Task paused by user. ${sessionToolCallCount} tool calls completed.`,
742974
- filesModified: sessionFilesTouched,
743258
+ progressSummary: `Task paused by user. ${activeToolCallCount} tool calls completed.`,
743259
+ filesModified: activeFilesTouched,
742975
743260
  bruteForce: bruteForceEnabled,
742976
743261
  savedAt: (/* @__PURE__ */ new Date()).toISOString(),
742977
- toolCallCount: sessionToolCallCount
743262
+ toolCallCount: activeToolCallCount
742978
743263
  });
742979
743264
  return true;
742980
743265
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.458",
3
+ "version": "1.0.460",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.458",
9
+ "version": "1.0.460",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
@@ -5940,9 +5940,9 @@
5940
5940
  }
5941
5941
  },
5942
5942
  "node_modules/p-queue": {
5943
- "version": "9.3.0",
5944
- "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.0.tgz",
5945
- "integrity": "sha512-7NED7xhQ74Ngp4JP/2e0VZHp7vSWfJfqeiR92jPgxsz6m0Se4P03YoTKa9dDXyZ3r6P616gUXttrB6nnHYKang==",
5943
+ "version": "9.3.1",
5944
+ "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.1.tgz",
5945
+ "integrity": "sha512-POWdiIPmsUPGwb4FeQ4OBg46aqmcInSWe45CKDsGHiOBiVQM9chqfQTuqhuTzcg2Vz9faTI65at0KkVyVEiCHw==",
5946
5946
  "license": "MIT",
5947
5947
  "dependencies": {
5948
5948
  "eventemitter3": "^5.0.4",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.458",
3
+ "version": "1.0.460",
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",