omnius 1.0.376 → 1.0.378

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
@@ -559711,13 +559711,6 @@ var init_completionLedger = __esm({
559711
559711
  // packages/orchestrator/dist/completionAutoFinalize.js
559712
559712
  function buildTruthBasedCompletion(input) {
559713
559713
  const maxAge = input.maxValidationAgeTurns ?? 8;
559714
- if (input.todos.length === 0) {
559715
- return { ready: false, reason: "no active todo tree" };
559716
- }
559717
- const open2 = input.todos.filter((todo) => todo.status !== "completed");
559718
- if (open2.length > 0) {
559719
- return { ready: false, reason: `${open2.length} open todo(s)` };
559720
- }
559721
559714
  if (input.verifyFailureCount > 0) {
559722
559715
  return {
559723
559716
  ready: false,
@@ -559735,6 +559728,33 @@ function buildTruthBasedCompletion(input) {
559735
559728
  };
559736
559729
  }
559737
559730
  const files = (input.filesEdited ?? []).filter((file) => file.path.trim().length > 0).slice(0, 12);
559731
+ if (input.todos.length === 0) {
559732
+ if (files.length === 0) {
559733
+ return { ready: false, reason: "no active todo tree or changed files" };
559734
+ }
559735
+ if (typeof input.lastMutationTurn === "number" && input.lastMutationTurn >= 0 && input.lastValidationTurn < input.lastMutationTurn) {
559736
+ return {
559737
+ ready: false,
559738
+ reason: "validation happened before the last mutation"
559739
+ };
559740
+ }
559741
+ const fileLines2 = files.map((file) => `- ${file.action ? `${file.action} ` : ""}${file.path}`).join("\n");
559742
+ const summary2 = [
559743
+ "Completed with direct task evidence.",
559744
+ fileLines2 ? `Files changed:
559745
+ ${fileLines2}` : null,
559746
+ `Validation passed after the last mutation: ${input.lastValidationCommand}`
559747
+ ].filter((line) => Boolean(line)).join("\n\n");
559748
+ return {
559749
+ ready: true,
559750
+ reason: `changed files validated ${age} turn(s) ago`,
559751
+ summary: summary2
559752
+ };
559753
+ }
559754
+ const open2 = input.todos.filter((todo) => todo.status !== "completed");
559755
+ if (open2.length > 0) {
559756
+ return { ready: false, reason: `${open2.length} open todo(s)` };
559757
+ }
559738
559758
  const todoLines = input.todos.slice(0, 12).map((todo) => {
559739
559759
  const id = todo.id ? `${todo.id}: ` : "";
559740
559760
  return `- ${id}${todo.content}`;
@@ -573462,6 +573482,9 @@ ${modelVisible}` : modelVisible || result.error || displayOutput || "";
573462
573482
  const realFileMutation = input.realFileMutation ?? this._isRealProjectMutation(input.toolName, input.result);
573463
573483
  const attemptedTargetPaths = this._extractToolTargetPaths(input.toolName, input.args, input.result);
573464
573484
  const realMutationPaths = input.realMutationPaths ?? (realFileMutation ? attemptedTargetPaths : []);
573485
+ if (this._shouldSuppressCompletionDiscoveryEvidence(input.toolName, input.result, attemptedTargetPaths)) {
573486
+ return;
573487
+ }
573465
573488
  this._completionLedger = recordToolEvidence(this._completionLedger, {
573466
573489
  name: input.toolName,
573467
573490
  success: input.result.success,
@@ -573483,6 +573506,14 @@ ${modelVisible}` : modelVisible || result.error || displayOutput || "";
573483
573506
  }
573484
573507
  this._saveCompletionLedgerSafe();
573485
573508
  }
573509
+ _shouldSuppressCompletionDiscoveryEvidence(toolName, result, targetPaths) {
573510
+ if (result.success !== true)
573511
+ return false;
573512
+ if (toolName === "file_read") {
573513
+ return targetPaths.length > 0 && targetPaths.some((path12) => this._evidenceLedger.hasFresh(path12));
573514
+ }
573515
+ return toolName === "list_directory" || toolName === "find_files" || toolName === "grep_search";
573516
+ }
573486
573517
  _isAtomicBatchEditAbort(toolName, result) {
573487
573518
  if (toolName !== "batch_edit" || !result || result.success !== false) {
573488
573519
  return false;
@@ -578285,6 +578316,7 @@ TASK: ${scrubbedTask}` : scrubbedTask;
578285
578316
  currentTurn: turn,
578286
578317
  lastValidationTurn: this._lastBuildSuccessTurn,
578287
578318
  lastValidationCommand: this._lastBuildSuccessCommand,
578319
+ lastMutationTurn: this._lastFileWriteTurn,
578288
578320
  verifyFailureCount: this._verifyFailures.size,
578289
578321
  filesEdited: [...this._taskState.modifiedFiles.entries()].map(([path12, action]) => ({ path: path12, action }))
578290
578322
  });
@@ -580568,6 +580600,43 @@ Use the saved fact to continue the promised synthesis or next concrete step, or
580568
580600
  systemGuidance: staleEditBlock
580569
580601
  };
580570
580602
  }
580603
+ const staleRewriteBlock = this.staleEditOverwritePreflightBlock(tc.name, tc.arguments ?? {});
580604
+ if (staleRewriteBlock) {
580605
+ this.emit({
580606
+ type: "tool_call",
580607
+ toolName: tc.name,
580608
+ toolArgs: tc.arguments,
580609
+ turn,
580610
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
580611
+ });
580612
+ this.emit({
580613
+ type: "tool_result",
580614
+ toolName: tc.name,
580615
+ success: false,
580616
+ content: staleRewriteBlock.slice(0, 120),
580617
+ turn,
580618
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
580619
+ });
580620
+ this._tagSyntheticFailure({
580621
+ mode: "step_repetition",
580622
+ rationale: "full-file overwrite attempted while a stale narrow-edit repair lock is active"
580623
+ });
580624
+ if (this._completionLedger) {
580625
+ this._completionLedger = recordToolEvidence(this._completionLedger, {
580626
+ name: tc.name,
580627
+ success: false,
580628
+ outputPreview: staleRewriteBlock.slice(0, 500),
580629
+ argsKey: tc.arguments ? JSON.stringify(tc.arguments).slice(0, 300) : ""
580630
+ });
580631
+ this._saveCompletionLedgerSafe();
580632
+ }
580633
+ return {
580634
+ tc,
580635
+ output: staleRewriteBlock,
580636
+ success: false,
580637
+ systemGuidance: staleRewriteBlock
580638
+ };
580639
+ }
580571
580640
  const baseIsReadLike = ![
580572
580641
  "file_write",
580573
580642
  "file_edit",
@@ -581517,8 +581586,10 @@ Respond with EXACTLY this structure before your next tool call:
581517
581586
  if (tc.name === "shell") {
581518
581587
  const _shellCmd2 = String(tc.arguments?.["command"] ?? tc.arguments?.["cmd"] ?? "");
581519
581588
  const _declaredVerify = this._matchedDeclaredVerifyCommand(_shellCmd2);
581589
+ const _lastVerifier = this._lastVerifierResult;
581590
+ const _noTodoDirectValidation = !_declaredVerify && (this.readSessionTodos() || []).length === 0 && this._taskState.modifiedFiles.size > 0 && _lastVerifier?.outcomeClass === "verified";
581520
581591
  const _legacyGenericValidation = process.env["OMNIUS_ENABLE_GENERIC_COMPLETION_COMMAND_HEURISTIC"] === "1" && /\b(build|test|run\b|start\b|serve\b|verify|check)\b/i.test(_shellCmd2);
581521
- if (_declaredVerify || _legacyGenericValidation) {
581592
+ if (_declaredVerify || _noTodoDirectValidation || _legacyGenericValidation) {
581522
581593
  this._lastBuildSuccessTurn = turn;
581523
581594
  this._lastBuildSuccessCommand = (_declaredVerify || _shellCmd2).slice(0, 200);
581524
581595
  this._truthAutoCompleteBlockedValidationTurn = -1;
@@ -582409,7 +582480,7 @@ Then use file_read on individual FILES inside it.`);
582409
582480
  handledIds.add(matchTc.id);
582410
582481
  const output = sr.result.success ? sr.result.output : `Error: ${sr.result.error || "unknown"}
582411
582482
  ${sr.result.output}`;
582412
- messages2.push(this.buildToolMessage(output, matchTc.id, matchTc.name));
582483
+ messages2.push(this.buildModelFacingToolMessage(output, matchTc.id, matchTc.name, matchTc.arguments, sr.result.success));
582413
582484
  if (matchTc.name === "task_complete") {
582414
582485
  if (!sr.result.success) {
582415
582486
  messages2.push({
@@ -582477,7 +582548,7 @@ ${sr.result.output}`;
582477
582548
  break;
582478
582549
  const r2 = await executeSingle(tc);
582479
582550
  if (r2) {
582480
- messages2.push(this.buildToolMessage(r2.output, r2.tc.id, r2.tc.name));
582551
+ messages2.push(this.buildModelFacingToolMessage(r2.output, r2.tc.id, r2.tc.name, r2.tc.arguments, r2.success));
582481
582552
  if (r2.systemGuidance) {
582482
582553
  messages2.push({
582483
582554
  role: "system",
@@ -582588,7 +582659,7 @@ ${sr.result.output}`;
582588
582659
  }, 5);
582589
582660
  for (const r2 of results) {
582590
582661
  if (r2) {
582591
- messages2.push(this.buildToolMessage(r2.output, r2.tc.id, r2.tc.name));
582662
+ messages2.push(this.buildModelFacingToolMessage(r2.output, r2.tc.id, r2.tc.name, r2.tc.arguments, r2.success));
582592
582663
  if (r2.systemGuidance) {
582593
582664
  messages2.push({
582594
582665
  role: "system",
@@ -583481,7 +583552,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
583481
583552
  } else {
583482
583553
  this._consecutiveEnoent = 0;
583483
583554
  }
583484
- const toolMsg = this.buildToolMessage(output, tc.id, tc.name);
583555
+ const toolMsg = this.buildModelFacingToolMessage(output, tc.id, tc.name, tc.arguments, result.success);
583485
583556
  messages2.push(toolMsg);
583486
583557
  if (tc.name === "task_complete") {
583487
583558
  if (!result.success) {
@@ -583630,6 +583701,60 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
583630
583701
  }
583631
583702
  }
583632
583703
  }
583704
+ if (!completed && !this._completionIncompleteVerification && process.env["OMNIUS_DISABLE_TRUTH_AUTOCOMPLETE"] !== "1") {
583705
+ try {
583706
+ const _finalTurn = Math.max(this._lastBuildSuccessTurn, this._lastFileWriteTurn, toolCallLog.at(-1)?.turn ?? -1, 0);
583707
+ const _todos = this.readSessionTodos() || [];
583708
+ const _truthCompletion = buildTruthBasedCompletion({
583709
+ todos: _todos,
583710
+ currentTurn: _finalTurn,
583711
+ lastValidationTurn: this._lastBuildSuccessTurn,
583712
+ lastValidationCommand: this._lastBuildSuccessCommand,
583713
+ lastMutationTurn: this._lastFileWriteTurn,
583714
+ verifyFailureCount: this._verifyFailures.size,
583715
+ filesEdited: [...this._taskState.modifiedFiles.entries()].map(([path12, action]) => ({ path: path12, action }))
583716
+ });
583717
+ if (_truthCompletion.ready && this._truthAutoCompleteBlockedValidationTurn !== this._lastBuildSuccessTurn) {
583718
+ const _summary = _truthCompletion.summary || "Completed.";
583719
+ const _args = { summary: _summary };
583720
+ if (!holdTaskCompleteGates(_args, _finalTurn)) {
583721
+ const _bpFinalTruth = await this._runBackwardPassReview(_finalTurn, toolCallLog, _summary);
583722
+ if (!_bpFinalTruth || _bpFinalTruth.proceed) {
583723
+ completed = true;
583724
+ summary = _summary;
583725
+ this.emit({
583726
+ type: "status",
583727
+ content: `REG-31: run-end truth-based completion synthesized (${_truthCompletion.reason})`,
583728
+ turn: _finalTurn,
583729
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
583730
+ });
583731
+ this._onTypedEvent?.({
583732
+ type: "completion_requested",
583733
+ runId: this._sessionId ?? "unknown",
583734
+ summary: summary.slice(0, 500),
583735
+ sourcePath: "direct",
583736
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
583737
+ });
583738
+ if (summary && !this._assistantTextEmitted) {
583739
+ this.emit({
583740
+ type: "assistant_text",
583741
+ content: summary,
583742
+ source: "task_complete_summary",
583743
+ turn: _finalTurn,
583744
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
583745
+ });
583746
+ this._assistantTextEmitted = true;
583747
+ }
583748
+ } else if (_bpFinalTruth.feedback) {
583749
+ emitBackwardPassAdvisory(_bpFinalTruth.feedback, _finalTurn);
583750
+ }
583751
+ } else {
583752
+ this._truthAutoCompleteBlockedValidationTurn = this._lastBuildSuccessTurn;
583753
+ }
583754
+ }
583755
+ } catch {
583756
+ }
583757
+ }
583633
583758
  const durationMs = Date.now() - start2;
583634
583759
  const incompleteVerification = this._completionIncompleteVerification;
583635
583760
  if (incompleteVerification && !summary) {
@@ -584460,6 +584585,75 @@ ${marker}` : marker);
584460
584585
  }
584461
584586
  return { role: "tool", content: messageContent, tool_call_id: toolCallId };
584462
584587
  }
584588
+ buildModelFacingToolMessage(output, toolCallId, toolName, args, success) {
584589
+ return this.buildToolMessage(this.compactDiscoveryOutputForModel(toolName, args, output, success), toolCallId, toolName);
584590
+ }
584591
+ compactDiscoveryOutputForModel(toolName, args, output, success) {
584592
+ if (success !== true)
584593
+ return output;
584594
+ if (this.shouldBypassDiscoveryCompaction(output))
584595
+ return output;
584596
+ const displayOutput = this.unwrapToolOutputForDisplay(output);
584597
+ if (toolName === "file_read") {
584598
+ const path13 = this.extractPrimaryToolPath(args);
584599
+ if (!path13 || !this._evidenceLedger.hasFresh(path13))
584600
+ return output;
584601
+ const entry = this._evidenceLedger.get(path13);
584602
+ return this.wrapToolOutputForModel(toolName, [
584603
+ "[DISCOVERY COMPACTED - file_read evidence captured]",
584604
+ `path=${path13}`,
584605
+ `captured=${this.countTextLines(displayOutput)} lines, ${displayOutput.length} chars${entry ? `, fidelity=${entry.fidelity}` : ""}`,
584606
+ 'active_context="Evidence already gathered this run"',
584607
+ "Use the active evidence frame. Re-read only if that frame marks this file STALE or you need a distinct range."
584608
+ ].join("\n"));
584609
+ }
584610
+ const previewSpec = toolName === "list_directory" ? { label: "directory listing", maxLines: 40, maxChars: 2400 } : toolName === "find_files" ? { label: "file discovery", maxLines: 60, maxChars: 3e3 } : toolName === "grep_search" ? { label: "search matches", maxLines: 40, maxChars: 3e3 } : null;
584611
+ if (!previewSpec)
584612
+ return output;
584613
+ const path12 = this.extractPrimaryToolPath(args);
584614
+ const preview = this.boundedDiscoveryPreview(displayOutput, previewSpec.maxLines, previewSpec.maxChars);
584615
+ return this.wrapToolOutputForModel(toolName, [
584616
+ `[DISCOVERY BOUNDED - ${previewSpec.label}]`,
584617
+ path12 ? `path=${path12}` : "",
584618
+ `captured=${this.countTextLines(displayOutput)} lines, ${displayOutput.length} chars`,
584619
+ `preview_lines=${preview.keptLines}/${preview.totalLines}`,
584620
+ "Keep these discovered candidates in mind; repeat this discovery only if the underlying filesystem/search scope has changed.",
584621
+ "",
584622
+ preview.text
584623
+ ].filter(Boolean).join("\n"));
584624
+ }
584625
+ shouldBypassDiscoveryCompaction(output) {
584626
+ return output.includes("[IMAGE_BASE64:") || output.includes("[BRANCH-EXTRACT]") || output.includes("[STOP RE-READING") || output.includes("[Tool output truncated") || output.includes(TRIAGE_ENVELOPE_MARKER);
584627
+ }
584628
+ countTextLines(text2) {
584629
+ if (!text2)
584630
+ return 0;
584631
+ return text2.split("\n").length;
584632
+ }
584633
+ boundedDiscoveryPreview(text2, maxLines, maxChars) {
584634
+ const lines = text2.split("\n");
584635
+ const kept = [];
584636
+ let used = 0;
584637
+ for (const line of lines) {
584638
+ if (kept.length >= maxLines)
584639
+ break;
584640
+ const next = line.slice(0, Math.max(0, maxChars - used));
584641
+ if (next.length === 0 && line.length > 0)
584642
+ break;
584643
+ kept.push(next);
584644
+ used += next.length + 1;
584645
+ if (used >= maxChars)
584646
+ break;
584647
+ }
584648
+ if (kept.length < lines.length) {
584649
+ kept.push(`[... ${lines.length - kept.length} additional line(s) compacted ...]`);
584650
+ }
584651
+ return {
584652
+ text: kept.join("\n"),
584653
+ totalLines: lines.length,
584654
+ keptLines: Math.min(kept.length, lines.length)
584655
+ };
584656
+ }
584463
584657
  // -------------------------------------------------------------------------
584464
584658
  // Output folding — keep head + tail, omit middle (preserves errors at end)
584465
584659
  // -------------------------------------------------------------------------
@@ -584544,15 +584738,32 @@ ${marker}` : marker);
584544
584738
  return "stale_old_string";
584545
584739
  return null;
584546
584740
  }
584547
- staleEditFamilyKey(toolName, path12, errorKind, targetHash) {
584548
- return toolName + ":" + path12 + ":" + errorKind + ":" + targetHash;
584741
+ staleEditPathKey(path12) {
584742
+ const trimmed = path12.trim();
584743
+ if (!trimmed)
584744
+ return "";
584745
+ try {
584746
+ return _pathResolve(this._workingDirectory || process.cwd(), trimmed).replace(/\\/g, "/");
584747
+ } catch {
584748
+ return trimmed.replace(/\\/g, "/").replace(/^\.\/+/, "");
584749
+ }
584750
+ }
584751
+ staleEditFamilyKey(toolName, pathKey, errorKind, targetHash, latestFileHash) {
584752
+ return [
584753
+ toolName,
584754
+ pathKey || "(unknown)",
584755
+ errorKind,
584756
+ targetHash,
584757
+ latestFileHash || "unknown-file-hash"
584758
+ ].join(":");
584549
584759
  }
584550
584760
  staleEditPreflightBlock(toolName, args) {
584551
584761
  const target = this.staleEditTarget(toolName, args);
584552
584762
  if (!target)
584553
584763
  return null;
584764
+ const pathKey = this.staleEditPathKey(target.path);
584554
584765
  for (const entry of this._staleEditFamilies.values()) {
584555
- if (entry.tool !== toolName || entry.path !== target.path || entry.targetHash !== target.targetHash)
584766
+ if (entry.tool !== toolName || entry.pathKey !== pathKey || entry.targetHash !== target.targetHash)
584556
584767
  continue;
584557
584768
  const hasFreshRead = entry.lastReadTurn > entry.lastFailureTurn;
584558
584769
  const hasFreshMutation = entry.lastMutationTurn > entry.lastFailureTurn;
@@ -584569,23 +584780,65 @@ ${marker}` : marker);
584569
584780
  }
584570
584781
  return null;
584571
584782
  }
584783
+ staleEditOverwritePreflightBlock(toolName, args) {
584784
+ if (toolName !== "file_write")
584785
+ return null;
584786
+ if (process.env["OMNIUS_ALLOW_STALE_REPAIR_OVERWRITE"] === "1")
584787
+ return null;
584788
+ if (this.options.modelTier !== "small" && this.options.modelTier !== "medium")
584789
+ return null;
584790
+ if (args?.["dry_run"] === true || args?.["dryRun"] === true)
584791
+ return null;
584792
+ const path12 = this.extractPrimaryToolPath(args);
584793
+ if (!path12)
584794
+ return null;
584795
+ const pathKey = this.staleEditPathKey(path12);
584796
+ const active = [...this._staleEditFamilies.values()].filter((entry) => entry.pathKey === pathKey).sort((a2, b) => b.lastFailureTurn - a2.lastFailureTurn).find((entry) => {
584797
+ const hasFreshRead = entry.lastReadTurn > entry.lastFailureTurn;
584798
+ const hasFreshMutation = entry.lastMutationTurn > entry.lastFailureTurn;
584799
+ return !hasFreshMutation && (entry.count >= 2 || !hasFreshRead);
584800
+ });
584801
+ if (!active)
584802
+ return null;
584803
+ return [
584804
+ `[EDIT REPAIR LOCK] A recent narrow edit to ${active.path} failed because the model-visible target diverged from disk (${active.errorKind}; latest_file_hash=${active.latestFileHash || "unknown"}).`,
584805
+ `This full-file overwrite was NOT executed. A stale narrow edit must not be repaired by broad file regeneration on ${this.options.modelTier ?? "unknown"} tier models.`,
584806
+ ``,
584807
+ `Allowed next actions:`,
584808
+ `1. file_read ${active.path} once and construct file_edit from exact current text.`,
584809
+ `2. file_patch/file_edit against the latest file hash or a different target.`,
584810
+ `3. file_write with dry_run=true only to validate a full rewrite proposal without changing disk.`,
584811
+ `4. run verification if the desired change is already present, or report the explicit blocker instead of completing.`,
584812
+ ``,
584813
+ `Stale target preview: ${active.preview}`
584814
+ ].join("\n");
584815
+ }
584572
584816
  noteStaleEditGuardOutcome(toolName, args, result, turn) {
584573
584817
  const path12 = this.extractPrimaryToolPath(args);
584818
+ const pathKey = path12 ? this.staleEditPathKey(path12) : "";
584574
584819
  if (toolName === "file_read" && path12 && result.success) {
584575
584820
  for (const entry of this._staleEditFamilies.values()) {
584576
- if (entry.path === path12)
584821
+ if (entry.pathKey === pathKey)
584577
584822
  entry.lastReadTurn = turn;
584578
584823
  }
584579
584824
  return;
584580
584825
  }
584826
+ if (toolName === "file_write" && path12 && result.success && result.mutated !== false) {
584827
+ for (const [key2, entry] of this._staleEditFamilies) {
584828
+ if (entry.pathKey === pathKey)
584829
+ this._staleEditFamilies.delete(key2);
584830
+ }
584831
+ return;
584832
+ }
584581
584833
  if (!this.isEditToolName(toolName))
584582
584834
  return;
584583
584835
  const target = this.staleEditTarget(toolName, args);
584584
584836
  if (!target)
584585
584837
  return;
584838
+ const targetPathKey = this.staleEditPathKey(target.path);
584586
584839
  if (result.success && result.mutated !== false) {
584587
584840
  for (const [key2, entry] of this._staleEditFamilies) {
584588
- if (entry.path === target.path)
584841
+ if (entry.pathKey === targetPathKey)
584589
584842
  this._staleEditFamilies.delete(key2);
584590
584843
  }
584591
584844
  return;
@@ -584593,14 +584846,17 @@ ${marker}` : marker);
584593
584846
  const errorKind = this.classifyStaleEditFailure(toolName, result);
584594
584847
  if (!errorKind)
584595
584848
  return;
584596
- const key = this.staleEditFamilyKey(toolName, target.path, errorKind, target.targetHash);
584849
+ const latestFileHash = typeof result.beforeHash === "string" && result.beforeHash.trim() ? result.beforeHash.trim() : typeof result.afterHash === "string" && result.afterHash.trim() ? result.afterHash.trim() : "unknown-file-hash";
584850
+ const key = this.staleEditFamilyKey(toolName, targetPathKey, errorKind, target.targetHash, latestFileHash);
584597
584851
  const existing = this._staleEditFamilies.get(key);
584598
584852
  this._staleEditFamilies.set(key, {
584599
584853
  count: (existing?.count ?? 0) + 1,
584600
584854
  path: target.path,
584855
+ pathKey: targetPathKey,
584601
584856
  tool: toolName,
584602
584857
  errorKind,
584603
584858
  targetHash: target.targetHash,
584859
+ latestFileHash,
584604
584860
  lastFailureTurn: turn,
584605
584861
  lastReadTurn: existing?.lastReadTurn ?? -1,
584606
584862
  lastMutationTurn: existing?.lastMutationTurn ?? -1,
@@ -652150,7 +652406,7 @@ function getModelTier(modelName) {
652150
652406
  if (sizeMatch) {
652151
652407
  const size = parseInt(sizeMatch[1], 10);
652152
652408
  if (size >= 30) return "large";
652153
- if (size >= 8) return "medium";
652409
+ if (size >= 14) return "medium";
652154
652410
  return "small";
652155
652411
  }
652156
652412
  if (/\b(small|mini|nano|tiny)\b/.test(m2)) return "small";
@@ -725784,6 +726040,7 @@ async function runCommand2(opts, config) {
725784
726040
  await runJson(opts.task, mergedConfig, opts.repoPath);
725785
726041
  } else {
725786
726042
  await runWithTUI(opts.task, mergedConfig, opts.repoPath);
726043
+ if (shouldForceSingleRunExit()) process.exit(0);
725787
726044
  }
725788
726045
  } else {
725789
726046
  await startInteractive(mergedConfig, opts.repoPath);
@@ -725883,6 +726140,12 @@ function shouldForceJsonExit() {
725883
726140
  return false;
725884
726141
  return true;
725885
726142
  }
726143
+ function shouldForceSingleRunExit() {
726144
+ if (process.env["OMNIUS_SINGLE_RUN_NO_FORCE_EXIT"] === "1") return false;
726145
+ if (process.env["VITEST"] === "true" || process.env["NODE_ENV"] === "test")
726146
+ return false;
726147
+ return true;
726148
+ }
725886
726149
  function extractSummary(captured) {
725887
726150
  const all2 = captured.join("");
725888
726151
  const match = all2.match(/task_complete.*?summary[:\s]*["']?([^"'\n]+)/i);
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.376",
3
+ "version": "1.0.378",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.376",
9
+ "version": "1.0.378",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.376",
3
+ "version": "1.0.378",
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",