omnius 1.0.365 → 1.0.367

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
@@ -558574,6 +558574,73 @@ function buildCriticPacketFromLedger(ledger) {
558574
558574
  }
558575
558575
  return lines.join("\n");
558576
558576
  }
558577
+ function appendUnresolved(items, text2, source) {
558578
+ const clean5 = cleanText(text2, 500);
558579
+ if (!clean5)
558580
+ return items;
558581
+ if (items.some((item) => item.text === clean5 && item.source === source)) {
558582
+ return items;
558583
+ }
558584
+ return [
558585
+ ...items,
558586
+ {
558587
+ id: nextId2("unresolved", items.length),
558588
+ text: clean5,
558589
+ source,
558590
+ recordedAtIso: nowIso2()
558591
+ }
558592
+ ];
558593
+ }
558594
+ function isMutationEvidence(entry) {
558595
+ if (entry.kind === "file_change")
558596
+ return true;
558597
+ return entry.success === true && /^(file_write|file_edit|file_patch|batch_edit)$/.test(entry.toolName ?? "");
558598
+ }
558599
+ function isSuccessfulVerificationEvidence(entry) {
558600
+ if (entry.success !== true)
558601
+ return false;
558602
+ const text2 = `${entry.toolName ?? ""} ${entry.summary}`.toLowerCase();
558603
+ return /\b(test|tests|tested|verify|verified|verification|build|built|compile|compiled|tsc|vitest|jest|pytest|go test|cargo test|pass|passed|success)\b/.test(text2);
558604
+ }
558605
+ function isFailedVerificationEvidence(entry) {
558606
+ if (entry.success !== false)
558607
+ return false;
558608
+ const text2 = `${entry.toolName ?? ""} ${entry.summary}`.toLowerCase();
558609
+ return /\b(test|tests|verify|verification|build|compile|tsc|vitest|jest|pytest|go test|cargo test)\b/.test(text2);
558610
+ }
558611
+ function isStaleEditEvidence(entry) {
558612
+ if (entry.success !== false)
558613
+ return false;
558614
+ const text2 = entry.summary.toLowerCase();
558615
+ return /stale edit loop blocked|old[_ -]?string|old text|expected[_ -]?hash|context mismatch|no occurrences|could not find/.test(text2);
558616
+ }
558617
+ function finalizeCompletionLedgerTruth(ledger) {
558618
+ let unresolved = [...ledger.unresolved];
558619
+ let lastMutation = -1;
558620
+ let lastVerification = -1;
558621
+ ledger.evidence.forEach((entry, index) => {
558622
+ if (isMutationEvidence(entry))
558623
+ lastMutation = index;
558624
+ if (isSuccessfulVerificationEvidence(entry))
558625
+ lastVerification = index;
558626
+ if (isFailedVerificationEvidence(entry)) {
558627
+ unresolved = appendUnresolved(unresolved, `Verification failed or did not prove success: ${entry.summary}`, entry.id);
558628
+ }
558629
+ if (isStaleEditEvidence(entry)) {
558630
+ unresolved = appendUnresolved(unresolved, `Stale edit failure remains unresolved: ${entry.summary}`, entry.id);
558631
+ }
558632
+ });
558633
+ if (lastVerification >= 0 && lastMutation > lastVerification) {
558634
+ unresolved = appendUnresolved(unresolved, "File changes occurred after the last successful verification; final verification is stale.", "verification_freshness");
558635
+ }
558636
+ const status = ledger.status === "blocked" || ledger.status === "request_changes" ? ledger.status : unresolved.length > 0 ? "incomplete_verification" : ledger.status;
558637
+ return {
558638
+ ...ledger,
558639
+ unresolved,
558640
+ status,
558641
+ updatedAtIso: nowIso2()
558642
+ };
558643
+ }
558577
558644
  function saveCompletionLedger(filePath, ledger) {
558578
558645
  mkdirSync49(dirname28(filePath), { recursive: true });
558579
558646
  writeFileSync40(filePath, `${JSON.stringify(ledger, null, 2)}
@@ -563850,11 +563917,59 @@ ${text2}` : SUMMARY_PREFIX;
563850
563917
  }
563851
563918
  });
563852
563919
 
563920
+ // packages/orchestrator/dist/artifactQuality.js
563921
+ function isInternalArtifactPrompt(text2) {
563922
+ const raw = String(text2 ?? "");
563923
+ if (!raw.trim())
563924
+ return false;
563925
+ return INTERNAL_PROMPT_PATTERNS.some((pattern) => pattern.test(raw));
563926
+ }
563927
+ function assessTaskArtifactQuality(input) {
563928
+ if (input.artifactMode === "internal") {
563929
+ return { eligible: false, reason: "internal artifact mode" };
563930
+ }
563931
+ const goal = String(input.goal ?? "");
563932
+ const summary = String(input.summary ?? "");
563933
+ if (isInternalArtifactPrompt(goal) || isInternalArtifactPrompt(summary)) {
563934
+ return { eligible: false, reason: "internal helper prompt" };
563935
+ }
563936
+ const toolsUsed = input.toolsUsed ?? [];
563937
+ const filesTouched = input.filesTouched ?? [];
563938
+ const turns = input.turns ?? 0;
563939
+ if (turns <= 0 && toolsUsed.length === 0) {
563940
+ return { eligible: false, reason: "zero-turn no-tool artifact" };
563941
+ }
563942
+ if (!summary.trim() && toolsUsed.length === 0 && filesTouched.length === 0) {
563943
+ return { eligible: false, reason: "empty no-evidence artifact" };
563944
+ }
563945
+ return { eligible: true };
563946
+ }
563947
+ var INTERNAL_PROMPT_PATTERNS;
563948
+ var init_artifactQuality = __esm({
563949
+ "packages/orchestrator/dist/artifactQuality.js"() {
563950
+ "use strict";
563951
+ INTERNAL_PROMPT_PATTERNS = [
563952
+ /\byou are an emotion center\b/i,
563953
+ /\bemotion center\b.*\brespond with one emoji\b/i,
563954
+ /\byou are the agent's private reflection process\b/i,
563955
+ /\bprefrontal cortex gating evaluator\b/i,
563956
+ /\bdentate gyrus pattern separation evaluator\b/i,
563957
+ /\bsnr evaluator\b/i,
563958
+ /\byou are the prefrontal cortex\b/i,
563959
+ /\byou are the hippocampus\b/i,
563960
+ /\byou are the amygdala\b/i,
563961
+ /\byou are the inner critic\b/i,
563962
+ /\byou are the basal ganglia\b/i
563963
+ ];
563964
+ }
563965
+ });
563966
+
563853
563967
  // packages/orchestrator/dist/reflectionBuffer.js
563854
563968
  var MAX_REFLECTIONS, MAX_TOTAL, TaskReflectionBuffer;
563855
563969
  var init_reflectionBuffer = __esm({
563856
563970
  "packages/orchestrator/dist/reflectionBuffer.js"() {
563857
563971
  "use strict";
563972
+ init_artifactQuality();
563858
563973
  MAX_REFLECTIONS = 5;
563859
563974
  MAX_TOTAL = 50;
563860
563975
  TaskReflectionBuffer = class {
@@ -563905,6 +564020,18 @@ var init_reflectionBuffer = __esm({
563905
564020
  */
563906
564021
  addReflection(params) {
563907
564022
  const { taskGoal, sessionId, turnsSpent, failedApproaches, toolCallLog, lastError, failedPaths } = params;
564023
+ const goalCoreForQuality = this.extractUserGoalCore(taskGoal) || taskGoal;
564024
+ const quality = assessTaskArtifactQuality({
564025
+ goal: goalCoreForQuality,
564026
+ summary: lastError,
564027
+ toolsUsed: toolCallLog.map((entry) => entry.tool),
564028
+ filesTouched: failedPaths || [],
564029
+ turns: turnsSpent
564030
+ });
564031
+ if (!quality.eligible) {
564032
+ const reason = quality.reason || "low-quality artifact";
564033
+ throw new Error("Reflection rejected: " + reason);
564034
+ }
563908
564035
  const taskFingerprint = this.computeFingerprint(taskGoal);
563909
564036
  const errorType = this.classifyError(toolCallLog, failedApproaches, lastError, turnsSpent);
563910
564037
  const failedTools = [...new Set(toolCallLog.filter((t2) => !t2.success).map((t2) => t2.tool))].slice(0, 5);
@@ -563953,23 +564080,26 @@ var init_reflectionBuffer = __esm({
563953
564080
  const fingerprint = this.computeFingerprint(taskGoal);
563954
564081
  const goalLower = goalCore.toLowerCase();
563955
564082
  const goalWords = new Set(goalLower.split(/\s+/).filter((w) => w.length > 3));
563956
- const scored = this.state.reflections.map((r2) => {
563957
- let score = 0;
564083
+ const scored = this.state.reflections.filter((r2) => !isInternalArtifactPrompt(r2.taskGoal) && !isInternalArtifactPrompt(r2.whatFailed) && !isInternalArtifactPrompt(r2.whatToDoDifferently)).map((r2) => {
564084
+ let baseScore = 0;
563958
564085
  if (r2.taskFingerprint === fingerprint)
563959
- score += 5;
564086
+ baseScore += 5;
563960
564087
  const rWords = new Set(r2.taskGoal.toLowerCase().split(/\s+/).filter((w) => w.length > 3));
563961
564088
  let overlap = 0;
563962
564089
  for (const w of goalWords)
563963
564090
  if (rWords.has(w))
563964
564091
  overlap++;
563965
- score += overlap;
564092
+ baseScore += overlap;
564093
+ if (baseScore <= 0)
564094
+ return { reflection: r2, score: 0, relevant: false };
564095
+ let score = baseScore;
563966
564096
  const hoursAgo = (Date.now() - r2.timestamp) / 36e5;
563967
564097
  score += Math.max(0, 2 - hoursAgo * 0.1);
563968
564098
  score += r2.confidence * 2;
563969
- return { reflection: r2, score };
564099
+ return { reflection: r2, score, relevant: true };
563970
564100
  });
563971
564101
  scored.sort((a2, b) => b.score - a2.score);
563972
- const results = scored.slice(0, maxResults).filter((s2) => s2.score > 1).map((s2) => s2.reflection);
564102
+ const results = scored.filter((s2) => s2.relevant && s2.score > 1).slice(0, maxResults).map((s2) => s2.reflection);
563973
564103
  this.state.totalConsumed += results.length;
563974
564104
  this.persist();
563975
564105
  return results;
@@ -564182,23 +564312,50 @@ function buildTaskHandoff(params) {
564182
564312
  const argHint = tc.argsKey ? ` ${tc.argsKey.slice(0, 80)}` : "";
564183
564313
  return `${tc.name}${argHint}`;
564184
564314
  });
564315
+ const artifactMode = params.artifactMode ?? "user-task";
564316
+ const filesTouched = [...new Set(params.filesModified)].slice(0, MAX_FILES);
564317
+ const toolsUsed = [...new Set(params.toolsUsed)].slice(0, MAX_TOOLS);
564318
+ const quality = assessTaskArtifactQuality({
564319
+ artifactMode,
564320
+ goal: params.goal,
564321
+ summary: params.summary,
564322
+ filesTouched,
564323
+ toolsUsed,
564324
+ turns: params.turns
564325
+ });
564185
564326
  return {
564186
564327
  v: 2,
564187
564328
  sessionId: params.sessionId,
564188
564329
  priorGoal: params.goal.slice(0, 500),
564189
564330
  priorOutcome: params.outcome,
564190
564331
  priorSummary: (params.summary || "").slice(0, MAX_SUMMARY_CHARS),
564191
- filesTouched: [...new Set(params.filesModified)].slice(0, MAX_FILES),
564192
- toolsUsed: [...new Set(params.toolsUsed)].slice(0, MAX_TOOLS),
564332
+ filesTouched,
564333
+ toolsUsed,
564193
564334
  lastActions,
564194
564335
  turns: params.turns,
564195
564336
  endedAt: Date.now(),
564337
+ artifactMode,
564338
+ quality,
564196
564339
  ...params.transcriptPath ? { transcriptPath: params.transcriptPath } : {}
564197
564340
  };
564198
564341
  }
564342
+ function shouldPersistTaskHandoff(handoff) {
564343
+ if (handoff.quality && handoff.quality.eligible === false)
564344
+ return false;
564345
+ return assessTaskArtifactQuality({
564346
+ artifactMode: handoff.artifactMode,
564347
+ goal: handoff.priorGoal,
564348
+ summary: handoff.priorSummary,
564349
+ toolsUsed: handoff.toolsUsed,
564350
+ filesTouched: handoff.filesTouched,
564351
+ turns: handoff.turns
564352
+ }).eligible;
564353
+ }
564199
564354
  function writeTaskHandoff(omniusDir, handoff) {
564200
564355
  if (!handoffEnabled())
564201
564356
  return;
564357
+ if (!shouldPersistTaskHandoff(handoff))
564358
+ return;
564202
564359
  try {
564203
564360
  const file = handoffPath(omniusDir);
564204
564361
  fs4.mkdirSync(path5.dirname(file), { recursive: true });
@@ -564219,6 +564376,8 @@ function readTaskHandoff(omniusDir, opts) {
564219
564376
  return null;
564220
564377
  }
564221
564378
  const handoff = parsed;
564379
+ if (!shouldPersistTaskHandoff(handoff))
564380
+ return null;
564222
564381
  const sameSession = handoff.sessionId === opts.currentSessionId;
564223
564382
  if (!sameSession) {
564224
564383
  const age = Date.now() - handoff.endedAt;
@@ -564287,6 +564446,7 @@ var DEFAULT_TTL_MS2, MAX_SUMMARY_CHARS, MAX_FILES, MAX_TOOLS, MAX_LAST_ACTIONS;
564287
564446
  var init_taskHandoff = __esm({
564288
564447
  "packages/orchestrator/dist/taskHandoff.js"() {
564289
564448
  "use strict";
564449
+ init_artifactQuality();
564290
564450
  DEFAULT_TTL_MS2 = 24 * 60 * 60 * 1e3;
564291
564451
  MAX_SUMMARY_CHARS = 8e3;
564292
564452
  MAX_FILES = 30;
@@ -564317,6 +564477,8 @@ function logPath2(omniusDir, sessionLogId) {
564317
564477
  function appendBoundaryToLog(omniusDir, handoff) {
564318
564478
  if (!logEnabled())
564319
564479
  return;
564480
+ if (!shouldPersistTaskHandoff(handoff))
564481
+ return;
564320
564482
  const id = tuiSessionLogId();
564321
564483
  if (!id)
564322
564484
  return;
@@ -564345,7 +564507,9 @@ function loadBoundaryRecords(omniusDir) {
564345
564507
  try {
564346
564508
  const parsed = JSON.parse(lines[i2]);
564347
564509
  if (parsed && parsed.v === 1 && parsed.handoff && typeof parsed.recordedAt === "number") {
564348
- records.push(parsed);
564510
+ const record = parsed;
564511
+ if (shouldPersistTaskHandoff(record.handoff))
564512
+ records.push(record);
564349
564513
  }
564350
564514
  } catch {
564351
564515
  }
@@ -565896,7 +566060,7 @@ function heuristicSummarize(inputs) {
565896
566060
  }
565897
566061
  }
565898
566062
  return {
565899
- functionalSummary: `Completed: ${inputs.todoContent.slice(0, 120)} (heuristic summary — use memex_retrieve(expand=true) for full context)`,
566063
+ functionalSummary: `Work recorded: ${inputs.todoContent.slice(0, 120)} (heuristic summary — use memex_retrieve(expand=true) for full context)`,
565900
566064
  keyFiles: [...files].slice(0, 30),
565901
566065
  criticalSymbols: {
565902
566066
  defined: [...new Set(symbolsDefined)].slice(0, 50),
@@ -565914,6 +566078,31 @@ function heuristicSummarize(inputs) {
565914
566078
  ].join("\n")
565915
566079
  };
565916
566080
  }
566081
+ function hasExplicitVerification(text2) {
566082
+ const raw = String(text2 || "").trim();
566083
+ if (!raw)
566084
+ return false;
566085
+ if (/^\(?no verification detected\)?$/i.test(raw))
566086
+ return false;
566087
+ if (/\b(no verification|not verified|not run|missing verification|none detected)\b/i.test(raw))
566088
+ return false;
566089
+ return /\b(pass|passed|success|succeeded|verified|tests?|build|compile|tsc|vitest|jest|pytest|go test|cargo test)\b/i.test(raw);
566090
+ }
566091
+ function deriveChunkStatus(verdict, toolCalls) {
566092
+ if ((verdict.unresolved || []).length > 0)
566093
+ return "blocked";
566094
+ if (toolCalls.some((tc) => !tc.success))
566095
+ return "partial";
566096
+ if (!hasExplicitVerification(verdict.verification || ""))
566097
+ return "unverified";
566098
+ return "completed";
566099
+ }
566100
+ function statusAwareFunctionalSummary(summary, status, fallback) {
566101
+ const raw = (summary || fallback).trim();
566102
+ if (status === "completed")
566103
+ return raw;
566104
+ return raw.replace(/^completed\s*:?/i, "Work recorded:");
566105
+ }
565917
566106
  async function runTodoChunker(opts) {
565918
566107
  const startMs = Date.now();
565919
566108
  const memexId = `todo-ctx-${sanitizeId(opts.inputs.todoId).slice(0, 20)}`;
@@ -565932,11 +566121,12 @@ async function runTodoChunker(opts) {
565932
566121
  usedFallback = true;
565933
566122
  }
565934
566123
  const estimatedTokens = Math.round(opts.inputs.transcript.length / 4);
566124
+ const status = deriveChunkStatus(verdict, opts.inputs.toolCalls);
565935
566125
  const chunk = {
565936
566126
  todoId: opts.inputs.todoId,
565937
566127
  todoContent: opts.inputs.todoContent,
565938
- status: "completed",
565939
- functionalSummary: verdict.functionalSummary || `Completed: ${opts.inputs.todoContent.slice(0, 120)}`,
566128
+ status,
566129
+ functionalSummary: statusAwareFunctionalSummary(verdict.functionalSummary, status, `Work recorded: ${opts.inputs.todoContent.slice(0, 120)}`),
565940
566130
  detailSummary: verdict.detailSummary || "",
565941
566131
  keyFiles: verdict.keyFiles || [],
565942
566132
  criticalSymbols: verdict.criticalSymbols || { defined: [], modified: [] },
@@ -567404,6 +567594,9 @@ function adversarySystemPrompt() {
567404
567594
  " • started ≠ running — a PID or a log line is not a liveness probe.",
567405
567595
  " • exit code 0 / 'build complete' ≠ success — the specific artifact must exist.",
567406
567596
  " • an edit ≠ a fix — the failing command must be re-run and pass.",
567597
+ " • file_write/file_read tool outcomes ARE first-class evidence for narrow file existence/content claims.",
567598
+ " Do not demand shell/cat proof when a successful file_write is followed by file_read evidence for the same path.",
567599
+ " • If a shell integrity check is truly needed, demand a newline-safe command such as: printf '\n---sha256---\n'; sha256sum <path>. Do not use brittle cat <path> && sha256sum <path> as the default.",
567407
567600
  " • simulation / mock / placeholder ≠ real.",
567408
567601
  " • partial progress ≠ done.",
567409
567602
  "Mixed results are the norm: do NOT let one success excuse an unproven completion claim.",
@@ -567424,7 +567617,11 @@ function adversarySystemPrompt() {
567424
567617
  ].join("\n");
567425
567618
  }
567426
567619
  function buildObservationPrompt(obs, recentLedger) {
567427
- const outcomes = obs.recentToolOutcomes.slice(-8).map((o2) => ` - ${o2.tool}: ${o2.succeeded ? "OK" : "FAIL"} — ${o2.preview.slice(0, 120)}`).join("\n");
567620
+ const outcomes = obs.recentToolOutcomes.slice(-8).map((o2) => {
567621
+ const target = o2.path ? ` path=${o2.path}` : "";
567622
+ const evidence = o2.evidence ? ` | evidence: ${o2.evidence.slice(0, 220)}` : "";
567623
+ return ` - ${o2.tool}: ${o2.succeeded ? "OK" : "FAIL"}${target} — ${o2.preview.slice(0, 160)}${evidence}`;
567624
+ }).join("\n");
567428
567625
  const priorDoubts = recentLedger.slice(-3).filter((e2) => e2.verdict !== "ok").map((e2) => ` - turn ${e2.turn}: ${e2.verdict} — demanded: ${e2.demand}`).join("\n");
567429
567626
  if (obs.loopSignal) {
567430
567627
  const ls2 = obs.loopSignal;
@@ -567479,6 +567676,47 @@ ${priorDoubts}` : "",
567479
567676
  "Audit this. Return ONLY the JSON object."
567480
567677
  ].join("\n");
567481
567678
  }
567679
+ function deterministicFileProofPaths(obs) {
567680
+ const writes = /* @__PURE__ */ new Set();
567681
+ const reads = /* @__PURE__ */ new Set();
567682
+ for (const outcome of obs.recentToolOutcomes) {
567683
+ if (!outcome.succeeded || !outcome.path)
567684
+ continue;
567685
+ if (/^(file_write|file_edit|file_patch|batch_edit)$/.test(outcome.tool)) {
567686
+ writes.add(outcome.path);
567687
+ }
567688
+ if (outcome.tool === "file_read")
567689
+ reads.add(outcome.path);
567690
+ }
567691
+ const proven = /* @__PURE__ */ new Set();
567692
+ for (const path12 of writes)
567693
+ if (reads.has(path12))
567694
+ proven.add(path12);
567695
+ return proven;
567696
+ }
567697
+ function hasRecentNonFileFailure(obs) {
567698
+ return obs.recentToolOutcomes.some((outcome) => !outcome.succeeded && !/^(file_write|file_edit|file_patch|batch_edit|file_read|task_complete)$/.test(outcome.tool));
567699
+ }
567700
+ function isNarrowFileCompletionClaim(text2) {
567701
+ return /\b(file|path|created|wrote|written|exists|content|reads?back|verified by read|single line)\b/i.test(text2);
567702
+ }
567703
+ function critiqueContradictedByFileProof(obs, critique2) {
567704
+ if (!obs.claimsCompletion)
567705
+ return false;
567706
+ if (hasRecentNonFileFailure(obs))
567707
+ return false;
567708
+ if (!isNarrowFileCompletionClaim(obs.assistantText))
567709
+ return false;
567710
+ if (deterministicFileProofPaths(obs).size === 0)
567711
+ return false;
567712
+ if (critique2.class === "ok")
567713
+ return false;
567714
+ const text2 = critique2.shortText + "\n" + critique2.details + "\n" + critique2.demand;
567715
+ return /no tool output|tool output|file creation|file exists|file content|cat\b|sha256|hash|unverified|unproven|readback|read back/i.test(text2);
567716
+ }
567717
+ function hasDeterministicFileCompletionProof(obs) {
567718
+ return obs.claimsCompletion && !hasRecentNonFileFailure(obs) && isNarrowFileCompletionClaim(obs.assistantText) && deterministicFileProofPaths(obs).size > 0;
567719
+ }
567482
567720
  function parseAdversaryCritique(raw) {
567483
567721
  if (!raw)
567484
567722
  return null;
@@ -567549,7 +567787,7 @@ var init_adversaryStream = __esm({
567549
567787
  */
567550
567788
  shouldAudit(obs) {
567551
567789
  if (obs.claimsCompletion)
567552
- return true;
567790
+ return !hasDeterministicFileCompletionProof(obs);
567553
567791
  if (obs.loopSignal)
567554
567792
  return true;
567555
567793
  if (obs.failingApproach)
@@ -567597,6 +567835,15 @@ var init_adversaryStream = __esm({
567597
567835
  }
567598
567836
  if (!critique2)
567599
567837
  return null;
567838
+ if (critiqueContradictedByFileProof(obs, critique2)) {
567839
+ critique2 = {
567840
+ class: "ok",
567841
+ shortText: "file proof present",
567842
+ confidence: 0.05,
567843
+ details: "The recent file_write/file_read outcomes provide deterministic evidence for this narrow file existence/content claim.",
567844
+ demand: ""
567845
+ };
567846
+ }
567600
567847
  this.ledger.push({
567601
567848
  ts: Date.now(),
567602
567849
  turn: obs.turn,
@@ -570272,6 +570519,7 @@ var init_agenticRunner = __esm({
570272
570519
  */
570273
570520
  _completionCaveat = null;
570274
570521
  _completionLedger = null;
570522
+ _staleEditFamilies = /* @__PURE__ */ new Map();
570275
570523
  // ── WO-AM-01/04/10: Associative memory stores ──
570276
570524
  // Episode store: every tool call → persistent episode with importance + decay
570277
570525
  // Temporal KG: entities + relations with temporal validity (valid_from/valid_until)
@@ -570620,6 +570868,7 @@ ${parts.join("\n")}
570620
570868
  memoryPrefix: options2?.memoryPrefix ?? "",
570621
570869
  memoryPrefixHash: options2?.memoryPrefixHash ?? "",
570622
570870
  stateDir: options2?.stateDir ?? "",
570871
+ artifactMode: options2?.artifactMode ?? "user-task",
570623
570872
  disablePersistentMemory: options2?.disablePersistentMemory ?? false,
570624
570873
  disableCodebaseMap: options2?.disableCodebaseMap ?? false,
570625
570874
  sessionId: options2?.sessionId ?? "",
@@ -570671,7 +570920,12 @@ ${parts.join("\n")}
570671
570920
  const configured = (this.options.stateDir || "").trim();
570672
570921
  return configured ? _pathResolve(configured) : _pathJoin(process.cwd(), ".omnius");
570673
570922
  }
570923
+ writesUserTaskArtifacts() {
570924
+ return this.options.artifactMode === "user-task" && !this.options.subAgent;
570925
+ }
570674
570926
  _persistCompletionContract(contract) {
570927
+ if (!this.writesUserTaskArtifacts())
570928
+ return;
570675
570929
  try {
570676
570930
  const dir = _pathJoin(this.omniusStateDir(), "completion-contracts");
570677
570931
  _fsMkdirSync(dir, { recursive: true });
@@ -570684,6 +570938,8 @@ ${parts.join("\n")}
570684
570938
  }
570685
570939
  }
570686
570940
  _saveCompletionLedgerSafe() {
570941
+ if (!this.writesUserTaskArtifacts())
570942
+ return;
570687
570943
  if (!this._completionLedger)
570688
570944
  return;
570689
570945
  try {
@@ -575456,6 +575712,7 @@ Respond with your assessment, then take action.`;
575456
575712
  this._completionIncompleteVerification = null;
575457
575713
  this._completionCaveat = null;
575458
575714
  this._completionLedger = null;
575715
+ this._staleEditFamilies.clear();
575459
575716
  this._lastWorldStateTurn = -1;
575460
575717
  this._fileWritesSinceLastWorldState = 0;
575461
575718
  this._resetVisualEvidenceState();
@@ -575598,11 +575855,16 @@ Respond with your assessment, then take action.`;
575598
575855
  verbose: false
575599
575856
  });
575600
575857
  this._hookManager.runSessionHook("session_start", this._sessionId);
575601
- this._initializeCompletionContract(task, context2, actualUserGoal);
575602
- this._completionLedger = createCompletionLedger({
575603
- runId: this._sessionId,
575604
- goal: userGoal
575605
- });
575858
+ if (this.writesUserTaskArtifacts()) {
575859
+ this._initializeCompletionContract(task, context2, actualUserGoal);
575860
+ this._completionLedger = createCompletionLedger({
575861
+ runId: this._sessionId,
575862
+ goal: userGoal
575863
+ });
575864
+ } else {
575865
+ this._completionContract = null;
575866
+ this._completionLedger = null;
575867
+ }
575606
575868
  this._sessionStartMs = Date.now();
575607
575869
  if (process.env["OMNIUS_DISABLE_PREFLIGHT"] !== "1") {
575608
575870
  try {
@@ -575878,6 +576140,8 @@ TASK: ${scrubbedTask}` : scrubbedTask;
575878
576140
  try {
575879
576141
  if (this.options.subAgent)
575880
576142
  throw "skip-handoff-subagent";
576143
+ if (!this.writesUserTaskArtifacts())
576144
+ throw "skip-handoff-artifact-mode";
575881
576145
  if (this.options.skipCrossTaskHandoff)
575882
576146
  throw "skip-handoff-caller-optout";
575883
576147
  if (/<task-handoff>|<session-recap>/.test(task))
@@ -575914,6 +576178,8 @@ TASK: ${scrubbedTask}` : scrubbedTask;
575914
576178
  } catch {
575915
576179
  }
575916
576180
  try {
576181
+ if (!this.writesUserTaskArtifacts())
576182
+ throw "skip-reflection-artifact-mode";
575917
576183
  if (!this._reflectionBuffer) {
575918
576184
  const omniusDir = this.options.stateDir ? _pathJoin(this.omniusStateDir(), "memory") : this._workingDirectory ? _pathJoin(this._workingDirectory, ".omnius", "memory") : null;
575919
576185
  if (omniusDir) {
@@ -576007,6 +576273,9 @@ TASK: ${scrubbedTask}` : scrubbedTask;
576007
576273
  backend: this._auxInferenceBackend(),
576008
576274
  persistPath,
576009
576275
  onCritique: (critique2, sourceTurn) => {
576276
+ if (completed || this._completionIncompleteVerification || this.aborted) {
576277
+ return;
576278
+ }
576010
576279
  if (this._adversaryMode === "skillcoach" || this._adversaryMode === "both") {
576011
576280
  this.pendingUserMessages.push(AdversaryStream.formatInjection(critique2));
576012
576281
  }
@@ -578512,6 +578781,43 @@ Use the saved fact to continue the promised synthesis or next concrete step, or
578512
578781
  systemGuidance: repeatNoopMsg
578513
578782
  };
578514
578783
  }
578784
+ const staleEditBlock = this.staleEditPreflightBlock(tc.name, tc.arguments ?? {});
578785
+ if (staleEditBlock) {
578786
+ this.emit({
578787
+ type: "tool_call",
578788
+ toolName: tc.name,
578789
+ toolArgs: tc.arguments,
578790
+ turn,
578791
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
578792
+ });
578793
+ this.emit({
578794
+ type: "tool_result",
578795
+ toolName: tc.name,
578796
+ success: false,
578797
+ content: staleEditBlock.slice(0, 120),
578798
+ turn,
578799
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
578800
+ });
578801
+ this._tagSyntheticFailure({
578802
+ mode: "step_repetition",
578803
+ rationale: "stale edit family retried without fresh read or mutation"
578804
+ });
578805
+ if (this._completionLedger) {
578806
+ this._completionLedger = recordToolEvidence(this._completionLedger, {
578807
+ name: tc.name,
578808
+ success: false,
578809
+ outputPreview: staleEditBlock.slice(0, 500),
578810
+ argsKey: tc.arguments ? JSON.stringify(tc.arguments).slice(0, 300) : ""
578811
+ });
578812
+ this._saveCompletionLedgerSafe();
578813
+ }
578814
+ return {
578815
+ tc,
578816
+ output: staleEditBlock,
578817
+ success: false,
578818
+ systemGuidance: staleEditBlock
578819
+ };
578820
+ }
578515
578821
  const baseIsReadLike = ![
578516
578822
  "file_write",
578517
578823
  "file_edit",
@@ -578626,7 +578932,9 @@ Use the saved fact to continue the promised synthesis or next concrete step, or
578626
578932
  recentToolOutcomes: this._adversaryToolOutcomes.slice(-8).map((o2) => ({
578627
578933
  tool: o2.tool,
578628
578934
  succeeded: o2.succeeded,
578629
- preview: o2.preview
578935
+ preview: o2.preview,
578936
+ path: o2.path,
578937
+ evidence: o2.evidence
578630
578938
  })),
578631
578939
  claimsCompletion: false,
578632
578940
  loopSignal: {
@@ -579992,6 +580300,7 @@ Evidence: ${evidencePreview}`.slice(0, 500);
579992
580300
  }
579993
580301
  const filePath = typeof tc.arguments?.path === "string" ? tc.arguments.path : "";
579994
580302
  recordToolExecution(this._appState, tc.name, performance.now() - toolStart, result.success, filePath || void 0);
580303
+ this.noteStaleEditGuardOutcome(tc.name, tc.arguments ?? {}, result, turn);
579995
580304
  if (tc.name === "todo_write") {
579996
580305
  this._lastTodoWriteTurn = turn;
579997
580306
  }
@@ -580546,7 +580855,10 @@ ${sr.result.output}`;
580546
580855
  loopInterventionCount++;
580547
580856
  const loopTier2 = this.options.modelTier ?? "large";
580548
580857
  const maxInterventions = loopTier2 === "small" ? 3 : loopTier2 === "medium" ? 5 : 8;
580858
+ let loopCircuitBreakerFired = false;
580859
+ const loopInterventionOrdinal = loopInterventionCount;
580549
580860
  if (loopInterventionCount >= maxInterventions) {
580861
+ loopCircuitBreakerFired = true;
580550
580862
  this.emit({
580551
580863
  type: "status",
580552
580864
  content: `Loop circuit breaker: ${loopInterventionCount} interventions — requesting user guidance`,
@@ -580557,15 +580869,16 @@ ${sr.result.output}`;
580557
580869
  role: "system",
580558
580870
  content: `LOOP CIRCUIT BREAKER: ${loopInterventionCount} interventions attempted but repetition continues.
580559
580871
 
580560
- MANDATORY: You MUST call ask_user to request guidance from the user. Present your options:
580872
+ MANDATORY: Change state before taking another action. Choose one:
580561
580873
  1. Try a completely different approach
580562
- 2. Provide more context or clarification
580563
- 3. Accept partial results and pivot to a related task
580564
- 4. Abort this specific subtask and move on
580874
+ 2. Re-read the exact current target once if the loop is caused by a stale edit
580875
+ 3. Run verification if files changed since the last successful check
580876
+ 4. Call ask_user if user input is the real blocker
580877
+ 5. Report blocked/incomplete with the concrete blocker if no safe progress path remains
580565
580878
 
580566
580879
  Your partial progress: ${partialResults}
580567
580880
 
580568
- Call ask_user(question="I've hit a repetitive loop. How would you like me to proceed?", options=[...]) NOW.`
580881
+ Do not call task_complete solely because this circuit breaker fired.`
580569
580882
  });
580570
580883
  loopInterventionCount = 0;
580571
580884
  }
@@ -580583,19 +580896,19 @@ Call ask_user(question="I've hit a repetitive loop. How would you like me to pro
580583
580896
  }
580584
580897
  const findingsSummary = findings.length > 0 ? `
580585
580898
 
580586
- Here is what you ALREADY found (use this for your summary):
580587
- ${findings.slice(0, 8).map((f2, i2) => `${i2 + 1}. ${f2}`).join("\n")}` : "\n\nYou found no actionable results. Report that the information could not be found.";
580899
+ Here is what you ALREADY found. Use this to choose the next non-repetitive action:
580900
+ ${findings.slice(0, 8).map((f2, i2) => `${i2 + 1}. ${f2}`).join("\n")}` : "\n\nYou found no actionable results. Ask for guidance or report the specific blocker; do not invent completion.";
580588
580901
  messages2.push({
580589
580902
  role: "system",
580590
- content: `LOOP DETECTED (intervention ${loopInterventionCount}/${maxInterventions}). The last ${repetitionWindow} tool calls are ${Math.round(currentRepScore * 100)}% repetitive: ${topRepeated}.
580903
+ content: `LOOP DETECTED (intervention ${loopInterventionOrdinal}/${maxInterventions}). The last ${repetitionWindow} tool calls are ${Math.round(currentRepScore * 100)}% repetitive: ${topRepeated}.
580591
580904
 
580592
- MANDATORY: You MUST call task_complete on your next response. Do NOT call ${[...freqMap.keys()].map((k) => k.split("(")[0]).filter((v, i2, a2) => a2.indexOf(v) === i2).join(", ")} again. These tools have returned the same results multiple times.` + findingsSummary + `
580905
+ RECOVERY REQUIRED: Do not call task_complete just because repetition was detected. Do NOT call ${[...freqMap.keys()].map((k) => k.split("(")[0]).filter((v, i2, a2) => a2.indexOf(v) === i2).join(", ")} again with the same arguments. These tools have returned the same results multiple times. Choose a different concrete action: read the exact current target once if an edit failed, run verification if files changed, use a different tool or target, or call ask_user when user input is the real blocker.` + findingsSummary + `
580593
580906
 
580594
- Call task_complete(summary="...") NOW with whatever you have.`
580907
+ Only call task_complete when the task is actually complete and the evidence is fresh. If work is partial, report the blocker explicitly instead of completing.`
580595
580908
  });
580596
580909
  this.emit({
580597
580910
  type: "status",
580598
- content: `Loop intervention ${loopInterventionCount}/${maxInterventions}: ${Math.round(currentRepScore * 100)}% repetitive (${topRepeated})`,
580911
+ content: `Loop intervention ${loopInterventionOrdinal}/${maxInterventions}: ${Math.round(currentRepScore * 100)}% repetitive (${topRepeated})${loopCircuitBreakerFired ? " (circuit breaker advisory)" : ""}`,
580599
580912
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
580600
580913
  });
580601
580914
  try {
@@ -581497,7 +581810,19 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
581497
581810
 
581498
581811
  ${this._completionCaveat}` : this._completionCaveat;
581499
581812
  }
581500
- const runStatus = completed ? "completed" : this._completionLedger?.status === "blocked" || this._completionLedger?.status === "request_changes" ? "incomplete_verification" : this._completionIncompleteVerification ? "incomplete_verification" : "incomplete";
581813
+ if (this._completionLedger) {
581814
+ this._completionLedger = finalizeCompletionLedgerTruth(this._completionLedger);
581815
+ this._saveCompletionLedgerSafe();
581816
+ if (completed && this._completionLedger.status === "incomplete_verification") {
581817
+ completed = false;
581818
+ const unresolvedSummary = this._completionLedger.unresolved.slice(-3).map((item) => item.text).join("; ");
581819
+ const caveat = unresolvedSummary ? `Incomplete verification: ${unresolvedSummary}` : "Incomplete verification: unresolved evidence remains in the completion ledger.";
581820
+ summary = summary ? `${summary}
581821
+
581822
+ ${caveat}` : caveat;
581823
+ }
581824
+ }
581825
+ const runStatus = completed ? "completed" : this._completionLedger?.status === "blocked" || this._completionLedger?.status === "request_changes" || this._completionLedger?.status === "incomplete_verification" ? "incomplete_verification" : this._completionIncompleteVerification ? "incomplete_verification" : "incomplete";
581501
581826
  this._emitMASTSummary("run-end");
581502
581827
  this.emit({
581503
581828
  type: "complete",
@@ -581545,6 +581870,8 @@ ${this._completionCaveat}` : this._completionCaveat;
581545
581870
  }
581546
581871
  }
581547
581872
  try {
581873
+ if (!this.writesUserTaskArtifacts())
581874
+ throw "skip-user-task-consolidation";
581548
581875
  const extractPaths = (entries, toolNames) => {
581549
581876
  return [
581550
581877
  ...new Set(entries.filter((tc) => toolNames.includes(tc.name)).map((tc) => {
@@ -581655,8 +581982,11 @@ ${this._completionCaveat}` : this._completionCaveat;
581655
581982
  toolsUsed: consolidation.toolsUsed,
581656
581983
  toolCallLog,
581657
581984
  turns: consolidation.turns,
581658
- transcriptPath
581985
+ transcriptPath,
581986
+ artifactMode: this.options.artifactMode
581659
581987
  });
581988
+ if (!shouldPersistTaskHandoff(handoff))
581989
+ throw "skip-low-quality-handoff";
581660
581990
  writeTaskHandoff(omniusDir, handoff);
581661
581991
  appendBoundaryToLog(omniusDir, handoff);
581662
581992
  trimLog(omniusDir);
@@ -581669,7 +581999,7 @@ ${this._completionCaveat}` : this._completionCaveat;
581669
581999
  });
581670
582000
  } catch {
581671
582001
  }
581672
- if (this._reflectionBuffer && !completed) {
582002
+ if (this._reflectionBuffer && !completed && this.writesUserTaskArtifacts()) {
581673
582003
  try {
581674
582004
  const reflection = this._reflectionBuffer.addReflection({
581675
582005
  taskGoal: persistentTaskGoal,
@@ -581692,7 +582022,7 @@ ${this._completionCaveat}` : this._completionCaveat;
581692
582022
  } catch {
581693
582023
  }
581694
582024
  }
581695
- if (this._episodeStore) {
582025
+ if (this._episodeStore && this.writesUserTaskArtifacts()) {
581696
582026
  try {
581697
582027
  const taskSummaryContent = `Task "${persistentTaskGoal.slice(0, 200)}" ${completed ? "completed" : "ended"}: ${cleanForStorage(summary).slice(0, 300)}`;
581698
582028
  if (this._crlMemoryStore) {
@@ -582305,6 +582635,150 @@ ${marker}` : marker);
582305
582635
  // -------------------------------------------------------------------------
582306
582636
  // Output folding — keep head + tail, omit middle (preserves errors at end)
582307
582637
  // -------------------------------------------------------------------------
582638
+ isEditToolName(name10) {
582639
+ return name10 === "file_edit" || name10 === "file_patch" || name10 === "batch_edit";
582640
+ }
582641
+ extractPrimaryToolPath(args) {
582642
+ if (!args)
582643
+ return "";
582644
+ const direct = args["path"] ?? args["file"] ?? args["filePath"] ?? args["file_path"];
582645
+ if (typeof direct === "string" && direct.trim())
582646
+ return direct.trim();
582647
+ const edits = args["edits"];
582648
+ if (Array.isArray(edits)) {
582649
+ for (const edit of edits) {
582650
+ if (!edit || typeof edit !== "object")
582651
+ continue;
582652
+ const rec = edit;
582653
+ const editPath = rec["path"] ?? rec["file"] ?? rec["filePath"] ?? rec["file_path"];
582654
+ if (typeof editPath === "string" && editPath.trim())
582655
+ return editPath.trim();
582656
+ }
582657
+ }
582658
+ return "";
582659
+ }
582660
+ staleEditTarget(toolName, args) {
582661
+ if (!this.isEditToolName(toolName) || !args)
582662
+ return null;
582663
+ const path12 = this.extractPrimaryToolPath(args);
582664
+ const parts = [];
582665
+ const directKeys = [
582666
+ "old_string",
582667
+ "oldString",
582668
+ "oldText",
582669
+ "search",
582670
+ "expected_old_string",
582671
+ "expectedHash",
582672
+ "expected_hash",
582673
+ "start_line"
582674
+ ];
582675
+ for (const key of directKeys) {
582676
+ const value2 = args[key];
582677
+ if (typeof value2 === "string" || typeof value2 === "number") {
582678
+ parts.push(key + "=" + String(value2));
582679
+ }
582680
+ }
582681
+ const edits = args["edits"];
582682
+ if (Array.isArray(edits)) {
582683
+ for (const edit of edits.slice(0, 6)) {
582684
+ if (!edit || typeof edit !== "object")
582685
+ continue;
582686
+ const rec = edit;
582687
+ const oldValue = rec["old_string"] ?? rec["oldString"] ?? rec["oldText"] ?? rec["search"] ?? rec["expected_old_string"];
582688
+ const editPath = rec["path"] ?? rec["file"] ?? rec["filePath"] ?? rec["file_path"];
582689
+ if (typeof editPath === "string" || typeof oldValue === "string") {
582690
+ parts.push(String(editPath ?? path12) + "=" + String(oldValue ?? ""));
582691
+ }
582692
+ }
582693
+ }
582694
+ if (!path12 && parts.length === 0)
582695
+ return null;
582696
+ const normalized = parts.join("\n").replace(/\s+/g, " ").trim() || JSON.stringify(args).slice(0, 1e3);
582697
+ return {
582698
+ path: path12 || "(unknown)",
582699
+ targetHash: this.quickHash(normalized),
582700
+ preview: normalized.slice(0, 160)
582701
+ };
582702
+ }
582703
+ classifyStaleEditFailure(toolName, result) {
582704
+ if (!this.isEditToolName(toolName) || result.success)
582705
+ return null;
582706
+ const text2 = String((result.error ?? "") + "\n" + (result.output ?? "")).toLowerCase();
582707
+ if (/ambiguous|multiple occurrences|matches more than once/.test(text2))
582708
+ return "ambiguous_old_string";
582709
+ if (/expected[_ -]?hash|hash mismatch|stale hash|beforehash|afterhash/.test(text2))
582710
+ return "stale_expected_hash";
582711
+ if (/expected.*content|content.*did not match|context mismatch|patch failed|hunk failed/.test(text2))
582712
+ return "stale_expected_content";
582713
+ if (/atomic.*abort|batch.*abort|skipped/.test(text2) && toolName === "batch_edit")
582714
+ return "atomic_batch_abort";
582715
+ if (/old[_ -]?string|old text|old content|not found|no occurrences|0 occurrences|could not find/.test(text2))
582716
+ return "stale_old_string";
582717
+ return null;
582718
+ }
582719
+ staleEditFamilyKey(toolName, path12, errorKind, targetHash) {
582720
+ return toolName + ":" + path12 + ":" + errorKind + ":" + targetHash;
582721
+ }
582722
+ staleEditPreflightBlock(toolName, args) {
582723
+ const target = this.staleEditTarget(toolName, args);
582724
+ if (!target)
582725
+ return null;
582726
+ for (const entry of this._staleEditFamilies.values()) {
582727
+ if (entry.tool !== toolName || entry.path !== target.path || entry.targetHash !== target.targetHash)
582728
+ continue;
582729
+ const hasFreshRead = entry.lastReadTurn > entry.lastFailureTurn;
582730
+ const hasFreshMutation = entry.lastMutationTurn > entry.lastFailureTurn;
582731
+ if (entry.count >= 2 && !hasFreshRead && !hasFreshMutation) {
582732
+ return [
582733
+ "[STALE EDIT LOOP BLOCKED] " + toolName + " has already failed " + entry.count + " times for " + entry.path + " (" + entry.errorKind + ").",
582734
+ "Do not retry the same stale edit target again. First file_read the current file content once, then either:",
582735
+ "1. confirm the desired change is already present and run verification,",
582736
+ "2. build a new edit from the exact current text, or",
582737
+ "3. choose a different target if this edit is no longer relevant.",
582738
+ "Previous stale target preview: " + entry.preview
582739
+ ].join("\n");
582740
+ }
582741
+ }
582742
+ return null;
582743
+ }
582744
+ noteStaleEditGuardOutcome(toolName, args, result, turn) {
582745
+ const path12 = this.extractPrimaryToolPath(args);
582746
+ if (toolName === "file_read" && path12 && result.success) {
582747
+ for (const entry of this._staleEditFamilies.values()) {
582748
+ if (entry.path === path12)
582749
+ entry.lastReadTurn = turn;
582750
+ }
582751
+ return;
582752
+ }
582753
+ if (!this.isEditToolName(toolName))
582754
+ return;
582755
+ const target = this.staleEditTarget(toolName, args);
582756
+ if (!target)
582757
+ return;
582758
+ if (result.success && result.mutated !== false) {
582759
+ for (const [key2, entry] of this._staleEditFamilies) {
582760
+ if (entry.path === target.path)
582761
+ this._staleEditFamilies.delete(key2);
582762
+ }
582763
+ return;
582764
+ }
582765
+ const errorKind = this.classifyStaleEditFailure(toolName, result);
582766
+ if (!errorKind)
582767
+ return;
582768
+ const key = this.staleEditFamilyKey(toolName, target.path, errorKind, target.targetHash);
582769
+ const existing = this._staleEditFamilies.get(key);
582770
+ this._staleEditFamilies.set(key, {
582771
+ count: (existing?.count ?? 0) + 1,
582772
+ path: target.path,
582773
+ tool: toolName,
582774
+ errorKind,
582775
+ targetHash: target.targetHash,
582776
+ lastFailureTurn: turn,
582777
+ lastReadTurn: existing?.lastReadTurn ?? -1,
582778
+ lastMutationTurn: existing?.lastMutationTurn ?? -1,
582779
+ preview: target.preview
582780
+ });
582781
+ }
582308
582782
  /**
582309
582783
  * Quick non-cryptographic hash for Memex experience IDs.
582310
582784
  * Produces a short hex string (8 chars) from input.
@@ -583638,6 +584112,39 @@ ${trimmedNew}`;
583638
584112
  * Generates typed self-reflections on task failure and injects them
583639
584113
  * into the next attempt's context for active learning. */
583640
584114
  _reflectionBuffer = null;
584115
+ buildAdversaryToolOutcomeEvidence(toolName, toolArgs, content, succeeded) {
584116
+ const pathValue = toolArgs?.["path"] ?? toolArgs?.["file"] ?? toolArgs?.["filePath"] ?? toolArgs?.["file_path"];
584117
+ const path12 = typeof pathValue === "string" && pathValue.trim() ? pathValue.trim() : void 0;
584118
+ const compact3 = content.replace(/\s+/g, " ").trim();
584119
+ const snippet = compact3.slice(0, 160);
584120
+ const digest3 = _createHash("sha256").update(content).digest("hex").slice(0, 16);
584121
+ const lineCount = content.length > 0 ? content.split("\n").length : 0;
584122
+ if (toolName === "file_read") {
584123
+ const evidence = path12 ? `file_read confirmed path=${path12}; lines=${lineCount}; sha256=${digest3}` : `file_read confirmed content; lines=${lineCount}; sha256=${digest3}`;
584124
+ return {
584125
+ path: path12,
584126
+ evidence,
584127
+ preview: `${evidence}; content="${snippet}"`
584128
+ };
584129
+ }
584130
+ if (/^(file_write|file_edit|file_patch|batch_edit)$/.test(toolName)) {
584131
+ const evidence = path12 ? `${toolName} succeeded for path=${path12}; output_sha256=${digest3}` : `${toolName} succeeded; output_sha256=${digest3}`;
584132
+ return {
584133
+ path: path12,
584134
+ evidence,
584135
+ preview: `${evidence}; output="${snippet}"`
584136
+ };
584137
+ }
584138
+ if (toolName === "shell") {
584139
+ const command = typeof toolArgs?.["command"] === "string" ? String(toolArgs["command"]) : void 0;
584140
+ return {
584141
+ path: command,
584142
+ evidence: succeeded ? `shell exited successfully; stdout_sha256=${digest3}` : `shell failed; output_sha256=${digest3}`,
584143
+ preview: snippet || content.slice(0, 160)
584144
+ };
584145
+ }
584146
+ return { preview: snippet || content.slice(0, 160) };
584147
+ }
583641
584148
  /**
583642
584149
  * Adversary: post-turn meta-analysis.
583643
584150
  *
@@ -583651,29 +584158,10 @@ ${trimmedNew}`;
583651
584158
  */
583652
584159
  adversaryObserve(messages2, turn) {
583653
584160
  const recent = messages2.slice(-6);
583654
- if (this._adversaryStream) {
583655
- const lastAssistantMsg = [...recent].reverse().find((m2) => m2.role === "assistant" && typeof m2.content === "string");
583656
- const assistantText = typeof lastAssistantMsg?.content === "string" ? lastAssistantMsg.content.replace(/<think>[\s\S]*?<\/think>/g, "").trim() : "";
583657
- if (assistantText) {
583658
- this._adversaryStream.observe({
583659
- turn,
583660
- assistantText,
583661
- recentToolOutcomes: this._adversaryToolOutcomes.slice(-8).map((o2) => ({
583662
- tool: o2.tool,
583663
- succeeded: o2.succeeded,
583664
- preview: o2.preview
583665
- })),
583666
- claimsCompletion: /task.?complete|all tests pass|\bdone\b|\bcomplete(d)?\b/i.test(assistantText)
583667
- });
583668
- void this._adversaryStream.tick().catch(() => {
583669
- });
583670
- }
583671
- }
583672
584161
  for (const msg of recent) {
583673
584162
  if (msg.role === "tool" && typeof msg.content === "string") {
583674
584163
  const isError2 = msg.content.startsWith("Error:") || /^(FAIL|ERR!|TypeError)/i.test(msg.content);
583675
584164
  const succeeded = !isError2;
583676
- const preview = msg.content.slice(0, 80);
583677
584165
  let toolName = "unknown";
583678
584166
  let toolArgs;
583679
584167
  if (msg.tool_call_id) {
@@ -583700,6 +584188,7 @@ ${trimmedNew}`;
583700
584188
  return o2.turn === turn && o2.tool === toolName && o2.fingerprint === fingerprint;
583701
584189
  });
583702
584190
  if (!alreadySeen) {
584191
+ const outcomeEvidence = this.buildAdversaryToolOutcomeEvidence(toolName, toolArgs, msg.content, succeeded);
583703
584192
  this._adversaryToolOutcomes.push({
583704
584193
  turn,
583705
584194
  tool: toolName,
@@ -583707,13 +584196,34 @@ ${trimmedNew}`;
583707
584196
  argsKey,
583708
584197
  fingerprint,
583709
584198
  succeeded,
583710
- preview
584199
+ ...outcomeEvidence
583711
584200
  });
583712
584201
  }
583713
584202
  }
583714
584203
  }
583715
584204
  while (this._adversaryToolOutcomes.length > 20)
583716
584205
  this._adversaryToolOutcomes.shift();
584206
+ if (this._adversaryStream && !this._completionIncompleteVerification) {
584207
+ const lastAssistantMsg = [...recent].reverse().find((m2) => m2.role === "assistant" && typeof m2.content === "string");
584208
+ const assistantText = typeof lastAssistantMsg?.content === "string" ? lastAssistantMsg.content.replace(/<think>[\s\S]*?<\/think>/g, "").trim() : "";
584209
+ if (assistantText) {
584210
+ const claimsCompletion = /task.?complete|all tests pass|\bdone\b|\bcomplete(d)?\b/i.test(assistantText);
584211
+ this._adversaryStream.observe({
584212
+ turn,
584213
+ assistantText,
584214
+ recentToolOutcomes: this._adversaryToolOutcomes.slice(-8).map((o2) => ({
584215
+ tool: o2.tool,
584216
+ succeeded: o2.succeeded,
584217
+ preview: o2.preview,
584218
+ path: o2.path,
584219
+ evidence: o2.evidence
584220
+ })),
584221
+ claimsCompletion
584222
+ });
584223
+ void this._adversaryStream.tick().catch(() => {
584224
+ });
584225
+ }
584226
+ }
583717
584227
  for (const [key, val] of this._adversaryRecentFlags) {
583718
584228
  if (turn - val.lastTurn > _AgenticRunner.ADVERSARY_FLAG_TTL)
583719
584229
  this._adversaryRecentFlags.delete(key);
@@ -654414,6 +654924,7 @@ Call task_complete with the JSON array when done.`,
654414
654924
  const runner = new AgenticRunner(backend, {
654415
654925
  maxTurns: 5,
654416
654926
  // Evaluators are very focused — 5 turns max
654927
+ artifactMode: "internal",
654417
654928
  maxTokens: 4096,
654418
654929
  temperature: 0,
654419
654930
  // Deterministic scoring
@@ -656923,6 +657434,7 @@ var init_dmn_engine = __esm({
656923
657434
  const runner = new AgenticRunner(backend, {
656924
657435
  maxTurns: 15,
656925
657436
  // DMN is lightweight — don't burn too many turns
657437
+ artifactMode: "internal",
656926
657438
  maxTokens: 8192,
656927
657439
  temperature: 0.4,
656928
657440
  // Slightly creative for exploratory reasoning
@@ -657220,6 +657732,7 @@ If decision is GO, selectedTask MUST be a fully-populated object (NEVER null)
657220
657732
  const runner = new AgenticRunner(backend, {
657221
657733
  maxTurns: 8,
657222
657734
  // Brain regions are fast, focused
657735
+ artifactMode: "internal",
657223
657736
  maxTokens: 4096,
657224
657737
  temperature: role === "amygdala" ? 0.2 : role === "pfc_planner" ? 0.5 : 0.3,
657225
657738
  requestTimeoutMs: this.config.timeoutMs,
@@ -657806,6 +658319,7 @@ var init_emotion_engine = __esm({
657806
658319
  );
657807
658320
  const runner = new AgenticRunner(backend, {
657808
658321
  maxTurns: 1,
658322
+ artifactMode: "internal",
657809
658323
  maxTokens: 64,
657810
658324
  temperature: 0.9,
657811
658325
  // High temperature for creative expression
@@ -657889,6 +658403,7 @@ var init_emotion_engine = __esm({
657889
658403
  );
657890
658404
  const runner = new AgenticRunner(backend, {
657891
658405
  maxTurns: 3,
658406
+ artifactMode: "internal",
657892
658407
  maxTokens: 512,
657893
658408
  temperature: 0.35,
657894
658409
  requestTimeoutMs: 2e4,
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.365",
3
+ "version": "1.0.367",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.365",
9
+ "version": "1.0.367",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
@@ -430,9 +430,9 @@
430
430
  }
431
431
  },
432
432
  "node_modules/@helia/utils/node_modules/cborg": {
433
- "version": "5.1.4",
434
- "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.4.tgz",
435
- "integrity": "sha512-EDoD59RBV51H5ar6i29ut7AyOJi0BUIEhtbnJJac3qYcMG74Db6eVce/dIh+Wh6tVwBi7cRWDXmdms+fKPQvcQ==",
433
+ "version": "5.1.5",
434
+ "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.5.tgz",
435
+ "integrity": "sha512-1qJ/E8jF1dmJlBm6V1z91iWTWfCK9SuCxPDLod+Ne7CMCASOQh346b+487oFt/zoBQW+XS5wNvMgV+7gs5sJJA==",
436
436
  "license": "Apache-2.0",
437
437
  "bin": {
438
438
  "cborg": "lib/bin.js"
@@ -461,9 +461,9 @@
461
461
  }
462
462
  },
463
463
  "node_modules/@ipld/dag-cbor/node_modules/cborg": {
464
- "version": "5.1.4",
465
- "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.4.tgz",
466
- "integrity": "sha512-EDoD59RBV51H5ar6i29ut7AyOJi0BUIEhtbnJJac3qYcMG74Db6eVce/dIh+Wh6tVwBi7cRWDXmdms+fKPQvcQ==",
464
+ "version": "5.1.5",
465
+ "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.5.tgz",
466
+ "integrity": "sha512-1qJ/E8jF1dmJlBm6V1z91iWTWfCK9SuCxPDLod+Ne7CMCASOQh346b+487oFt/zoBQW+XS5wNvMgV+7gs5sJJA==",
467
467
  "license": "Apache-2.0",
468
468
  "bin": {
469
469
  "cborg": "lib/bin.js"
@@ -480,9 +480,9 @@
480
480
  }
481
481
  },
482
482
  "node_modules/@ipld/dag-json/node_modules/cborg": {
483
- "version": "5.1.4",
484
- "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.4.tgz",
485
- "integrity": "sha512-EDoD59RBV51H5ar6i29ut7AyOJi0BUIEhtbnJJac3qYcMG74Db6eVce/dIh+Wh6tVwBi7cRWDXmdms+fKPQvcQ==",
483
+ "version": "5.1.5",
484
+ "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.5.tgz",
485
+ "integrity": "sha512-1qJ/E8jF1dmJlBm6V1z91iWTWfCK9SuCxPDLod+Ne7CMCASOQh346b+487oFt/zoBQW+XS5wNvMgV+7gs5sJJA==",
486
486
  "license": "Apache-2.0",
487
487
  "bin": {
488
488
  "cborg": "lib/bin.js"
@@ -4293,9 +4293,9 @@
4293
4293
  }
4294
4294
  },
4295
4295
  "node_modules/ipns/node_modules/cborg": {
4296
- "version": "5.1.4",
4297
- "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.4.tgz",
4298
- "integrity": "sha512-EDoD59RBV51H5ar6i29ut7AyOJi0BUIEhtbnJJac3qYcMG74Db6eVce/dIh+Wh6tVwBi7cRWDXmdms+fKPQvcQ==",
4296
+ "version": "5.1.5",
4297
+ "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.5.tgz",
4298
+ "integrity": "sha512-1qJ/E8jF1dmJlBm6V1z91iWTWfCK9SuCxPDLod+Ne7CMCASOQh346b+487oFt/zoBQW+XS5wNvMgV+7gs5sJJA==",
4299
4299
  "license": "Apache-2.0",
4300
4300
  "bin": {
4301
4301
  "cborg": "lib/bin.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.365",
3
+ "version": "1.0.367",
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",