omnius 1.0.557 → 1.0.558

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
@@ -14857,14 +14857,14 @@ var init_file_edit = __esm({
14857
14857
  },
14858
14858
  expected_hash: {
14859
14859
  type: "string",
14860
- description: "SHA-256 from the most recent file_read for this file. The runner refuses unverified exact replacements that omit or mismatch this hash."
14860
+ description: "Optional SHA-256 from file_read. When present, the edit is compare-and-swap protected against concurrent file changes; otherwise old_string must match current file text exactly."
14861
14861
  },
14862
14862
  dry_run: {
14863
14863
  type: "boolean",
14864
14864
  description: "Validate the edit and preview the diff without modifying disk."
14865
14865
  }
14866
14866
  },
14867
- required: ["path", "expected_hash"],
14867
+ required: ["path"],
14868
14868
  allOf: [
14869
14869
  { anyOf: [{ required: ["old_string"] }, { required: ["old_string_base64"] }] },
14870
14870
  { anyOf: [{ required: ["new_string"] }, { required: ["new_string_base64"] }] }
@@ -29478,10 +29478,10 @@ var init_batch_edit = __esm({
29478
29478
  },
29479
29479
  expected_hash: {
29480
29480
  type: "string",
29481
- description: "SHA-256 from the most recent file_read for this file. All edits for a file must use the same verified hash."
29481
+ description: "Optional SHA-256 from file_read. When supplied, all edits for a file must use the same value and the atomic batch checks it before writing."
29482
29482
  }
29483
29483
  },
29484
- required: ["path", "expected_hash"],
29484
+ required: ["path"],
29485
29485
  allOf: [
29486
29486
  { anyOf: [{ required: ["old_string"] }, { required: ["old_string_base64"] }] },
29487
29487
  { anyOf: [{ required: ["new_string"] }, { required: ["new_string_base64"] }] }
@@ -579380,9 +579380,9 @@ var init_evidenceLedger = __esm({
579380
579380
  const { path: path16, content, range, fileVersion, turn } = input;
579381
579381
  if (!path16 || !content)
579382
579382
  return;
579383
- const built = buildExtract(content);
579384
- if (input.fidelity)
579385
- built.fidelity = input.fidelity;
579383
+ const built = input.fidelity === "full" ? { text: content, fidelity: "full" } : buildExtract(content);
579384
+ if (input.fidelity === "extract")
579385
+ built.fidelity = "extract";
579386
579386
  const existing = this.entries.get(path16);
579387
579387
  if (existing && existing.readVersion === fileVersion && !existing.stale) {
579388
579388
  const keepNew = input.fidelity === "extract" || built.text.length >= existing.content.length;
@@ -580968,7 +580968,7 @@ ${input.error}`;
580968
580968
  diagnoses.add("tool-failure");
580969
580969
  if (input.failureKind)
580970
580970
  diagnoses.add(input.failureKind);
580971
- if (out.includes("[FOCUS SUPERVISOR BLOCK]")) {
580971
+ if (!input.success && out.includes("[FOCUS SUPERVISOR BLOCK]")) {
580972
580972
  diagnoses.add("focus-supervisor-block");
580973
580973
  }
580974
580974
  if (input.toolName === "task_status" && /Task not found/i.test(out)) {
@@ -584760,12 +584760,12 @@ var init_completion_resolution_verifier = __esm({
584760
584760
  import { createHash as createHash33 } from "node:crypto";
584761
584761
  function buildBranchExtractionBrief(input) {
584762
584762
  const path16 = cleanBriefText(input.path, 320) || "the requested file";
584763
- const intent = firstBriefText([
584763
+ const intent = fileLocalDiscoveryQuestion(firstBriefText([
584764
584764
  input.assistantIntent,
584765
584765
  input.trajectoryNextAction,
584766
584766
  input.currentStep
584767
- ]);
584768
- const openQuestion = cleanBriefText(input.trajectoryOpenQuestion, 280);
584767
+ ]), path16);
584768
+ const openQuestion = fileLocalDiscoveryQuestion(cleanBriefText(input.trajectoryOpenQuestion, 280), path16);
584769
584769
  const focus = openQuestion || intent;
584770
584770
  const goalAnchor = cleanBriefText(input.goalAnchor || input.currentStep || input.trajectoryAssessment || intent, 320);
584771
584771
  const request = openQuestion ? `Determine the exact file-local facts in ${path16} that answer this unresolved agent question: ${openQuestion}` : intent ? `Identify the exact file-local facts in ${path16} that the active agent needs before it can ${asActionClause(intent)}.` : `Identify the exact declarations, behavior, and configuration in ${path16} needed to choose the next narrow action.`;
@@ -584779,11 +584779,12 @@ function buildBranchExtractionBrief(input) {
584779
584779
  input.recentFailure ? `Recent unresolved evidence: ${cleanBriefText(input.recentFailure, 320)}` : ""
584780
584780
  ]);
584781
584781
  const returnContract = focus ? `Return only the exact declarations, values, behavior, and line spans that resolve: ${focus}` : "Return only the exact declarations, values, behavior, and line spans needed for the next safe action.";
584782
+ const relatedFailure = fileLocalFailureForPath(input.recentFailure, path16);
584782
584783
  const requirementQuestions = uniqueBriefLines([
584783
584784
  openQuestion,
584784
584785
  intent,
584785
- input.currentStep && input.currentStep !== intent ? input.currentStep : "",
584786
- input.recentFailure ? `Which file-local declaration, value, or behavior explains this unresolved failure: ${cleanBriefText(input.recentFailure, 260)}` : ""
584786
+ input.currentStep && input.currentStep !== intent ? fileLocalDiscoveryQuestion(input.currentStep, path16) : "",
584787
+ relatedFailure ? `Which file-local declaration, value, or behavior explains this unresolved failure: ${relatedFailure}` : ""
584787
584788
  ]).slice(0, 3);
584788
584789
  if (requirementQuestions.length === 0) {
584789
584790
  requirementQuestions.push(`Which declarations, values, and behavior in this file are required for the next narrow action?`);
@@ -584879,6 +584880,28 @@ function uniqueBriefLines(values) {
584879
584880
  function asActionClause(value2) {
584880
584881
  return cleanBriefText(value2, 320).replace(/^to\s+/i, "").replace(/[.?!]+$/, "").replace(/^([A-Z])/, (match) => match.toLowerCase());
584881
584882
  }
584883
+ function fileLocalDiscoveryQuestion(value2, path16) {
584884
+ const clean5 = cleanBriefText(value2, 320);
584885
+ if (!clean5)
584886
+ return "";
584887
+ if (/^(?:exploring|editing|reading|verifying|current|next(?:_valid)?_action)\s*:/i.test(clean5) || /\b(?:controller state|branch-extract|active context frame|file_read block|runtime repair|recovery required)\b/i.test(clean5)) {
584888
+ return "";
584889
+ }
584890
+ const referencedPaths = clean5.match(/[\w./-]+\.(?:[cm]?[jt]sx?|py|cpp|cxx|h(?:pp)?|md|json|yaml|yml)/g) ?? [];
584891
+ const targetBase = path16.split("/").pop() ?? path16;
584892
+ if (referencedPaths.length > 0 && !referencedPaths.some((candidate) => candidate === targetBase || path16.endsWith(candidate))) {
584893
+ return "";
584894
+ }
584895
+ return clean5;
584896
+ }
584897
+ function fileLocalFailureForPath(value2, path16) {
584898
+ const clean5 = fileLocalDiscoveryQuestion(value2, path16);
584899
+ if (!clean5)
584900
+ return "";
584901
+ const targetBase = path16.split("/").pop() ?? path16;
584902
+ const mentionsTarget = clean5.includes(targetBase) || clean5.includes(path16);
584903
+ return mentionsTarget || !/[\w./-]+\.(?:[cm]?[jt]sx?|py|cpp|cxx|h(?:pp)?)/.test(clean5) ? clean5 : "";
584904
+ }
584882
584905
  function selectWindows(lines, terms2) {
584883
584906
  const matched = [];
584884
584907
  for (let i2 = 0; i2 < lines.length; i2++) {
@@ -589379,9 +589402,6 @@ var init_agenticRunner = __esm({
589379
589402
  _branchEvidenceCache = /* @__PURE__ */ new Map();
589380
589403
  /** Latest curated node per canonical path for safe post-compaction recovery. */
589381
589404
  _branchEvidenceByPath = /* @__PURE__ */ new Map();
589382
- /** Exact read fingerprints resolved from canonical evidence, not a fresh tool call. */
589383
- _resolvedReadEvidence = /* @__PURE__ */ new Map();
589384
- _deterministicNarrowReadFallbacks = /* @__PURE__ */ new Set();
589385
589405
  // OBS-1: durable "current observed state" for non-file_read tool outputs
589386
589406
  // (shell/web_fetch/list_directory/…). EvidenceLedger's counterpart for the
589387
589407
  // observation channels that were previously invisible after compaction —
@@ -592686,21 +592706,13 @@ ${extras.join("\n")}`;
592686
592706
  });
592687
592707
  }
592688
592708
  /**
592689
- * Very small local models benefit from forced next-action rails when they
592690
- * become lost. Medium and large models need room to investigate, compare
592691
- * hypotheses, and choose a verifier appropriate to new evidence. Safety,
592692
- * steering, and evidence-before-mutation remain universal; only controller
592693
- * action coercion is tier-gated here. An operator can override for a model
592694
- * whose observed behavior differs from its nominal tier.
592709
+ * Action rails are an explicitly opt-in diagnostic experiment, never a
592710
+ * normal-model policy. They created deadlocks by denying the very reads and
592711
+ * edits needed to revise a hypothesis. Evidence and the tools' own atomic
592712
+ * checks remain available without a controller admission gate.
592695
592713
  */
592696
592714
  _enforcesStrictActionBoundaries() {
592697
- const tier = this.options.modelTier ?? "large";
592698
- if (tier !== "small")
592699
- return false;
592700
- const override = process.env["OMNIUS_STRICT_ACTION_BOUNDARIES"];
592701
- if (override === "0")
592702
- return false;
592703
- return true;
592715
+ return process.env["OMNIUS_ENABLE_EXPERIMENTAL_ACTION_GATES"] === "1";
592704
592716
  }
592705
592717
  /** Consecutive preflight blocks before the gate yields instead of blocking. */
592706
592718
  static COMPILE_FIX_GATE_YIELD_AFTER = 3;
@@ -593184,6 +593196,8 @@ ${result.output ?? ""}`;
593184
593196
  return openTodoLeaves(todos);
593185
593197
  }
593186
593198
  _todoExpansionRequiredBlocker(toolName) {
593199
+ if (!this._enforcesStrictActionBoundaries())
593200
+ return null;
593187
593201
  if (!this._todoWriteAvailable())
593188
593202
  return null;
593189
593203
  if (toolName === "todo_write" || toolName === "todo_read")
@@ -597814,57 +597828,28 @@ ${notice}`;
597814
597828
  }
597815
597829
  }
597816
597830
  _canonicalReadEvidencePayload(canonicalPath, contentHash2) {
597831
+ const evidence = this._evidenceLedger.get(canonicalPath);
597832
+ if (evidence && !evidence.stale && evidence.contentHash === contentHash2 && evidence.fidelity === "full" && this._mustHonorExplicitFullFileRead(Buffer.byteLength(evidence.content, "utf8"), evidence.content.split("\n").length, this._branchRoutingContextWindow())) {
597833
+ return evidence.content;
597834
+ }
597817
597835
  const branch = this._branchEvidenceByPath.get(canonicalPath);
597818
- if (branch && branch.contentHash === contentHash2 && branch.taskEpoch === this._taskEpoch) {
597836
+ if (branch && branch.contentHash === contentHash2 && branch.taskEpoch === this._taskEpoch && branch.contractComplete) {
597819
597837
  return branch.output;
597820
597838
  }
597821
597839
  return null;
597822
597840
  }
597823
597841
  _rehydrateResolvedReadEvidence(input) {
597824
- const previous = this._resolvedReadEvidence.get(input.fingerprint);
597825
- const handle2 = previous?.handle ?? `evidence:${input.canonicalPath}:${input.contentHash.slice(0, 16)}`;
597826
- this._resolvedReadEvidence.set(input.fingerprint, {
597827
- state: "resolved_from_cache",
597828
- handle: handle2,
597829
- path: input.canonicalPath,
597830
- contentHash: input.contentHash,
597831
- resolvedTurn: input.turn,
597832
- consumed: false
597833
- });
597834
597842
  return [
597835
597843
  "[REHYDRATED_FILE_EVIDENCE]",
597836
- `handle=${handle2}`,
597837
- "fingerprint_state=resolved_from_cache",
597838
597844
  `path=${input.canonicalPath}`,
597845
+ "source=canonical_branch_cache",
597839
597846
  `sha256=${input.contentHash}`,
597840
- "Facts below are canonical current-run evidence. Consume these facts in the next decision; do not repeat the identical read.",
597847
+ "This is an unchanged, complete branch extraction. A later file_read may still execute whenever current source or broader coverage is needed.",
597841
597848
  "[CANONICAL_FACTS]",
597842
597849
  input.payload.slice(0, 7e3),
597843
597850
  "[/CANONICAL_FACTS]"
597844
597851
  ].join("\n");
597845
597852
  }
597846
- _rejectRepeatedResolvedRead(tc, messages2) {
597847
- if (tc.name !== "file_read") {
597848
- for (const state2 of this._resolvedReadEvidence.values()) {
597849
- state2.consumed = true;
597850
- }
597851
- return null;
597852
- }
597853
- const fingerprint = this._buildToolFingerprint(tc.name, tc.arguments);
597854
- const state = this._resolvedReadEvidence.get(fingerprint);
597855
- if (!state)
597856
- return null;
597857
- const latestAssistant = [...messages2].reverse().find((message2) => message2.role === "assistant" && typeof message2.content === "string");
597858
- if (latestAssistant && typeof latestAssistant.content === "string" && latestAssistant.content.includes(state.handle)) {
597859
- state.consumed = true;
597860
- }
597861
- return [
597862
- "[REPEATED_READ_REJECTED]",
597863
- `handle=${state.handle}`,
597864
- `fingerprint_state=${state.state}`,
597865
- state.consumed ? "The evidence handle was acknowledged, but an identical read cannot add facts. Change file/range/query scope or take the evidence-backed next action." : "Consume the rehydrated evidence handle in your next decision before requesting another read. Change file/range/query scope if a different fact is required."
597866
- ].join("\n");
597867
- }
597868
597853
  async _drainPendingSteeringMessages(messages2, turn) {
597869
597854
  this.drainPendingRuntimeGuidance(turn);
597870
597855
  const pending2 = this.pendingSteeringInputs.filter((record) => (record.state === "queued" || record.state === "acknowledged") && (!record.taskEpoch || record.taskEpoch === this._taskEpoch));
@@ -598265,6 +598250,16 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598265
598250
  _mustInlineSmallFileRead(selectedBytes, selectedLines) {
598266
598251
  return selectedBytes <= 8e3 && selectedLines <= 200;
598267
598252
  }
598253
+ /**
598254
+ * `mode:"full"` is a first-class model choice, not a request for a wrapper.
598255
+ * Honor it for a bounded source body that still leaves normal output room;
598256
+ * truly overwhelming files continue through the isolated extractor.
598257
+ */
598258
+ _mustHonorExplicitFullFileRead(selectedBytes, selectedLines, contextWindow) {
598259
+ const projected = estimateFileReadInjectionTokens(selectedBytes, selectedLines);
598260
+ const cap = Math.max(4096, Math.min(8192, Math.floor(Math.max(0, contextWindow) * 0.15)));
598261
+ return selectedBytes <= 32e3 && selectedLines <= 800 && projected <= cap;
598262
+ }
598268
598263
  /**
598269
598264
  * Route using the same sanitized, model-facing request shape that will be
598270
598265
  * sent after the tool turn—not the unreduced historical transcript. Using
@@ -598374,8 +598369,10 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598374
598369
  });
598375
598370
  const requestedMode = this._fileReadMode(input.args);
598376
598371
  const explicitExtraction = requestedMode === "extract";
598372
+ const explicitFull = requestedMode === "full";
598377
598373
  const inlineSmallRead = this._mustInlineSmallFileRead(selectedBytes, selectedLines.length);
598378
- if ((!decision2.branch || inlineSmallRead) && !explicitExtraction) {
598374
+ const honorFull = explicitFull && this._mustHonorExplicitFullFileRead(selectedBytes, selectedLines.length, contextWindow);
598375
+ if ((!decision2.branch || inlineSmallRead || honorFull) && !explicitExtraction) {
598379
598376
  input.batchBudget.inlineTokens += decision2.projectedReadTokens;
598380
598377
  input.batchBudget.reservations.set(input.callId, decision2.projectedReadTokens);
598381
598378
  return null;
@@ -598395,7 +598392,7 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598395
598392
  const branchRequestId = `branch:${this._taskEpoch}:${_createHash("sha256").update(`${canonicalPath}|${fullHash}|${offset ?? 0}:${limit ?? "EOF"}|${contractFingerprint}`).digest("hex").slice(0, 20)}`;
598396
598393
  const cacheKey = `${this._taskEpoch}|${canonicalPath}|${fullHash}|${offset ?? 0}:${limit ?? "EOF"}|${contractFingerprint}`;
598397
598394
  const cached2 = this._branchEvidenceCache.get(cacheKey);
598398
- if (cached2) {
598395
+ if (cached2?.contractComplete) {
598399
598396
  const fingerprint = this._buildToolFingerprint(input.toolName, input.args);
598400
598397
  const rehydrated = this._rehydrateResolvedReadEvidence({
598401
598398
  fingerprint,
@@ -598407,7 +598404,7 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598407
598404
  this.emit({
598408
598405
  type: "status",
598409
598406
  toolName: input.toolName,
598410
- content: `Branch-extract cache rehydrated: ${rawPath} sha256=${fullHash.slice(0, 12)} contract=${contractFingerprint} fingerprint_state=resolved_from_cache`,
598407
+ content: `Complete branch extraction reused: ${rawPath} sha256=${fullHash.slice(0, 12)} contract=${contractFingerprint}`,
598411
598408
  turn: input.turn,
598412
598409
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
598413
598410
  });
@@ -598459,17 +598456,17 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598459
598456
  `[VERIFIED_RUNTIME_FILE_READ] request_id=${branchRequestId} task_epoch=${this._taskEpoch}`,
598460
598457
  `routing=${explicitExtraction ? "manual" : "mandatory"} reasons=${decision2.reasons.join(",") || "explicit_extract"} projected_read_tokens=${decision2.projectedReadTokens} fraction_limit_tokens=${decision2.fractionLimitTokens} available_headroom_tokens=${decision2.availableHeadroomTokens}`,
598461
598458
  `source=sha256:${fullHash} selected_lines=${selectedLines.length} selected_bytes=${selectedBytes}${hasRange ? ` range=${offset ?? 1}:${limit ?? "EOF"}` : " range=whole"}`,
598462
- `[DISCOVERY CONTRACT]`,
598463
- `Goal anchor: ${branchBrief.discoveryContract?.goalAnchor ?? this._taskState.currentStep}`,
598464
- `Request: ${branchBrief.request}`,
598465
- `Required discoveries:`,
598459
+ `[EXTRACTION CONTRACT]`,
598460
+ `Task: ${branchBrief.discoveryContract?.goalAnchor ?? this._taskState.currentStep}`,
598461
+ `Question: ${branchBrief.request}`,
598462
+ `Requirements:`,
598466
598463
  ...(branchBrief.discoveryContract?.requirements ?? []).map((requirement) => `- ${requirement.id}${requirement.required ? " [required]" : ""}: ${requirement.question}`),
598467
598464
  `Stop conditions: ${(branchBrief.discoveryContract?.completionCriteria ?? []).join(" | ")}`,
598468
598465
  `[CURATED SEGMENTS]`,
598469
598466
  ev.claim,
598470
598467
  ...requirementCoverage,
598471
598468
  `provenance=content:${ev.provenance.contentHash} searches:${ev.provenance.searchRounds.length} ranges:${ev.provenance.exploredRanges.map((range) => `L${range.startLine}-L${range.endLine}`).join(",")}`,
598472
- ev.contractComplete ? `Contract: every declared requirement has anchored evidence. Use these anchors as evidence; file_read(mode="full") remains available when live admission permits it.` : `Contract: this extraction is PARTIAL. Do not treat it as sufficient for a mutation that depends on an unresolved requirement; execute that requirement's listed bounded recovery. Do not use shell/cat to bypass context routing.`
598469
+ ev.contractComplete ? `Coverage: complete; every declared requirement has anchored evidence.` : `Coverage: partial; unresolved requirements include their source-based reason and suggested next evidence query. This extract is advisory and does not restrict other tool calls.`
598473
598470
  ].join("\n");
598474
598471
  const outputBudgetChars = Math.max(800, decision2.fractionLimitTokens * 4);
598475
598472
  let output = verboseOutput;
@@ -598479,7 +598476,7 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598479
598476
  `[BRANCH-EXTRACT v2] path=${rawPath} sha256=${fullHash}`,
598480
598477
  `[VERIFIED_RUNTIME_FILE_READ] request_id=${branchRequestId} task_epoch=${this._taskEpoch}`,
598481
598478
  `routing=${decision2.reasons.join(",")} projected=${decision2.projectedReadTokens}/${contextWindow}t limit=${decision2.fractionLimitTokens}t`,
598482
- `[DISCOVERY CONTRACT] required=${required || "next narrow file-local fact"}`,
598479
+ `[EXTRACTION CONTRACT] required=${required || "next narrow file-local fact"}`,
598483
598480
  `[CURATED SEGMENTS]`
598484
598481
  ].join("\n");
598485
598482
  const suffix = [
@@ -598587,8 +598584,10 @@ ${suffix}`.slice(0, outputBudgetChars);
598587
598584
  safeContextTokens: this.contextLimits().compactionThreshold
598588
598585
  });
598589
598586
  const explicitExtraction = this._fileReadMode(input.args) === "extract";
598587
+ const explicitFull = this._fileReadMode(input.args) === "full";
598590
598588
  const inlineSmallRead = this._mustInlineSmallFileRead(Buffer.byteLength(input.result.output, "utf8"), lines.length);
598591
- if ((!decision2.branch || inlineSmallRead) && !explicitExtraction) {
598589
+ const honorFull = explicitFull && this._mustHonorExplicitFullFileRead(Buffer.byteLength(input.result.output, "utf8"), lines.length, contextWindow);
598590
+ if ((!decision2.branch || inlineSmallRead || honorFull) && !explicitExtraction) {
598592
598591
  if (reservedForThisCall === 0) {
598593
598592
  input.batchBudget.inlineTokens += decision2.projectedReadTokens;
598594
598593
  input.batchBudget.reservations.set(input.callId, decision2.projectedReadTokens);
@@ -598622,12 +598621,12 @@ ${suffix}`.slice(0, outputBudgetChars);
598622
598621
  `[BRANCH-EXTRACT v2] path=${path16}`,
598623
598622
  `[VERIFIED_RUNTIME_FILE_READ] request_id=branch:${this._taskEpoch}:${input.callId} task_epoch=${this._taskEpoch}`,
598624
598623
  `routing=${explicitExtraction ? "manual" : "post-execution-failsafe"} reasons=${decision2.reasons.join(",") || "explicit_extract"} projected_read_tokens=${decision2.projectedReadTokens}`,
598625
- `[DISCOVERY CONTRACT] ${brief.request}`,
598624
+ `[EXTRACTION CONTRACT] ${brief.request}`,
598626
598625
  `[CURATED SEGMENTS]`,
598627
598626
  ev.claim,
598628
598627
  ...requirementCoverage,
598629
598628
  `provenance=content:${ev.provenance.contentHash} ranges:${ev.provenance.exploredRanges.map((range) => `L${range.startLine}-L${range.endLine}`).join(",")}`,
598630
- ev.contractComplete ? "All declared requirements are grounded." : "PARTIAL contract: execute the listed bounded recovery before relying on an unresolved requirement."
598629
+ ev.contractComplete ? "Coverage: complete; all declared requirements are grounded." : "Coverage: partial; unresolved requirements include a source-based recovery suggestion. This extract is advisory and does not restrict other tool calls."
598631
598630
  ].join("\n").slice(0, Math.max(800, decision2.fractionLimitTokens * 4));
598632
598631
  return {
598633
598632
  ...input.result,
@@ -600082,7 +600081,6 @@ ${dynamicProjectContext}`
600082
600081
  let lastShellPivotTurn = -1;
600083
600082
  const recentToolResults = /* @__PURE__ */ new Map();
600084
600083
  const exactFileReadObservations = /* @__PURE__ */ new Map();
600085
- const exactReadEvidenceEpochs = /* @__PURE__ */ new Map();
600086
600084
  let fileMutationEpoch = 0;
600087
600085
  const dedupHitCount = /* @__PURE__ */ new Map();
600088
600086
  const noopedMemoryWriteFingerprints = /* @__PURE__ */ new Set();
@@ -602515,17 +602513,6 @@ ${memoryLines.join("\n")}`
602515
602513
  return { tc, output: steeringGate, success: false };
602516
602514
  }
602517
602515
  this._markFirstSteeringAffectedAction(tc.name, this._currentSteeringTurn);
602518
- const resolvedReadBlock = this._rejectRepeatedResolvedRead(tc, messages2);
602519
- if (resolvedReadBlock) {
602520
- this.emit({
602521
- type: "status",
602522
- toolName: tc.name,
602523
- content: "Repeated planned file_read rejected until evidence scope changes.",
602524
- turn,
602525
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
602526
- });
602527
- return { tc, output: resolvedReadBlock, success: true };
602528
- }
602529
602516
  const cohortKey = this.buildArgCohortKey(tc.name, tc.arguments);
602530
602517
  const cohort = this._argCohorts.get(cohortKey);
602531
602518
  if (cohort && cohort.failure >= 3 && cohort.success === 0) {
@@ -603161,47 +603148,6 @@ Read the current file if needed, make a different concrete edit, or move to veri
603161
603148
  adversaryRedundantSignal
603162
603149
  });
603163
603150
  let repeatShortCircuit = null;
603164
- const exactReadArgs = tc.arguments;
603165
- const exactReadPath = String(exactReadArgs?.["path"] ?? exactReadArgs?.["file"] ?? "");
603166
- const exactReadEvidence = exactReadEvidenceEpochs.get(toolFingerprint);
603167
- const exactReadEvidenceFresh = tc.name === "file_read" && exactReadPath.length > 0 && this._evidenceLedger.validateFreshness(this._normalizeEvidencePath(exactReadPath), this._absoluteToolPath(exactReadPath));
603168
- if (tc.name === "file_read" && exactReadEvidenceFresh && exactReadEvidence?.taskEpoch === this._taskEpoch && exactReadEvidence.mutationEpoch === fileMutationEpoch) {
603169
- const path16 = this._normalizeEvidencePath(exactReadPath);
603170
- const evidence = this._evidenceLedger.get(path16);
603171
- const rawCurated = this._branchEvidenceByPath.get(path16) ?? [...this._branchEvidenceByPath.entries()].find(([candidate]) => this._normalizeEvidencePath(candidate) === path16)?.[1];
603172
- const curated = rawCurated?.taskEpoch === this._taskEpoch ? rawCurated : void 0;
603173
- const curatedPayload = curated?.output ?? (evidence?.fidelity === "extract" && evidence.content.includes("[BRANCH-EXTRACT") ? evidence.content : null);
603174
- repeatShortCircuit = {
603175
- success: true,
603176
- output: curatedPayload ? this._rehydrateResolvedReadEvidence({
603177
- fingerprint: toolFingerprint,
603178
- canonicalPath: path16,
603179
- contentHash: curated?.contentHash ?? evidence?.contentHash ?? "unknown",
603180
- payload: curatedPayload,
603181
- turn
603182
- }) : [
603183
- ...evidence?.fidelity === "extract" ? [
603184
- "[REHYDRATED_FILE_EVIDENCE]",
603185
- "source=active_context_frame fidelity=extract"
603186
- ] : [],
603187
- "[READ EVIDENCE REFERENCE]",
603188
- `path=${path16 || "unknown"}`,
603189
- `task_epoch=${this._taskEpoch}`,
603190
- `freshness=${evidence?.stale ? "stale" : "fresh"}`,
603191
- evidence?.contentHash ? `sha256=${evidence.contentHash}` : null,
603192
- "Exact unchanged range was not re-executed. Use the existing evidence handle or request a newly uncovered range after identifying the missing fact."
603193
- ].filter(Boolean).join("\n"),
603194
- runtimeAuthored: true,
603195
- noop: true
603196
- };
603197
- this.emit({
603198
- type: "status",
603199
- toolName: tc.name,
603200
- content: `Exact unchanged file_read blocked before dispatch: ${path16}`,
603201
- turn,
603202
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
603203
- });
603204
- }
603205
603151
  if (criticDecision.decision === "guidance" && !repeatShortCircuit) {
603206
603152
  dedupHitCount.set(toolFingerprint, criticDecision.hitNumber);
603207
603153
  const _existingFp = recentToolResults.get(toolFingerprint);
@@ -603243,67 +603189,11 @@ Read the current file if needed, make a different concrete edit, or move to veri
603243
603189
  }
603244
603190
  const _repeatGateMax = this._resolveRepeatGateMax();
603245
603191
  const isFailedShellRepeat = this._enforcesStrictActionBoundaries() && tc.name === "shell" && typeof _existingFp?.result === "string" && _existingFp.result.includes("status: failure") && (_existingFp.mutationEpoch ?? fileMutationEpoch) === fileMutationEpoch && !this._compileFixLoopRequiresLiveShell(String(tc.arguments?.["command"] ?? tc.arguments?.["cmd"] ?? "")) && !shellLikelyMutatesFilesystem;
603246
- const repeatGateEligible = isReadLike || tc.name === "memory_write" || isFailedShellRepeat;
603192
+ const repeatGateEligible = isReadLike && tc.name !== "file_read" || tc.name === "memory_write" || isFailedShellRepeat;
603247
603193
  const suppressSuccessfulShellCacheGuidance = tc.name === "shell" && !isFailedShellRepeat;
603248
603194
  if (suppressSuccessfulShellCacheGuidance)
603249
603195
  criticGuidance = null;
603250
- let exactReadEvidenceFresh2 = true;
603251
- if (isReadLike && this._evidenceLedger) {
603252
- const readArgs = tc.arguments;
603253
- const readPath2 = String(readArgs?.["path"] ?? readArgs?.["file"] ?? "");
603254
- if (readPath2) {
603255
- const evidencePath = this._normalizeEvidencePath(readPath2);
603256
- const wasFresh = evidencePath && this._evidenceLedger.validateFreshness(evidencePath, this._absoluteToolPath(readPath2));
603257
- exactReadEvidenceFresh2 = Boolean(wasFresh);
603258
- if (!wasFresh) {
603259
- recentToolResults.delete(toolFingerprint);
603260
- dedupHitCount.delete(toolFingerprint);
603261
- this._recentFailures = (this._recentFailures ?? []).filter((f2) => f2.fingerprint !== toolFingerprint);
603262
- repeatShortCircuit = null;
603263
- this.emit({
603264
- type: "status",
603265
- content: `[EXTERNAL MUTATION] ${readPath2} mtime changed since last read — cache invalidated, fresh read allowed`,
603266
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
603267
- });
603268
- }
603269
- }
603270
- }
603271
- const exactReadEvidence2 = exactReadEvidenceEpochs.get(toolFingerprint);
603272
- const exactFileReadReference = tc.name === "file_read" && exactReadEvidenceFresh2 && exactReadEvidence2?.taskEpoch === this._taskEpoch && exactReadEvidence2.mutationEpoch === fileMutationEpoch;
603273
- if (exactFileReadReference) {
603274
- const path16 = this._normalizeEvidencePath(String(tc.arguments?.["path"] ?? tc.arguments?.["file"] ?? ""));
603275
- const evidence = this._evidenceLedger?.get(path16);
603276
- const rawCurated = this._branchEvidenceByPath.get(path16) ?? [...this._branchEvidenceByPath.entries()].find(([candidate]) => this._normalizeEvidencePath(candidate) === path16)?.[1];
603277
- const curated = rawCurated?.taskEpoch === this._taskEpoch ? rawCurated : void 0;
603278
- const curatedPayload = curated?.output ?? (evidence?.fidelity === "extract" && evidence.content.includes("[BRANCH-EXTRACT") ? evidence.content : null);
603279
- repeatShortCircuit = {
603280
- success: true,
603281
- // Curated branch output is the bounded authoritative payload
603282
- // for this source version. Rehydrate it instead of replacing
603283
- // it with a pointer; exact/overlap suppression must not force
603284
- // the model to reread a large source merely to recover facts.
603285
- output: curatedPayload ? this._rehydrateResolvedReadEvidence({
603286
- fingerprint: toolFingerprint,
603287
- canonicalPath: path16,
603288
- contentHash: curated?.contentHash ?? evidence?.contentHash ?? "unknown",
603289
- payload: curatedPayload,
603290
- turn
603291
- }) : [
603292
- ...evidence?.fidelity === "extract" ? [
603293
- "[REHYDRATED_FILE_EVIDENCE]",
603294
- "source=active_context_frame fidelity=extract"
603295
- ] : [],
603296
- "[READ EVIDENCE REFERENCE]",
603297
- `path=${path16 || "unknown"}`,
603298
- `task_epoch=${this._taskEpoch}`,
603299
- `freshness=${evidence?.stale ? "stale" : "fresh"}`,
603300
- evidence?.contentHash ? `sha256=${evidence.contentHash}` : null,
603301
- "Exact unchanged range was not re-executed. Use the existing evidence handle or request a newly uncovered range after identifying the missing fact."
603302
- ].filter(Boolean).join("\n"),
603303
- runtimeAuthored: true,
603304
- noop: true
603305
- };
603306
- } else if (repeatGateEligible && _existingFp !== void 0 && _repeatGateMax > 0) {
603196
+ if (repeatGateEligible && _existingFp !== void 0 && _repeatGateMax > 0) {
603307
603197
  const _rehydrateArgs = tc.arguments;
603308
603198
  const _rehydratePath = String(_rehydrateArgs?.["path"] ?? _rehydrateArgs?.["file"] ?? "");
603309
603199
  const _visibleViaEvidenceFrame = _rehydratePath.length > 0 && (this._evidenceLedger?.renderedFullInLastBlock(this._normalizeEvidencePath(_rehydratePath)) ?? false);
@@ -603492,7 +603382,7 @@ ${cachedResult}`,
603492
603382
  tc.arguments = this._normalizeToolArgsForExecution(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
603493
603383
  tc.arguments = this._autoDeriveDelegationMutationScope(resolvedTool?.name ?? tc.name, tc.arguments ?? {}, turn);
603494
603384
  tc.arguments = await this._enrichDelegationToolArgs(resolvedTool?.name ?? tc.name, tc.arguments ?? {}, messages2, turn);
603495
- validationError = this._partialBranchExplorationMutationBlock(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
603385
+ validationError = this._partialBranchExplorationMutationBlock(resolvedTool?.name ?? tc.name, tc.arguments ?? {}, turn);
603496
603386
  if (!validationError)
603497
603387
  validationError = this._validateFileWriteOverwriteContract(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
603498
603388
  }
@@ -603633,7 +603523,9 @@ ${cachedResult}`,
603633
603523
  exactFileReadObservations.set(exactReadKey, currentRead);
603634
603524
  const canonicalPayload = this._canonicalReadEvidencePayload(currentRead.canonicalPath, currentRead.contentHash);
603635
603525
  if (canonicalPayload) {
603636
- const rehydrated = this._rehydrateResolvedReadEvidence({
603526
+ const evidence = this._evidenceLedger.get(currentRead.canonicalPath);
603527
+ const fullSource = evidence?.fidelity === "full" && evidence.content === canonicalPayload;
603528
+ const delivered = fullSource ? canonicalPayload : this._rehydrateResolvedReadEvidence({
603637
603529
  fingerprint: exactReadKey,
603638
603530
  canonicalPath: currentRead.canonicalPath,
603639
603531
  contentHash: currentRead.contentHash,
@@ -603642,8 +603534,8 @@ ${cachedResult}`,
603642
603534
  });
603643
603535
  branchEvidenceResult = {
603644
603536
  success: true,
603645
- output: rehydrated,
603646
- llmContent: rehydrated,
603537
+ output: delivered,
603538
+ llmContent: delivered,
603647
603539
  beforeHash: currentRead.contentHash,
603648
603540
  runtimeAuthored: true,
603649
603541
  noop: true,
@@ -603656,44 +603548,19 @@ ${cachedResult}`,
603656
603548
  this.emit({
603657
603549
  type: "status",
603658
603550
  toolName: normalizedDispatchName,
603659
- content: `Exact unchanged file_read rehydrated: ${currentRead.path} sha256=${currentRead.contentHash.slice(0, 12)} fingerprint_state=resolved_from_cache`,
603551
+ content: fullSource ? `Exact unchanged file_read served as canonical full source: ${currentRead.path} sha256=${currentRead.contentHash.slice(0, 12)}` : `Exact unchanged file_read reused complete branch evidence: ${currentRead.path} sha256=${currentRead.contentHash.slice(0, 12)}`,
603660
603552
  turn,
603661
603553
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
603662
603554
  });
603663
603555
  } else {
603664
- if (this._deterministicNarrowReadFallbacks.has(exactReadKey)) {
603665
- const fallbackBlocked = [
603666
- "[REPEATED_NARROW_READ_REJECTED]",
603667
- `path=${currentRead.path}`,
603668
- "No canonical payload was produced by the allowed narrow reread. Change scope with a new range or symbol query; do not repeat identical arguments."
603669
- ].join("\n");
603670
- branchEvidenceResult = {
603671
- success: true,
603672
- output: fallbackBlocked,
603673
- llmContent: fallbackBlocked,
603674
- beforeHash: currentRead.contentHash,
603675
- runtimeAuthored: true,
603676
- noop: true
603677
- };
603678
- } else {
603679
- this._deterministicNarrowReadFallbacks.add(exactReadKey);
603680
- const previousOffset = tc.arguments["offset"];
603681
- const previousLimit = tc.arguments["limit"];
603682
- Object.assign(finalArgs, {
603683
- offset: typeof previousOffset === "number" && Number.isFinite(previousOffset) ? Math.max(1, Math.floor(previousOffset)) : 1,
603684
- limit: typeof previousLimit === "number" && Number.isFinite(previousLimit) ? Math.max(1, Math.min(160, Math.floor(previousLimit))) : 160
603685
- });
603686
- tc.arguments = finalArgs;
603687
- this._deterministicNarrowReadFallbacks.add(this._buildToolFingerprint("file_read", tc.arguments));
603688
- exactFileReadObservations.delete(exactReadKey);
603689
- this.emit({
603690
- type: "status",
603691
- toolName: normalizedDispatchName,
603692
- content: `Exact read cache lacked canonical payload; allowing one deterministic narrow reread: ${currentRead.path} offset=${tc.arguments["offset"]} limit=${tc.arguments["limit"]}`,
603693
- turn,
603694
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
603695
- });
603696
- }
603556
+ exactFileReadObservations.delete(exactReadKey);
603557
+ this.emit({
603558
+ type: "status",
603559
+ toolName: normalizedDispatchName,
603560
+ content: `Exact read cache lacks model-visible source; executing requested read: ${currentRead.path}`,
603561
+ turn,
603562
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
603563
+ });
603697
603564
  }
603698
603565
  } else {
603699
603566
  exactFileReadObservations.delete(exactReadKey);
@@ -603963,7 +603830,7 @@ ${cachedResult}`,
603963
603830
  fileVersion: this._worldFacts.files.get(p2)?.writeCount ?? 0,
603964
603831
  mtimeMs: this._statMtimeMsForToolPath(p2),
603965
603832
  turn,
603966
- fidelity: result.runtimeAuthored === true && result.output.startsWith("[BRANCH-EXTRACT") ? "extract" : void 0
603833
+ fidelity: result.runtimeAuthored === true && result.output.startsWith("[BRANCH-EXTRACT") ? "extract" : this._fileReadMode(tc.arguments) === "full" && this._mustHonorExplicitFullFileRead(Buffer.byteLength(result.output, "utf8"), result.output.split("\n").length, this._branchRoutingContextWindow()) ? "full" : void 0
603967
603834
  });
603968
603835
  if (result.runtimeAuthored !== true && this._fileReadMode(tc.arguments) !== "extract" && typeof result.beforeHash === "string") {
603969
603836
  this._inlineReadArtifacts.set(tc.id, {
@@ -603983,10 +603850,6 @@ ${cachedResult}`,
603983
603850
  this._inlineReadArtifacts.delete(oldest);
603984
603851
  }
603985
603852
  }
603986
- exactReadEvidenceEpochs.set(toolFingerprint, {
603987
- taskEpoch: this._taskEpoch,
603988
- mutationEpoch: fileMutationEpoch
603989
- });
603990
603853
  this._registerReadCoverage("file_read", tc.arguments, toolFingerprint);
603991
603854
  }
603992
603855
  if (this._fileSummaryStore && result.success && result.output && result.output.length > 100) {
@@ -607718,6 +607581,17 @@ ${marker}` : marker);
607718
607581
  if (toolName === "file_read") {
607719
607582
  const path17 = this.extractPrimaryToolPath(args);
607720
607583
  const evidencePath = path17 ? this._normalizeEvidencePath(path17) : "";
607584
+ const explicitBoundedFullRead = this._fileReadMode(args ?? {}) === "full" && this._mustHonorExplicitFullFileRead(Buffer.byteLength(displayOutput, "utf8"), this.countTextLines(displayOutput), this._branchRoutingContextWindow());
607585
+ if (explicitBoundedFullRead) {
607586
+ return [
607587
+ "[ADMITTED_FILE_READ v1]",
607588
+ `path=${path17 || "unknown"}`,
607589
+ "delivery=explicit_full_source",
607590
+ "The requested bounded full source is present below. It may be reread after a filesystem change or when a new range is needed.",
607591
+ "",
607592
+ output
607593
+ ].join("\n");
607594
+ }
607721
607595
  const admitted = [...this._inlineReadArtifacts.values()].find((artifact) => artifact.path === evidencePath && output.includes(`sha256=${artifact.contentHash}`));
607722
607596
  if (admitted) {
607723
607597
  return [
@@ -607725,7 +607599,7 @@ ${marker}` : marker);
607725
607599
  `path=${admitted.path}`,
607726
607600
  `sha256=${admitted.contentHash}`,
607727
607601
  "delivery=full_body_once",
607728
- 'The full selected source body below is canonical for this turn. To replace it with compact verified anchors, call file_read again with mode="extract" and purpose="the exact fact needed". Do not use shell/cat as a read workaround.',
607602
+ 'The full selected source body below is canonical for this turn. To replace it with compact verified anchors, call file_read again with mode="extract" and purpose="the exact fact needed".',
607729
607603
  "",
607730
607604
  output
607731
607605
  ].join("\n");
@@ -607757,7 +607631,7 @@ ${marker}` : marker);
607757
607631
  ].filter(Boolean).join("\n"));
607758
607632
  }
607759
607633
  shouldBypassDiscoveryCompaction(output) {
607760
- return output.includes("[IMAGE_BASE64:") || output.includes("[ADMITTED_FILE_READ") || /^\[BRANCH-EXTRACT(?:\s+v\d+)?\]/m.test(output) || output.includes("[REPEAT GATE - cached evidence not re-sent]") || output.includes("[REPEATED_READ_REJECTED]") || output.includes("[REPEATED_NARROW_READ_REJECTED]") || output.includes("[CACHED READ — content unchanged") || output.includes("[REHYDRATED FROM CACHE") || output.includes("[Tool output truncated") || output.includes(TRIAGE_ENVELOPE_MARKER);
607634
+ return output.includes("[IMAGE_BASE64:") || output.includes("[ADMITTED_FILE_READ") || /^\[BRANCH-EXTRACT(?:\s+v\d+)?\]/m.test(output) || output.includes("[REPEAT GATE - cached evidence not re-sent]") || output.includes("[CACHED READ — content unchanged") || output.includes("[REHYDRATED FROM CACHE") || output.includes("[Tool output truncated") || output.includes(TRIAGE_ENVELOPE_MARKER);
607761
607635
  }
607762
607636
  countTextLines(text2) {
607763
607637
  if (!text2)
@@ -608193,6 +608067,8 @@ ${marker}` : marker);
608193
608067
  _validateFileWriteOverwriteContract(toolName, args) {
608194
608068
  if (toolName !== "file_write")
608195
608069
  return null;
608070
+ if (!this._enforcesStrictActionBoundaries())
608071
+ return null;
608196
608072
  if (process.env["OMNIUS_ALLOW_UNVERIFIED_FILE_WRITE_OVERWRITE"] === "1") {
608197
608073
  return null;
608198
608074
  }
@@ -608256,12 +608132,13 @@ ${marker}` : marker);
608256
608132
  return null;
608257
608133
  }
608258
608134
  /**
608259
- * A branch result that still has unanswered discovery requirements is an
608260
- * exploration state, not mutation authority. Without this admission gate a
608261
- * large model could receive one attractive anchor, invent the rest, and make
608262
- * a broad edit before the branch's own listed recovery was attempted.
608135
+ * Partial branch coverage is useful evidence, never mutation authority and
608136
+ * never a tool admission gate. The parent model may decide that its current
608137
+ * evidence is sufficient, request more branch work, or perform a narrow edit
608138
+ * validated by the normal file hash contract. Blocking here caused file_edit
608139
+ * calls to be mislabeled as stale hashes and stranded real exploration.
608263
608140
  */
608264
- _partialBranchExplorationMutationBlock(toolName, args) {
608141
+ _partialBranchExplorationMutationBlock(toolName, args, turn) {
608265
608142
  const delegatedMutation = (toolName === "sub_agent" || toolName === "agent") && (args["mutation_role"] === "mutation_worker" || args["subagent_type"] === "fixer");
608266
608143
  if (!this._isProjectEditTool(toolName) && !delegatedMutation)
608267
608144
  return null;
@@ -608275,19 +608152,19 @@ ${marker}` : marker);
608275
608152
  if (!partial)
608276
608153
  continue;
608277
608154
  const [path16, node] = partial;
608278
- return [
608279
- "[EXPLORATION ADMISSION BLOCK]",
608280
- `${toolName} was not executed: ${path16} has a fresh but partial branch discovery contract.`,
608281
- `unresolved=${node.unresolvedRequirementIds.join(",") || "unknown"}`,
608282
- "The model must not make a creative/source mutation while a required file-local fact is unresolved.",
608283
- "Required bounded recovery:",
608284
- ...node.unresolvedRecoveries.length > 0 ? node.unresolvedRecoveries.map((recovery) => `- ${recovery}`) : ["- issue one narrow file_read or grep_search for the unresolved requirement"],
608285
- "After a complete anchored branch contract is recorded, retry the scoped mutation with fresh hash evidence."
608286
- ].join("\n");
608155
+ this.emit({
608156
+ type: "status",
608157
+ content: `branch_discovery_partial_advisory: ${toolName} is proceeding with ${path16}; unresolved=${node.unresolvedRequirementIds.join(",") || "unknown"}; coverage is visible evidence, not an admission block`,
608158
+ turn,
608159
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
608160
+ });
608161
+ return null;
608287
608162
  }
608288
608163
  return null;
608289
608164
  }
608290
608165
  _validateFreshExpectedHashesForEdit(toolName, args) {
608166
+ if (!this._enforcesStrictActionBoundaries())
608167
+ return null;
608291
608168
  if (process.env["OMNIUS_ALLOW_UNVERIFIED_OLD_STRING_EDIT"] === "1") {
608292
608169
  return null;
608293
608170
  }
@@ -608448,6 +608325,8 @@ ${marker}` : marker);
608448
608325
  ].join("\n");
608449
608326
  }
608450
608327
  editReversalPreflightBlock(toolName, args, turn) {
608328
+ if (!this._enforcesStrictActionBoundaries())
608329
+ return null;
608451
608330
  if (process.env["OMNIUS_ALLOW_BLIND_EDIT_REVERSAL"] === "1")
608452
608331
  return null;
608453
608332
  const replacements = this.extractReplacementEdits(toolName, args);
@@ -608643,6 +608522,10 @@ ${marker}` : marker);
608643
608522
  return this.wrapToolOutputForModel(toolName, `Error: ${result.error || "unknown error"}
608644
608523
  ${errOutput}`);
608645
608524
  }
608525
+ const explicitBoundedFullRead = toolName === "file_read" && this._fileReadMode(args) === "full" && this._mustHonorExplicitFullFileRead(Buffer.byteLength(modelContent, "utf8"), modelContent.split("\n").length, this._branchRoutingContextWindow());
608526
+ if (explicitBoundedFullRead) {
608527
+ return this.wrapToolOutputForModel(toolName, modelContent);
608528
+ }
608646
608529
  if (modelContent.length <= maxLen) {
608647
608530
  return this.wrapToolOutputForModel(toolName, modelContent);
608648
608531
  }
@@ -610015,10 +609898,39 @@ Describe what you see and integrate this into your current approach.` : "[User s
610015
609898
  const postChars = combinedSummary.length + recent.reduce((s2, m2) => s2 + _estimateMsgChars(m2), 0) + head.reduce((s2, m2) => s2 + _estimateMsgChars(m2), 0);
610016
609899
  const postTokens = Math.ceil(postChars / 4);
610017
609900
  const savedTokens = preTokens - postTokens;
609901
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
609902
+ const removedMessages = messages2.slice(headEndIdx, recentStart).map((message2, offset) => {
609903
+ const content = typeof message2.content === "string" ? message2.content : JSON.stringify(message2.content);
609904
+ const isLegacy = this._isLegacyControlMessage(message2);
609905
+ const isPriorSummary = message2.role === "system" && typeof message2.content === "string" && message2.content.startsWith("[Context compacted");
609906
+ return {
609907
+ index: headEndIdx + offset,
609908
+ role: message2.role,
609909
+ content,
609910
+ chars: content.length,
609911
+ reason: isLegacy ? "legacy_control_retired" : isPriorSummary ? "prior_summary_folded" : "history_summarized",
609912
+ ...message2.tool_call_id ? { toolCallId: message2.tool_call_id } : {}
609913
+ };
609914
+ });
609915
+ const compactionAudit = {
609916
+ id: `cmp-${this.currentArtifactRunId()}-${Date.now().toString(36)}`,
609917
+ runId: this.currentArtifactRunId(),
609918
+ sessionId: this._sessionId,
609919
+ timestamp,
609920
+ strategy,
609921
+ manual: force,
609922
+ beforeTokens: preTokens,
609923
+ afterTokens: postTokens,
609924
+ savedTokens,
609925
+ retainedMessages: head.length + recent.length + 1,
609926
+ removedMessages,
609927
+ summary: combinedSummary
609928
+ };
610018
609929
  this.emit({
610019
609930
  type: "compaction",
610020
- content: `Compacted ${middle.length} messages${strategyLabel}${forceLabel}${previousSummary ? " (progressive)" : ""} | ~${preTokens.toLocaleString()} → ~${postTokens.toLocaleString()} tokens (saved ~${savedTokens.toLocaleString()})`,
610021
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
609931
+ content: `Compacted ${removedMessages.length} messages${strategyLabel}${forceLabel}${previousSummary ? " (progressive)" : ""} | ~${preTokens.toLocaleString()} → ~${postTokens.toLocaleString()} tokens (saved ~${savedTokens.toLocaleString()})`,
609932
+ timestamp,
609933
+ compaction: compactionAudit
610022
609934
  });
610023
609935
  const tier = this.options.modelTier ?? "large";
610024
609936
  if (tier === "small") {
@@ -610198,6 +610110,21 @@ ${telegramPersonaHead}` : stripped
610198
610110
  const fileRecoveryBudget = Math.floor((this._branchRoutingContextWindow() || 32768) * 0.15);
610199
610111
  const maxRecoverFiles = tier === "small" ? 3 : tier === "medium" ? 4 : 5;
610200
610112
  const recoveredFiles = [];
610113
+ const alreadyVisiblePaths = /* @__PURE__ */ new Set();
610114
+ for (const message2 of result) {
610115
+ if (typeof message2.content !== "string")
610116
+ continue;
610117
+ const content = message2.content;
610118
+ const matches = [
610119
+ ...content.matchAll(/(?:^|\n)path=([^\n]+)/g),
610120
+ ...content.matchAll(/<recovered-(?:branch-evidence|file-reference|file) path="([^"]+)"/g)
610121
+ ];
610122
+ for (const match of matches) {
610123
+ const path16 = String(match[1] ?? "").trim();
610124
+ if (path16)
610125
+ alreadyVisiblePaths.add(this._normalizeEvidencePath(path16));
610126
+ }
610127
+ }
610201
610128
  if (this._fileRegistry.size > 0) {
610202
610129
  const entries = Array.from(this._fileRegistry.entries()).sort((a2, b) => {
610203
610130
  if (a2[1].modified && !b[1].modified)
@@ -610208,18 +610135,36 @@ ${telegramPersonaHead}` : stripped
610208
610135
  }).slice(0, maxRecoverFiles);
610209
610136
  let recoveredTokens = 0;
610210
610137
  for (const [filePath, entry] of entries) {
610138
+ const canonicalPath = this._normalizeEvidencePath(filePath);
610139
+ if (alreadyVisiblePaths.has(canonicalPath))
610140
+ continue;
610211
610141
  try {
610212
610142
  const { readFileSync: readFileSync144 } = await import("node:fs");
610213
610143
  const absolutePath = this._absoluteToolPath(filePath);
610214
610144
  const content = readFileSync144(absolutePath, "utf8");
610215
610145
  const tokenEst = Math.ceil(content.length / 4);
610216
- const canonicalPath = this._normalizeEvidencePath(filePath);
610217
610146
  const branchNode = this._branchEvidenceByPath.get(canonicalPath);
610218
610147
  const currentMtime = this._statMtimeMsForToolPath(filePath) ?? 0;
610148
+ const smallCompleteSource = this._mustHonorExplicitFullFileRead(Buffer.byteLength(content, "utf8"), content.split("\n").length, this._branchRoutingContextWindow());
610149
+ if (smallCompleteSource) {
610150
+ const sourceTokens = Math.ceil(content.length / 4);
610151
+ if (recoveredTokens + sourceTokens > fileRecoveryBudget)
610152
+ continue;
610153
+ result.push({
610154
+ role: "system",
610155
+ content: `<recovered-file path="${filePath}" status="${entry.modified ? "modified" : "read"}" sha256="${_createHash("sha256").update(content).digest("hex")}" truncated="false">
610156
+ ${content}
610157
+ </recovered-file>`
610158
+ });
610159
+ alreadyVisiblePaths.add(canonicalPath);
610160
+ recoveredFiles.push(filePath);
610161
+ recoveredTokens += sourceTokens;
610162
+ continue;
610163
+ }
610219
610164
  if (branchNode && // Pre-epoch in-memory nodes are same-run compatibility records;
610220
610165
  // retain their verified curated evidence during compaction rather
610221
610166
  // than falling back to a raw-file recovery reference.
610222
- (branchNode.taskEpoch === void 0 || branchNode.taskEpoch === this._taskEpoch) && branchNode.mtimeMs === currentMtime) {
610167
+ (branchNode.taskEpoch === void 0 || branchNode.taskEpoch === this._taskEpoch) && branchNode.mtimeMs === currentMtime && branchNode.contractComplete) {
610223
610168
  const nodeTokens = Math.ceil(branchNode.output.length / 4);
610224
610169
  if (recoveredTokens + nodeTokens > fileRecoveryBudget)
610225
610170
  continue;
@@ -610231,6 +610176,18 @@ ${branchNode.output}
610231
610176
  });
610232
610177
  recoveredFiles.push(filePath);
610233
610178
  recoveredTokens += nodeTokens;
610179
+ alreadyVisiblePaths.add(canonicalPath);
610180
+ continue;
610181
+ }
610182
+ if (branchNode && !branchNode.contractComplete) {
610183
+ const partialReference = `<recovered-file-reference path="${filePath}" status="partial-extract" sha256="${branchNode.contentHash}">A prior isolated extraction was partial; it is advisory only. Request full source or a new targeted range if this file is now needed.</recovered-file-reference>`;
610184
+ const referenceTokens = Math.ceil(partialReference.length / 4);
610185
+ if (recoveredTokens + referenceTokens > fileRecoveryBudget)
610186
+ continue;
610187
+ result.push({ role: "system", content: partialReference });
610188
+ alreadyVisiblePaths.add(canonicalPath);
610189
+ recoveredFiles.push(filePath);
610190
+ recoveredTokens += referenceTokens;
610234
610191
  continue;
610235
610192
  }
610236
610193
  const recoveryDecision = assessBranchRead({
@@ -610247,6 +610204,7 @@ ${branchNode.output}
610247
610204
  const referenceTokens = Math.ceil(reference.length / 4);
610248
610205
  if (recoveredTokens + referenceTokens <= fileRecoveryBudget) {
610249
610206
  result.push({ role: "system", content: reference });
610207
+ alreadyVisiblePaths.add(canonicalPath);
610250
610208
  recoveredFiles.push(filePath);
610251
610209
  recoveredTokens += referenceTokens;
610252
610210
  }
@@ -644372,6 +644330,7 @@ var init_ollama_gpu_policy = __esm({
644372
644330
  var omnius_directory_exports = {};
644373
644331
  __export(omnius_directory_exports, {
644374
644332
  OMNIUS_DIR: () => OMNIUS_DIR,
644333
+ appendCompactionAudit: () => appendCompactionAudit,
644375
644334
  buildContextRestorePrompt: () => buildContextRestorePrompt,
644376
644335
  buildContextRestoreSnapshot: () => buildContextRestoreSnapshot,
644377
644336
  buildHandoffPrompt: () => buildHandoffPrompt,
@@ -645076,6 +645035,32 @@ function pruneContextLedger(ledgerPath) {
645076
645035
  } catch {
645077
645036
  }
645078
645037
  }
645038
+ function appendCompactionAudit(repoRoot, record) {
645039
+ try {
645040
+ const contextDir = join136(repoRoot, OMNIUS_DIR, "context");
645041
+ mkdirSync76(contextDir, { recursive: true });
645042
+ const ledgerPath = join136(contextDir, COMPACTION_AUDIT_FILE);
645043
+ appendFileSync14(ledgerPath, JSON.stringify(record) + "\n", "utf-8");
645044
+ const st = statSync51(ledgerPath);
645045
+ if (st.size > 64 * 1024 * 1024) {
645046
+ const lines = readFileSync102(ledgerPath, "utf-8").split(/\r?\n/).filter((line) => line.trim());
645047
+ if (lines.length > 100) {
645048
+ const archiveDir = join136(contextDir, "archive");
645049
+ mkdirSync76(archiveDir, { recursive: true });
645050
+ const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
645051
+ writeFileSync64(
645052
+ join136(archiveDir, `compactions.${stamp}.jsonl`),
645053
+ lines.slice(0, -100).join("\n") + "\n",
645054
+ "utf-8"
645055
+ );
645056
+ writeFileSync64(ledgerPath, lines.slice(-100).join("\n") + "\n", "utf-8");
645057
+ }
645058
+ }
645059
+ return ledgerPath;
645060
+ } catch {
645061
+ return null;
645062
+ }
645063
+ }
645079
645064
  function saveSessionContext(repoRoot, entry) {
645080
645065
  const contextDir = join136(repoRoot, OMNIUS_DIR, "context");
645081
645066
  mkdirSync76(contextDir, { recursive: true });
@@ -646032,7 +646017,7 @@ function deleteUsageRecord(kind, value2, repoRoot) {
646032
646017
  remove(join136(repoRoot, OMNIUS_DIR, USAGE_HISTORY_FILE));
646033
646018
  }
646034
646019
  }
646035
- var OMNIUS_DIR, LEGACY_DIRS, SUBDIRS, gitignoreWatchers, gitignoreRetryTimers, CONTEXT_FILES, PENDING_TASK_FILE, HANDOFF_FILE, CONTEXT_SAVE_FILE, CONTEXT_LEDGER_FILE, MAX_CONTEXT_ENTRIES, MAX_SESSION_DIARY_ENTRIES, MAX_SESSION_DIARY_DETAILED_ENTRIES, MAX_CONTEXT_LEDGER_LINES, MAX_CONTEXT_LEDGER_BYTES, SAME_TASK_REPLACE_WINDOW_MS, LOCK_TIMEOUT_MS, LOCK_RETRY_MS, LOCK_RETRY_MAX, MODEL_CONTEXT_NOISE_LINE_RE, DEFAULT_RESTORED_SESSION_HISTORY_MAX_LINES, DEICTIC_CONTINUATION_TERMS, SESSIONS_DIR, SESSIONS_INDEX, TUI_STATE_SUFFIX, AUTHORED_SESSION_LINE, VISUAL_CHROME_LINE, SKIP_DIRS3, HOME_SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
646020
+ var OMNIUS_DIR, LEGACY_DIRS, SUBDIRS, gitignoreWatchers, gitignoreRetryTimers, CONTEXT_FILES, PENDING_TASK_FILE, HANDOFF_FILE, CONTEXT_SAVE_FILE, CONTEXT_LEDGER_FILE, COMPACTION_AUDIT_FILE, MAX_CONTEXT_ENTRIES, MAX_SESSION_DIARY_ENTRIES, MAX_SESSION_DIARY_DETAILED_ENTRIES, MAX_CONTEXT_LEDGER_LINES, MAX_CONTEXT_LEDGER_BYTES, SAME_TASK_REPLACE_WINDOW_MS, LOCK_TIMEOUT_MS, LOCK_RETRY_MS, LOCK_RETRY_MAX, MODEL_CONTEXT_NOISE_LINE_RE, DEFAULT_RESTORED_SESSION_HISTORY_MAX_LINES, DEICTIC_CONTINUATION_TERMS, SESSIONS_DIR, SESSIONS_INDEX, TUI_STATE_SUFFIX, AUTHORED_SESSION_LINE, VISUAL_CHROME_LINE, SKIP_DIRS3, HOME_SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
646036
646021
  var init_omnius_directory = __esm({
646037
646022
  "packages/cli/src/tui/omnius-directory.ts"() {
646038
646023
  init_dist5();
@@ -646056,6 +646041,7 @@ var init_omnius_directory = __esm({
646056
646041
  HANDOFF_FILE = "task-handoff.json";
646057
646042
  CONTEXT_SAVE_FILE = "session-context.json";
646058
646043
  CONTEXT_LEDGER_FILE = "session-context.events.jsonl";
646044
+ COMPACTION_AUDIT_FILE = "compactions.jsonl";
646059
646045
  MAX_CONTEXT_ENTRIES = 200;
646060
646046
  MAX_SESSION_DIARY_ENTRIES = 80;
646061
646047
  MAX_SESSION_DIARY_DETAILED_ENTRIES = 50;
@@ -664897,6 +664883,7 @@ __export(daemon_exports, {
664897
664883
  ensureDaemonVersion: () => ensureDaemonVersion,
664898
664884
  forceKillDaemon: () => forceKillDaemon,
664899
664885
  getDaemonPid: () => getDaemonPid,
664886
+ getDaemonReportedIdentity: () => getDaemonReportedIdentity,
664900
664887
  getDaemonReportedVersion: () => getDaemonReportedVersion,
664901
664888
  getDaemonStatus: () => getDaemonStatus,
664902
664889
  getLocalCliVersion: () => getLocalCliVersion,
@@ -665048,17 +665035,26 @@ function getLocalCliVersion() {
665048
665035
  }
665049
665036
  return "0.0.0";
665050
665037
  }
665051
- async function getDaemonReportedVersion(port) {
665038
+ async function getDaemonReportedIdentity(port) {
665052
665039
  const p2 = port ?? getDaemonPort();
665053
665040
  try {
665054
665041
  const resp = await fetch(`http://127.0.0.1:${p2}/health`, { signal: AbortSignal.timeout(2e3) });
665055
665042
  if (!resp.ok) return null;
665056
665043
  const data = await resp.json();
665057
- return data.version ?? null;
665044
+ const version5 = data.boot_version ?? data.version;
665045
+ if (!version5) return null;
665046
+ return {
665047
+ version: version5,
665048
+ bootVersion: data.boot_version ?? version5,
665049
+ bootPackageHash: data.boot_package_hash ?? null
665050
+ };
665058
665051
  } catch {
665059
665052
  return null;
665060
665053
  }
665061
665054
  }
665055
+ async function getDaemonReportedVersion(port) {
665056
+ return (await getDaemonReportedIdentity(port))?.bootVersion ?? null;
665057
+ }
665062
665058
  async function waitForDaemonReady(port, expectedVersion, attempts = 24) {
665063
665059
  let observedVersion = null;
665064
665060
  for (let attempt = 0; attempt < attempts; attempt++) {
@@ -665112,6 +665108,8 @@ async function repairManagedDaemonUnit(port) {
665112
665108
  `Description=Omnius API Daemon (port ${port})`,
665113
665109
  "After=network-online.target",
665114
665110
  "Wants=network-online.target",
665111
+ "StartLimitIntervalSec=30",
665112
+ "StartLimitBurst=10",
665115
665113
  "",
665116
665114
  "[Service]",
665117
665115
  "Type=simple",
@@ -665121,8 +665119,6 @@ async function repairManagedDaemonUnit(port) {
665121
665119
  `ExecStart=${execStart}`,
665122
665120
  "Restart=always",
665123
665121
  "RestartSec=3",
665124
- "StartLimitIntervalSec=30",
665125
- "StartLimitBurst=10",
665126
665122
  `StandardOutput=append:${join149(logDir, "daemon.log")}`,
665127
665123
  `StandardError=append:${join149(logDir, "daemon.err.log")}`,
665128
665124
  "",
@@ -665450,13 +665446,14 @@ async function recoverDaemonVersionBoundedly(expectedVersion, observe, recover,
665450
665446
  return { ok: false, observedVersion, attempts: boundedAttempts };
665451
665447
  }
665452
665448
  async function ensureDaemonVersion(expectedVersion = getLocalCliVersion(), port = getDaemonPort()) {
665453
- const finish = (ok3, action, observedVersion, recoveryAttempts = 0) => ({
665449
+ const finish = (ok3, action, observedVersion, recoveryAttempts = 0, requiresPrivilegedMigration = false) => ({
665454
665450
  ok: ok3,
665455
665451
  action,
665456
665452
  expectedVersion,
665457
665453
  observedVersion,
665458
665454
  port,
665459
- recoveryAttempts
665455
+ recoveryAttempts,
665456
+ requiresPrivilegedMigration
665460
665457
  });
665461
665458
  if (await isDaemonRunning(port)) {
665462
665459
  if (process.env["OMNIUS_NO_VERSION_GUARD"] !== "1") {
@@ -665471,7 +665468,8 @@ async function ensureDaemonVersion(expectedVersion = getLocalCliVersion(), port
665471
665468
  recovery.ok,
665472
665469
  recovery.ok ? "restarted" : "failed",
665473
665470
  recovery.observedVersion,
665474
- recovery.attempts
665471
+ recovery.attempts,
665472
+ !recovery.ok && process.platform === "linux"
665475
665473
  );
665476
665474
  }
665477
665475
  }
@@ -673385,52 +673383,83 @@ async function acquireSudoCredentials(ctx3, reason) {
673385
673383
  });
673386
673384
  });
673387
673385
  }
673386
+ async function runSudoScriptChecked(ctx3, script) {
673387
+ const { spawn: spawn40 } = await import("node:child_process");
673388
+ const full = `set -e; ${script}`;
673389
+ await withTransientTerminalPrivilegePrompt(
673390
+ ctx3,
673391
+ "Running elevated system changes.",
673392
+ () => new Promise((resolve82, reject) => {
673393
+ const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
673394
+ const hasInteractiveTty = Boolean(
673395
+ process.stdin.isTTY && process.stdout.isTTY
673396
+ );
673397
+ const cmd = isRoot ? "bash" : "sudo";
673398
+ const args = isRoot ? ["-lc", full] : hasInteractiveTty ? ["bash", "-lc", full] : ["-n", "bash", "-lc", full];
673399
+ const child = spawn40(cmd, args, {
673400
+ stdio: hasInteractiveTty ? "inherit" : ["ignore", "pipe", "pipe"],
673401
+ env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
673402
+ });
673403
+ let stdout = "";
673404
+ let stderr = "";
673405
+ child.stdout?.on("data", (data) => {
673406
+ stdout += data.toString();
673407
+ });
673408
+ child.stderr?.on("data", (data) => {
673409
+ stderr += data.toString();
673410
+ });
673411
+ onChildExit(child, (code8) => {
673412
+ if (code8 === 0) {
673413
+ resolve82();
673414
+ return;
673415
+ }
673416
+ reject(
673417
+ new Error(
673418
+ (stderr || stdout || `elevated command exited with ${code8}`).trim().slice(0, 500)
673419
+ )
673420
+ );
673421
+ });
673422
+ onChildError(child, (err) => reject(err));
673423
+ })
673424
+ );
673425
+ }
673388
673426
  async function runSudoScript(ctx3, script) {
673389
673427
  try {
673390
- const { spawn: spawn40 } = await import("node:child_process");
673391
- const full = `set -e; ${script}`;
673392
- await withTransientTerminalPrivilegePrompt(
673393
- ctx3,
673394
- "Running elevated system changes.",
673395
- () => new Promise((resolve82, reject) => {
673396
- const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
673397
- const hasInteractiveTty = Boolean(
673398
- process.stdin.isTTY && process.stdout.isTTY
673399
- );
673400
- const cmd = isRoot ? "bash" : "sudo";
673401
- const args = isRoot ? ["-lc", full] : hasInteractiveTty ? ["bash", "-lc", full] : ["-n", "bash", "-lc", full];
673402
- const child = spawn40(cmd, args, {
673403
- stdio: hasInteractiveTty ? "inherit" : ["ignore", "pipe", "pipe"],
673404
- env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
673405
- });
673406
- let stdout = "";
673407
- let stderr = "";
673408
- child.stdout?.on("data", (data) => {
673409
- stdout += data.toString();
673410
- });
673411
- child.stderr?.on("data", (data) => {
673412
- stderr += data.toString();
673413
- });
673414
- onChildExit(child, (code8) => {
673415
- if (code8 === 0) {
673416
- resolve82();
673417
- return;
673418
- }
673419
- reject(
673420
- new Error(
673421
- (stderr || stdout || `elevated command exited with ${code8}`).trim().slice(0, 500)
673422
- )
673423
- );
673424
- });
673425
- onChildError(child, (err) => reject(err));
673426
- })
673427
- );
673428
+ await runSudoScriptChecked(ctx3, script);
673428
673429
  } catch (err) {
673429
673430
  renderWarning(
673430
673431
  `Elevated command failed: ${err instanceof Error ? err.message : String(err)}`
673431
673432
  );
673432
673433
  }
673433
673434
  }
673435
+ async function migrateAttestedPrivilegedDaemonOwner(ctx3, port) {
673436
+ if (process.platform !== "linux" || !Number.isInteger(port) || port <= 0) {
673437
+ return false;
673438
+ }
673439
+ const script = [
673440
+ "set -euo pipefail",
673441
+ `port=${port}`,
673442
+ "found=0",
673443
+ "for pid in $( { lsof -nP -t -iTCP:${port} -sTCP:LISTEN 2>/dev/null || true; fuser ${port}/tcp 2>/dev/null || true; } | tr ' ' '\\n' | sort -un); do",
673444
+ " [ -r /proc/$pid/cmdline ] || continue",
673445
+ " cmd=$(tr '\\000' ' ' </proc/$pid/cmdline)",
673446
+ ' case "$cmd" in *omnius*serve*--daemon*) ;; *) continue ;; esac',
673447
+ " unit=$(sed -nE 's#.*(/[^:]*\\.service).*#\\1#p' /proc/$pid/cgroup | head -n1 | sed 's#.*/##')",
673448
+ ' [ "$unit" = power-monitor.service ] || continue',
673449
+ ' echo "Migrating attested Omnius daemon owner: $unit (pid $pid)"',
673450
+ ' systemctl restart "$unit"',
673451
+ " found=1",
673452
+ " break",
673453
+ "done",
673454
+ '[ "$found" = 1 ]'
673455
+ ].join("\n");
673456
+ try {
673457
+ await runSudoScriptChecked(ctx3, script);
673458
+ return true;
673459
+ } catch {
673460
+ return false;
673461
+ }
673462
+ }
673434
673463
  async function ensureVoiceDeps(ctx3) {
673435
673464
  try {
673436
673465
  const mod3 = await Promise.resolve().then(() => (init_py_embed(), py_embed_exports));
@@ -689147,13 +689176,29 @@ async function handleUpdate(subcommand, ctx3) {
689147
689176
  installOverlay.setStatus("Gracefully upgrading shared daemon...");
689148
689177
  const { ensureDaemonVersion: ensureDaemonVersion2, getLocalCliVersion: getLocalCliVersion2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
689149
689178
  const expectedDaemonVersion = getLocalCliVersion2();
689150
- const daemonUpgrade = await ensureDaemonVersion2(expectedDaemonVersion);
689179
+ let daemonUpgrade = await ensureDaemonVersion2(expectedDaemonVersion);
689180
+ if (!daemonUpgrade.ok && daemonUpgrade.requiresPrivilegedMigration) {
689181
+ installOverlay.stop("Migrating the verified privileged daemon owner...");
689182
+ await new Promise((r2) => setTimeout(r2, 300));
689183
+ installOverlay.dismiss();
689184
+ const migrated = await migrateAttestedPrivilegedDaemonOwner(
689185
+ ctx3,
689186
+ daemonUpgrade.port
689187
+ );
689188
+ if (migrated) {
689189
+ const migrationOverlay = startInstallOverlay(targetVersion);
689190
+ Object.assign(installOverlay, migrationOverlay);
689191
+ installOverlay.setPhase("Daemon");
689192
+ installOverlay.setStatus("Verifying the migrated daemon...");
689193
+ daemonUpgrade = await ensureDaemonVersion2(expectedDaemonVersion);
689194
+ }
689195
+ }
689151
689196
  if (!daemonUpgrade.ok) {
689152
689197
  installOverlay.stop("Update installed, but daemon upgrade was not verified");
689153
689198
  await new Promise((r2) => setTimeout(r2, 1200));
689154
689199
  installOverlay.dismiss();
689155
689200
  renderError(
689156
- `Updated CLI to ${expectedDaemonVersion}, but automatic daemon recovery exhausted ${daemonUpgrade.recoveryAttempts} verified restart round(s) and the shared daemon still reports ${daemonUpgrade.observedVersion ?? "unavailable"}. The TUI remains open. Run /daemon status and inspect ~/.omnius/daemon.err.log; the service may be blocked outside Omnius.`
689201
+ `Updated CLI to ${expectedDaemonVersion}, but the shared daemon still reports ${daemonUpgrade.observedVersion ?? "unavailable"} after ${daemonUpgrade.recoveryAttempts} verified recovery round(s). A privileged owner was ${daemonUpgrade.requiresPrivilegedMigration ? "not safely migratable" : "not detected"}; no arbitrary port holder was terminated.`
689157
689202
  );
689158
689203
  return;
689159
689204
  }
@@ -745062,6 +745107,7 @@ var init_embedding_workers = __esm({
745062
745107
  var serve_exports = {};
745063
745108
  __export(serve_exports, {
745064
745109
  apiServeCommand: () => apiServeCommand,
745110
+ readServerPackageIdentity: () => readServerPackageIdentity,
745065
745111
  startApiServer: () => startApiServer
745066
745112
  });
745067
745113
  import * as http5 from "node:http";
@@ -745086,8 +745132,7 @@ import {
745086
745132
  readSync as readSync4,
745087
745133
  closeSync as closeSync8
745088
745134
  } from "node:fs";
745089
- import { randomBytes as randomBytes29, randomUUID as randomUUID21, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
745090
- import { createHash as createHash52 } from "node:crypto";
745135
+ import { createHash as createHash52, randomBytes as randomBytes29, randomUUID as randomUUID21, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
745091
745136
  function memoryDbPaths3(baseDir = process.cwd()) {
745092
745137
  const dir = join183(baseDir, ".omnius");
745093
745138
  return {
@@ -745096,7 +745141,7 @@ function memoryDbPaths3(baseDir = process.cwd()) {
745096
745141
  knowledge: join183(dir, "knowledge.db")
745097
745142
  };
745098
745143
  }
745099
- function getVersion3() {
745144
+ function readServerPackageIdentity() {
745100
745145
  try {
745101
745146
  const thisDir = dirname56(fileURLToPath23(import.meta.url));
745102
745147
  const candidates = [
@@ -745107,9 +745152,14 @@ function getVersion3() {
745107
745152
  for (const pkgPath of candidates) {
745108
745153
  try {
745109
745154
  if (!existsSync173(pkgPath)) continue;
745110
- const pkg = JSON.parse(readFileSync140(pkgPath, "utf8"));
745155
+ const raw = readFileSync140(pkgPath, "utf8");
745156
+ const pkg = JSON.parse(raw);
745111
745157
  if (pkg.name === "omnius" || pkg.name === "@omnius/cli" || pkg.name === "@omnius/monorepo") {
745112
- return pkg.version ?? "0.0.0";
745158
+ return {
745159
+ version: pkg.version ?? "0.0.0",
745160
+ packagePath: pkgPath,
745161
+ packageHash: createHash52("sha256").update(raw).digest("hex")
745162
+ };
745113
745163
  }
745114
745164
  } catch {
745115
745165
  continue;
@@ -745117,7 +745167,10 @@ function getVersion3() {
745117
745167
  }
745118
745168
  } catch {
745119
745169
  }
745120
- return "0.0.0";
745170
+ return { version: "0.0.0", packagePath: null, packageHash: null };
745171
+ }
745172
+ function getVersion3() {
745173
+ return SERVER_BOOT_IDENTITY.version;
745121
745174
  }
745122
745175
  function normalizeLocalhostForDaemon(url) {
745123
745176
  if (process.env["OMNIUS_KEEP_LOCALHOST"] === "1") return url;
@@ -746923,7 +746976,12 @@ function handleHealth(res) {
746923
746976
  jsonResponse(res, 200, {
746924
746977
  status: "ok",
746925
746978
  uptime_s: Math.floor((Date.now() - startedAt) / 1e3),
746926
- version: version5
746979
+ version: version5,
746980
+ // `version` is retained for old clients. These explicit boot fields let
746981
+ // an updater prove that the process, rather than only its install path,
746982
+ // changed after an npm swap.
746983
+ boot_version: SERVER_BOOT_IDENTITY.version,
746984
+ boot_package_hash: SERVER_BOOT_IDENTITY.packageHash
746927
746985
  });
746928
746986
  }
746929
746987
  async function handleHealthReady(res, ollamaUrl) {
@@ -746956,6 +747014,8 @@ function handleVersion(res) {
746956
747014
  const version5 = getVersion3();
746957
747015
  jsonResponse(res, 200, {
746958
747016
  version: version5,
747017
+ boot_version: SERVER_BOOT_IDENTITY.version,
747018
+ boot_package_hash: SERVER_BOOT_IDENTITY.packageHash,
746959
747019
  node: process.version,
746960
747020
  platform: process.platform
746961
747021
  });
@@ -754485,27 +754545,11 @@ function startApiServer(options2 = {}) {
754485
754545
  omnius API server v${version5}
754486
754546
  `);
754487
754547
  if (process.env["OMNIUS_DAEMON"] === "1" && process.env["OMNIUS_NO_VERSION_GUARD"] !== "1") {
754488
- const readDiskVersion = () => {
754489
- try {
754490
- const here = dirname56(fileURLToPath23(import.meta.url));
754491
- for (const rel of ["../package.json", "../../package.json", "../../../package.json", "../../../../package.json"]) {
754492
- const p2 = join183(here, rel);
754493
- if (existsSync173(p2)) {
754494
- const pkg = JSON.parse(readFileSync140(p2, "utf8"));
754495
- if (pkg.name === "omnius" || pkg.name === "@omnius/cli" || pkg.name === "@omnius/monorepo") {
754496
- return pkg.version ?? null;
754497
- }
754498
- }
754499
- }
754500
- } catch {
754501
- }
754502
- return null;
754503
- };
754504
- const bootVersion = readDiskVersion() ?? version5;
754548
+ const bootIdentity = SERVER_BOOT_IDENTITY;
754505
754549
  const versionWatch = setInterval(() => {
754506
- const disk = readDiskVersion();
754507
- if (disk && disk !== bootVersion) {
754508
- log22(` [daemon] version changed on disk ${bootVersion} -> ${disk}; restarting for the new version…
754550
+ const disk = readServerPackageIdentity();
754551
+ if (disk.version !== bootIdentity.version || disk.packageHash && disk.packageHash !== bootIdentity.packageHash) {
754552
+ log22(` [daemon] package identity changed on disk ${bootIdentity.version} -> ${disk.version}; restarting for the new version…
754509
754553
  `);
754510
754554
  try {
754511
754555
  server2.close(() => process.exit(0));
@@ -755387,7 +755431,7 @@ function setTimerEnabled(name10, enabled2) {
755387
755431
  return false;
755388
755432
  }
755389
755433
  }
755390
- var require4, NEXUS_DIRECTORY_ORIGIN2, NEXUS_SPONSORS_URL2, endpointRegistry, modelRouteMap, endpointUsage, _lastEndpointDiagnostics, BACKEND_TIMEOUT_DEFAULT_MS, BACKEND_TIMEOUT_MAX_MS, MODEL_LIST_TIMEOUT_DEFAULT_MS, metrics, startedAt, FILE_MIME_BY_EXT, realtimeOllamaFallbackCache, runningProcesses, LOCAL_UI_SESSION_COOKIE, LOCAL_UI_SESSION_TOKEN, perKeyUsage, CRON_MARKER2;
755434
+ var require4, NEXUS_DIRECTORY_ORIGIN2, NEXUS_SPONSORS_URL2, SERVER_BOOT_IDENTITY, endpointRegistry, modelRouteMap, endpointUsage, _lastEndpointDiagnostics, BACKEND_TIMEOUT_DEFAULT_MS, BACKEND_TIMEOUT_MAX_MS, MODEL_LIST_TIMEOUT_DEFAULT_MS, metrics, startedAt, FILE_MIME_BY_EXT, realtimeOllamaFallbackCache, runningProcesses, LOCAL_UI_SESSION_COOKIE, LOCAL_UI_SESSION_TOKEN, perKeyUsage, CRON_MARKER2;
755391
755435
  var init_serve = __esm({
755392
755436
  "packages/cli/src/api/serve.ts"() {
755393
755437
  init_config();
@@ -755424,6 +755468,7 @@ var init_serve = __esm({
755424
755468
  require4 = createRequire8(import.meta.url);
755425
755469
  NEXUS_DIRECTORY_ORIGIN2 = (process.env["OMNIUS_NEXUS_DIRECTORY_ORIGIN"] || process.env["OMNIUS_NEXUS_SIGNALING_SERVER"] || "https://openagents.nexus").replace(/\/+$/, "");
755426
755470
  NEXUS_SPONSORS_URL2 = `${NEXUS_DIRECTORY_ORIGIN2}/api/v1/sponsors`;
755471
+ SERVER_BOOT_IDENTITY = readServerPackageIdentity();
755427
755472
  endpointRegistry = [];
755428
755473
  modelRouteMap = /* @__PURE__ */ new Map();
755429
755474
  endpointUsage = /* @__PURE__ */ new Map();
@@ -756584,6 +756629,57 @@ function appendSubAgentNoteBox(statusBar, agentId, event, title, metrics2, conte
756584
756629
  spec
756585
756630
  );
756586
756631
  }
756632
+ function prepareCompactionAudit(event) {
756633
+ const record = event.compaction;
756634
+ if (!record) {
756635
+ return {
756636
+ display: event.content ?? "Context compacted (legacy event without an audit payload).",
756637
+ ledger: {
756638
+ schemaVersion: 1,
756639
+ timestamp: event.timestamp,
756640
+ legacy: true,
756641
+ summary: event.content ?? "",
756642
+ removedMessages: []
756643
+ }
756644
+ };
756645
+ }
756646
+ const redactor = getSecretRedactor();
756647
+ const removedMessages = record.removedMessages.map((message2) => ({
756648
+ ...message2,
756649
+ content: redactor.redactText(message2.content)
756650
+ }));
756651
+ const summary = redactor.redactText(record.summary);
756652
+ const lines = [
756653
+ "[COMPACTION AUDIT]",
756654
+ `id=${record.id}`,
756655
+ `reason=context budget; strategy=${record.strategy}${record.manual ? "; manual" : ""}`,
756656
+ `tokens=~${record.beforeTokens.toLocaleString()} → ~${record.afterTokens.toLocaleString()} (saved ~${record.savedTokens.toLocaleString()})`,
756657
+ `removed=${removedMessages.length}; retained=${record.retainedMessages}`,
756658
+ "ledger=.omnius/context/compactions.jsonl",
756659
+ "",
756660
+ "Summary retained for the model:",
756661
+ summary || "(none)",
756662
+ "",
756663
+ `Exact removed model-visible messages (${removedMessages.length}):`
756664
+ ];
756665
+ for (const message2 of removedMessages) {
756666
+ lines.push(
756667
+ `--- removed[${message2.index}] role=${message2.role} chars=${message2.chars} reason=${message2.reason}${message2.toolCallId ? ` tool_call_id=${message2.toolCallId}` : ""} ---`,
756668
+ message2.content || "(empty)"
756669
+ );
756670
+ }
756671
+ return {
756672
+ display: lines.join("\n"),
756673
+ ledger: {
756674
+ schemaVersion: 1,
756675
+ ...record,
756676
+ summary,
756677
+ removedMessages,
756678
+ recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
756679
+ source: "interactive-tui"
756680
+ }
756681
+ };
756682
+ }
756587
756683
  function writeSubAgentEventForView(statusBar, agentId, event, verbose = false) {
756588
756684
  const previewLine = formatSubAgentEventForView(event);
756589
756685
  statusBar.updateAgentViewEvent(agentId, event, previewLine ?? event.type);
@@ -759336,11 +759432,18 @@ ${entry.fullContent}`
759336
759432
  statusBar?.updateTrajectoryCheckpoint(event.trajectory ?? null);
759337
759433
  break;
759338
759434
  case "compaction":
759435
+ const compactionAudit = prepareCompactionAudit(event);
759436
+ appendCompactionAudit(process.cwd(), compactionAudit.ledger);
759339
759437
  if (isNeovimActive()) {
759340
- writeToNeovimOutput("\x1B[33m⚠ Context compacted\x1B[0m\r\n");
759438
+ writeToNeovimOutput("\x1B[33m⚠ Context compacted — audit: .omnius/context/compactions.jsonl\x1B[0m\r\n");
759341
759439
  } else {
759342
759440
  contentWrite(
759343
- () => renderWarning(`Context compacted: ${event.content}`)
759441
+ () => renderToolResult(
759442
+ "context_compaction",
759443
+ true,
759444
+ compactionAudit.display,
759445
+ { verbose: config.verbose }
759446
+ )
759344
759447
  );
759345
759448
  }
759346
759449
  if (onCompaction) onCompaction();