omnius 1.0.556 → 1.0.557

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
@@ -9349,9 +9349,9 @@ function normalizeCameraRotationDegrees(value2) {
9349
9349
  const raw = String(value2).trim().toLowerCase();
9350
9350
  if (!raw)
9351
9351
  return 0;
9352
- const numeric = Number(raw.replace(/deg(?:rees)?$/i, ""));
9353
- if (Number.isFinite(numeric))
9354
- return normalizeCameraRotationDegrees(numeric);
9352
+ const numeric2 = Number(raw.replace(/deg(?:rees)?$/i, ""));
9353
+ if (Number.isFinite(numeric2))
9354
+ return normalizeCameraRotationDegrees(numeric2);
9355
9355
  if (["none", "off", "upright", "normal", "0"].includes(raw))
9356
9356
  return 0;
9357
9357
  if (["cw", "clockwise", "right", "rotate-cw", "rotate_cw", "90"].includes(raw))
@@ -26877,6 +26877,16 @@ function isRetirableEvidence(message2, minChars) {
26877
26877
  }
26878
26878
  function foldEvidenceOutcome(message2) {
26879
26879
  const text2 = message2.content;
26880
+ const admissionBlock = text2.match(RUNTIME_ADMISSION_BLOCK);
26881
+ if (admissionBlock) {
26882
+ const after = text2.slice((admissionBlock.index ?? 0) + admissionBlock[0].length);
26883
+ const reason = after.split("\n").map((line) => line.trim()).find((line) => line.length > 0 && !/^\w+=/.test(line));
26884
+ return `runtime admission: ${admissionBlock[0]}${reason ? ` — ${reason.slice(0, 160)}` : ""}`;
26885
+ }
26886
+ const runtimeException = text2.match(RUNTIME_EXCEPTION_LINE);
26887
+ if (runtimeException) {
26888
+ return `runtime exception: ${runtimeException[0].trim().slice(0, 220)}`;
26889
+ }
26880
26890
  const diag = extractDiagnosticSymbols(text2);
26881
26891
  if (diag.count > 0) {
26882
26892
  const syms = diag.symbols.slice(0, 6);
@@ -26938,12 +26948,14 @@ function retireStaleEvidence(messages2, options2) {
26938
26948
  });
26939
26949
  return { messages: out, retiredCount, reclaimedChars };
26940
26950
  }
26941
- var DIAG_LINE, QUOTED_SYMBOL, EVIDENCE_MARKERS;
26951
+ var DIAG_LINE, QUOTED_SYMBOL, RUNTIME_ADMISSION_BLOCK, RUNTIME_EXCEPTION_LINE, EVIDENCE_MARKERS;
26942
26952
  var init_evidence_retirement = __esm({
26943
26953
  "packages/memory/dist/evidence-retirement.js"() {
26944
26954
  "use strict";
26945
26955
  DIAG_LINE = /\berror\b\s*:/i;
26946
26956
  QUOTED_SYMBOL = /['"`]([A-Za-z_][A-Za-z0-9_:.<>]{1,80})['"`]/g;
26957
+ RUNTIME_ADMISSION_BLOCK = /\[(?:COMPILE ERROR FIX LOOP BLOCKED|EXPLORATION ADMISSION BLOCK|PARENT(?:\s+[^\]]*)?\s+BLOCK(?:ED)?|FOCUS SUPERVISOR BLOCK|STEERING RECONCILIATION REQUIRED|STALE EDIT LOOP BLOCKED|FULL FILE WRITE LOOP BLOCKED)[^\]]*\]/i;
26958
+ RUNTIME_EXCEPTION_LINE = /^\s*(?:[A-Za-z_][\w.]*?(?:Error|Exception)|AssertionError)\s*:\s*(.+)$/m;
26947
26959
  EVIDENCE_MARKERS = [
26948
26960
  "[SHELL TRANSCRIPT]",
26949
26961
  "[FILE CONTEXT",
@@ -62146,12 +62158,12 @@ var init_mock_stream = __esm({
62146
62158
  });
62147
62159
 
62148
62160
  // ../node_modules/unlimited-timeout/index.js
62149
- function setTimeout2(callback, delay4, ...arguments_) {
62161
+ function setTimeout2(callback, delay5, ...arguments_) {
62150
62162
  if (typeof callback !== "function") {
62151
62163
  throw new TypeError("Expected callback to be a function");
62152
62164
  }
62153
- delay4 ??= 0;
62154
- delay4 = Number(delay4);
62165
+ delay5 ??= 0;
62166
+ delay5 = Number(delay5);
62155
62167
  let shouldUnref = false;
62156
62168
  const timeout2 = {
62157
62169
  [brandSymbol]: true,
@@ -62168,13 +62180,13 @@ function setTimeout2(callback, delay4, ...arguments_) {
62168
62180
  return timeout2;
62169
62181
  }
62170
62182
  };
62171
- if (delay4 === Number.POSITIVE_INFINITY || delay4 > Number.MAX_SAFE_INTEGER) {
62183
+ if (delay5 === Number.POSITIVE_INFINITY || delay5 > Number.MAX_SAFE_INTEGER) {
62172
62184
  return timeout2;
62173
62185
  }
62174
- if (!Number.isFinite(delay4) || delay4 < 0) {
62175
- delay4 = 0;
62186
+ if (!Number.isFinite(delay5) || delay5 < 0) {
62187
+ delay5 = 0;
62176
62188
  }
62177
- const targetTime = performance.now() + delay4;
62189
+ const targetTime = performance.now() + delay5;
62178
62190
  const schedule = (remainingDelay) => {
62179
62191
  if (timeout2.cleared) {
62180
62192
  return;
@@ -62199,7 +62211,7 @@ function setTimeout2(callback, delay4, ...arguments_) {
62199
62211
  }
62200
62212
  }
62201
62213
  };
62202
- schedule(delay4);
62214
+ schedule(delay5);
62203
62215
  return timeout2;
62204
62216
  }
62205
62217
  function clearTimeout2(timeout2) {
@@ -72204,15 +72216,15 @@ var init_dist3 = __esm({
72204
72216
  const activeTicksCount = this.#getActiveTicksCount();
72205
72217
  if (activeTicksCount >= this.#intervalCap) {
72206
72218
  const oldestTick = this.#strictTicks[this.#strictTicksStartIndex];
72207
- const delay4 = this.#interval - (now2 - oldestTick);
72208
- this.#createIntervalTimeout(delay4);
72219
+ const delay5 = this.#interval - (now2 - oldestTick);
72220
+ this.#createIntervalTimeout(delay5);
72209
72221
  return true;
72210
72222
  }
72211
72223
  return false;
72212
72224
  }
72213
72225
  if (this.#intervalId === void 0) {
72214
- const delay4 = this.#intervalEnd - now2;
72215
- if (delay4 < 0) {
72226
+ const delay5 = this.#intervalEnd - now2;
72227
+ if (delay5 < 0) {
72216
72228
  if (this.#lastExecutionTime > 0) {
72217
72229
  const timeSinceLastExecution = now2 - this.#lastExecutionTime;
72218
72230
  if (timeSinceLastExecution < this.#interval) {
@@ -72222,19 +72234,19 @@ var init_dist3 = __esm({
72222
72234
  }
72223
72235
  this.#intervalCount = this.#carryoverIntervalCount ? this.#pending : 0;
72224
72236
  } else {
72225
- this.#createIntervalTimeout(delay4);
72237
+ this.#createIntervalTimeout(delay5);
72226
72238
  return true;
72227
72239
  }
72228
72240
  }
72229
72241
  return false;
72230
72242
  }
72231
- #createIntervalTimeout(delay4) {
72243
+ #createIntervalTimeout(delay5) {
72232
72244
  if (this.#timeoutId !== void 0) {
72233
72245
  return;
72234
72246
  }
72235
72247
  this.#timeoutId = setTimeout(() => {
72236
72248
  this.#onResumeInterval();
72237
- }, delay4);
72249
+ }, delay5);
72238
72250
  }
72239
72251
  #clearIntervalTimer() {
72240
72252
  if (this.#intervalId) {
@@ -84795,8 +84807,8 @@ function validateKeyName(name10) {
84795
84807
  async function randomDelay() {
84796
84808
  const min = 200;
84797
84809
  const max = 1e3;
84798
- const delay4 = Math.random() * (max - min) + min;
84799
- await new Promise((resolve82) => setTimeout(resolve82, delay4));
84810
+ const delay5 = Math.random() * (max - min) + min;
84811
+ await new Promise((resolve82) => setTimeout(resolve82, delay5));
84800
84812
  }
84801
84813
  function DsName(name10) {
84802
84814
  return new Key(keyPrefix + name10);
@@ -97999,13 +98011,13 @@ var require_lazy_helpers = __commonJS({
97999
98011
  }
98000
98012
  };
98001
98013
  exports.DelayedConstructor = DelayedConstructor;
98002
- function delay4(wrappedConstructor) {
98014
+ function delay5(wrappedConstructor) {
98003
98015
  if (typeof wrappedConstructor === "undefined") {
98004
98016
  throw new Error("Attempt to `delay` undefined. Constructor must be wrapped in a callback");
98005
98017
  }
98006
98018
  return new DelayedConstructor(wrappedConstructor);
98007
98019
  }
98008
- exports.delay = delay4;
98020
+ exports.delay = delay5;
98009
98021
  }
98010
98022
  });
98011
98023
 
@@ -103023,12 +103035,12 @@ var require_x509_cjs = __commonJS({
103023
103035
  var require_crypto = __commonJS({
103024
103036
  "../node_modules/acme-client/src/crypto/index.js"(exports) {
103025
103037
  var net5 = __require("net");
103026
- var { promisify: promisify9 } = __require("util");
103038
+ var { promisify: promisify10 } = __require("util");
103027
103039
  var crypto14 = __require("crypto");
103028
103040
  var asn1js4 = require_build2();
103029
103041
  var x5093 = require_x509_cjs();
103030
- var randomInt2 = promisify9(crypto14.randomInt);
103031
- var generateKeyPair2 = promisify9(crypto14.generateKeyPair);
103042
+ var randomInt2 = promisify10(crypto14.randomInt);
103043
+ var generateKeyPair2 = promisify10(crypto14.generateKeyPair);
103032
103044
  x5093.cryptoProvider.set(crypto14.webcrypto);
103033
103045
  var subjectAltNameOID = "2.5.29.17";
103034
103046
  var alpnAcmeIdentifierOID = "1.3.6.1.5.5.7.1.31";
@@ -137873,9 +137885,9 @@ var require_lib = __commonJS({
137873
137885
  var require_forge2 = __commonJS({
137874
137886
  "../node_modules/acme-client/src/crypto/forge.js"(exports) {
137875
137887
  var net5 = __require("net");
137876
- var { promisify: promisify9 } = __require("util");
137888
+ var { promisify: promisify10 } = __require("util");
137877
137889
  var forge = require_lib();
137878
- var generateKeyPair2 = promisify9(forge.pki.rsa.generateKeyPair);
137890
+ var generateKeyPair2 = promisify10(forge.pki.rsa.generateKeyPair);
137879
137891
  function forgeObjectFromPem(input) {
137880
137892
  const msg = forge.pem.decode(input)[0];
137881
137893
  let result;
@@ -142419,9 +142431,9 @@ var require_timers = __commonJS({
142419
142431
  * before the specified function or code is executed.
142420
142432
  * @param {*} arg
142421
142433
  */
142422
- constructor(callback, delay4, arg) {
142434
+ constructor(callback, delay5, arg) {
142423
142435
  this._onTimeout = callback;
142424
- this._idleTimeout = delay4;
142436
+ this._idleTimeout = delay5;
142425
142437
  this._timerArg = arg;
142426
142438
  this.refresh();
142427
142439
  }
@@ -142466,8 +142478,8 @@ var require_timers = __commonJS({
142466
142478
  * when the timer expires.
142467
142479
  * @returns {NodeJS.Timeout|FastTimer}
142468
142480
  */
142469
- setTimeout(callback, delay4, arg) {
142470
- return delay4 <= RESOLUTION_MS ? setTimeout(callback, delay4, arg) : new FastTimer(callback, delay4, arg);
142481
+ setTimeout(callback, delay5, arg) {
142482
+ return delay5 <= RESOLUTION_MS ? setTimeout(callback, delay5, arg) : new FastTimer(callback, delay5, arg);
142471
142483
  },
142472
142484
  /**
142473
142485
  * The clearTimeout method cancels an instantiated Timer previously created
@@ -142493,8 +142505,8 @@ var require_timers = __commonJS({
142493
142505
  * when the timer expires.
142494
142506
  * @returns {FastTimer}
142495
142507
  */
142496
- setFastTimeout(callback, delay4, arg) {
142497
- return new FastTimer(callback, delay4, arg);
142508
+ setFastTimeout(callback, delay5, arg) {
142509
+ return new FastTimer(callback, delay5, arg);
142498
142510
  },
142499
142511
  /**
142500
142512
  * The clearTimeout method cancels an instantiated FastTimer previously
@@ -142520,8 +142532,8 @@ var require_timers = __commonJS({
142520
142532
  * @deprecated
142521
142533
  * @param {number} [delay=0] The delay in milliseconds to add to the now value.
142522
142534
  */
142523
- tick(delay4 = 0) {
142524
- fastNow += delay4 - RESOLUTION_MS + 1;
142535
+ tick(delay5 = 0) {
142536
+ fastNow += delay5 - RESOLUTION_MS + 1;
142525
142537
  onTick();
142526
142538
  onTick();
142527
142539
  },
@@ -148914,21 +148926,21 @@ var require_client_h1 = __commonJS({
148914
148926
  this.connection = "";
148915
148927
  this.maxResponseSize = client[kMaxResponseSize];
148916
148928
  }
148917
- setTimeout(delay4, type) {
148918
- if (delay4 !== this.timeoutValue || type & USE_FAST_TIMER ^ this.timeoutType & USE_FAST_TIMER) {
148929
+ setTimeout(delay5, type) {
148930
+ if (delay5 !== this.timeoutValue || type & USE_FAST_TIMER ^ this.timeoutType & USE_FAST_TIMER) {
148919
148931
  if (this.timeout) {
148920
148932
  timers.clearTimeout(this.timeout);
148921
148933
  this.timeout = null;
148922
148934
  }
148923
- if (delay4) {
148935
+ if (delay5) {
148924
148936
  if (type & USE_FAST_TIMER) {
148925
- this.timeout = timers.setFastTimeout(onParserTimeout, delay4, new WeakRef(this));
148937
+ this.timeout = timers.setFastTimeout(onParserTimeout, delay5, new WeakRef(this));
148926
148938
  } else {
148927
- this.timeout = setTimeout(onParserTimeout, delay4, new WeakRef(this));
148939
+ this.timeout = setTimeout(onParserTimeout, delay5, new WeakRef(this));
148928
148940
  this.timeout?.unref();
148929
148941
  }
148930
148942
  }
148931
- this.timeoutValue = delay4;
148943
+ this.timeoutValue = delay5;
148932
148944
  } else if (this.timeout) {
148933
148945
  if (this.timeout.refresh) {
148934
148946
  this.timeout.refresh();
@@ -154794,7 +154806,7 @@ var require_mock_utils = __commonJS({
154794
154806
  if (mockDispatch2.data.callback) {
154795
154807
  mockDispatch2.data = { ...mockDispatch2.data, ...mockDispatch2.data.callback(opts) };
154796
154808
  }
154797
- const { data: { statusCode, data, headers, trailers, error }, delay: delay4, persist: persist4 } = mockDispatch2;
154809
+ const { data: { statusCode, data, headers, trailers, error }, delay: delay5, persist: persist4 } = mockDispatch2;
154798
154810
  const { timesInvoked, times } = mockDispatch2;
154799
154811
  mockDispatch2.consumed = !persist4 && timesInvoked >= times;
154800
154812
  mockDispatch2.pending = timesInvoked < times;
@@ -154817,11 +154829,11 @@ var require_mock_utils = __commonJS({
154817
154829
  handler.onError(err);
154818
154830
  }
154819
154831
  handler.onConnect?.(abort, null);
154820
- if (typeof delay4 === "number" && delay4 > 0) {
154832
+ if (typeof delay5 === "number" && delay5 > 0) {
154821
154833
  timer = setTimeout(() => {
154822
154834
  timer = null;
154823
154835
  handleReply(this[kDispatches]);
154824
- }, delay4);
154836
+ }, delay5);
154825
154837
  } else {
154826
154838
  handleReply(this[kDispatches]);
154827
154839
  }
@@ -155101,7 +155113,7 @@ var require_mock_interceptor = __commonJS({
155101
155113
  var require_mock_client = __commonJS({
155102
155114
  "../node_modules/undici/lib/mock/mock-client.js"(exports, module) {
155103
155115
  "use strict";
155104
- var { promisify: promisify9 } = __require("node:util");
155116
+ var { promisify: promisify10 } = __require("node:util");
155105
155117
  var Client2 = require_client2();
155106
155118
  var { buildMockDispatch } = require_mock_utils();
155107
155119
  var {
@@ -155149,7 +155161,7 @@ var require_mock_client = __commonJS({
155149
155161
  this[kDispatches] = [];
155150
155162
  }
155151
155163
  async [kClose]() {
155152
- await promisify9(this[kOriginalClose])();
155164
+ await promisify10(this[kOriginalClose])();
155153
155165
  this[kConnected] = 0;
155154
155166
  this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
155155
155167
  }
@@ -155362,7 +155374,7 @@ var require_mock_call_history = __commonJS({
155362
155374
  var require_mock_pool = __commonJS({
155363
155375
  "../node_modules/undici/lib/mock/mock-pool.js"(exports, module) {
155364
155376
  "use strict";
155365
- var { promisify: promisify9 } = __require("node:util");
155377
+ var { promisify: promisify10 } = __require("node:util");
155366
155378
  var Pool = require_pool();
155367
155379
  var { buildMockDispatch } = require_mock_utils();
155368
155380
  var {
@@ -155410,7 +155422,7 @@ var require_mock_pool = __commonJS({
155410
155422
  this[kDispatches] = [];
155411
155423
  }
155412
155424
  async [kClose]() {
155413
- await promisify9(this[kOriginalClose])();
155425
+ await promisify10(this[kOriginalClose])();
155414
155426
  this[kConnected] = 0;
155415
155427
  this[kMockAgent][Symbols.kClients].delete(this[kOrigin]);
155416
155428
  }
@@ -288327,9 +288339,9 @@ function inferHoleRadius(lower) {
288327
288339
  function inferHoleCount(lower) {
288328
288340
  if (!/hole|bolt|mount|screw|fastener/.test(lower))
288329
288341
  return 0;
288330
- const numeric = lower.match(/\b(\d{1,2})\s*(?:x\s*)?(?:corner\s*)?(?:mounting\s*)?(?:holes?|bolts?|screws?|fasteners?)\b/);
288331
- if (numeric)
288332
- return clampInteger(Number(numeric[1]), 0, 16, 4);
288342
+ const numeric2 = lower.match(/\b(\d{1,2})\s*(?:x\s*)?(?:corner\s*)?(?:mounting\s*)?(?:holes?|bolts?|screws?|fasteners?)\b/);
288343
+ if (numeric2)
288344
+ return clampInteger(Number(numeric2[1]), 0, 16, 4);
288333
288345
  const wordCounts = {
288334
288346
  one: 1,
288335
288347
  two: 2,
@@ -289570,12 +289582,12 @@ ${plan.notes.map((n2) => `- ${n2}`).join("\n")}`,
289570
289582
  durationMs: Date.now() - t0
289571
289583
  };
289572
289584
  }
289573
- const delay4 = Math.min(BASE_DELAY * Math.pow(2, attempt - 1), MAX_BACKOFF);
289585
+ const delay5 = Math.min(BASE_DELAY * Math.pow(2, attempt - 1), MAX_BACKOFF);
289574
289586
  this.emitProgress({
289575
289587
  stage: "generate",
289576
- message: `Attempt ${attempt} ${msg.includes("timed out") ? "timed out" : "backend unavailable"}, retrying in ${Math.round(delay4 / 1e3)}s...`
289588
+ message: `Attempt ${attempt} ${msg.includes("timed out") ? "timed out" : "backend unavailable"}, retrying in ${Math.round(delay5 / 1e3)}s...`
289577
289589
  });
289578
- await new Promise((r2) => setTimeout(r2, delay4));
289590
+ await new Promise((r2) => setTimeout(r2, delay5));
289579
289591
  }
289580
289592
  }
289581
289593
  let result = {};
@@ -298094,6 +298106,9 @@ function validateCardTransition(from3, to) {
298094
298106
  return { valid: true, message: "transition allowed" };
298095
298107
  }
298096
298108
  function verifyCardEvidence(card) {
298109
+ const declaredVerifierEvidence = verifyDeclaredVerifierEvidence(card);
298110
+ if (!declaredVerifierEvidence.valid)
298111
+ return declaredVerifierEvidence;
298097
298112
  const compileEvidence = verifyCompileCardEvidence(card);
298098
298113
  if (!compileEvidence.valid)
298099
298114
  return compileEvidence;
@@ -298115,6 +298130,13 @@ function verifyCardEvidence(card) {
298115
298130
  });
298116
298131
  return { valid: missing.length === 0, missing };
298117
298132
  }
298133
+ function verifyDeclaredVerifierEvidence(card) {
298134
+ const verifier = normalizeCommandText(card.verifierCommand ?? "");
298135
+ if (!verifier)
298136
+ return { valid: true, missing: [] };
298137
+ const hasExactLiveCommand = card.evidence.some((evidence) => evidence.kind === "tool_result" && normalizeCommandText(evidence.command ?? "") === verifier);
298138
+ return hasExactLiveCommand ? { valid: true, missing: [] } : { valid: false, missing: [`live verifier output: ${card.verifierCommand}`] };
298139
+ }
298118
298140
  function verifyCompileCardEvidence(card) {
298119
298141
  if (!card.diagnosticFingerprint && !card.id.startsWith("compile-")) {
298120
298142
  return { valid: true, missing: [] };
@@ -491768,14 +491790,14 @@ ${content}
491768
491790
  function getOrganizeImportsUnicodeStringComparer(ignoreCase, preferences) {
491769
491791
  const resolvedLocale = getOrganizeImportsLocale(preferences);
491770
491792
  const caseFirst = preferences.organizeImportsCaseFirst ?? false;
491771
- const numeric = preferences.organizeImportsNumericCollation ?? false;
491793
+ const numeric2 = preferences.organizeImportsNumericCollation ?? false;
491772
491794
  const accents = preferences.organizeImportsAccentCollation ?? true;
491773
491795
  const sensitivity = ignoreCase ? accents ? "accent" : "base" : accents ? "variant" : "case";
491774
491796
  const collator = new Intl.Collator(resolvedLocale, {
491775
491797
  usage: "sort",
491776
491798
  caseFirst: caseFirst || "false",
491777
491799
  sensitivity,
491778
- numeric
491800
+ numeric: numeric2
491779
491801
  });
491780
491802
  return collator.compare;
491781
491803
  }
@@ -502591,12 +502613,12 @@ ${options2.prefix}` : "\n" : options2.prefix
502591
502613
  * of the new one. (Note that the amount of time the canceled operation had been
502592
502614
  * waiting does not affect the amount of time that the new operation waits.)
502593
502615
  */
502594
- schedule(operationId, delay4, cb) {
502616
+ schedule(operationId, delay5, cb) {
502595
502617
  const pendingTimeout = this.pendingTimeouts.get(operationId);
502596
502618
  if (pendingTimeout) {
502597
502619
  this.host.clearTimeout(pendingTimeout);
502598
502620
  }
502599
- this.pendingTimeouts.set(operationId, this.host.setTimeout(_ThrottledOperations.run, delay4, operationId, this, cb));
502621
+ this.pendingTimeouts.set(operationId, this.host.setTimeout(_ThrottledOperations.run, delay5, operationId, this, cb));
502600
502622
  if (this.logger) {
502601
502623
  this.logger.info(`Scheduled: ${operationId}${pendingTimeout ? ", Cancelled earlier one" : ""}`);
502602
502624
  }
@@ -502616,9 +502638,9 @@ ${options2.prefix}` : "\n" : options2.prefix
502616
502638
  }
502617
502639
  };
502618
502640
  var GcTimer = class _GcTimer {
502619
- constructor(host, delay4, logger2) {
502641
+ constructor(host, delay5, logger2) {
502620
502642
  this.host = host;
502621
- this.delay = delay4;
502643
+ this.delay = delay5;
502622
502644
  this.logger = logger2;
502623
502645
  }
502624
502646
  scheduleCollect() {
@@ -512967,12 +512989,12 @@ Project '${project.projectName}' (${ProjectKind[project.projectKind]}) ${counter
512967
512989
  const project = this.projectService.tryGetDefaultProjectForFile(fileName);
512968
512990
  return project && { fileName, project };
512969
512991
  }
512970
- getDiagnostics(next, delay4, fileArgs) {
512992
+ getDiagnostics(next, delay5, fileArgs) {
512971
512993
  if (this.suppressDiagnosticEvents) {
512972
512994
  return;
512973
512995
  }
512974
512996
  if (fileArgs.length > 0) {
512975
- this.updateErrorCheck(next, fileArgs, delay4);
512997
+ this.updateErrorCheck(next, fileArgs, delay5);
512976
512998
  }
512977
512999
  }
512978
513000
  change(args) {
@@ -513372,7 +513394,7 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
513372
513394
  const spans = languageService.getBraceMatchingAtPosition(file, position);
513373
513395
  return !spans ? void 0 : simplifiedResult ? spans.map((span) => toProtocolTextSpan(span, scriptInfo)) : spans;
513374
513396
  }
513375
- getDiagnosticsForProject(next, delay4, fileName) {
513397
+ getDiagnosticsForProject(next, delay5, fileName) {
513376
513398
  if (this.suppressDiagnosticEvents) {
513377
513399
  return;
513378
513400
  }
@@ -513417,7 +513439,7 @@ Additional information: BADCLIENT: Bad error code, ${badCode} not found in range
513417
513439
  this.updateErrorCheck(
513418
513440
  next,
513419
513441
  checkList,
513420
- delay4,
513442
+ delay5,
513421
513443
  /*requireOpen*/
513422
513444
  false
513423
513445
  );
@@ -514947,7 +514969,7 @@ var require_commonjs2 = __commonJS({
514947
514969
  var commaPattern = /\\,/g;
514948
514970
  var periodPattern = /\\\./g;
514949
514971
  exports.EXPANSION_MAX = 1e5;
514950
- function numeric(str) {
514972
+ function numeric2(str) {
514951
514973
  return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
514952
514974
  }
514953
514975
  function escapeBraces(str) {
@@ -515037,10 +515059,10 @@ var require_commonjs2 = __commonJS({
515037
515059
  }
515038
515060
  let N;
515039
515061
  if (isSequence && n2[0] !== void 0 && n2[1] !== void 0) {
515040
- const x = numeric(n2[0]);
515041
- const y = numeric(n2[1]);
515062
+ const x = numeric2(n2[0]);
515063
+ const y = numeric2(n2[1]);
515042
515064
  const width = Math.max(n2[0].length, n2[1].length);
515043
- let incr = n2.length === 3 && n2[2] !== void 0 ? Math.max(Math.abs(numeric(n2[2])), 1) : 1;
515065
+ let incr = n2.length === 3 && n2[2] !== void 0 ? Math.max(Math.abs(numeric2(n2[2])), 1) : 1;
515044
515066
  let test = lte;
515045
515067
  const reverse = y < x;
515046
515068
  if (reverse) {
@@ -563021,8 +563043,8 @@ var init_VllmBackend = __esm({
563021
563043
  const errorText = await response.text().catch(() => "");
563022
563044
  const isRetryable = response.status >= 500 || response.status === 429;
563023
563045
  if (isRetryable && attempt < this.maxRetries) {
563024
- const delay4 = Math.min(100 * Math.pow(2, attempt), 2e3);
563025
- await new Promise((r2) => setTimeout(r2, delay4));
563046
+ const delay5 = Math.min(100 * Math.pow(2, attempt), 2e3);
563047
+ await new Promise((r2) => setTimeout(r2, delay5));
563026
563048
  return this.postWithRetry(path16, body, attempt + 1);
563027
563049
  }
563028
563050
  throw new Error(`vLLM POST ${path16} failed with HTTP ${response.status}: ${errorText}`);
@@ -563032,8 +563054,8 @@ var init_VllmBackend = __esm({
563032
563054
  clearTimeout(timer);
563033
563055
  const isNetworkError2 = err instanceof TypeError || err instanceof Error && err.name === "AbortError";
563034
563056
  if (isNetworkError2 && attempt < this.maxRetries) {
563035
- const delay4 = Math.min(100 * Math.pow(2, attempt), 2e3);
563036
- await new Promise((r2) => setTimeout(r2, delay4));
563057
+ const delay5 = Math.min(100 * Math.pow(2, attempt), 2e3);
563058
+ await new Promise((r2) => setTimeout(r2, delay5));
563037
563059
  return this.postWithRetry(path16, body, attempt + 1);
563038
563060
  }
563039
563061
  throw err;
@@ -563281,8 +563303,8 @@ var init_OllamaBackend = __esm({
563281
563303
  const errorText = await response.text().catch(() => "");
563282
563304
  const isRetryable = response.status >= 500 || response.status === 429;
563283
563305
  if (isRetryable && attempt < this.maxRetries) {
563284
- const delay4 = Math.min(100 * Math.pow(2, attempt), 2e3);
563285
- await new Promise((r2) => setTimeout(r2, delay4));
563306
+ const delay5 = Math.min(100 * Math.pow(2, attempt), 2e3);
563307
+ await new Promise((r2) => setTimeout(r2, delay5));
563286
563308
  return this.postWithRetry(path16, body, attempt + 1);
563287
563309
  }
563288
563310
  throw new Error(`Ollama POST ${path16} failed with HTTP ${response.status}: ${errorText}`);
@@ -563292,8 +563314,8 @@ var init_OllamaBackend = __esm({
563292
563314
  clearTimeout(timer);
563293
563315
  const isNetworkError2 = err instanceof TypeError || err instanceof Error && err.name === "AbortError";
563294
563316
  if (isNetworkError2 && attempt < this.maxRetries) {
563295
- const delay4 = Math.min(100 * Math.pow(2, attempt), 2e3);
563296
- await new Promise((r2) => setTimeout(r2, delay4));
563317
+ const delay5 = Math.min(100 * Math.pow(2, attempt), 2e3);
563318
+ await new Promise((r2) => setTimeout(r2, delay5));
563297
563319
  return this.postWithRetry(path16, body, attempt + 1);
563298
563320
  }
563299
563321
  throw err;
@@ -565670,9 +565692,9 @@ var init_verifierRunner = __esm({
565670
565692
  async executeTests(patch, repoRoot) {
565671
565693
  if (patch.testsToRun.length === 0)
565672
565694
  return "(no tests specified)";
565673
- const { execFile: execFile11 } = await import("node:child_process");
565674
- const { promisify: promisify9 } = await import("node:util");
565675
- const execFileAsync6 = promisify9(execFile11);
565695
+ const { execFile: execFile12 } = await import("node:child_process");
565696
+ const { promisify: promisify10 } = await import("node:util");
565697
+ const execFileAsync7 = promisify10(execFile12);
565676
565698
  const outputs = [];
565677
565699
  const workDir = this.options.workingDir || repoRoot;
565678
565700
  for (const cmd of patch.testsToRun.slice(0, 3)) {
@@ -565681,7 +565703,7 @@ var init_verifierRunner = __esm({
565681
565703
  const [bin, ...args] = parts;
565682
565704
  if (!bin)
565683
565705
  continue;
565684
- const { stdout, stderr } = await execFileAsync6(bin, args, {
565706
+ const { stdout, stderr } = await execFileAsync7(bin, args, {
565685
565707
  cwd: workDir,
565686
565708
  timeout: 15e3,
565687
565709
  maxBuffer: 1024 * 1024
@@ -574071,15 +574093,19 @@ function buildTrajectoryCheckpoint(input) {
574071
574093
  const latestFailure = [...observations].reverse().find((item) => item.type === "tool_result" && item.success === false || item.type === "error");
574072
574094
  const failureText = sanitizeTrajectoryText(latestFailure?.content, 300);
574073
574095
  const fallbackFailure = input.recentFailures?.at(-1);
574096
+ const failureTurn = Math.max(typeof latestFailure?.turn === "number" ? latestFailure.turn : -1, typeof fallbackFailure?.turn === "number" ? fallbackFailure.turn : -1);
574097
+ const verifiedFailureRecovery = input.lastVerifier?.passed === true && typeof input.lastVerifier.turn === "number" && input.lastVerifier.turn > failureTurn;
574074
574098
  const combinedFailure = [
574075
- failureText,
574076
- sanitizeTrajectoryText(fallbackFailure?.error || fallbackFailure?.output, 300)
574099
+ ...verifiedFailureRecovery ? [] : [
574100
+ failureText,
574101
+ sanitizeTrajectoryText(fallbackFailure?.error || fallbackFailure?.output, 300)
574102
+ ]
574077
574103
  ].filter(Boolean).join(" ");
574078
574104
  const focus = sanitizeTrajectoryText(input.focusDirective, 300);
574079
574105
  const targetPath = inferTargetPath(combinedFailure || outcomeText || focus) ?? latestFailure?.targetPath ?? mostRecentTargetForTool(observations, latestFailure?.toolName);
574080
574106
  const targetFreshness = targetPath ? input.evidenceFreshness?.(targetPath) ?? "unknown" : "unknown";
574081
574107
  const modifiedFiles = Array.from(state.modifiedFiles).slice(-3);
574082
- const fullWriteIssue = (latestFailure?.toolName === "file_write" || fallbackFailure?.tool === "file_write" || /file_write/i.test(combinedFailure)) && /FULL FILE (?:WRITE LOOP BLOCKED|REWRITE CONTRACT)|overwrite(?:=true)?|expected_hash|Refusing to overwrite existing file/i.test(combinedFailure);
574108
+ const fullWriteIssue = !verifiedFailureRecovery && (latestFailure?.toolName === "file_write" || fallbackFailure?.tool === "file_write" || /file_write/i.test(combinedFailure)) && /FULL FILE (?:WRITE LOOP BLOCKED|REWRITE CONTRACT)|overwrite(?:=true)?|expected_hash|Refusing to overwrite existing file/i.test(combinedFailure);
574083
574109
  const fullWriteRecoveredByMutation = fullWriteIssue && Boolean(targetPath) && modifiedFiles.some(([path16]) => sameProjectPath(path16, targetPath)) && typeof latestFailure?.turn === "number" && typeof input.lastMutationTurn === "number" && input.lastMutationTurn > latestFailure.turn;
574084
574110
  const explicitBlock = /(?:permission denied|needs user input|ask_user|cannot proceed|external dependency|\[.*BLOCKED\])/i.test(combinedFailure);
574085
574111
  const hasRecentFailure = Boolean(combinedFailure);
@@ -578615,17 +578641,12 @@ var init_context_fabric = __esm({
578615
578641
  "Scope: runtime state for the next action. Do not quote or re-emit this frame. Prior evidence is orientation; execute a narrow file_read or the declared verifier whenever current text/hash or post-mutation proof is required."
578616
578642
  ].filter(Boolean);
578617
578643
  let content = [...header, "", ...sectionLines].join("\n").trim();
578618
- const controlChars = included.filter(isControlSignal).reduce((sum2, signal) => sum2 + signal.content.length, 0);
578619
- const evidenceChars = included.filter(isEvidenceSignal).reduce((sum2, signal) => sum2 + signal.content.length, 0);
578620
- const controlToEvidenceRatio = Number((controlChars / Math.max(1, evidenceChars)).toFixed(3));
578644
+ let visibleIncluded = [...included];
578645
+ let controlChars = 0;
578646
+ let evidenceChars = 0;
578647
+ let controlToEvidenceRatio = 0;
578621
578648
  const qualityWarnings = [];
578622
578649
  const maxControlRatio = options2.maxControlToEvidenceRatio ?? 0.45;
578623
- if (controlToEvidenceRatio > maxControlRatio) {
578624
- qualityWarnings.push(`control_context_ratio_high:${controlToEvidenceRatio}`);
578625
- }
578626
- const activeFrameCount = (content.match(/\[ACTIVE CONTEXT FRAME\]/g) ?? []).length;
578627
- if (activeFrameCount > 1)
578628
- qualityWarnings.push(`active_frame_count:${activeFrameCount}`);
578629
578650
  if (sectionLines.length === 0) {
578630
578651
  return {
578631
578652
  content: null,
@@ -578661,6 +578682,21 @@ var init_context_fabric = __esm({
578661
578682
  dropped.push(signal);
578662
578683
  }
578663
578684
  }
578685
+ visibleIncluded = included.filter((signal) => content.includes(signal.content));
578686
+ for (const signal of included) {
578687
+ if (!visibleIncluded.includes(signal) && !dropped.includes(signal)) {
578688
+ dropped.push(signal);
578689
+ }
578690
+ }
578691
+ controlChars = visibleIncluded.filter(isControlSignal).reduce((sum2, signal) => sum2 + signal.content.length, 0);
578692
+ evidenceChars = visibleIncluded.filter(isEvidenceSignal).reduce((sum2, signal) => sum2 + signal.content.length, 0);
578693
+ controlToEvidenceRatio = Number((controlChars / Math.max(1, evidenceChars)).toFixed(3));
578694
+ if (controlToEvidenceRatio > maxControlRatio) {
578695
+ qualityWarnings.push(`control_context_ratio_high:${controlToEvidenceRatio}`);
578696
+ }
578697
+ const activeFrameCount = (content.match(/\[ACTIVE CONTEXT FRAME\]/g) ?? []).length;
578698
+ if (activeFrameCount > 1)
578699
+ qualityWarnings.push(`active_frame_count:${activeFrameCount}`);
578664
578700
  if (options2.includeDiagnostics) {
578665
578701
  content += `
578666
578702
 
@@ -578669,7 +578705,7 @@ context_fabric: included=${included.length} dropped=${dropped.length} truncated=
578669
578705
  return {
578670
578706
  content,
578671
578707
  diagnostics: {
578672
- includedSignals: included.length,
578708
+ includedSignals: visibleIncluded.length,
578673
578709
  droppedSignals: dropped.length + droppedByAdmission.length,
578674
578710
  hiddenSignals: hidden.length,
578675
578711
  semanticDedupedSignals,
@@ -578678,7 +578714,7 @@ context_fabric: included=${included.length} dropped=${dropped.length} truncated=
578678
578714
  truncatedSignals,
578679
578715
  estimatedTokens: estimateTokens2(content),
578680
578716
  totalChars: content.length,
578681
- semanticChunkCount: included.filter((signal) => signal.kind === "semantic_chunk").length,
578717
+ semanticChunkCount: visibleIncluded.filter((signal) => signal.kind === "semantic_chunk").length,
578682
578718
  controlChars,
578683
578719
  evidenceChars,
578684
578720
  controlToEvidenceRatio,
@@ -578686,7 +578722,7 @@ context_fabric: included=${included.length} dropped=${dropped.length} truncated=
578686
578722
  ...metadataReports,
578687
578723
  sections: sectionDiagnostics
578688
578724
  },
578689
- included,
578725
+ included: visibleIncluded,
578690
578726
  dropped: [...dropped, ...droppedByAdmission, ...hidden]
578691
578727
  };
578692
578728
  }
@@ -578710,7 +578746,7 @@ function isAdmittedFileReadMessage(message2) {
578710
578746
  function isProtectedControllerMessage(message2) {
578711
578747
  return isControllerStateMessage(message2) || isActionGroundTruthMessage(message2) || isActiveSteeringMessage(message2);
578712
578748
  }
578713
- function modelFacingMessageCap(message2) {
578749
+ function modelFacingMessageCapWithLimits(message2, limits) {
578714
578750
  if (isControllerStateMessage(message2)) {
578715
578751
  return MODEL_FACING_CONTROLLER_STATE_CHAR_CAP;
578716
578752
  }
@@ -578721,12 +578757,12 @@ function modelFacingMessageCap(message2) {
578721
578757
  return Math.max(MODEL_FACING_ACTION_GROUND_TRUTH_CHAR_CAP, 7e3);
578722
578758
  }
578723
578759
  if (isAdmittedFileReadMessage(message2)) {
578724
- return MODEL_FACING_ADMITTED_FILE_READ_CHAR_CAP;
578760
+ return limits.admittedFileReadChars ?? MODEL_FACING_ADMITTED_FILE_READ_CHAR_CAP;
578725
578761
  }
578726
578762
  if (message2.role === "tool")
578727
- return MODEL_FACING_TOOL_CHAR_CAP;
578763
+ return limits.toolChars ?? MODEL_FACING_TOOL_CHAR_CAP;
578728
578764
  if (message2.role === "system")
578729
- return MODEL_FACING_SYSTEM_CHAR_CAP;
578765
+ return limits.systemChars ?? MODEL_FACING_SYSTEM_CHAR_CAP;
578730
578766
  return messageText(message2.content).length;
578731
578767
  }
578732
578768
  function stripLegacyRuntimeControlFragments(content) {
@@ -578736,18 +578772,18 @@ function stripLegacyRuntimeControlFragments(content) {
578736
578772
  out = pieces.map((piece) => LEGACY_RUNTIME_CONTROL_FRAGMENT_RE.test(piece) ? "" : piece).join("");
578737
578773
  return collapseWhitespace(out);
578738
578774
  }
578739
- function splitOversizedSystemMessages(messages2) {
578775
+ function splitOversizedSystemMessages(messages2, systemCharCap = MODEL_FACING_SYSTEM_CHAR_CAP) {
578740
578776
  const out = [];
578741
578777
  for (const message2 of messages2) {
578742
- if (message2.role !== "system" || typeof message2.content !== "string" || isProtectedControllerMessage(message2) || message2.content.length <= MODEL_FACING_SYSTEM_CHAR_CAP) {
578778
+ if (message2.role !== "system" || typeof message2.content !== "string" || isProtectedControllerMessage(message2) || message2.content.length <= systemCharCap) {
578743
578779
  out.push(message2);
578744
578780
  continue;
578745
578781
  }
578746
578782
  let remaining = message2.content.trim();
578747
- while (remaining.length > MODEL_FACING_SYSTEM_CHAR_CAP) {
578748
- const window2 = remaining.slice(0, MODEL_FACING_SYSTEM_CHAR_CAP);
578783
+ while (remaining.length > systemCharCap) {
578784
+ const window2 = remaining.slice(0, systemCharCap);
578749
578785
  const boundary = Math.max(window2.lastIndexOf("\n\n"), window2.lastIndexOf("\n"));
578750
- const cut = boundary >= Math.floor(MODEL_FACING_SYSTEM_CHAR_CAP * 0.5) ? boundary : MODEL_FACING_SYSTEM_CHAR_CAP;
578786
+ const cut = boundary >= Math.floor(systemCharCap * 0.5) ? boundary : systemCharCap;
578751
578787
  const chunk = remaining.slice(0, cut).trim();
578752
578788
  if (chunk)
578753
578789
  out.push({ ...message2, content: chunk });
@@ -578761,17 +578797,17 @@ function splitOversizedSystemMessages(messages2) {
578761
578797
  function isCurrentGoalMessage(message2) {
578762
578798
  return typeof message2.content === "string" && message2.content.includes("[CURRENT USER GOAL]");
578763
578799
  }
578764
- function applyModelFacingBudget(messages2, preserveFirstSystem) {
578800
+ function applyModelFacingBudget(messages2, preserveFirstSystem, limits = {}) {
578765
578801
  const reservedTransaction = latestResolvedToolTransaction(messages2);
578766
- const reservedChars = [...reservedTransaction].reduce((sum2, index) => sum2 + modelFacingReservedChars(messages2[index]), 0);
578767
- let remaining = Math.max(0, MODEL_FACING_CONTEXT_CHAR_BUDGET - reservedChars);
578802
+ const reservedChars = [...reservedTransaction].reduce((sum2, index) => sum2 + modelFacingReservedChars(messages2[index], limits), 0);
578803
+ let remaining = Math.max(0, (limits.contextChars ?? MODEL_FACING_CONTEXT_CHAR_BUDGET) - reservedChars);
578768
578804
  const kept = [];
578769
578805
  for (let index = 0; index < messages2.length; index++) {
578770
578806
  const message2 = messages2[index];
578771
578807
  const content = messageText(message2.content);
578772
578808
  const isReservedTransactionMessage = reservedTransaction.has(index);
578773
578809
  const isPriorityIntent = message2.role === "user" || isCurrentGoalMessage(message2) || isActiveSteeringMessage(message2);
578774
- const perMessageCap = modelFacingMessageCap(message2);
578810
+ const perMessageCap = modelFacingMessageCapWithLimits(message2, limits);
578775
578811
  const isProtectedController = isProtectedControllerMessage(message2);
578776
578812
  const allowed = isReservedTransactionMessage ? perMessageCap : isPriorityIntent ? content.length : isProtectedController ? perMessageCap : Math.min(remaining, perMessageCap);
578777
578813
  if (!isReservedTransactionMessage && !isPriorityIntent && !isProtectedController && allowed <= 0) {
@@ -578882,9 +578918,9 @@ function latestResolvedToolTransaction(messages2) {
578882
578918
  }
578883
578919
  return /* @__PURE__ */ new Set();
578884
578920
  }
578885
- function modelFacingReservedChars(message2) {
578921
+ function modelFacingReservedChars(message2, limits = {}) {
578886
578922
  const content = messageText(message2.content);
578887
- const cap = modelFacingMessageCap(message2);
578923
+ const cap = modelFacingMessageCapWithLimits(message2, limits);
578888
578924
  return Math.min(content.length, cap);
578889
578925
  }
578890
578926
  function retireLinkedAssistantReadIntents(messages2) {
@@ -578906,6 +578942,64 @@ function retireLinkedAssistantReadIntents(messages2) {
578906
578942
  return { ...message2, content: ASSISTANT_READ_INTENT_RETIRED_MARKER };
578907
578943
  });
578908
578944
  }
578945
+ function retireHistoricalAssistantNarratives(messages2) {
578946
+ const resolvedToolCallIds = new Set(messages2.filter((message2) => message2.role === "tool").map(linkedToolCallId).filter((id2) => id2 !== null));
578947
+ const newestTransaction = latestResolvedToolTransaction(messages2);
578948
+ const keepFreeform = /* @__PURE__ */ new Set();
578949
+ let freeformSlots = 1;
578950
+ const assistantControllerRecap = /(?:\[?(?:controller state v1|active context frame|trajectory checkpoint|branch-extract(?: v\d+)?|recent action ground truth)\]?|\b(?:controller|admin)\s+(?:directive|state|summary|recap|reflection)\b|\b(?:verifier|compile)\s+(?:is\s+)?locked\b|\b(?:read tool|read wrapper)\s+(?:is|was)\s+(?:contaminated|untrusted)\b|\b(?:failure|recovery|doom)[ -]?(?:loop|recap|summary)\b)/i;
578951
+ for (let index = messages2.length - 1; index >= 0; index--) {
578952
+ const message2 = messages2[index];
578953
+ if (message2.role !== "assistant" || typeof message2.content !== "string" || toolCallIds(message2).length > 0 || !message2.content.trim() || assistantControllerRecap.test(message2.content)) {
578954
+ continue;
578955
+ }
578956
+ if (freeformSlots-- > 0)
578957
+ keepFreeform.add(index);
578958
+ }
578959
+ return messages2.map((message2, index) => {
578960
+ if (message2.role !== "assistant" || typeof message2.content !== "string") {
578961
+ return message2;
578962
+ }
578963
+ if (assistantControllerRecap.test(message2.content)) {
578964
+ return { ...message2, content: "" };
578965
+ }
578966
+ const callIds = toolCallIds(message2);
578967
+ if (callIds.length > 0) {
578968
+ const allResolved = callIds.every((id2) => resolvedToolCallIds.has(id2));
578969
+ if (allResolved && !newestTransaction.has(index)) {
578970
+ return { ...message2, content: "" };
578971
+ }
578972
+ return message2;
578973
+ }
578974
+ if (!keepFreeform.has(index))
578975
+ return { ...message2, content: "" };
578976
+ return message2;
578977
+ });
578978
+ }
578979
+ function retireHistoricalRunEvidence(messages2) {
578980
+ const retainedByBucket = /* @__PURE__ */ new Map();
578981
+ const limitByBucket = {
578982
+ discovery: 3,
578983
+ mutation: 2,
578984
+ verification: 1
578985
+ };
578986
+ const out = [...messages2];
578987
+ for (let index = out.length - 1; index >= 0; index--) {
578988
+ const message2 = out[index];
578989
+ if (message2.role !== "system" || typeof message2.content !== "string" || !message2.content.includes("[RUN EVIDENCE]")) {
578990
+ continue;
578991
+ }
578992
+ const text2 = message2.content.toLowerCase();
578993
+ const bucket = /\b(?:file_edit|file_write|patch|apply_patch)\b/.test(text2) ? "mutation" : /\b(?:shell|verifier|compile|build|test)\b/.test(text2) ? "verification" : "discovery";
578994
+ const retained = retainedByBucket.get(bucket) ?? 0;
578995
+ if (retained >= limitByBucket[bucket]) {
578996
+ out[index] = { ...message2, content: "" };
578997
+ continue;
578998
+ }
578999
+ retainedByBucket.set(bucket, retained + 1);
579000
+ }
579001
+ return out.filter((message2) => message2.role !== "system" || typeof message2.content !== "string" || message2.content.trim());
579002
+ }
578909
579003
  function runtimeControlSemanticKey(content) {
578910
579004
  const normalized = content.replace(/\s+/g, " ").trim().toLowerCase();
578911
579005
  if (!normalized)
@@ -578969,9 +579063,13 @@ function hasAssistantPayload(message2) {
578969
579063
  }
578970
579064
  function staleToolFailureKey(content) {
578971
579065
  const text2 = content.replace(/\s+/g, " ").trim();
578972
- if (!/(FAILED:|failed again|doom-loop|result compacted|Earlier read of .* cleared)/i.test(text2)) {
579066
+ const runtimeBlock = text2.match(/\[(COMPILE ERROR FIX LOOP BLOCKED|EXPLORATION ADMISSION BLOCK|PARENT(?:\s+[^\]]*)?\s+BLOCK(?:ED)?|FOCUS SUPERVISOR BLOCK|STEERING RECONCILIATION REQUIRED|STALE EDIT LOOP BLOCKED|FULL FILE WRITE LOOP BLOCKED)[^\]]*\]/i);
579067
+ if (!/(FAILED:|failed again|doom-loop|result compacted|Earlier read of .* cleared)/i.test(text2) && !runtimeBlock) {
578973
579068
  return null;
578974
579069
  }
579070
+ if (runtimeBlock) {
579071
+ return `runtime-block|${runtimeBlock[1].toLowerCase().replace(/\s+/g, "-")}`;
579072
+ }
578975
579073
  const tool = text2.match(/^\[?([a-zA-Z_][a-zA-Z0-9_]*)\(/)?.[1] ?? "tool";
578976
579074
  const path16 = text2.match(/"path"\s*:\s*"([^"]+)"/)?.[1] ?? text2.match(/Earlier read of ([^ ]+) cleared/)?.[1] ?? "";
578977
579075
  const family = text2.match(/FAILED:\s*\[([^\]\n]+)/i)?.[1] ?? text2.match(/(doom-loop[^.]+)/i)?.[1] ?? text2.match(/(Earlier read of [^ ]+ cleared)/i)?.[1] ?? "failure";
@@ -579003,6 +579101,12 @@ function retireDuplicateToolFailures(messages2) {
579003
579101
  }
579004
579102
  function prepareModelFacingApiMessages(input) {
579005
579103
  const preserveFirstSystem = input.preserveFirstSystem !== false;
579104
+ const limits = {
579105
+ contextChars: input.contextBudgetChars,
579106
+ systemChars: input.systemMessageChars,
579107
+ toolChars: input.toolMessageChars,
579108
+ admittedFileReadChars: input.admittedFileReadChars
579109
+ };
579006
579110
  const sanitized = [];
579007
579111
  const withoutLegacyControl = input.messages.flatMap((message2) => {
579008
579112
  if (message2.role !== "system" || typeof message2.content !== "string" || isProtectedControllerMessage(message2)) {
@@ -579011,7 +579115,7 @@ function prepareModelFacingApiMessages(input) {
579011
579115
  const stripped = stripLegacyRuntimeControlFragments(message2.content);
579012
579116
  return stripped ? [{ ...message2, content: stripped }] : [];
579013
579117
  });
579014
- const independentlyBounded = splitOversizedSystemMessages(withoutLegacyControl);
579118
+ const independentlyBounded = splitOversizedSystemMessages(withoutLegacyControl, limits.systemChars);
579015
579119
  for (let index = 0; index < independentlyBounded.length; index++) {
579016
579120
  const rawMessage = independentlyBounded[index];
579017
579121
  const message2 = {
@@ -579070,7 +579174,7 @@ function prepareModelFacingApiMessages(input) {
579070
579174
  }
579071
579175
  seenSystemKeys.add(key);
579072
579176
  }
579073
- const deduped = retireDuplicateToolFailures(epochScoped.filter((_message, index) => keep[index]));
579177
+ const deduped = retireDuplicateToolFailures(retireHistoricalRunEvidence(epochScoped.filter((_message, index) => keep[index])));
579074
579178
  if (!hasUserMessage(deduped) && !hasConcreteGoalMessage(deduped)) {
579075
579179
  const goal = deriveCurrentGoal({
579076
579180
  explicitGoal: input.currentGoal,
@@ -579088,7 +579192,8 @@ function prepareModelFacingApiMessages(input) {
579088
579192
  const insertAt = preserveFirstSystem && deduped[0]?.role === "system" ? 1 : 0;
579089
579193
  deduped.splice(insertAt, 0, goalMessage);
579090
579194
  }
579091
- return retireLinkedAssistantReadIntents(applyModelFacingBudget(deduped, preserveFirstSystem));
579195
+ const historyPruned = retireHistoricalAssistantNarratives(retireLinkedAssistantReadIntents(deduped));
579196
+ return applyModelFacingBudget(historyPruned, preserveFirstSystem, limits).filter((message2) => message2.role !== "assistant" || hasAssistantPayload(message2));
579092
579197
  }
579093
579198
  function deriveCurrentGoal(input) {
579094
579199
  const explicit = sanitizeModelVisibleContextText(input.explicitGoal ?? "");
@@ -581797,7 +581902,7 @@ var init_focusSupervisor = __esm({
581797
581902
  this.expireDirectiveIfNeeded(this.lastObservedTurn);
581798
581903
  if (!this.enabled || !this.directive)
581799
581904
  return null;
581800
- if (this.modelTier === "large")
581905
+ if (this.modelTier !== "small")
581801
581906
  return null;
581802
581907
  const d2 = this.directive;
581803
581908
  return [
@@ -582178,13 +582283,10 @@ var init_focusSupervisor = __esm({
582178
582283
  return true;
582179
582284
  if (this.mode === "off")
582180
582285
  return false;
582181
- if (this.modelTier === "small" || this.modelTier === "medium")
582286
+ if (this.modelTier === "small")
582182
582287
  return true;
582183
- if (!context2)
582184
- return false;
582185
- const pressure = context2.pressureRatio ?? 0;
582186
- const ratio = context2.signalToNoiseRatio;
582187
- return pressure >= 0.85 || ratio !== void 0 && ratio < 1.2;
582288
+ void context2;
582289
+ return false;
582188
582290
  }
582189
582291
  hasLowSignalContext(context2) {
582190
582292
  if (!context2)
@@ -584689,7 +584791,10 @@ function buildBranchExtractionBrief(input) {
584689
584791
  const requirements = requirementQuestions.map((question, index) => ({
584690
584792
  id: `R${index + 1}`,
584691
584793
  question,
584692
- required: index === 0 || requirementQuestions.length === 1,
584794
+ // A declared discovery question is never decorative. The branch may
584795
+ // return a justified partial result, but it cannot call its contract
584796
+ // complete until every listed requirement has anchored evidence.
584797
+ required: true,
584693
584798
  expectedEvidence: "Exact source declarations, literal values, control/configuration behavior, and their line anchors.",
584694
584799
  searchTerms: queryTerms(question).slice(0, 16)
584695
584800
  }));
@@ -584704,7 +584809,7 @@ function buildBranchExtractionBrief(input) {
584704
584809
  query: cleanBriefText(retrievalQuery, 700),
584705
584810
  requirements,
584706
584811
  completionCriteria: [
584707
- "Every required requirement is either supported by an exact anchored segment or explicitly marked unresolved.",
584812
+ "Every declared requirement is either supported by an exact anchored segment or has an explicit source-based unresolved reason and deterministic recovery action.",
584708
584813
  "Every returned factual claim names its source line span; discontiguous evidence remains separate.",
584709
584814
  "Stop when the contract is satisfied, no new query/range is available, or the bounded search budget is exhausted."
584710
584815
  ],
@@ -585019,6 +585124,44 @@ function deterministicSegments(input) {
585019
585124
  });
585020
585125
  return { segments, satisfied: [...satisfied], rounds };
585021
585126
  }
585127
+ function buildRequirementCoverage(input) {
585128
+ return input.requirements.map((requirement) => {
585129
+ const anchors = input.segments.filter((segment) => segment.requirementIds.includes(requirement.id)).map((segment) => ({
585130
+ startLine: segment.anchor.startLine,
585131
+ endLine: segment.anchor.endLine
585132
+ }));
585133
+ if (anchors.length > 0) {
585134
+ return {
585135
+ id: requirement.id,
585136
+ question: requirement.question,
585137
+ status: "satisfied",
585138
+ anchors
585139
+ };
585140
+ }
585141
+ const terms2 = queryTerms(requirement.question);
585142
+ const candidateIndex = input.lines.findIndex((line) => {
585143
+ const lower = line.toLowerCase();
585144
+ return terms2.some((term) => lower.includes(term));
585145
+ });
585146
+ const reason = candidateIndex >= 0 ? "A candidate source line was found, but no bounded, line-anchored segment established the declared requirement." : terms2.length > 0 ? "None of the requirement's discriminating search terms occurred in the selected source range." : "The requirement had no discriminating file-local search term after normalization.";
585147
+ const recovery = candidateIndex >= 0 ? `file_read({"path":${JSON.stringify(input.path)},"offset":${input.sourceLineOffset + Math.max(1, candidateIndex - 3)},"limit":12,"mode":"full"})` : `grep_search({"pattern":${JSON.stringify(terms2[0] ?? requirement.question.slice(0, 80))},"path":${JSON.stringify(input.path)}})`;
585148
+ return {
585149
+ id: requirement.id,
585150
+ question: requirement.question,
585151
+ status: "unresolved",
585152
+ anchors: [],
585153
+ reason,
585154
+ recovery
585155
+ };
585156
+ });
585157
+ }
585158
+ function renderBranchRequirementCoverage(evidence) {
585159
+ return [
585160
+ `[REQUIREMENT COVERAGE]`,
585161
+ ...evidence.requirementCoverage.map((coverage) => coverage.status === "satisfied" ? `- ${coverage.id} satisfied anchors=${coverage.anchors.map((anchor) => `L${anchor.startLine}-L${anchor.endLine}`).join(",")}` : `- ${coverage.id} unresolved reason=${coverage.reason ?? "no bounded anchor returned"} recovery=${coverage.recovery ?? "narrow the source query"}`),
585162
+ `branch_contract=${evidence.contractComplete ? "complete" : "partial"}`
585163
+ ];
585164
+ }
585022
585165
  async function extractEvidence(opts) {
585023
585166
  const { path: path16, content, fileVersion, backend } = opts;
585024
585167
  const sourceLineOffset = Math.max(0, Math.floor(opts.sourceLineOffset ?? 0));
@@ -585051,12 +585194,19 @@ async function extractEvidence(opts) {
585051
585194
  brief,
585052
585195
  maxSegments
585053
585196
  });
585054
- const requiredIds = requirements.filter((requirement) => requirement.required).map((requirement) => requirement.id);
585197
+ const requiredIds = requirements.map((requirement) => requirement.id);
585055
585198
  const deterministicSatisfied = new Set(deterministic.satisfied);
585056
585199
  const deterministicComplete = deterministic.segments.length > 0 && requiredIds.every((id2) => deterministicSatisfied.has(id2));
585057
585200
  if (deterministicComplete && !backend) {
585058
585201
  const claim = renderSegments(deterministic.segments, maxInjectedChars);
585059
585202
  const legacySpan = legacyContiguousSpan(deterministic.segments);
585203
+ const requirementCoverage2 = buildRequirementCoverage({
585204
+ requirements,
585205
+ segments: deterministic.segments,
585206
+ lines,
585207
+ path: path16,
585208
+ sourceLineOffset
585209
+ });
585060
585210
  return {
585061
585211
  path: path16,
585062
585212
  query,
@@ -585068,8 +585218,10 @@ async function extractEvidence(opts) {
585068
585218
  exploredLines: lines.length,
585069
585219
  injectedChars: claim.length,
585070
585220
  segments: deterministic.segments,
585071
- satisfiedRequirementIds: [...deterministicSatisfied],
585072
- unresolvedRequirementIds: requirements.map((requirement) => requirement.id).filter((id2) => !deterministicSatisfied.has(id2)),
585221
+ satisfiedRequirementIds: requirementCoverage2.filter((coverage) => coverage.status === "satisfied").map((coverage) => coverage.id),
585222
+ unresolvedRequirementIds: requirementCoverage2.filter((coverage) => coverage.status === "unresolved").map((coverage) => coverage.id),
585223
+ requirementCoverage: requirementCoverage2,
585224
+ contractComplete: requirementCoverage2.every((coverage) => coverage.status === "satisfied"),
585073
585225
  provenance: {
585074
585226
  contentHash: contentHash2,
585075
585227
  byteCount,
@@ -585177,14 +585329,16 @@ async function extractEvidence(opts) {
585177
585329
  if (semanticSegment && !segments.some((segment) => rangesOverlap(segment.anchor, semanticSegment.anchor))) {
585178
585330
  segments.push(semanticSegment);
585179
585331
  }
585180
- const satisfied = new Set(deterministic.satisfied);
585181
- for (const segment of segments) {
585182
- for (const id2 of segment.requirementIds)
585183
- satisfied.add(id2);
585184
- }
585185
585332
  if (segments.length > 0) {
585186
585333
  const claim = renderSegments(segments, maxInjectedChars);
585187
585334
  const legacySpan = legacyContiguousSpan(segments);
585335
+ const requirementCoverage2 = buildRequirementCoverage({
585336
+ requirements,
585337
+ segments,
585338
+ lines,
585339
+ path: path16,
585340
+ sourceLineOffset
585341
+ });
585188
585342
  return {
585189
585343
  path: path16,
585190
585344
  query,
@@ -585196,8 +585350,10 @@ async function extractEvidence(opts) {
585196
585350
  exploredLines: Math.min(lines.length, parsedWindows.reduce((sum2, window2) => sum2 + (window2.end - window2.start + 1), 0) || lines.length),
585197
585351
  injectedChars: claim.length,
585198
585352
  segments,
585199
- satisfiedRequirementIds: [...satisfied],
585200
- unresolvedRequirementIds: requirements.map((requirement) => requirement.id).filter((id2) => !satisfied.has(id2)),
585353
+ satisfiedRequirementIds: requirementCoverage2.filter((coverage) => coverage.status === "satisfied").map((coverage) => coverage.id),
585354
+ unresolvedRequirementIds: requirementCoverage2.filter((coverage) => coverage.status === "unresolved").map((coverage) => coverage.id),
585355
+ requirementCoverage: requirementCoverage2,
585356
+ contractComplete: requirementCoverage2.every((coverage) => coverage.status === "satisfied"),
585201
585357
  provenance: {
585202
585358
  contentHash: contentHash2,
585203
585359
  byteCount,
@@ -585234,6 +585390,13 @@ async function extractEvidence(opts) {
585234
585390
  matches: 1
585235
585391
  });
585236
585392
  }
585393
+ const requirementCoverage = buildRequirementCoverage({
585394
+ requirements,
585395
+ segments: [structuralSegment],
585396
+ lines,
585397
+ path: path16,
585398
+ sourceLineOffset
585399
+ });
585237
585400
  return {
585238
585401
  path: path16,
585239
585402
  query,
@@ -585246,7 +585409,9 @@ async function extractEvidence(opts) {
585246
585409
  injectedChars: Math.min(structuralClaim.length, maxInjectedChars),
585247
585410
  segments: [structuralSegment],
585248
585411
  satisfiedRequirementIds: [],
585249
- unresolvedRequirementIds: requirements.map((requirement) => requirement.id),
585412
+ unresolvedRequirementIds: requirementCoverage.map((coverage) => coverage.id),
585413
+ requirementCoverage,
585414
+ contractComplete: false,
585250
585415
  provenance: {
585251
585416
  contentHash: contentHash2,
585252
585417
  byteCount,
@@ -585668,16 +585833,32 @@ var init_contextEngine = __esm({
585668
585833
  let evidenceDropped = 0;
585669
585834
  if (allowCompaction && budget && before > budget) {
585670
585835
  const overhead = estimateTokens3([...evidence, ...hints, ...contract]);
585671
- const retained = [];
585672
- let used = overhead;
585673
- for (const message2 of [...input.messages].reverse()) {
585836
+ const lastUserIndex = input.messages.map((message2, index) => message2.role === "user" ? index : -1).filter((index) => index >= 0).at(-1);
585837
+ const lastTransactionStart = Math.max(0, input.messages.length - 3);
585838
+ const protectedIndexes = /* @__PURE__ */ new Set();
585839
+ for (let index = lastTransactionStart; index < input.messages.length; index++) {
585840
+ protectedIndexes.add(index);
585841
+ }
585842
+ if (lastUserIndex !== void 0)
585843
+ protectedIndexes.add(lastUserIndex);
585844
+ input.messages.forEach((message2, index) => {
585845
+ if (message2.role === "system" && /\[(?:ACTIVE USER STEERING|CONTROLLER STATE v1|RECENT ACTION GROUND TRUTH|EXPLORATION ADMISSION BLOCK|COMPILE ERROR FIX LOOP BLOCKED|BRANCH-EXTRACT)/.test(message2.content)) {
585846
+ protectedIndexes.add(index);
585847
+ }
585848
+ });
585849
+ const retainedIndexes = new Set(protectedIndexes);
585850
+ let used = overhead + [...protectedIndexes].reduce((sum2, index) => sum2 + estimateTokens3([input.messages[index]]), 0);
585851
+ for (let index = input.messages.length - 1; index >= 0; index--) {
585852
+ if (retainedIndexes.has(index))
585853
+ continue;
585854
+ const message2 = input.messages[index];
585674
585855
  const cost = estimateTokens3([message2]);
585675
585856
  if (used + cost > budget)
585676
585857
  continue;
585677
- retained.push(message2);
585858
+ retainedIndexes.add(index);
585678
585859
  used += cost;
585679
585860
  }
585680
- compactedMessages = retained.reverse();
585861
+ compactedMessages = input.messages.filter((_message, index) => retainedIndexes.has(index));
585681
585862
  compacted = compactedMessages.length !== input.messages.length;
585682
585863
  evidenceDropped = 0;
585683
585864
  }
@@ -587812,6 +587993,13 @@ function stripShellQuotedSegments(command) {
587812
587993
  }
587813
587994
  return out;
587814
587995
  }
587996
+ function isCompilerLikeVerifierCommand(command) {
587997
+ const normalized = command.toLowerCase();
587998
+ return /\b(?:pio|platformio|tsc|gcc|g\+\+|clang\+\+?|clang|cargo\s+(?:build|check)|go\s+(?:build|test)|javac|gradle|mvn|msbuild|dotnet\s+build|python(?:3)?\s+-m\s+(?:py_compile|compileall)|mypy|pyright)\b/.test(normalized);
587999
+ }
588000
+ function isRecoveryCriticalRuntimeOutcome(content) {
588001
+ return /\[(?:COMPILE ERROR FIX LOOP BLOCKED|EXPLORATION ADMISSION BLOCK|PARENT(?:\s+[^\]]*)?\s+BLOCK(?:ED)?|FOCUS SUPERVISOR BLOCK|STEERING RECONCILIATION REQUIRED|STALE EDIT LOOP BLOCKED|FULL FILE WRITE LOOP BLOCKED)\b/i.test(content);
588002
+ }
587815
588003
  function parsePersistentMemoryMode(value2) {
587816
588004
  if (value2 === "full" || value2 === "deferred" || value2 === "off")
587817
588005
  return value2;
@@ -589221,6 +589409,9 @@ var init_agenticRunner = __esm({
589221
589409
  /** Auto-delegation: directive ids we've already auto-delegated for (once each). */
589222
589410
  _autoDelegatedDirectiveIds = /* @__PURE__ */ new Set();
589223
589411
  _compileFixLoop = null;
589412
+ /** A verifier produced a concrete card; the next parent tool slot is an
589413
+ * orchestrator-owned isolated fixer, not another model-chosen broad edit. */
589414
+ _pendingCompileDelegationCardId = null;
589224
589415
  _declaredVerifierCommand = null;
589225
589416
  _lastDeclaredVerifierOutput = null;
589226
589417
  _lastDeclaredVerifierDiagnostics = [];
@@ -591177,9 +591368,18 @@ Your hypotheses MUST address this specific error, not generic causes.
591177
591368
  }
591178
591369
  }
591179
591370
  _prepareModelFacingMessages(messages2, _turn) {
591371
+ const tier = this.options.modelTier ?? "large";
591372
+ const contextWindow = this.options.contextWindowSize ?? 0;
591373
+ const contextBudgetChars = contextWindow > 0 ? Math.max(48e3, Math.min(384e3, Math.floor(contextWindow * 4 * 0.7))) : tier === "large" ? 16e4 : tier === "medium" ? 96e3 : 48e3;
591374
+ const systemMessageChars = Math.max(8e3, Math.min(32e3, Math.floor(contextBudgetChars * 0.16)));
591375
+ const toolMessageChars = Math.max(6e3, Math.min(64e3, Math.floor(contextBudgetChars * 0.25)));
591180
591376
  const prepared = prepareModelFacingApiMessages({
591181
591377
  messages: messages2,
591182
- currentGoal: this._taskState.originalGoal || this._taskState.goal || this._taskState.currentStep || this._taskState.nextAction || ""
591378
+ currentGoal: this._taskState.originalGoal || this._taskState.goal || this._taskState.currentStep || this._taskState.nextAction || "",
591379
+ contextBudgetChars,
591380
+ systemMessageChars,
591381
+ toolMessageChars,
591382
+ admittedFileReadChars: Math.min(128e3, contextBudgetChars)
591183
591383
  });
591184
591384
  const withCurrentUserIntent = sanitizeHistoryThink(prepared);
591185
591385
  if (!withCurrentUserIntent.some((message2) => message2.role === "user")) {
@@ -591459,6 +591659,8 @@ ${currentIntent.trim().slice(0, 6e3)}`,
591459
591659
  * from main-loop fires in the status emit (e.g. "bf-cycle 2").
591460
591660
  */
591461
591661
  _runReg61Check(turn, toolCallLog, messages2, cycleLabel) {
591662
+ if ((this.options.modelTier ?? "large") !== "small")
591663
+ return;
591462
591664
  const REG61_TURN_FLOOR = 4;
591463
591665
  const REG61_MIN_READS = 3;
591464
591666
  const REG61_NO_WRITE_GAP = 5;
@@ -591579,7 +591781,7 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
591579
591781
  const _editPath = _editPaths.find((p2) => !this._decomp2MainContextFiles.has(p2)) ?? "";
591580
591782
  if (!_editPath)
591581
591783
  return null;
591582
- const _hardBlock = process.env["OMNIUS_ENABLE_DECOMP2_HARD_BLOCK"] === "1";
591784
+ const _hardBlock = this._enforcesStrictActionBoundaries() && process.env["OMNIUS_ENABLE_DECOMP2_HARD_BLOCK"] === "1";
591583
591785
  this.emit({
591584
591786
  type: "status",
591585
591787
  content: _hardBlock ? `DECOMP-2 NEW-FILE BLOCK — rejected ${tc.name}('${_editPath}') at turn ${turn}; gate stays active until sub_agent succeeds` : `DECOMP-2 NEW-FILE WARN — ${tc.name}('${_editPath}') at turn ${turn} would have been blocked (${this._decomp2MainContextFiles.size} files edited without sub_agent); proceeding anyway`,
@@ -592078,7 +592280,7 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
592078
592280
  return this._declaredVerifierCommand;
592079
592281
  }
592080
592282
  const diagnostics = parseCompilerDiagnostics(output);
592081
- if (diagnostics.length > 0 && !commandIsPureReadOnlyPipeline(trimmed)) {
592283
+ if (diagnostics.length > 0 && isCompilerLikeVerifierCommand(trimmed) && !commandIsPureReadOnlyPipeline(trimmed)) {
592082
592284
  const latched = stripVerifierFallbackSuffix(trimmed);
592083
592285
  return latched || trimmed;
592084
592286
  }
@@ -592187,7 +592389,7 @@ ${extras.join("\n")}`;
592187
592389
  verifierResultSignature,
592188
592390
  verifierStasisCount,
592189
592391
  verifierStasisBlocked: verifierStasisCount >= 3 && !(input.success && diagnostics.length === 0),
592190
- prerequisiteRecoverySignature: void 0
592392
+ prerequisiteRecoverySignatures: []
592191
592393
  };
592192
592394
  if (this._compileFixLoop.verifierStasisBlocked) {
592193
592395
  this.emit({
@@ -592227,6 +592429,9 @@ ${extras.join("\n")}`;
592227
592429
  this._compileFixLoop.cards = this._compileFixLoop.cards.map((card) => card.id === top.id ? top : card);
592228
592430
  this._mirrorCompileFixCardAssigned(top, input.turn);
592229
592431
  }
592432
+ if (this._enforcesStrictActionBoundaries() && !this.options.subAgent && this.tools.has("sub_agent")) {
592433
+ this._pendingCompileDelegationCardId = top.id;
592434
+ }
592230
592435
  this.emit({
592231
592436
  type: "status",
592232
592437
  content: `compile_error_fix_loop_started: verifierCommand=${verifierCommand}; cardId=${top.id}; diagnosticFingerprint=${top.diagnostic.fingerprint}; afterDiagnosticCount=${diagnostics.length}`,
@@ -592437,7 +592642,7 @@ ${extras.join("\n")}`;
592437
592642
  state.lastMutationTurn = turn;
592438
592643
  state.verifierStasisCount = 0;
592439
592644
  state.verifierStasisBlocked = false;
592440
- state.prerequisiteRecoverySignature = void 0;
592645
+ state.prerequisiteRecoverySignatures = [];
592441
592646
  this._focusSupervisor?.markCompletionBlocked({
592442
592647
  turn,
592443
592648
  reason: "A source mutation invalidated the declared verifier; verifier evidence now owns the active focus.",
@@ -592480,12 +592685,31 @@ ${extras.join("\n")}`;
592480
592685
  return owned.some((ownedPath) => this._pathsOverlapForVerifier(pathValue, ownedPath)) || artifacts.some((artifactPath) => this._pathsOverlapForVerifier(pathValue, artifactPath)) || /\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|kt|c|cc|cpp|cxx|h|hpp|hh|hxx|ino)$/i.test(pathValue);
592481
592686
  });
592482
592687
  }
592688
+ /**
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.
592695
+ */
592696
+ _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;
592704
+ }
592483
592705
  /** Consecutive preflight blocks before the gate yields instead of blocking. */
592484
592706
  static COMPILE_FIX_GATE_YIELD_AFTER = 3;
592485
592707
  _compileFixLoopPreflightBlock(toolName, args, turn, shellLikelyMutatesFilesystem) {
592486
592708
  const state = this._compileFixLoop;
592487
592709
  if (!state?.active)
592488
592710
  return null;
592711
+ if (!this._enforcesStrictActionBoundaries())
592712
+ return null;
592489
592713
  const action = compileFixLoopNextRequiredAction(state);
592490
592714
  const verifierLocked = action === "run_declared_verifier" || state.verifierStasisBlocked === true;
592491
592715
  if (!verifierLocked)
@@ -592503,7 +592727,7 @@ ${extras.join("\n")}`;
592503
592727
  `lastVerifierRunTurn=${state.lastVerifierRunTurn}`,
592504
592728
  `stasisRounds=${state.verifierStasisCount ?? 0}`,
592505
592729
  `blockedTool=${toolName} consecutiveBlocks=${streak}`,
592506
- `Allowed next actions: the declared verifier; one narrow prerequisite read of an owned file; or a scoped source fix that changes verifier inputs.`
592730
+ `Allowed next actions: the declared verifier; up to three distinct bounded prerequisite reads/searches; or a scoped source fix that changes verifier inputs.`
592507
592731
  ].join("\n")
592508
592732
  };
592509
592733
  };
@@ -592527,16 +592751,17 @@ ${extras.join("\n")}`;
592527
592751
  "file_explore"
592528
592752
  ]);
592529
592753
  if (readLike.has(toolName)) {
592530
- const target = String(args["path"] ?? args["file"] ?? args["file_path"] ?? "");
592531
- const owned = state.cards.flatMap((card) => card.ownedFiles);
592532
- const scoped = target.length > 0 && owned.some((path16) => this._pathsOverlapForVerifier(target, path16));
592533
592754
  const signature = `${toolName}:${this._buildExactArgsKey(args)}`;
592534
- if (scoped && state.prerequisiteRecoverySignature !== signature) {
592535
- state.prerequisiteRecoverySignature = signature;
592755
+ const prior = state.prerequisiteRecoverySignatures ?? [];
592756
+ const target = String(args["path"] ?? args["file"] ?? args["file_path"] ?? "").trim();
592757
+ const pattern = String(args["pattern"] ?? "").trim();
592758
+ const explicitBoundedRecovery = toolName === "file_read" && target.length > 0 || toolName === "grep_search" && (target.length > 0 || pattern.length > 0) || toolName === "find_files" && pattern.length > 0 || toolName === "list_directory" && target.length > 0 || toolName === "file_explore" && target.length > 0;
592759
+ if (explicitBoundedRecovery && !prior.includes(signature) && prior.length < 3) {
592760
+ state.prerequisiteRecoverySignatures = [...prior, signature];
592536
592761
  state.preflightBlockStreak = 0;
592537
592762
  return null;
592538
592763
  }
592539
- return blocked(scoped ? "The one prerequisite-recovery read has already been used; act on its evidence instead of reading again." : "Prerequisite recovery must be a narrow read of a compile-card owned file.");
592764
+ return blocked(prior.includes(signature) ? "This exact prerequisite recovery was already admitted; use its evidence or change the path/range/pattern." : prior.length >= 3 ? "The bounded prerequisite-recovery budget is exhausted; synthesize the three fresh observations before another read." : "Prerequisite recovery must name a file path or search pattern; broad unscoped exploration is not admitted while verifier evidence is locked.");
592540
592765
  }
592541
592766
  if (this._isProjectEditTool(toolName)) {
592542
592767
  const targetPaths = this._extractToolTargetPaths(toolName, args);
@@ -596372,6 +596597,9 @@ ${blob}
596372
596597
  }
596373
596598
  microcompact(messages2, recentToolResults) {
596374
596599
  const tier = this.options.modelTier ?? "large";
596600
+ if (tier !== "small" && process.env["OMNIUS_ENABLE_AGGRESSIVE_MICROCOMPACTION"] !== "1") {
596601
+ return;
596602
+ }
596375
596603
  let keepResults = tier === "small" ? 6 : tier === "medium" ? 10 : 20;
596376
596604
  const idleGapMs = Date.now() - this._lastAssistantTimestamp;
596377
596605
  const IDLE_THRESHOLD_MS = 5 * 6e4;
@@ -598026,6 +598254,17 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598026
598254
  const value2 = String(args["mode"] ?? "auto").trim().toLowerCase();
598027
598255
  return value2 === "full" || value2 === "extract" ? value2 : "auto";
598028
598256
  }
598257
+ /**
598258
+ * A small canonical source file is more useful as a complete first-class
598259
+ * read than as a one-line branch extract. In particular, a stale/noisy
598260
+ * resident-context estimate must not turn a 36-line file into a curated
598261
+ * wrapper merely because computed headroom is momentarily zero. This cap is
598262
+ * deliberately far below ordinary tool output limits and is still subject to
598263
+ * normal model-facing budgeting on the next request.
598264
+ */
598265
+ _mustInlineSmallFileRead(selectedBytes, selectedLines) {
598266
+ return selectedBytes <= 8e3 && selectedLines <= 200;
598267
+ }
598029
598268
  /**
598030
598269
  * Route using the same sanitized, model-facing request shape that will be
598031
598270
  * sent after the tool turn—not the unreduced historical transcript. Using
@@ -598135,7 +598374,8 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598135
598374
  });
598136
598375
  const requestedMode = this._fileReadMode(input.args);
598137
598376
  const explicitExtraction = requestedMode === "extract";
598138
- if (!decision2.branch && !explicitExtraction) {
598377
+ const inlineSmallRead = this._mustInlineSmallFileRead(selectedBytes, selectedLines.length);
598378
+ if ((!decision2.branch || inlineSmallRead) && !explicitExtraction) {
598139
598379
  input.batchBudget.inlineTokens += decision2.projectedReadTokens;
598140
598380
  input.batchBudget.reservations.set(input.callId, decision2.projectedReadTokens);
598141
598381
  return null;
@@ -598195,7 +598435,9 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598195
598435
  sourceRange: {
598196
598436
  startLine: startIndex + 1,
598197
598437
  endLine: startIndex + Math.max(1, selectedLines.length)
598198
- }
598438
+ },
598439
+ contractComplete: cached2.contractComplete,
598440
+ unresolvedRequirementIds: cached2.unresolvedRequirementIds
598199
598441
  }
598200
598442
  };
598201
598443
  }
@@ -598211,6 +598453,7 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598211
598453
  backend: extractionBackend,
598212
598454
  timeoutMs: 3e4
598213
598455
  });
598456
+ const requirementCoverage = renderBranchRequirementCoverage(ev);
598214
598457
  const verboseOutput = [
598215
598458
  `[BRANCH-EXTRACT v2] path=${rawPath}`,
598216
598459
  `[VERIFIED_RUNTIME_FILE_READ] request_id=${branchRequestId} task_epoch=${this._taskEpoch}`,
@@ -598224,10 +598467,9 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598224
598467
  `Stop conditions: ${(branchBrief.discoveryContract?.completionCriteria ?? []).join(" | ")}`,
598225
598468
  `[CURATED SEGMENTS]`,
598226
598469
  ev.claim,
598227
- `satisfied=${ev.satisfiedRequirementIds.join(",") || "none"}`,
598228
- `unresolved=${ev.unresolvedRequirementIds.join(",") || "none"}`,
598470
+ ...requirementCoverage,
598229
598471
  `provenance=content:${ev.provenance.contentHash} searches:${ev.provenance.searchRounds.length} ranges:${ev.provenance.exploredRanges.map((range) => `L${range.startLine}-L${range.endLine}`).join(",")}`,
598230
- `Contract: use these anchors as evidence. If a required item remains unresolved, issue one narrow grep_search or bounded file_read for that item. Do not use shell/cat to bypass context routing; file_read(mode="full") remains available when live admission permits it.`
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.`
598231
598473
  ].join("\n");
598232
598474
  const outputBudgetChars = Math.max(800, decision2.fractionLimitTokens * 4);
598233
598475
  let output = verboseOutput;
@@ -598241,9 +598483,9 @@ The steering reconciliation was emitted this turn. Wait for the next model decis
598241
598483
  `[CURATED SEGMENTS]`
598242
598484
  ].join("\n");
598243
598485
  const suffix = [
598244
- `unresolved=${ev.unresolvedRequirementIds.join(",") || "none"}`,
598486
+ ...requirementCoverage,
598245
598487
  `anchors=${ev.provenance.exploredRanges.map((range) => `L${range.startLine}-L${range.endLine}`).join(",")}`,
598246
- `Do not whole-read again; act on these anchors or issue one narrower search.`
598488
+ ev.contractComplete ? `All declared requirements are grounded; act on these anchors.` : `PARTIAL contract: execute the listed bounded recovery before relying on an unresolved requirement.`
598247
598489
  ].join("\n");
598248
598490
  const claimBudget = Math.max(120, outputBudgetChars - prefix.length - suffix.length - 2);
598249
598491
  output = `${prefix}
@@ -598257,13 +598499,19 @@ ${suffix}`.slice(0, outputBudgetChars);
598257
598499
  sourceBytes: stat9.size,
598258
598500
  createdAt: Date.now(),
598259
598501
  taskEpoch: this._taskEpoch,
598260
- requestId: branchRequestId
598502
+ requestId: branchRequestId,
598503
+ contractComplete: ev.contractComplete,
598504
+ unresolvedRequirementIds: ev.unresolvedRequirementIds,
598505
+ unresolvedRecoveries: ev.requirementCoverage.filter((coverage) => coverage.status === "unresolved").map((coverage) => `${coverage.id}: ${coverage.recovery ?? "narrow recovery required"}`)
598261
598506
  });
598262
598507
  this._branchEvidenceByPath.set(canonicalPath, {
598263
598508
  output,
598264
598509
  contentHash: fullHash,
598265
598510
  mtimeMs: stat9.mtimeMs,
598266
- taskEpoch: this._taskEpoch
598511
+ taskEpoch: this._taskEpoch,
598512
+ contractComplete: ev.contractComplete,
598513
+ unresolvedRequirementIds: ev.unresolvedRequirementIds,
598514
+ unresolvedRecoveries: ev.requirementCoverage.filter((coverage) => coverage.status === "unresolved").map((coverage) => `${coverage.id}: ${coverage.recovery ?? "narrow recovery required"}`)
598267
598515
  });
598268
598516
  if (explicitExtraction) {
598269
598517
  const evicted = this._evictInlineReadArtifacts(input.messages, canonicalPath, fullHash, "verified_branch_extract");
@@ -598306,7 +598554,9 @@ ${suffix}`.slice(0, outputBudgetChars);
598306
598554
  sourceRange: {
598307
598555
  startLine: startIndex + 1,
598308
598556
  endLine: startIndex + Math.max(1, selectedLines.length)
598309
- }
598557
+ },
598558
+ contractComplete: ev.contractComplete,
598559
+ unresolvedRequirementIds: ev.unresolvedRequirementIds
598310
598560
  }
598311
598561
  };
598312
598562
  }
@@ -598337,7 +598587,8 @@ ${suffix}`.slice(0, outputBudgetChars);
598337
598587
  safeContextTokens: this.contextLimits().compactionThreshold
598338
598588
  });
598339
598589
  const explicitExtraction = this._fileReadMode(input.args) === "extract";
598340
- if (!decision2.branch && !explicitExtraction) {
598590
+ const inlineSmallRead = this._mustInlineSmallFileRead(Buffer.byteLength(input.result.output, "utf8"), lines.length);
598591
+ if ((!decision2.branch || inlineSmallRead) && !explicitExtraction) {
598341
598592
  if (reservedForThisCall === 0) {
598342
598593
  input.batchBudget.inlineTokens += decision2.projectedReadTokens;
598343
598594
  input.batchBudget.reservations.set(input.callId, decision2.projectedReadTokens);
@@ -598366,6 +598617,7 @@ ${suffix}`.slice(0, outputBudgetChars);
598366
598617
  backend: process.env["OMNIUS_DISABLE_BRANCH_EXTRACT"] === "1" ? void 0 : this._auxInferenceBackend(),
598367
598618
  timeoutMs: 3e4
598368
598619
  });
598620
+ const requirementCoverage = renderBranchRequirementCoverage(ev);
598369
598621
  const output = [
598370
598622
  `[BRANCH-EXTRACT v2] path=${path16}`,
598371
598623
  `[VERIFIED_RUNTIME_FILE_READ] request_id=branch:${this._taskEpoch}:${input.callId} task_epoch=${this._taskEpoch}`,
@@ -598373,8 +598625,9 @@ ${suffix}`.slice(0, outputBudgetChars);
598373
598625
  `[DISCOVERY CONTRACT] ${brief.request}`,
598374
598626
  `[CURATED SEGMENTS]`,
598375
598627
  ev.claim,
598376
- `unresolved=${ev.unresolvedRequirementIds.join(",") || "none"}`,
598377
- `provenance=content:${ev.provenance.contentHash} ranges:${ev.provenance.exploredRanges.map((range) => `L${range.startLine}-L${range.endLine}`).join(",")}`
598628
+ ...requirementCoverage,
598629
+ `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."
598378
598631
  ].join("\n").slice(0, Math.max(800, decision2.fractionLimitTokens * 4));
598379
598632
  return {
598380
598633
  ...input.result,
@@ -598397,7 +598650,9 @@ ${suffix}`.slice(0, outputBudgetChars);
598397
598650
  sourceRange: {
598398
598651
  startLine: 1,
598399
598652
  endLine: Math.max(1, lines.length)
598400
- }
598653
+ },
598654
+ contractComplete: ev.contractComplete,
598655
+ unresolvedRequirementIds: ev.unresolvedRequirementIds
598401
598656
  }
598402
598657
  };
598403
598658
  }
@@ -599082,6 +599337,7 @@ Respond with the assessment and take the selected evidence-backed action.`;
599082
599337
  this._completionLedger = null;
599083
599338
  this._focusTerminalLedgerRecorded = false;
599084
599339
  this._compileFixLoop = null;
599340
+ this._pendingCompileDelegationCardId = null;
599085
599341
  this._declaredVerifierCommand = null;
599086
599342
  this._lastDeclaredVerifierOutput = null;
599087
599343
  this._lastDeclaredVerifierDiagnostics = [];
@@ -599841,21 +600097,7 @@ ${dynamicProjectContext}`
599841
600097
  find_files: 10,
599842
600098
  grep_search: 12,
599843
600099
  camera_capture: 3
599844
- } : loopTier === "medium" ? {
599845
- web_search: 10,
599846
- web_fetch: 8,
599847
- list_directory: 18,
599848
- find_files: 14,
599849
- grep_search: 18,
599850
- camera_capture: 4
599851
- } : {
599852
- web_search: 20,
599853
- web_fetch: 15,
599854
- list_directory: 30,
599855
- find_files: 20,
599856
- grep_search: 30,
599857
- camera_capture: 5
599858
- };
600100
+ } : {};
599859
600101
  for (const [tool, budget] of Object.entries(toolBudgets)) {
599860
600102
  toolCallBudget.set(tool, budget);
599861
600103
  }
@@ -601365,7 +601607,7 @@ Respond with EXACTLY this structure before your next tool call:
601365
601607
  }
601366
601608
  }
601367
601609
  const turnTier = this.options.modelTier ?? "large";
601368
- if (turn === 0 && !this.options.disableTodoPlanningNudges && this._todoWriteAvailable() && (turnTier === "small" || turnTier === "medium")) {
601610
+ if (turn === 0 && !this.options.disableTodoPlanningNudges && this._todoWriteAvailable() && turnTier === "small") {
601369
601611
  const goal = this._taskState.goal || "";
601370
601612
  const substantiveGoal = goal.replace(/\b(?:then\s+)?call\s+task_complete\b[^.?!;]*/gi, "").replace(/\b(?:observe|report|summarize|finish|complete)\b[^.?!;]*/gi, "");
601371
601613
  const wordCount2 = substantiveGoal.split(/\s+/).filter(Boolean).length;
@@ -601428,7 +601670,7 @@ Now call file_write with YOUR skeleton for this task.`
601428
601670
  });
601429
601671
  }
601430
601672
  }
601431
- if (turn === 0 && (turnTier === "small" || turnTier === "medium")) {
601673
+ if (turn === 0 && turnTier === "small") {
601432
601674
  const taskGoal = this._taskState.goal || "";
601433
601675
  const taskLower = taskGoal.toLowerCase();
601434
601676
  const taskTokens = new Set(taskLower.split(/\s+/).filter((w) => w.length > 2));
@@ -601471,7 +601713,7 @@ Now call file_write with YOUR skeleton for this task.`
601471
601713
  ${top.map((t2) => `- ${t2.name}: ${t2.desc}`).join("\n")}`);
601472
601714
  }
601473
601715
  }
601474
- if (turn === 0 && (turnTier === "small" || turnTier === "medium")) {
601716
+ if (turn === 0 && turnTier === "small") {
601475
601717
  const taskGoal = (this._taskState.goal || "").toLowerCase();
601476
601718
  const isSimpleTask = taskGoal.length < 150 && (taskGoal.match(/\band\b|\bthen\b/gi) || []).length < 3;
601477
601719
  const isSearchTask = /\bfind\b|\bsearch\b|\bwhere\b|\bwhich file\b|\bcontain/i.test(taskGoal);
@@ -601496,7 +601738,7 @@ ${top.map((t2) => `- ${t2.name}: ${t2.desc}`).join("\n")}`);
601496
601738
  ${hints.join("\n")}`);
601497
601739
  }
601498
601740
  }
601499
- if (turn === 0 && (turnTier === "small" || turnTier === "medium")) {
601741
+ if (turn === 0 && turnTier === "small") {
601500
601742
  const taskGoal = this._taskState.goal || "";
601501
601743
  const hasMultiplePremises = (taskGoal.match(/\band\b|\bthen\b|\bif\b|\bbecause\b|\bsince\b|\bgiven\b/gi) || []).length >= 3;
601502
601744
  const hasConditionalLogic = (taskGoal.match(/\bif\b.*\bthen\b|\bwhen\b.*\bshould\b|\bassuming\b/gi) || []).length >= 1;
@@ -601568,7 +601810,7 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
601568
601810
  compacted = messages2;
601569
601811
  }
601570
601812
  this._retireStaleEvidenceInPlace(messages2, turn);
601571
- if (turn > 0 && this._toolEvents.length > 0) {
601813
+ if (turn > 0 && this._toolEvents.length > 0 && ((this.options.modelTier ?? "large") === "small" || process.env["OMNIUS_ENABLE_LEGACY_CONTEXT_ENGINE_TRIM"] === "1")) {
601572
601814
  try {
601573
601815
  const _limits = this.contextLimits();
601574
601816
  const ceCompactInput = {
@@ -602100,7 +602342,7 @@ ${memoryLines.join("\n")}`
602100
602342
  "shell"
602101
602343
  ]);
602102
602344
  const selfConsistencyK = this.options.selfConsistencyK ?? 0;
602103
- const shouldVote = selfConsistencyK >= 2 && this._selfConsistencyVotes < 2 && (this.options.modelTier === "small" || this.options.modelTier === "medium") && firstToolCall && HIGH_STAKE_TOOLS.has(firstToolCall.name) && turn <= 3;
602345
+ const shouldVote = selfConsistencyK >= 2 && this._selfConsistencyVotes < 2 && this.options.modelTier === "small" && firstToolCall && HIGH_STAKE_TOOLS.has(firstToolCall.name) && turn <= 3;
602104
602346
  if (shouldVote && firstToolCall) {
602105
602347
  try {
602106
602348
  const alternativeA = {
@@ -602157,7 +602399,7 @@ ${memoryLines.join("\n")}`
602157
602399
  const isEmptyResponse = !isThinkOnly && (!msg.content || !msg.content.trim()) && (!msg.toolCalls || msg.toolCalls.length === 0);
602158
602400
  if (isEmptyResponse) {
602159
602401
  consecutiveEmptyResponses++;
602160
- if (consecutiveEmptyResponses >= 2) {
602402
+ if (consecutiveEmptyResponses >= 2 && (this.options.modelTier ?? "large") === "small") {
602161
602403
  this.emit({
602162
602404
  type: "status",
602163
602405
  content: `${consecutiveEmptyResponses} consecutive empty responses — injecting recovery nudge`,
@@ -602178,6 +602420,18 @@ ${memoryLines.join("\n")}`
602178
602420
  continue;
602179
602421
  }
602180
602422
  consecutiveEmptyResponses = 0;
602423
+ const pendingCompileDelegation = this._steeringToolGate(turn) ? null : this._takePendingCompileDelegation(messages2, turn);
602424
+ if (pendingCompileDelegation) {
602425
+ const supersededCalls = msg.toolCalls?.length ?? 0;
602426
+ msg.toolCalls = [pendingCompileDelegation];
602427
+ msg.content = null;
602428
+ this.emit({
602429
+ type: "status",
602430
+ content: `[FAN-OUT] automatic compile-fixer dispatch preempted ${supersededCalls} model-selected call${supersededCalls === 1 ? "" : "s"}; the parent will resume only after the isolated fold-back.`,
602431
+ turn,
602432
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
602433
+ });
602434
+ }
602181
602435
  if (msg.toolCalls && msg.toolCalls.length > 0) {
602182
602436
  consecutiveTextOnly = 0;
602183
602437
  consecutiveThinkOnly = 0;
@@ -602190,15 +602444,10 @@ ${memoryLines.join("\n")}`
602190
602444
  });
602191
602445
  continue;
602192
602446
  }
602193
- const _RESPONSE_CALL_CAPS = {
602194
- small: 2,
602195
- medium: 4,
602196
- large: 6
602197
- };
602198
- const _responseCap = _RESPONSE_CALL_CAPS[this.options.modelTier ?? "large"] ?? 6;
602447
+ const _responseCap = (this.options.modelTier ?? "large") === "small" ? 2 : Number.POSITIVE_INFINITY;
602199
602448
  const _originalCallCount = msg.toolCalls.length;
602200
602449
  let _capDeferredCount = 0;
602201
- if (msg.toolCalls.length > _responseCap) {
602450
+ if (Number.isFinite(_responseCap) && msg.toolCalls.length > _responseCap) {
602202
602451
  _capDeferredCount = msg.toolCalls.length - _responseCap;
602203
602452
  msg.toolCalls = msg.toolCalls.slice(0, _responseCap);
602204
602453
  this.emit({
@@ -602236,7 +602485,7 @@ ${memoryLines.join("\n")}`
602236
602485
  role: "system",
602237
602486
  content: [
602238
602487
  `[BATCH CAPPED]`,
602239
- `You emitted ${_originalCallCount} tool calls in one response. The orchestrator caps responses at ${_responseCap} for the ${this.options.modelTier ?? "large"} model tier.`,
602488
+ `You emitted ${_originalCallCount} tool calls in one response. The small-model safety profile caps responses at ${_responseCap}.`,
602240
602489
  `The first ${_responseCap} executed; the remaining ${_capDeferredCount} were DROPPED.`,
602241
602490
  ``,
602242
602491
  `Best practice for this model tier: emit at most ${_responseCap} tool calls per turn.`,
@@ -602366,7 +602615,8 @@ Corrective action: try a different approach first: read relevant files, adjust a
602366
602615
  timestampMs: Date.now()
602367
602616
  });
602368
602617
  const _toolLogTailIdx = toolCallLog.length - 1;
602369
- if (tc.name !== "task_complete") {
602618
+ const isDeclaredCompileVerifier = tc.name === "shell" && Boolean(this._compileFixLoop?.active) && commandReliablySatisfiesVerifyCommand(String((tc.arguments ?? {})["command"] ?? (tc.arguments ?? {})["cmd"] ?? "").trim(), this._compileFixLoop?.verifierCommand ?? "");
602619
+ if (this._enforcesStrictActionBoundaries() && tc.name !== "task_complete" && !isDeclaredCompileVerifier) {
602370
602620
  const doomHistory = toolCallLog.slice(-5).map((e2) => ({ tool: e2.name, args: e2.argsKey }));
602371
602621
  doomHistory.push({
602372
602622
  tool: tc.name,
@@ -602501,7 +602751,7 @@ Corrective action: try a different approach first: read relevant files, adjust a
602501
602751
  detail: `attempted_tool=${tc.name}`
602502
602752
  });
602503
602753
  }
602504
- if (this._reg61PerpetualGateActive && !focusDirectiveForEditPressure && !REG61_BYPASS_TOOLS.has(tc.name) && process.env["OMNIUS_DISABLE_REG61_COERCE"] !== "1") {
602754
+ if (this._enforcesStrictActionBoundaries() && this._reg61PerpetualGateActive && !focusDirectiveForEditPressure && !REG61_BYPASS_TOOLS.has(tc.name) && process.env["OMNIUS_DISABLE_REG61_COERCE"] !== "1") {
602505
602755
  const _dbgLoop = this._detectDebugLoop([
602506
602756
  ...toolCallLog,
602507
602757
  { name: tc.name, argsKey }
@@ -602596,7 +602846,7 @@ Corrective action: try a different approach first: read relevant files, adjust a
602596
602846
  const toolFingerprint = this._resolveReadCoverageFingerprint(tc.name, tc.arguments ?? {}, exactToolFingerprint);
602597
602847
  const repeatedMemoryWriteNoop = tc.name === "memory_write" && noopedMemoryWriteFingerprints.has(toolFingerprint);
602598
602848
  const repeatedProjectWriteNoop = this._isProjectEditTool(tc.name) && noopedProjectWriteFingerprints.has(toolFingerprint);
602599
- if (repeatedMemoryWriteNoop || repeatedProjectWriteNoop) {
602849
+ if (this._enforcesStrictActionBoundaries() && (repeatedMemoryWriteNoop || repeatedProjectWriteNoop)) {
602600
602850
  this.emit({
602601
602851
  type: "tool_call",
602602
602852
  toolName: tc.name,
@@ -602628,7 +602878,7 @@ Read the current file if needed, make a different concrete edit, or move to veri
602628
602878
  systemGuidance: repeatNoopMsg
602629
602879
  };
602630
602880
  }
602631
- const staleEditBlock = this.staleEditPreflightBlock(tc.name, tc.arguments ?? {});
602881
+ const staleEditBlock = this._enforcesStrictActionBoundaries() ? this.staleEditPreflightBlock(tc.name, tc.arguments ?? {}) : null;
602632
602882
  if (staleEditBlock) {
602633
602883
  const focusDecision2 = this._focusSupervisor?.evaluateProposedCall({
602634
602884
  turn,
@@ -602693,7 +602943,7 @@ Read the current file if needed, make a different concrete edit, or move to veri
602693
602943
  systemGuidance: staleBlockOutput
602694
602944
  };
602695
602945
  }
602696
- const staleRewriteBlock = this.staleEditOverwritePreflightBlock(tc.name, tc.arguments ?? {}, turn);
602946
+ const staleRewriteBlock = this._enforcesStrictActionBoundaries() ? this.staleEditOverwritePreflightBlock(tc.name, tc.arguments ?? {}, turn) : null;
602697
602947
  if (staleRewriteBlock) {
602698
602948
  const focusDecision2 = this._focusSupervisor?.evaluateProposedCall({
602699
602949
  turn,
@@ -602992,7 +603242,7 @@ Read the current file if needed, make a different concrete edit, or move to veri
602992
603242
  });
602993
603243
  }
602994
603244
  const _repeatGateMax = this._resolveRepeatGateMax();
602995
- const isFailedShellRepeat = 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;
603245
+ 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;
602996
603246
  const repeatGateEligible = isReadLike || tc.name === "memory_write" || isFailedShellRepeat;
602997
603247
  const suppressSuccessfulShellCacheGuidance = tc.name === "shell" && !isFailedShellRepeat;
602998
603248
  if (suppressSuccessfulShellCacheGuidance)
@@ -603119,6 +603369,15 @@ ${cachedResult}`,
603119
603369
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
603120
603370
  });
603121
603371
  }
603372
+ if (!repeatShortCircuit && this.options.subAgent && tc.name === "workboard_complete_card" && String((tc.arguments ?? {})["outcome"] ?? "completed") !== "request_changes") {
603373
+ repeatShortCircuit = {
603374
+ success: false,
603375
+ output: "",
603376
+ error: "[PARENT_COMPLETION_AUTHORITY] A sub-agent may attach action/verifier evidence or request changes, but only its parent/coordinator may complete or verify a workboard card.",
603377
+ runtimeAuthored: true,
603378
+ noop: true
603379
+ };
603380
+ }
603122
603381
  const focusCachedEntry = recentToolResults.get(toolFingerprint);
603123
603382
  const focusDuplicateHits = criticDecision.decision === "guidance" ? dedupHitCount.get(toolFingerprint) ?? criticDecision.hitNumber : dedupHitCount.get(toolFingerprint) ?? 0;
603124
603383
  const usesAuthoritativeTargetEvidence = this._toolCallUsesFreshFileReadEvidence(tc.name, tc.arguments ?? {});
@@ -603138,8 +603397,9 @@ ${cachedResult}`,
603138
603397
  taskEpoch: this._taskEpoch
603139
603398
  });
603140
603399
  if (focusDecision && focusDecision.kind !== "pass") {
603400
+ const advisoryOnlyForLargeModel = focusDecision.kind === "block_tool_call" && !this._enforcesStrictActionBoundaries() && tc.name !== "task_complete";
603141
603401
  this._emitFocusSupervisorEvent({
603142
- decision: focusDecision.kind,
603402
+ decision: advisoryOnlyForLargeModel ? "inject_guidance" : focusDecision.kind,
603143
603403
  state: focusDecision.state,
603144
603404
  directiveId: focusDecision.directive.id,
603145
603405
  reason: focusDecision.directive.reason,
@@ -603147,22 +603407,26 @@ ${cachedResult}`,
603147
603407
  blockedTool: focusDecision.kind === "block_tool_call" ? tc.name : void 0,
603148
603408
  turn
603149
603409
  });
603150
- this._maybeMarkFocusTerminalIncomplete({
603151
- decision: focusDecision,
603152
- blockedTool: focusDecision.kind === "block_tool_call" ? tc.name : void 0,
603153
- turn
603154
- });
603155
- if (focusDecision.kind === "block_tool_call" && this._maybeAutoDelegate(tc, focusDecision.directive, messages2, turn)) {
603156
- } else if (focusDecision.kind === "inject_guidance") {
603157
- void focusDecision.message;
603158
- } else if (!repeatShortCircuit) {
603159
- repeatShortCircuit = {
603160
- success: focusDecision.success,
603161
- output: focusDecision.message,
603162
- error: focusDecision.success ? void 0 : focusDecision.message,
603163
- runtimeAuthored: true,
603164
- noop: true
603165
- };
603410
+ if (advisoryOnlyForLargeModel) {
603411
+ pushSoftInjection("system", `[FOCUS ADVISORY — large-model freedom] ${focusDecision.message}`);
603412
+ } else {
603413
+ this._maybeMarkFocusTerminalIncomplete({
603414
+ decision: focusDecision,
603415
+ blockedTool: focusDecision.kind === "block_tool_call" ? tc.name : void 0,
603416
+ turn
603417
+ });
603418
+ if (focusDecision.kind === "block_tool_call" && this._maybeAutoDelegate(tc, focusDecision.directive, messages2, turn)) {
603419
+ } else if (focusDecision.kind === "inject_guidance") {
603420
+ void focusDecision.message;
603421
+ } else if (!repeatShortCircuit) {
603422
+ repeatShortCircuit = {
603423
+ success: focusDecision.success,
603424
+ output: focusDecision.message,
603425
+ error: focusDecision.success ? void 0 : focusDecision.message,
603426
+ runtimeAuthored: true,
603427
+ noop: true
603428
+ };
603429
+ }
603166
603430
  }
603167
603431
  }
603168
603432
  const compileLoopPreflight = !repeatShortCircuit ? this._compileFixLoopPreflightBlock(tc.name, tc.arguments ?? {}, turn, shellLikelyMutatesFilesystem) : null;
@@ -603228,7 +603492,9 @@ ${cachedResult}`,
603228
603492
  tc.arguments = this._normalizeToolArgsForExecution(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
603229
603493
  tc.arguments = this._autoDeriveDelegationMutationScope(resolvedTool?.name ?? tc.name, tc.arguments ?? {}, turn);
603230
603494
  tc.arguments = await this._enrichDelegationToolArgs(resolvedTool?.name ?? tc.name, tc.arguments ?? {}, messages2, turn);
603231
- validationError = this._validateFileWriteOverwriteContract(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
603495
+ validationError = this._partialBranchExplorationMutationBlock(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
603496
+ if (!validationError)
603497
+ validationError = this._validateFileWriteOverwriteContract(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
603232
603498
  }
603233
603499
  if (!validationError) {
603234
603500
  validationError = this._validateFreshExpectedHashesForEdit(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
@@ -604643,7 +604909,7 @@ ${bookkeepingGuidance}`;
604643
604909
 
604644
604910
  ${bookkeepingGuidance}` : bookkeepingGuidance;
604645
604911
  }
604646
- if (!result.success && (this.options.modelTier === "small" || this.options.modelTier === "medium")) {
604912
+ if (!result.success && this.options.modelTier === "small") {
604647
604913
  const recovery = this.buildRecoveryGuidance(tc.name, result.error ?? "", tc.arguments);
604648
604914
  if (recovery)
604649
604915
  output += "\n\n" + recovery;
@@ -605094,7 +605360,7 @@ ${delegateDir}` : delegateDir;
605094
605360
  sameToolFailStreak = 1;
605095
605361
  }
605096
605362
  const consecutiveSameTool = Math.max(sameToolFailStreak, this._taskState.failedApproaches.slice(-2).filter((f2) => f2.startsWith(`${tc.name}(`)).length);
605097
- if (sameToolFailStreak >= 5 && (this.options.modelTier === "small" || this.options.modelTier === "medium")) {
605363
+ if (sameToolFailStreak >= 5 && this.options.modelTier === "small") {
605098
605364
  this.enqueueRuntimeGuidance(`[BRANCH — evaluate alternatives before acting]
605099
605365
  Tool "${tc.name}" has failed ${sameToolFailStreak} times. STOP and enumerate:
605100
605366
  Option A: refresh the exact evidence or correct the current tool arguments
@@ -605104,7 +605370,7 @@ Pick the BEST option and explain why, then execute it. Do NOT retry ${tc.name} w
605104
605370
  sameToolFailStreak = 0;
605105
605371
  sameToolFailName = null;
605106
605372
  }
605107
- if (consecutiveSameTool >= 2 && (this.options.modelTier === "small" || this.options.modelTier === "medium")) {
605373
+ if (consecutiveSameTool >= 2 && this.options.modelTier === "small") {
605108
605374
  this.enqueueRuntimeGuidance(`[PIVOT REQUIRED] You have failed ${consecutiveSameTool + 1} times in a row with ${tc.name}. Your current approach is not working. You MUST try something fundamentally different:
605109
605375
  - If file_edit/file_patch keeps failing: re-read the implicated current range, then correct the exact text/range/hash or inspect git diff
605110
605376
  - If shell keeps failing: try a different command or check prerequisites
@@ -605151,7 +605417,7 @@ Do NOT retry ${tc.name} with similar arguments and do NOT use file_write to esca
605151
605417
  } catch {
605152
605418
  }
605153
605419
  }
605154
- if (isModify && (turnTier === "small" || turnTier === "medium")) {
605420
+ if (isModify && turnTier === "small") {
605155
605421
  const modCount = this._taskState.modifiedFiles.size;
605156
605422
  if (modCount >= 2 && modCount % 2 === 0) {
605157
605423
  this.enqueueRuntimeGuidance(`[Test reminder] You've modified ${modCount} files. Run relevant tests NOW to verify: shell(command="npm test") or the project's test command. Fix any failures before continuing.`);
@@ -607943,7 +608209,7 @@ ${marker}` : marker);
607943
608209
  });
607944
608210
  if (active) {
607945
608211
  const tier = this.options.modelTier ?? "large";
607946
- if (tier !== "small" && tier !== "medium")
608212
+ if (tier !== "small")
607947
608213
  return null;
607948
608214
  return [
607949
608215
  `[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"}).`,
@@ -607989,6 +608255,38 @@ ${marker}` : marker);
607989
608255
  }
607990
608256
  return null;
607991
608257
  }
608258
+ /**
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.
608263
+ */
608264
+ _partialBranchExplorationMutationBlock(toolName, args) {
608265
+ const delegatedMutation = (toolName === "sub_agent" || toolName === "agent") && (args["mutation_role"] === "mutation_worker" || args["subagent_type"] === "fixer");
608266
+ if (!this._isProjectEditTool(toolName) && !delegatedMutation)
608267
+ return null;
608268
+ const targetPaths = this._isProjectEditTool(toolName) ? this._extractToolTargetPaths(toolName, args) : [
608269
+ ...Array.isArray(args["owned_files"]) ? args["owned_files"] : [],
608270
+ ...Array.isArray(args["relevant_files"]) ? args["relevant_files"] : []
608271
+ ].filter((value2) => typeof value2 === "string");
608272
+ for (const target of targetPaths) {
608273
+ const normalizedTarget = this._normalizeEvidencePath(target);
608274
+ const partial = [...this._branchEvidenceByPath.entries()].find(([path17, node2]) => node2.taskEpoch === this._taskEpoch && !node2.contractComplete && this._pathsOverlapForVerifier(normalizedTarget, path17));
608275
+ if (!partial)
608276
+ continue;
608277
+ 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");
608287
+ }
608288
+ return null;
608289
+ }
607992
608290
  _validateFreshExpectedHashesForEdit(toolName, args) {
607993
608291
  if (process.env["OMNIUS_ALLOW_UNVERIFIED_OLD_STRING_EDIT"] === "1") {
607994
608292
  return null;
@@ -608806,7 +609104,50 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
608806
609104
  *
608807
609105
  * Returns true if it rewrote `tc` (the caller must let it EXECUTE, not noop it).
608808
609106
  */
609107
+ _takePendingCompileDelegation(messages2, turn) {
609108
+ const cardId = this._pendingCompileDelegationCardId;
609109
+ if (!cardId || !this._enforcesStrictActionBoundaries() || this.options.subAgent || !this.tools.has("sub_agent")) {
609110
+ return null;
609111
+ }
609112
+ const state = this._compileFixLoop;
609113
+ const card = state?.cards.find((candidate) => candidate.id === cardId && (candidate.status === "open" || candidate.status === "assigned" || candidate.status === "needs_changes"));
609114
+ if (!card) {
609115
+ this._pendingCompileDelegationCardId = null;
609116
+ return null;
609117
+ }
609118
+ this._pendingCompileDelegationCardId = null;
609119
+ card.status = "assigned";
609120
+ card.assignedTurn = turn;
609121
+ this._mirrorCompileFixCardAssigned(card, turn);
609122
+ const contract = buildMutationWorkerContractForCard(card);
609123
+ const prompt = buildCuratedFixerPrompt({
609124
+ card,
609125
+ sourceExcerpt: this._compileFixSourceExcerpt(card.diagnostic.file, card.diagnostic.line),
609126
+ declarationExcerpt: card.declarationFiles.length > 0 ? this._compileFixSourceExcerpt(card.declarationFiles[0], void 0) : void 0
609127
+ });
609128
+ const parentTok = estimateMessagesTokens2(messages2);
609129
+ this.emit({
609130
+ type: "status",
609131
+ content: `[FAN-OUT] compile verifier produced ${card.id}; orchestrator is launching one isolated fixer (main ~${parentTok.toLocaleString()} tok -> curated worker frame: ${card.ownedFiles.join(", ") || "diagnostic target"}).`,
609132
+ turn,
609133
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
609134
+ });
609135
+ return {
609136
+ id: `auto-compile-${card.id}-${turn}`,
609137
+ name: "sub_agent",
609138
+ arguments: {
609139
+ subagent_type: "fixer",
609140
+ description: `fix ${card.id}`,
609141
+ prompt,
609142
+ relevant_files: card.ownedFiles,
609143
+ exit_criterion: "diagnostic fingerprint disappeared after verifier rerun",
609144
+ ...contract
609145
+ }
609146
+ };
609147
+ }
608809
609148
  _maybeAutoDelegate(tc, directive, messages2, turn) {
609149
+ if (!this._enforcesStrictActionBoundaries())
609150
+ return false;
608810
609151
  if (directive.requiredNextAction !== "delegate_isolated_fix")
608811
609152
  return false;
608812
609153
  if (tc.name === "sub_agent" || tc.name === "agent")
@@ -608904,11 +609245,20 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
608904
609245
  _retireStaleEvidenceInPlace(messages2, currentTurn) {
608905
609246
  if (process.env["OMNIUS_DISABLE_EVIDENCE_RETIREMENT"] === "1")
608906
609247
  return;
609248
+ const tier = this.options.modelTier ?? "large";
609249
+ const forceRetirement = process.env["OMNIUS_FORCE_EVIDENCE_RETIREMENT"] === "1";
609250
+ const residentTokens = estimateMessagesTokens2(messages2);
609251
+ const pressureThreshold = Math.floor(this.contextLimits().compactionThreshold * 0.9);
609252
+ if (tier !== "small" && !forceRetirement && residentTokens < pressureThreshold) {
609253
+ return;
609254
+ }
608907
609255
  const keepRecent = Math.max(0, Number(process.env["OMNIUS_EVIDENCE_KEEP_TURNS"] ?? 2));
608908
609256
  const minChars = Math.max(512, Number(process.env["OMNIUS_EVIDENCE_MIN_CHARS"] ?? 2e3));
608909
609257
  const staleBefore = currentTurn - keepRecent;
608910
609258
  if (staleBefore <= 0)
608911
609259
  return;
609260
+ const liveToolCallIds = new Set(this._recentToolOutcomes.slice(-4).map((outcome) => outcome.toolCallId).filter((id2) => Boolean(id2)));
609261
+ const unresolvedBranchPaths = [...this._branchEvidenceByPath.entries()].filter(([, node]) => node.taskEpoch === this._taskEpoch && !node.contractComplete).map(([path16]) => this._normalizeEvidencePath(path16)).filter(Boolean);
608912
609262
  let turnCount = 0;
608913
609263
  let retired = 0;
608914
609264
  let reclaimed = 0;
@@ -608922,9 +609272,20 @@ Actions: (1) list_directory on the parent directory to see what's there, (2) Che
608922
609272
  const content = typeof msg.content === "string" ? msg.content : "";
608923
609273
  if (!content)
608924
609274
  continue;
609275
+ if (msg.role === "tool" && liveToolCallIds.has(msg.tool_call_id ?? "")) {
609276
+ continue;
609277
+ }
608925
609278
  if (content.startsWith("[RETIRED EVIDENCE") || content.startsWith("[Todo context archived") || content.startsWith("[Tool result cleared")) {
608926
609279
  continue;
608927
609280
  }
609281
+ if (isRecoveryCriticalRuntimeOutcome(content))
609282
+ continue;
609283
+ if (unresolvedBranchPaths.some((path16) => content.includes(path16)))
609284
+ continue;
609285
+ const fileContextPath = /\[FILE CONTEXT\s*\|\s*([^|\n]+)/.exec(content)?.[1]?.trim();
609286
+ if (fileContextPath && !this._evidenceLedger.hasFresh(this._normalizeEvidencePath(fileContextPath))) {
609287
+ continue;
609288
+ }
608928
609289
  const rm4 = { role: msg.role, content };
608929
609290
  if (!isRetirableEvidence(rm4, minChars))
608930
609291
  continue;
@@ -609463,6 +609824,23 @@ Describe what you see and integrate this into your current approach.` : "[User s
609463
609824
  if (!force && estimatedTokens < limits.compactionThreshold) {
609464
609825
  return messages2;
609465
609826
  }
609827
+ if (!force) {
609828
+ const partialBranchActive = [...this._branchEvidenceByPath.values()].some((node) => node.taskEpoch === this._taskEpoch && !node.contractComplete);
609829
+ const decision2 = decideCompaction({
609830
+ pressureRatio: estimatedTokens / Math.max(1, limits.compactionThreshold),
609831
+ lastSubtaskResolved: this._recentToolOutcomes.at(-1)?.succeeded === true,
609832
+ midDerivation: partialBranchActive,
609833
+ convergenceStalled: this._compileFixLoop?.verifierStasisBlocked === true
609834
+ });
609835
+ if (!decision2.compact) {
609836
+ this.emit({
609837
+ type: "status",
609838
+ content: `[semantic-compaction] held: ${decision2.reason}`,
609839
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
609840
+ });
609841
+ return messages2;
609842
+ }
609843
+ }
609466
609844
  if (force && messages2.length < 5)
609467
609845
  return messages2;
609468
609846
  let keepRecent = limits.keepRecent;
@@ -609643,7 +610021,7 @@ Describe what you see and integrate this into your current approach.` : "[User s
609643
610021
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
609644
610022
  });
609645
610023
  const tier = this.options.modelTier ?? "large";
609646
- if (tier === "small" || tier === "medium") {
610024
+ if (tier === "small") {
609647
610025
  this._taskState.nextAction = this.inferNextAction(recent);
609648
610026
  }
609649
610027
  const manifestText = (() => {
@@ -609745,14 +610123,14 @@ ${postCompactRestore.join("\n")}`);
609745
610123
  const goalReminder = this._taskState.goal ? `
609746
610124
 
609747
610125
  **YOUR ACTIVE TASK:** ${this._taskState.goal}` : "";
609748
- const nextActionDirective = (tier === "small" || tier === "medium") && this._taskState.nextAction ? `
610126
+ const nextActionDirective = tier === "small" && this._taskState.nextAction ? `
609749
610127
 
609750
610128
  **DO THIS NEXT:** ${this._taskState.nextAction}` : "";
609751
610129
  const toolCallingReminder = tier === "small" ? `
609752
610130
 
609753
610131
  **IMPORTANT:** You MUST invoke tools through the function calling interface. Do NOT write tool names as text, markdown, or code blocks — that does nothing. Call tools using the structured tool/function API.` : "";
609754
610132
  const readFilesList = Array.from(this._fileRegistry.entries()).filter(([, e2]) => e2.accessCount > 0).map(([p2]) => p2).slice(0, 10);
609755
- const fileFreshnessReminder = (tier === "small" || tier === "medium") && readFilesList.length > 0 ? `
610133
+ const fileFreshnessReminder = tier === "small" && readFilesList.length > 0 ? `
609756
610134
 
609757
610135
  **PREVIOUSLY OBSERVED FILES:** ${readFilesList.join(", ")}. Treat restored or summarized text as orientation, not guaranteed current bytes. Before editing, make a narrow live read when the body is elided/truncated, the file may have changed, a hash or edit anchor is stale, or exact current text is otherwise required. Avoid only redundant reads when the latest complete authoritative content is still visible and unchanged.` : "";
609758
610136
  const ephemeralSkillPackReminder = this._ephemeralSkillPackContext ? `
@@ -609990,6 +610368,23 @@ ${content.slice(0, 8e3)}${truncated ? "\n[truncated recovery; use a narrow live
609990
610368
  });
609991
610369
  }
609992
610370
  }
610371
+ const pinnedSymbols = [
610372
+ ...[...this._branchEvidenceByPath.entries()].filter(([, node]) => node.taskEpoch === this._taskEpoch && !node.contractComplete).map(([path16]) => this._normalizeEvidencePath(path16)).filter(Boolean),
610373
+ ...this._recentToolOutcomes.slice(-2).map((outcome) => outcome.path).filter((path16) => Boolean(path16))
610374
+ ];
610375
+ const activeSteering = this._renderActiveSteeringSlot();
610376
+ const validation = validateCompaction(result.map((message2) => typeof message2.content === "string" ? message2.content : JSON.stringify(message2.content)).join("\n"), {
610377
+ symbols: pinnedSymbols,
610378
+ ...activeSteering ? { openBugs: ["[ACTIVE USER STEERING]"] } : {}
610379
+ });
610380
+ if (!validation.valid) {
610381
+ this.emit({
610382
+ type: "status",
610383
+ content: `[semantic-compaction] rollback: ${validation.reason}`,
610384
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
610385
+ });
610386
+ return messages2;
610387
+ }
609993
610388
  if (result.length < 2)
609994
610389
  return messages2;
609995
610390
  return result;
@@ -610222,7 +610617,7 @@ ${trimmedNew}`;
610222
610617
  ];
610223
610618
  const tier = this.options.modelTier ?? "large";
610224
610619
  const directive = this._focusSupervisor?.snapshot().directive;
610225
- if (directive && tier !== "large") {
610620
+ if (directive && tier === "small") {
610226
610621
  const expiresTurn = Math.max(turn + 1, directive.createdTurn + 6);
610227
610622
  lines.push(`active_directive=next_action:${directive.requiredNextAction}; evidence:${directive.reason.replace(/\s+/g, " ").slice(0, 260)}; expires_turn:${expiresTurn}; exit_when:action_evidence_or_verified_mutation_or_user_redirect`);
610228
610623
  }
@@ -610234,7 +610629,7 @@ ${trimmedNew}`;
610234
610629
  const resultState = outcome ? outcome.succeeded ? "tool_result=success" : "tool_result=failure" : "tool_result=not_recorded";
610235
610630
  const hash = evidence?.contentHash ?? "unknown";
610236
610631
  const bytes = fact && typeof fact.size === "number" ? String(fact.size) : "unknown";
610237
- const nextAction = verifierRequired ? "run_declared_verifier" : outcome?.succeeded ? "verify_or_complete_distinct_leaf" : "inspect_external_blocker_or_change_scope";
610632
+ const nextAction = tier === "small" ? verifierRequired ? "run_declared_verifier" : outcome?.succeeded ? "verify_or_complete_distinct_leaf" : "inspect_external_blocker_or_change_scope" : "model_select_from_current_evidence";
610238
610633
  const doNot = action === "created" ? "do_not_create_again" : action === "modified" ? "do_not_full_rewrite_without_fresh_read" : "do_not_recreate_without_authoritative_target";
610239
610634
  lines.push(`${action} path=${entry.path} hash=${hash} bytes=${bytes} ${resultState} stateVersion=${outcome?.stateVersion ?? this._adversaryStateVersion} turn=${outcome?.turn ?? turn} next_valid_action=${nextAction} ${doNot}`);
610240
610635
  }
@@ -612241,8 +612636,8 @@ ${description}`
612241
612636
  });
612242
612637
  }
612243
612638
  }
612244
- const delay4 = isGpuSlotUnavailable ? baseDelayMs : Math.min(baseDelayMs * Math.pow(2, attempt - 1), maxDelayMs);
612245
- const effectiveDelay = delay4;
612639
+ const delay5 = isGpuSlotUnavailable ? baseDelayMs : Math.min(baseDelayMs * Math.pow(2, attempt - 1), maxDelayMs);
612640
+ const effectiveDelay = delay5;
612246
612641
  const attemptLabel = maxRetries === Infinity ? `${attempt}` : `${attempt}/${maxRetries}`;
612247
612642
  if (isGpuSlotUnavailable) {
612248
612643
  this.emit({
@@ -624294,8 +624689,8 @@ function normalizeLiveCameraRotation(value2) {
624294
624689
  if (n2 === 0 || n2 === 90 || n2 === 180 || n2 === 270) return n2;
624295
624690
  }
624296
624691
  const raw = String(value2).trim().toLowerCase();
624297
- const numeric = Number(raw.replace(/deg(?:rees)?$/i, ""));
624298
- if (Number.isFinite(numeric)) return normalizeLiveCameraRotation(numeric);
624692
+ const numeric2 = Number(raw.replace(/deg(?:rees)?$/i, ""));
624693
+ if (Number.isFinite(numeric2)) return normalizeLiveCameraRotation(numeric2);
624299
624694
  if (["none", "off", "upright", "normal", "0"].includes(raw)) return 0;
624300
624695
  if (["cw", "clockwise", "right", "rotate-cw", "rotate_cw", "90"].includes(raw)) return 90;
624301
624696
  if (["180", "upside-down", "upside_down", "flip", "inverted"].includes(raw)) return 180;
@@ -627783,8 +628178,8 @@ function finiteRecord(value2) {
627783
628178
  return result;
627784
628179
  }
627785
628180
  function sampleTime(value2) {
627786
- const numeric = finiteNumber(value2);
627787
- if (numeric !== null) return numeric < 1e11 ? numeric * 1e3 : numeric;
628181
+ const numeric2 = finiteNumber(value2);
628182
+ if (numeric2 !== null) return numeric2 < 1e11 ? numeric2 * 1e3 : numeric2;
627788
628183
  if (typeof value2 !== "string") return null;
627789
628184
  const parsed = Date.parse(value2);
627790
628185
  return Number.isFinite(parsed) ? parsed : null;
@@ -643845,6 +644240,134 @@ var init_profiles = __esm({
643845
644240
  }
643846
644241
  });
643847
644242
 
644243
+ // packages/cli/src/tui/ollama-gpu-policy.ts
644244
+ import { execFile as execFile9 } from "node:child_process";
644245
+ import { promisify as promisify6 } from "node:util";
644246
+ function numeric(value2) {
644247
+ const parsed = Number.parseFloat((value2 ?? "").trim());
644248
+ return Number.isFinite(parsed) ? parsed : null;
644249
+ }
644250
+ function parseNvidiaGpuCsv(stdout) {
644251
+ const result = [];
644252
+ for (const rawLine of stdout.split(/\r?\n/)) {
644253
+ const line = rawLine.trim();
644254
+ if (!line) continue;
644255
+ const [rawIndex, rawUuid, rawName, rawMemory, rawCapability] = line.split(",").map((value2) => value2.trim());
644256
+ const index = numeric(rawIndex);
644257
+ const memoryTotalMiB = numeric(rawMemory);
644258
+ const computeCapability = numeric(rawCapability);
644259
+ const uuid = rawUuid ?? "";
644260
+ if (index === null || memoryTotalMiB === null || computeCapability === null || !uuid || !CUDA_IDENTIFIER.test(uuid)) {
644261
+ continue;
644262
+ }
644263
+ result.push({
644264
+ index,
644265
+ uuid,
644266
+ name: rawName ?? "NVIDIA GPU",
644267
+ memoryTotalMiB,
644268
+ computeCapability
644269
+ });
644270
+ }
644271
+ return result;
644272
+ }
644273
+ function satisfiesOllamaGpuMinimum(gpu) {
644274
+ return gpu.memoryTotalMiB >= MIN_OLLAMA_GPU_VRAM_MIB && gpu.computeCapability >= MIN_OLLAMA_GPU_COMPUTE_CAPABILITY;
644275
+ }
644276
+ function isA100ClassAccelerator(name10) {
644277
+ return /\b(?:A100|H100|H200|B100|B200|GB200)\b/i.test(name10);
644278
+ }
644279
+ function describeGpu(gpu) {
644280
+ return `${gpu.name} (${gpu.uuid}; ${Math.round(gpu.memoryTotalMiB / 1024)} GiB; compute ${gpu.computeCapability})`;
644281
+ }
644282
+ function selectApprovedOllamaGpu(gpus, configuredUuid = process.env[OMNIUS_OLLAMA_GPU_UUID_ENV]) {
644283
+ const requestedUuid = configuredUuid?.trim();
644284
+ if (requestedUuid) {
644285
+ const requested = gpus.find((gpu) => gpu.uuid === requestedUuid);
644286
+ if (!requested) {
644287
+ return {
644288
+ ok: false,
644289
+ reason: `${OMNIUS_OLLAMA_GPU_UUID_ENV}=${requestedUuid} was not found in the current NVIDIA inventory. Refusing to launch Ollama on an inferred device.`
644290
+ };
644291
+ }
644292
+ if (!satisfiesOllamaGpuMinimum(requested)) {
644293
+ return {
644294
+ ok: false,
644295
+ reason: `Configured GPU ${describeGpu(requested)} does not meet the required ${MIN_OLLAMA_GPU_VRAM_MIB / 1024} GiB VRAM and compute capability ${MIN_OLLAMA_GPU_COMPUTE_CAPABILITY}. Refusing to launch Ollama.`
644296
+ };
644297
+ }
644298
+ return {
644299
+ ok: true,
644300
+ approval: {
644301
+ gpu: requested,
644302
+ source: "configured_uuid",
644303
+ cudaVisibleDevices: requested.uuid
644304
+ }
644305
+ };
644306
+ }
644307
+ const automatic = gpus.filter(
644308
+ (gpu) => satisfiesOllamaGpuMinimum(gpu) && isA100ClassAccelerator(gpu.name)
644309
+ ).sort(
644310
+ (left, right) => right.memoryTotalMiB - left.memoryTotalMiB || right.computeCapability - left.computeCapability || left.index - right.index
644311
+ )[0];
644312
+ if (automatic) {
644313
+ return {
644314
+ ok: true,
644315
+ approval: {
644316
+ gpu: automatic,
644317
+ source: "a100_class_auto",
644318
+ cudaVisibleDevices: automatic.uuid
644319
+ }
644320
+ };
644321
+ }
644322
+ const discovered = gpus.length ? gpus.map(describeGpu).join("; ") : "no queryable NVIDIA GPUs";
644323
+ return {
644324
+ ok: false,
644325
+ reason: `No approved GPU is available (${discovered}). Set ${OMNIUS_OLLAMA_GPU_UUID_ENV} to the UUID of a designated GPU meeting ${MIN_OLLAMA_GPU_VRAM_MIB / 1024} GiB VRAM and compute capability ${MIN_OLLAMA_GPU_COMPUTE_CAPABILITY}, or make an A100-class accelerator visible.`
644326
+ };
644327
+ }
644328
+ async function defaultNvidiaSmiRunner(command, args) {
644329
+ const { stdout } = await execFileAsync5(command, args, {
644330
+ timeout: 5e3,
644331
+ windowsHide: true
644332
+ });
644333
+ return { stdout };
644334
+ }
644335
+ async function resolveApprovedOllamaGpu(options2 = {}) {
644336
+ try {
644337
+ const runner = options2.runner ?? defaultNvidiaSmiRunner;
644338
+ const { stdout } = await runner("nvidia-smi", [
644339
+ "--query-gpu=index,uuid,name,memory.total,compute_cap",
644340
+ "--format=csv,noheader,nounits"
644341
+ ]);
644342
+ return selectApprovedOllamaGpu(
644343
+ parseNvidiaGpuCsv(stdout),
644344
+ options2.configuredUuid
644345
+ );
644346
+ } catch (error) {
644347
+ const detail = error instanceof Error ? error.message : String(error);
644348
+ return {
644349
+ ok: false,
644350
+ reason: `Could not verify NVIDIA GPU placement with nvidia-smi (${detail}). Refusing to launch Ollama.`
644351
+ };
644352
+ }
644353
+ }
644354
+ function withApprovedOllamaGpu(env2, approval) {
644355
+ return {
644356
+ ...env2,
644357
+ CUDA_VISIBLE_DEVICES: approval.cudaVisibleDevices
644358
+ };
644359
+ }
644360
+ var execFileAsync5, OMNIUS_OLLAMA_GPU_UUID_ENV, MIN_OLLAMA_GPU_VRAM_MIB, MIN_OLLAMA_GPU_COMPUTE_CAPABILITY, CUDA_IDENTIFIER;
644361
+ var init_ollama_gpu_policy = __esm({
644362
+ "packages/cli/src/tui/ollama-gpu-policy.ts"() {
644363
+ execFileAsync5 = promisify6(execFile9);
644364
+ OMNIUS_OLLAMA_GPU_UUID_ENV = "OMNIUS_OLLAMA_GPU_UUID";
644365
+ MIN_OLLAMA_GPU_VRAM_MIB = 16 * 1024;
644366
+ MIN_OLLAMA_GPU_COMPUTE_CAPABILITY = 7;
644367
+ CUDA_IDENTIFIER = /^[A-Za-z0-9._:-]+$/;
644368
+ }
644369
+ });
644370
+
643848
644371
  // packages/cli/src/tui/omnius-directory.ts
643849
644372
  var omnius_directory_exports = {};
643850
644373
  __export(omnius_directory_exports, {
@@ -644009,7 +644532,7 @@ function watchForOmniusGitignore(repoRoot) {
644009
644532
  function scheduleOmniusGitignoreRescans(repoRoot) {
644010
644533
  const key = resolve62(repoRoot);
644011
644534
  if (gitignoreRetryTimers.has(key)) return;
644012
- const timers = [25, 100, 250, 500, 1e3].map((delay4) => {
644535
+ const timers = [25, 100, 250, 500, 1e3].map((delay5) => {
644013
644536
  const timer = setTimeout(() => {
644014
644537
  try {
644015
644538
  ensureOmniusIgnored(repoRoot);
@@ -644021,7 +644544,7 @@ function scheduleOmniusGitignoreRescans(repoRoot) {
644021
644544
  if (idx >= 0) list.splice(idx, 1);
644022
644545
  if (list.length === 0) gitignoreRetryTimers.delete(key);
644023
644546
  }
644024
- }, delay4);
644547
+ }, delay5);
644025
644548
  timer.unref?.();
644026
644549
  return timer;
644027
644550
  });
@@ -648871,8 +649394,8 @@ var init_project_context = __esm({
648871
649394
  });
648872
649395
 
648873
649396
  // packages/cli/src/tui/disk-monitor.ts
648874
- import { execFile as execFile9 } from "node:child_process";
648875
- import { promisify as promisify6 } from "node:util";
649397
+ import { execFile as execFile10 } from "node:child_process";
649398
+ import { promisify as promisify7 } from "node:util";
648876
649399
  function unavailableDiskMetrics(path16 = process.cwd()) {
648877
649400
  return {
648878
649401
  path: path16,
@@ -648886,7 +649409,7 @@ function unavailableDiskMetrics(path16 = process.cwd()) {
648886
649409
  async function collectDiskMetrics(path16 = process.cwd()) {
648887
649410
  if (process.platform === "win32") return unavailableDiskMetrics(path16);
648888
649411
  try {
648889
- const { stdout } = await execFileAsync5("df", ["-Pk", path16], {
649412
+ const { stdout } = await execFileAsync6("df", ["-Pk", path16], {
648890
649413
  encoding: "utf8",
648891
649414
  timeout: 3e3,
648892
649415
  maxBuffer: 128 * 1024
@@ -648916,10 +649439,10 @@ async function collectDiskMetrics(path16 = process.cwd()) {
648916
649439
  return unavailableDiskMetrics(path16);
648917
649440
  }
648918
649441
  }
648919
- var execFileAsync5;
649442
+ var execFileAsync6;
648920
649443
  var init_disk_monitor = __esm({
648921
649444
  "packages/cli/src/tui/disk-monitor.ts"() {
648922
- execFileAsync5 = promisify6(execFile9);
649445
+ execFileAsync6 = promisify7(execFile10);
648923
649446
  }
648924
649447
  });
648925
649448
 
@@ -652628,7 +653151,7 @@ var init_status_bar = __esm({
652628
653151
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
652629
653152
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
652630
653153
  buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K`;
652631
- buf += `${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
653154
+ buf += `${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
652632
653155
  buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
652633
653156
  }
652634
653157
  buf += this.buildEnhanceSegment(
@@ -653893,6 +654416,10 @@ ${CONTENT_BG_SEQ}`);
653893
654416
  );
653894
654417
  return `\x1B[38;2;${r2};${g};${b}m`;
653895
654418
  }
654419
+ /** Keep the rail before the `+` prompt static while stream frames animate. */
654420
+ inputLeftRailSeq() {
654421
+ return BOX_FG;
654422
+ }
653896
654423
  /** Box top border with an optional ┬ carving out the enhance segment. */
653897
654424
  buildInputBoxTop(w) {
653898
654425
  if (!this.enhanceSegEnabled(w)) {
@@ -654406,7 +654933,7 @@ ${CONTENT_BG_SEQ}`);
654406
654933
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
654407
654934
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
654408
654935
  buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K`;
654409
- buf += `${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
654936
+ buf += `${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
654410
654937
  buf += `${PANEL_BG_SEQ}\x1B[K`;
654411
654938
  buf += `\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
654412
654939
  }
@@ -654425,7 +654952,7 @@ ${CONTENT_BG_SEQ}`);
654425
654952
  const fg2 = isHighlighted ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
654426
654953
  const slash = isHighlighted ? `\x1B[38;5;245m` : `\x1B[38;5;${TEXT_DIM}m`;
654427
654954
  const marker = isHighlighted ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
654428
- buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
654955
+ buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
654429
654956
  buf += `${bg} ${marker}${slash}/${fg2}${cmd}`;
654430
654957
  buf += `${PANEL_BG_SEQ}\x1B[K`;
654431
654958
  buf += `\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
@@ -654480,7 +655007,7 @@ ${CONTENT_BG_SEQ}`);
654480
655007
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
654481
655008
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
654482
655009
  buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K`;
654483
- buf += `${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
655010
+ buf += `${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
654484
655011
  buf += `${PANEL_BG_SEQ}\x1B[K`;
654485
655012
  buf += `\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
654486
655013
  }
@@ -654503,7 +655030,7 @@ ${CONTENT_BG_SEQ}`);
654503
655030
  const isHl = si === this._suggestIndex;
654504
655031
  const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
654505
655032
  const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
654506
- buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
655033
+ buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
654507
655034
  buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}`;
654508
655035
  }
654509
655036
  buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}`;
@@ -654570,7 +655097,7 @@ ${CONTENT_BG_SEQ}`);
654570
655097
  const row2 = pos.inputStartRow + 1 + i2;
654571
655098
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
654572
655099
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
654573
- buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}`;
655100
+ buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}`;
654574
655101
  }
654575
655102
  buf += this.buildEnhanceSegment(
654576
655103
  w,
@@ -654585,7 +655112,7 @@ ${CONTENT_BG_SEQ}`);
654585
655112
  const bg = isHl ? `\x1B[48;5;235m` : PANEL_BG_SEQ;
654586
655113
  const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
654587
655114
  const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
654588
- buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
655115
+ buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
654589
655116
  buf += `${bg} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
654590
655117
  buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}`;
654591
655118
  }
@@ -654613,7 +655140,7 @@ ${CONTENT_BG_SEQ}`);
654613
655140
  const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
654614
655141
  const lineContent = `${prefix}${inputWrap.lines[i2]}`;
654615
655142
  buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K`;
654616
- buf += `${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
655143
+ buf += `${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
654617
655144
  buf += `${PANEL_BG_SEQ}\x1B[K`;
654618
655145
  buf += `\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
654619
655146
  }
@@ -654630,7 +655157,7 @@ ${CONTENT_BG_SEQ}`);
654630
655157
  const bg = isHl ? `\x1B[48;5;235m` : PANEL_BG_SEQ;
654631
655158
  const fg2 = isHl ? `\x1B[1;38;5;${TEXT_PRIMARY}m` : `\x1B[38;5;${TEXT_PRIMARY}m`;
654632
655159
  const marker = isHl ? `\x1B[38;5;${TEXT_PRIMARY}m› ` : " ";
654633
- buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.borderVSeq(1)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
655160
+ buf += `\x1B[${row2};1H${PANEL_BG_SEQ}\x1B[2K${this.inputLeftRailSeq()}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
654634
655161
  buf += `${bg} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
654635
655162
  buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row2};${w}H${this.borderVSeq(w)}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
654636
655163
  }
@@ -656814,7 +657341,7 @@ __export(setup_exports, {
656814
657341
  });
656815
657342
  import * as readline from "node:readline";
656816
657343
  import { spawn as spawn34, exec as exec5 } from "node:child_process";
656817
- import { promisify as promisify7 } from "node:util";
657344
+ import { promisify as promisify8 } from "node:util";
656818
657345
  import { existsSync as existsSync132, writeFileSync as writeFileSync68, readFileSync as readFileSync109, appendFileSync as appendFileSync15, mkdirSync as mkdirSync80, chmodSync as chmodSync3 } from "node:fs";
656819
657346
  import { delimiter as pathDelimiter, join as join143 } from "node:path";
656820
657347
  import { freemem as freemem8, homedir as homedir48, platform as platform6, totalmem as totalmem9 } from "node:os";
@@ -657646,6 +658173,30 @@ async function installOllamaWindows() {
657646
658173
  return false;
657647
658174
  }
657648
658175
  }
658176
+ async function startApprovedOllamaServe() {
658177
+ const admission = await resolveApprovedOllamaGpu();
658178
+ if (!admission.ok) {
658179
+ process.stdout.write(
658180
+ ` ${c3.red("✖")} Ollama launch blocked by GPU safety policy: ${admission.reason}
658181
+ `
658182
+ );
658183
+ return false;
658184
+ }
658185
+ try {
658186
+ const child = spawn34("ollama", ["serve"], {
658187
+ stdio: "ignore",
658188
+ detached: true,
658189
+ env: withApprovedOllamaGpu(process.env, admission.approval)
658190
+ });
658191
+ child.unref();
658192
+ return true;
658193
+ } catch (error) {
658194
+ const detail = error instanceof Error ? error.message : String(error);
658195
+ process.stdout.write(` ${c3.cyan("⚠")} Could not start ollama serve: ${detail}
658196
+ `);
658197
+ return false;
658198
+ }
658199
+ }
657649
658200
  async function ensureOllamaRunning(backendUrl2, rl) {
657650
658201
  const ollamaInstalled = hasCmd("ollama");
657651
658202
  if (!ollamaInstalled) {
@@ -657674,13 +658225,8 @@ async function ensureOllamaRunning(backendUrl2, rl) {
657674
658225
  }
657675
658226
  process.stdout.write(` ${c3.cyan("●")} Starting ollama serve...
657676
658227
  `);
657677
- try {
657678
- const child = spawn34("ollama", ["serve"], { stdio: "ignore", detached: true });
657679
- child.unref();
657680
- } catch {
657681
- process.stdout.write(` ${c3.cyan("⚠")} Could not start ollama serve.
657682
-
657683
- `);
658228
+ if (!await startApprovedOllamaServe()) {
658229
+ process.stdout.write("\n");
657684
658230
  return false;
657685
658231
  }
657686
658232
  for (let i2 = 0; i2 < 5; i2++) {
@@ -657698,7 +658244,7 @@ async function ensureOllamaRunning(backendUrl2, rl) {
657698
658244
  } catch {
657699
658245
  }
657700
658246
  }
657701
- process.stdout.write(` ${c3.cyan("⚠")} Ollama started but not responding. Try ${c3.bold("ollama serve")} manually.
658247
+ process.stdout.write(` ${c3.cyan("⚠")} Ollama started on the approved GPU but is not responding yet.
657702
658248
 
657703
658249
  `);
657704
658250
  return false;
@@ -658367,9 +658913,7 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
658367
658913
  process.stdout.write(`
658368
658914
  ${c3.cyan("●")} Ollama is installed but not running. Starting automatically...
658369
658915
  `);
658370
- try {
658371
- const child = spawn34("ollama", ["serve"], { stdio: "ignore", detached: true });
658372
- child.unref();
658916
+ if (await startApprovedOllamaServe()) {
658373
658917
  await new Promise((resolve82) => setTimeout(resolve82, 3e3));
658374
658918
  try {
658375
658919
  models = await fetchOllamaModels(config.backendUrl);
@@ -658381,8 +658925,8 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
658381
658925
 
658382
658926
  `);
658383
658927
  }
658384
- } catch {
658385
- process.stdout.write(` ${c3.cyan("⚠")} Could not start Ollama. Try running ${c3.bold("ollama serve")} manually.
658928
+ } else {
658929
+ process.stdout.write(` ${c3.cyan("⚠")} Ollama was not started. Configure an approved GPU or a custom endpoint.
658386
658930
 
658387
658931
  `);
658388
658932
  }
@@ -658395,9 +658939,7 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
658395
658939
  process.stdout.write(`
658396
658940
  ${c3.cyan("●")} Starting ollama serve...
658397
658941
  `);
658398
- try {
658399
- const child = spawn34("ollama", ["serve"], { stdio: "ignore", detached: true });
658400
- child.unref();
658942
+ if (await startApprovedOllamaServe()) {
658401
658943
  await new Promise((resolve82) => setTimeout(resolve82, 3e3));
658402
658944
  try {
658403
658945
  models = await fetchOllamaModels(config.backendUrl);
@@ -658405,12 +658947,12 @@ ${c3.cyan(OMNIUS_FIRST_RUN_BANNER)}
658405
658947
 
658406
658948
  `);
658407
658949
  } catch {
658408
- process.stdout.write(` ${c3.cyan("⚠")} Ollama installed but not responding yet. Try ${c3.bold("ollama serve")} manually.
658950
+ process.stdout.write(` ${c3.cyan("⚠")} Ollama installed but not responding yet.
658409
658951
 
658410
658952
  `);
658411
658953
  }
658412
- } catch {
658413
- process.stdout.write(` ${c3.cyan("⚠")} Ollama installed. Start it with: ${c3.bold("ollama serve")}
658954
+ } else {
658955
+ process.stdout.write(` ${c3.cyan("⚠")} Ollama installed but was not started without an approved GPU.
658414
658956
 
658415
658957
  `);
658416
658958
  }
@@ -659685,7 +660227,8 @@ var init_setup = __esm({
659685
660227
  init_dist6();
659686
660228
  init_tui_select();
659687
660229
  init_listen();
659688
- execAsync2 = promisify7(exec5);
660230
+ init_ollama_gpu_policy();
660231
+ execAsync2 = promisify8(exec5);
659689
660232
  OMNIUS_FIRST_RUN_BANNER = [
659690
660233
  " ░▒▓██████▓▒░░▒▓██████████████▓▒░░▒▓███████▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓███████▓▒░ ",
659691
660234
  "░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ",
@@ -664358,6 +664901,7 @@ __export(daemon_exports, {
664358
664901
  getDaemonStatus: () => getDaemonStatus,
664359
664902
  getLocalCliVersion: () => getLocalCliVersion,
664360
664903
  isDaemonRunning: () => isDaemonRunning,
664904
+ recoverDaemonVersionBoundedly: () => recoverDaemonVersionBoundedly,
664361
664905
  releaseDaemonEndpointClaim: () => releaseDaemonEndpointClaim,
664362
664906
  releaseDaemonEndpointForCurrentProcess: () => releaseDaemonEndpointForCurrentProcess,
664363
664907
  restartDaemon: () => restartDaemon,
@@ -664365,7 +664909,7 @@ __export(daemon_exports, {
664365
664909
  stopDaemon: () => stopDaemon
664366
664910
  });
664367
664911
  import { spawn as spawn35 } from "node:child_process";
664368
- import { existsSync as existsSync140, readFileSync as readFileSync114, writeFileSync as writeFileSync70, mkdirSync as mkdirSync82, unlinkSync as unlinkSync27, openSync as openSync5, closeSync as closeSync5, writeSync as writeSync2, statSync as statSync57 } from "node:fs";
664912
+ import { existsSync as existsSync140, readFileSync as readFileSync114, writeFileSync as writeFileSync70, mkdirSync as mkdirSync82, unlinkSync as unlinkSync27, openSync as openSync5, closeSync as closeSync5, writeSync as writeSync2, statSync as statSync57, renameSync as renameSync13 } from "node:fs";
664369
664913
  import { join as join149 } from "node:path";
664370
664914
  import { homedir as homedir51 } from "node:os";
664371
664915
  import { fileURLToPath as fileURLToPath20 } from "node:url";
@@ -664527,22 +665071,165 @@ async function waitForDaemonReady(port, expectedVersion, attempts = 24) {
664527
665071
  }
664528
665072
  return { ok: false, observedVersion };
664529
665073
  }
664530
- async function restartDaemon(port, expectedVersion) {
664531
- const p2 = port ?? getDaemonPort();
665074
+ function delay4(ms) {
665075
+ return new Promise((resolve82) => setTimeout(resolve82, ms));
665076
+ }
665077
+ async function runUserSystemctl(args, timeout2 = 2e4) {
664532
665078
  try {
664533
665079
  const { spawnSync: spawnSync9 } = await import("node:child_process");
664534
- const enabled2 = spawnSync9("systemctl", ["--user", "is-enabled", "omnius-daemon.service"], {
665080
+ const result = spawnSync9("systemctl", ["--user", ...args], {
664535
665081
  stdio: "ignore",
664536
- timeout: 5e3
665082
+ timeout: timeout2
665083
+ });
665084
+ return { available: !result.error, ok: result.status === 0 };
665085
+ } catch {
665086
+ return { available: false, ok: false };
665087
+ }
665088
+ }
665089
+ async function hasManagedDaemonService() {
665090
+ const enabled2 = await runUserSystemctl(["is-enabled", "omnius-daemon.service"], 5e3);
665091
+ if (enabled2.ok) return true;
665092
+ const active = await runUserSystemctl(["is-active", "omnius-daemon.service"], 5e3);
665093
+ return active.ok;
665094
+ }
665095
+ function systemdQuote(value2) {
665096
+ return /[\s"\\]/.test(value2) ? `"${value2.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : value2;
665097
+ }
665098
+ async function repairManagedDaemonUnit(port) {
665099
+ if (process.platform !== "linux") return false;
665100
+ const command = await resolveDaemonCommand(process.execPath);
665101
+ if (!command) return false;
665102
+ try {
665103
+ const configHome2 = process.env["XDG_CONFIG_HOME"] || join149(homedir51(), ".config");
665104
+ const unitDir = join149(configHome2, "systemd", "user");
665105
+ const unitPath = join149(unitDir, "omnius-daemon.service");
665106
+ const logDir = join149(OMNIUS_DIR2);
665107
+ mkdirSync82(unitDir, { recursive: true });
665108
+ mkdirSync82(logDir, { recursive: true });
665109
+ const execStart = [command.command, ...command.args].map(systemdQuote).join(" ");
665110
+ const unit = [
665111
+ "[Unit]",
665112
+ `Description=Omnius API Daemon (port ${port})`,
665113
+ "After=network-online.target",
665114
+ "Wants=network-online.target",
665115
+ "",
665116
+ "[Service]",
665117
+ "Type=simple",
665118
+ "Environment=OMNIUS_DAEMON=1",
665119
+ `Environment=OMNIUS_PORT=${port}`,
665120
+ "Environment=NODE_ENV=production",
665121
+ `ExecStart=${execStart}`,
665122
+ "Restart=always",
665123
+ "RestartSec=3",
665124
+ "StartLimitIntervalSec=30",
665125
+ "StartLimitBurst=10",
665126
+ `StandardOutput=append:${join149(logDir, "daemon.log")}`,
665127
+ `StandardError=append:${join149(logDir, "daemon.err.log")}`,
665128
+ "",
665129
+ "[Install]",
665130
+ "WantedBy=default.target",
665131
+ ""
665132
+ ].join("\n");
665133
+ const tmp = `${unitPath}.tmp.${process.pid}.${Date.now()}`;
665134
+ writeFileSync70(tmp, unit, { encoding: "utf8", mode: 384 });
665135
+ renameSync13(tmp, unitPath);
665136
+ return (await runUserSystemctl(["daemon-reload"], 1e4)).ok;
665137
+ } catch {
665138
+ return false;
665139
+ }
665140
+ }
665141
+ async function portHolderPids(port) {
665142
+ try {
665143
+ const { spawnSync: spawnSync9 } = await import("node:child_process");
665144
+ const lsof = spawnSync9("lsof", ["-ti", `:${port}`], {
665145
+ encoding: "utf8",
665146
+ stdio: ["ignore", "pipe", "ignore"],
665147
+ timeout: 3e3
664537
665148
  });
664538
- if (enabled2.status === 0) {
664539
- spawnSync9("systemctl", ["--user", "restart", "omnius-daemon.service"], { stdio: "ignore", timeout: 2e4 });
664540
- return (await waitForDaemonReady(p2, expectedVersion)).ok;
665149
+ let output = lsof.stdout ?? "";
665150
+ if (!output.trim()) {
665151
+ const fuser = spawnSync9("fuser", [`${port}/tcp`], {
665152
+ encoding: "utf8",
665153
+ stdio: ["ignore", "pipe", "ignore"],
665154
+ timeout: 3e3
665155
+ });
665156
+ output = `${fuser.stdout ?? ""}
665157
+ ${fuser.stderr ?? ""}`;
665158
+ if (lsof.error && fuser.error) return null;
664541
665159
  }
665160
+ return output.split(/[\s\n]+/).map((value2) => parseInt(value2, 10)).filter((pid) => Number.isInteger(pid) && pid > 0 && pid !== process.pid);
665161
+ } catch {
665162
+ return null;
665163
+ }
665164
+ }
665165
+ function processCommandLine(pid) {
665166
+ try {
665167
+ return readFileSync114(`/proc/${pid}/cmdline`, "utf8").replace(/\0/g, " ");
664542
665168
  } catch {
665169
+ return "";
665170
+ }
665171
+ }
665172
+ function isOwnedOmniusDaemon(pid, daemonPid) {
665173
+ if (pid === daemonPid) return true;
665174
+ if (listProcessLeases({ includeInactive: false }).some((lease) => lease.pid === pid && lease.ownerKind === "daemon")) {
665175
+ return true;
665176
+ }
665177
+ const command = processCommandLine(pid);
665178
+ return /(?:^|[\\/\s])omnius(?:[\\/\s]|$)|omnius-daemon|[\\/]dist[\\/]index\.js\b|launcher\.cjs\b/i.test(command);
665179
+ }
665180
+ async function ownedDaemonPids(port) {
665181
+ const daemonPid = getDaemonPid();
665182
+ const candidates = /* @__PURE__ */ new Set();
665183
+ if (daemonPid) candidates.add(daemonPid);
665184
+ const holders = await portHolderPids(port);
665185
+ for (const pid of holders ?? []) candidates.add(pid);
665186
+ return [...candidates].filter((pid) => processIsAlive(pid) && isOwnedOmniusDaemon(pid, daemonPid));
665187
+ }
665188
+ async function waitForDaemonStopped(port, attempts = DAEMON_GRACEFUL_STOP_ATTEMPTS) {
665189
+ for (let attempt = 0; attempt < attempts; attempt++) {
665190
+ const healthy = await isDaemonRunning(port);
665191
+ const holders = await portHolderPids(port);
665192
+ if (!healthy && (holders === null || holders.length === 0)) return true;
665193
+ await delay4(500);
664543
665194
  }
664544
- await forceKillDaemon(p2);
664545
- const pid = await startDaemon();
665195
+ return false;
665196
+ }
665197
+ async function gracefullyStopOwnedDaemon(port) {
665198
+ const pids = await ownedDaemonPids(port);
665199
+ for (const pid of pids) {
665200
+ try {
665201
+ process.kill(pid, "SIGTERM");
665202
+ } catch {
665203
+ }
665204
+ }
665205
+ if (await waitForDaemonStopped(port)) return true;
665206
+ const survivors = await ownedDaemonPids(port);
665207
+ for (const pid of survivors) {
665208
+ try {
665209
+ process.kill(pid, "SIGKILL");
665210
+ } catch {
665211
+ }
665212
+ }
665213
+ return waitForDaemonStopped(port, 10);
665214
+ }
665215
+ async function restartDaemon(port, expectedVersion) {
665216
+ const p2 = port ?? getDaemonPort();
665217
+ const managed = await hasManagedDaemonService();
665218
+ if (managed) {
665219
+ const restarted = await runUserSystemctl(["restart", "omnius-daemon.service"]);
665220
+ if (restarted.ok && (await waitForDaemonReady(p2, expectedVersion)).ok) return true;
665221
+ const repaired = await repairManagedDaemonUnit(p2);
665222
+ if (repaired) {
665223
+ await runUserSystemctl(["stop", "omnius-daemon.service"]);
665224
+ await waitForDaemonStopped(p2);
665225
+ const started = await runUserSystemctl(["start", "omnius-daemon.service"]);
665226
+ if (started.ok && (await waitForDaemonReady(p2, expectedVersion)).ok) return true;
665227
+ }
665228
+ await runUserSystemctl(["stop", "omnius-daemon.service"]);
665229
+ if (!await waitForDaemonStopped(p2)) return false;
665230
+ }
665231
+ if (await isDaemonRunning(p2) && !await gracefullyStopOwnedDaemon(p2)) return false;
665232
+ const pid = await startDaemon(p2);
664546
665233
  if (!pid) return false;
664547
665234
  return (await waitForDaemonReady(p2, expectedVersion)).ok;
664548
665235
  }
@@ -664579,6 +665266,8 @@ function commandForEntrypoint(path16, nodeExe) {
664579
665266
  }
664580
665267
  async function resolveDaemonCommand(nodeExe) {
664581
665268
  const candidates = [];
665269
+ const thisDir = dirname47(fileURLToPath20(import.meta.url));
665270
+ candidates.push(join149(thisDir, "index.js"));
664582
665271
  if (process.argv[1]) candidates.push(process.argv[1]);
664583
665272
  try {
664584
665273
  const { spawnSync: spawnSync9 } = await import("node:child_process");
@@ -664590,8 +665279,6 @@ async function resolveDaemonCommand(nodeExe) {
664590
665279
  if (first2) candidates.push(first2);
664591
665280
  } catch {
664592
665281
  }
664593
- const thisDir = dirname47(fileURLToPath20(import.meta.url));
664594
- candidates.push(join149(thisDir, "index.js"));
664595
665282
  const seen = /* @__PURE__ */ new Set();
664596
665283
  for (const candidate of candidates) {
664597
665284
  if (!candidate || seen.has(candidate)) continue;
@@ -664601,9 +665288,9 @@ async function resolveDaemonCommand(nodeExe) {
664601
665288
  }
664602
665289
  return null;
664603
665290
  }
664604
- async function startDaemon() {
665291
+ async function startDaemon(port = getDaemonPort()) {
664605
665292
  mkdirSync82(OMNIUS_DIR2, { recursive: true });
664606
- const daemonPort = getDaemonPort();
665293
+ const daemonPort = port;
664607
665294
  const endpointClaim = claimDaemonEndpoint(daemonPort);
664608
665295
  if (!endpointClaim) return null;
664609
665296
  const nodeExe = process.execPath;
@@ -664627,6 +665314,7 @@ async function startDaemon() {
664627
665314
  ...processLeaseEnv(leaseId, ownerId, process.cwd()),
664628
665315
  OMNIUS_DAEMON: "1",
664629
665316
  // signal to serve.ts that it's running as daemon
665317
+ OMNIUS_PORT: String(daemonPort),
664630
665318
  OMNIUS_DAEMON_LOCK_TOKEN: endpointClaim.token,
664631
665319
  OMNIUS_DAEMON_LOCK_PORT: String(daemonPort),
664632
665320
  OMNIUS_PROCESS_OWNER_KIND: "daemon",
@@ -664746,15 +665434,45 @@ async function forceKillDaemon(port) {
664746
665434
  }
664747
665435
  return killed;
664748
665436
  }
665437
+ async function recoverDaemonVersionBoundedly(expectedVersion, observe, recover, maxAttempts = DAEMON_VERSION_RECOVERY_ATTEMPTS) {
665438
+ let observedVersion = await observe();
665439
+ if (expectedVersion === "0.0.0" || observedVersion === expectedVersion) {
665440
+ return { ok: true, observedVersion, attempts: 0 };
665441
+ }
665442
+ const boundedAttempts = Math.max(1, Math.min(3, Math.floor(maxAttempts)));
665443
+ for (let attempt = 1; attempt <= boundedAttempts; attempt++) {
665444
+ await recover();
665445
+ observedVersion = await observe();
665446
+ if (observedVersion === expectedVersion) {
665447
+ return { ok: true, observedVersion, attempts: attempt };
665448
+ }
665449
+ }
665450
+ return { ok: false, observedVersion, attempts: boundedAttempts };
665451
+ }
664749
665452
  async function ensureDaemonVersion(expectedVersion = getLocalCliVersion(), port = getDaemonPort()) {
664750
- const finish = (ok3, action, observedVersion) => ({ ok: ok3, action, expectedVersion, observedVersion, port });
665453
+ const finish = (ok3, action, observedVersion, recoveryAttempts = 0) => ({
665454
+ ok: ok3,
665455
+ action,
665456
+ expectedVersion,
665457
+ observedVersion,
665458
+ port,
665459
+ recoveryAttempts
665460
+ });
664751
665461
  if (await isDaemonRunning(port)) {
664752
665462
  if (process.env["OMNIUS_NO_VERSION_GUARD"] !== "1") {
664753
665463
  const running = await getDaemonReportedVersion(port);
664754
665464
  if (expectedVersion !== "0.0.0" && running !== expectedVersion) {
664755
- const ok3 = await restartDaemon(port, expectedVersion);
664756
- const observedVersion = await getDaemonReportedVersion(port);
664757
- return finish(ok3 && observedVersion === expectedVersion, ok3 ? "restarted" : "failed", observedVersion);
665465
+ const recovery = await recoverDaemonVersionBoundedly(
665466
+ expectedVersion,
665467
+ () => getDaemonReportedVersion(port),
665468
+ () => restartDaemon(port, expectedVersion)
665469
+ );
665470
+ return finish(
665471
+ recovery.ok,
665472
+ recovery.ok ? "restarted" : "failed",
665473
+ recovery.observedVersion,
665474
+ recovery.attempts
665475
+ );
664758
665476
  }
664759
665477
  }
664760
665478
  return finish(true, "unchanged", await getDaemonReportedVersion(port));
@@ -664770,7 +665488,7 @@ async function ensureDaemonVersion(expectedVersion = getLocalCliVersion(), port
664770
665488
  } catch {
664771
665489
  }
664772
665490
  }
664773
- const pid = await startDaemon();
665491
+ const pid = await startDaemon(port);
664774
665492
  if (!pid) {
664775
665493
  for (let i2 = 0; i2 < 20; i2++) {
664776
665494
  await new Promise((r2) => setTimeout(r2, 500));
@@ -664817,7 +665535,7 @@ async function getDaemonStatus() {
664817
665535
  }
664818
665536
  return { running, pid, port, uptime: uptime2, pidFile: PID_FILE2 };
664819
665537
  }
664820
- var OMNIUS_DIR2, PID_FILE2, DEFAULT_PORT2, LOCK_INITIALIZATION_GRACE_MS;
665538
+ var OMNIUS_DIR2, PID_FILE2, DEFAULT_PORT2, LOCK_INITIALIZATION_GRACE_MS, DAEMON_VERSION_RECOVERY_ATTEMPTS, DAEMON_GRACEFUL_STOP_ATTEMPTS;
664821
665539
  var init_daemon = __esm({
664822
665540
  "packages/cli/src/daemon.ts"() {
664823
665541
  init_dist5();
@@ -664825,6 +665543,8 @@ var init_daemon = __esm({
664825
665543
  PID_FILE2 = join149(OMNIUS_DIR2, "daemon.pid");
664826
665544
  DEFAULT_PORT2 = 11435;
664827
665545
  LOCK_INITIALIZATION_GRACE_MS = 5e3;
665546
+ DAEMON_VERSION_RECOVERY_ATTEMPTS = 2;
665547
+ DAEMON_GRACEFUL_STOP_ATTEMPTS = 20;
664828
665548
  }
664829
665549
  });
664830
665550
 
@@ -686539,6 +687259,15 @@ async function handleParallel(arg, ctx3) {
686539
687259
  );
686540
687260
  return;
686541
687261
  }
687262
+ const gpuAdmission = await resolveApprovedOllamaGpu();
687263
+ if (!gpuAdmission.ok) {
687264
+ renderError(`Ollama restart blocked by GPU safety policy: ${gpuAdmission.reason}`);
687265
+ return;
687266
+ }
687267
+ const approvedGpuEnv = withApprovedOllamaGpu(
687268
+ process.env,
687269
+ gpuAdmission.approval
687270
+ );
686542
687271
  let isSystemd = false;
686543
687272
  try {
686544
687273
  const out = (await execFileText5(
@@ -686557,6 +687286,7 @@ async function handleParallel(arg, ctx3) {
686557
687286
  const overrideFile = `${overrideDir}/parallel.conf`;
686558
687287
  const overrideContent = `[Service]
686559
687288
  Environment="OLLAMA_NUM_PARALLEL=${n2}"
687289
+ Environment="CUDA_VISIBLE_DEVICES=${gpuAdmission.approval.cudaVisibleDevices}"
686560
687290
  `;
686561
687291
  const { runElevatedCommand: runElev } = await Promise.resolve().then(() => (init_setup(), setup_exports));
686562
687292
  await runElev(`mkdir -p ${overrideDir}`, { timeoutMs: 3e4 });
@@ -686592,7 +687322,7 @@ ${escapedContent}EOF'`, {
686592
687322
  renderInfo(
686593
687323
  `Manual steps:
686594
687324
  sudo mkdir -p /etc/systemd/system/ollama.service.d
686595
- echo '[Service]\\nEnvironment="OLLAMA_NUM_PARALLEL=${n2}"' | sudo tee /etc/systemd/system/ollama.service.d/parallel.conf
687325
+ printf '[Service]\\nEnvironment="OLLAMA_NUM_PARALLEL=${n2}"\\nEnvironment="CUDA_VISIBLE_DEVICES=${gpuAdmission.approval.cudaVisibleDevices}"\\n' | sudo tee /etc/systemd/system/ollama.service.d/parallel.conf
686596
687326
  sudo systemctl daemon-reload && sudo systemctl restart ollama`
686597
687327
  );
686598
687328
  }
@@ -686615,13 +687345,14 @@ ${escapedContent}EOF'`, {
686615
687345
  }
686616
687346
  await new Promise((r2) => setTimeout(r2, 1e3));
686617
687347
  process.env.OLLAMA_NUM_PARALLEL = String(n2);
687348
+ process.env.CUDA_VISIBLE_DEVICES = gpuAdmission.approval.cudaVisibleDevices;
686618
687349
  const { spawn: spawn40 } = await import("node:child_process");
686619
687350
  const leaseId = newProcessLeaseId("model-service");
686620
687351
  const child = spawn40("ollama", ["serve"], {
686621
687352
  stdio: "ignore",
686622
687353
  detached: true,
686623
687354
  env: {
686624
- ...process.env,
687355
+ ...approvedGpuEnv,
686625
687356
  ...processLeaseEnv(leaseId, "ollama", process.cwd()),
686626
687357
  OMNIUS_PROCESS_OWNER_KIND: "model_service",
686627
687358
  OMNIUS_PROCESS_LIFECYCLE: "model",
@@ -688422,14 +689153,13 @@ async function handleUpdate(subcommand, ctx3) {
688422
689153
  await new Promise((r2) => setTimeout(r2, 1200));
688423
689154
  installOverlay.dismiss();
688424
689155
  renderError(
688425
- `Updated CLI to ${expectedDaemonVersion}, but the shared daemon still reports ${daemonUpgrade.observedVersion ?? "unavailable"}. The TUI will remain open; retry /update after resolving the daemon service.`
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.`
688426
689157
  );
688427
689158
  return;
688428
689159
  }
688429
689160
  installOverlay.setStatus(
688430
689161
  daemonUpgrade.action === "restarted" ? `Daemon upgraded to ${expectedDaemonVersion}` : `Daemon verified at ${expectedDaemonVersion}`
688431
689162
  );
688432
- registry2.killAll();
688433
689163
  ctx3.contextSave?.();
688434
689164
  const hadActiveTask = ctx3.savePendingTaskState?.() ?? false;
688435
689165
  const resumeFlag = hadActiveTask ? "1" : "update-only";
@@ -688439,7 +689169,7 @@ async function handleUpdate(subcommand, ctx3) {
688439
689169
  await new Promise((r2) => setTimeout(r2, 200));
688440
689170
  ctx3.contextSave?.();
688441
689171
  if (ctx3.hasActiveTask?.()) ctx3.abortActiveTask?.();
688442
- ctx3.killEphemeral?.();
689172
+ ctx3.killEphemeral?.({ preserveInfrastructure: true });
688443
689173
  process.exit(120);
688444
689174
  }
688445
689175
  async function switchModel(query, ctx3, local = false) {
@@ -688929,6 +689659,7 @@ var OMNIUS_PINNED_DEPENDENCY_SPECS, NEXUS_DIRECTORY_ORIGIN, NEXUS_SPONSORS_URL,
688929
689659
  var init_commands = __esm({
688930
689660
  "packages/cli/src/tui/commands.ts"() {
688931
689661
  init_model_picker();
689662
+ init_ollama_gpu_policy();
688932
689663
  init_render();
688933
689664
  init_session_summary();
688934
689665
  init_generative_progress();
@@ -689487,7 +690218,7 @@ import {
689487
690218
  readFileSync as readFileSync121,
689488
690219
  readdirSync as readdirSync50,
689489
690220
  writeFileSync as writeFileSync76,
689490
- renameSync as renameSync14,
690221
+ renameSync as renameSync15,
689491
690222
  mkdirSync as mkdirSync88,
689492
690223
  unlinkSync as unlinkSync31,
689493
690224
  appendFileSync as appendFileSync17
@@ -689511,7 +690242,7 @@ function persistSession(s2) {
689511
690242
  const final2 = sessionPath(s2.id);
689512
690243
  const tmp = `${final2}.tmp.${process.pid}.${Date.now()}`;
689513
690244
  writeFileSync76(tmp, JSON.stringify(s2, null, 2), "utf-8");
689514
- renameSync14(tmp, final2);
690245
+ renameSync15(tmp, final2);
689515
690246
  } catch {
689516
690247
  }
689517
690248
  }
@@ -689521,7 +690252,7 @@ function persistInFlight(j) {
689521
690252
  const final2 = inFlightPath(j.sessionId);
689522
690253
  const tmp = `${final2}.tmp.${process.pid}.${Date.now()}`;
689523
690254
  writeFileSync76(tmp, JSON.stringify(j, null, 2), "utf-8");
689524
- renameSync14(tmp, final2);
690255
+ renameSync15(tmp, final2);
689525
690256
  } catch {
689526
690257
  }
689527
690258
  }
@@ -696046,7 +696777,7 @@ import {
696046
696777
  } from "node:fs";
696047
696778
  import { join as join165, basename as basename39 } from "node:path";
696048
696779
  import { exec as exec6 } from "node:child_process";
696049
- import { promisify as promisify8 } from "node:util";
696780
+ import { promisify as promisify9 } from "node:util";
696050
696781
  function buildDMNGatherPrompt(recentTaskSummaries, dueReminders, attentionItems, memoryTopics, capabilities, competence, reflectionBuffer, projectOpportunities = []) {
696051
696782
  const competenceReport = competence.length > 0 ? competence.map((c9) => {
696052
696783
  const rate = c9.attempts > 0 ? Math.round(c9.successes / c9.attempts * 100) : 0;
@@ -696170,7 +696901,7 @@ var init_dmn_engine = __esm({
696170
696901
  init_render();
696171
696902
  init_promptLoader3();
696172
696903
  init_tool_adapter();
696173
- execAsync3 = promisify8(exec6);
696904
+ execAsync3 = promisify9(exec6);
696174
696905
  DMNEngine = class {
696175
696906
  constructor(config, repoRoot) {
696176
696907
  this.config = config;
@@ -709937,8 +710668,8 @@ ${mediaContext}` : ""
709937
710668
  }
709938
710669
  }
709939
710670
  telegramChatIdFromArtifact(artifact) {
709940
- const numeric = Number(artifact.chatId);
709941
- return Number.isFinite(numeric) && String(Math.trunc(numeric)) === artifact.chatId ? Math.trunc(numeric) : artifact.chatId;
710671
+ const numeric2 = Number(artifact.chatId);
710672
+ return Number.isFinite(numeric2) && String(Math.trunc(numeric2)) === artifact.chatId ? Math.trunc(numeric2) : artifact.chatId;
709942
710673
  }
709943
710674
  async maybeSendTelegramReflectionFollowup(sessionKey, artifact, reason = "reflection") {
709944
710675
  if (!this.agentConfig)
@@ -723591,7 +724322,7 @@ __export(projects_exports, {
723591
724322
  setCurrentProject: () => setCurrentProject,
723592
724323
  unregisterProject: () => unregisterProject
723593
724324
  });
723594
- import { readFileSync as readFileSync132, writeFileSync as writeFileSync86, mkdirSync as mkdirSync99, existsSync as existsSync161, statSync as statSync63, renameSync as renameSync15 } from "node:fs";
724325
+ import { readFileSync as readFileSync132, writeFileSync as writeFileSync86, mkdirSync as mkdirSync99, existsSync as existsSync161, statSync as statSync63, renameSync as renameSync16 } from "node:fs";
723595
724326
  import { homedir as homedir58 } from "node:os";
723596
724327
  import { basename as basename43, join as join171, resolve as resolve74 } from "node:path";
723597
724328
  import { randomUUID as randomUUID19 } from "node:crypto";
@@ -723610,7 +724341,7 @@ function writeAll(file) {
723610
724341
  mkdirSync99(OMNIUS_DIR3, { recursive: true });
723611
724342
  const tmp = `${PROJECTS_FILE}.${randomUUID19().slice(0, 8)}.tmp`;
723612
724343
  writeFileSync86(tmp, JSON.stringify(file, null, 2), "utf8");
723613
- renameSync15(tmp, PROJECTS_FILE);
724344
+ renameSync16(tmp, PROJECTS_FILE);
723614
724345
  }
723615
724346
  function listProjects() {
723616
724347
  const { projects } = readAll2();
@@ -724585,7 +725316,7 @@ var init_access_policy = __esm({
724585
725316
 
724586
725317
  // packages/cli/src/api/project-preferences.ts
724587
725318
  import { createHash as createHash50 } from "node:crypto";
724588
- import { existsSync as existsSync162, mkdirSync as mkdirSync100, readFileSync as readFileSync133, renameSync as renameSync16, writeFileSync as writeFileSync87, unlinkSync as unlinkSync37 } from "node:fs";
725319
+ import { existsSync as existsSync162, mkdirSync as mkdirSync100, readFileSync as readFileSync133, renameSync as renameSync17, writeFileSync as writeFileSync87, unlinkSync as unlinkSync37 } from "node:fs";
724589
725320
  import { homedir as homedir59 } from "node:os";
724590
725321
  import { join as join172, resolve as resolve75 } from "node:path";
724591
725322
  import { randomUUID as randomUUID20 } from "node:crypto";
@@ -724639,7 +725370,7 @@ function writeProjectPreferences(root, partial) {
724639
725370
  const tmp = `${file}.${randomUUID20().slice(0, 8)}.tmp`;
724640
725371
  writeFileSync87(tmp, JSON.stringify(merged, null, 2), "utf8");
724641
725372
  try {
724642
- renameSync16(tmp, file);
725373
+ renameSync17(tmp, file);
724643
725374
  } catch (err) {
724644
725375
  try {
724645
725376
  writeFileSync87(file, JSON.stringify(merged, null, 2), "utf8");
@@ -725689,7 +726420,7 @@ var init_direct_tool_registry = __esm({
725689
726420
  });
725690
726421
 
725691
726422
  // packages/cli/src/api/external-tool-registry.ts
725692
- import { existsSync as existsSync166, mkdirSync as mkdirSync104, readFileSync as readFileSync135, writeFileSync as writeFileSync88, renameSync as renameSync17 } from "node:fs";
726423
+ import { existsSync as existsSync166, mkdirSync as mkdirSync104, readFileSync as readFileSync135, writeFileSync as writeFileSync88, renameSync as renameSync18 } from "node:fs";
725693
726424
  import { join as join175 } from "node:path";
725694
726425
  function externalToolStorePath(workingDir) {
725695
726426
  return join175(workingDir, ".omnius", "external-tools.json");
@@ -725713,7 +726444,7 @@ function persist3(workingDir, tools) {
725713
726444
  const file = { version: STORE_VERSION, tools };
725714
726445
  const tmp = `${path16}.tmp`;
725715
726446
  writeFileSync88(tmp, JSON.stringify(file, null, 2), { mode: 384 });
725716
- renameSync17(tmp, path16);
726447
+ renameSync18(tmp, path16);
725717
726448
  }
725718
726449
  function validateManifest2(input, existing) {
725719
726450
  if (!input || typeof input !== "object") {
@@ -744348,7 +745079,7 @@ import {
744348
745079
  readdirSync as readdirSync59,
744349
745080
  existsSync as existsSync173,
744350
745081
  watch as fsWatch5,
744351
- renameSync as renameSync18,
745082
+ renameSync as renameSync19,
744352
745083
  unlinkSync as unlinkSync38,
744353
745084
  statSync as statSync68,
744354
745085
  openSync as openSync8,
@@ -745967,7 +746698,7 @@ function atomicJobWrite(dir, id2, job) {
745967
746698
  const tmpPath = `${finalPath}.tmp.${process.pid}.${Date.now()}`;
745968
746699
  try {
745969
746700
  writeFileSync92(tmpPath, JSON.stringify(job, null, 2), "utf-8");
745970
- renameSync18(tmpPath, finalPath);
746701
+ renameSync19(tmpPath, finalPath);
745971
746702
  } catch {
745972
746703
  try {
745973
746704
  writeFileSync92(finalPath, JSON.stringify(job, null, 2), "utf-8");
@@ -747768,7 +748499,7 @@ function writeUpdateState(state) {
747768
748499
  const finalPath = updateStateFile();
747769
748500
  const tmpPath = `${finalPath}.tmp.${process.pid}`;
747770
748501
  writeFileSync92(tmpPath, JSON.stringify(state, null, 2), "utf-8");
747771
- renameSync18(tmpPath, finalPath);
748502
+ renameSync19(tmpPath, finalPath);
747772
748503
  } catch {
747773
748504
  }
747774
748505
  }
@@ -755120,9 +755851,9 @@ ${incompleteList}${more}
755120
755851
  const checkScript = scripts["typecheck"] ? "typecheck" : scripts["build"] ? "build" : null;
755121
755852
  if (checkScript) {
755122
755853
  const { exec: exec7 } = await import("node:child_process");
755123
- const { promisify: promisify9 } = await import("node:util");
755854
+ const { promisify: promisify10 } = await import("node:util");
755124
755855
  try {
755125
- await promisify9(exec7)(`npm run ${checkScript} --silent 2>&1`, {
755856
+ await promisify10(exec7)(`npm run ${checkScript} --silent 2>&1`, {
755126
755857
  cwd: cwd4,
755127
755858
  timeout: 12e4,
755128
755859
  encoding: "utf-8",
@@ -762073,11 +762804,11 @@ The user pasted a clipboard image saved at ${relPath}. Use the OCR, vision analy
762073
762804
  };
762074
762805
  }
762075
762806
  },
762076
- killEphemeral() {
762807
+ killEphemeral(options2) {
762077
762808
  if (_shellToolRef) _shellToolRef.killAll();
762078
762809
  killAllFullSubAgents();
762079
762810
  taskManager.stopAll();
762080
- registry2.killAll();
762811
+ if (!options2?.preserveInfrastructure) registry2.killAll();
762081
762812
  if (_replToolRef) {
762082
762813
  try {
762083
762814
  _replToolRef.dispose();