@quantiya/codevibe-core 2.0.72 → 2.0.73

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.
@@ -321,6 +321,92 @@ function isAgentInstalled(agent, env, commonPaths = COMMON_AGENT_PATHS) {
321
321
  return !1;
322
322
  }
323
323
  }
324
+ function firstNonEmpty(...values) {
325
+ for (let v of values)
326
+ if (typeof v == "string") {
327
+ let trimmed = v.trim();
328
+ if (trimmed.length > 0) return trimmed;
329
+ }
330
+ return null;
331
+ }
332
+ function detectAgentModel(agent, env = process.env, homeDirOrOptions, options) {
333
+ let homeDir = typeof homeDirOrOptions == "string" ? homeDirOrOptions : void 0, opts = typeof homeDirOrOptions == "object" && homeDirOrOptions !== null ? homeDirOrOptions : options, envKey = `CODEVIBE_${agent}_MODEL`, envKeyVal = firstNonEmpty(env[envKey]);
334
+ if (envKeyVal) return envKeyVal;
335
+ if (agent === "ANTIGRAVITY") {
336
+ let agyExplicit = firstNonEmpty(env.CODEVIBE_AGY_MODEL, env.CODEVIBE_ANTIGRAVITY_MODEL);
337
+ if (agyExplicit) return agyExplicit;
338
+ }
339
+ if (opts?.explicitOnly)
340
+ return null;
341
+ if (agent === "CODEX") {
342
+ let codexVal = firstNonEmpty(env.CODEX_MODEL, env.OPENAI_MODEL);
343
+ if (codexVal) return codexVal;
344
+ } else if (agent === "ANTIGRAVITY") {
345
+ let agyVal = firstNonEmpty(env.ANTIGRAVITY_MODEL, env.AGY_MODEL, env.GEMINI_MODEL);
346
+ if (agyVal) return agyVal;
347
+ } else if (agent === "CLAUDE") {
348
+ let claudeVal = firstNonEmpty(env.CLAUDE_MODEL, env.ANTHROPIC_MODEL);
349
+ if (claudeVal) return claudeVal;
350
+ }
351
+ let resolvedHome = homeDir ?? env.HOME;
352
+ if (agent === "CODEX")
353
+ try {
354
+ let codexHome = env.CODEX_HOME && env.CODEX_HOME.trim() ? env.CODEX_HOME.trim() : resolvedHome && resolvedHome.trim() ? path34.join(resolvedHome, ".codex") : null;
355
+ if (codexHome) {
356
+ let configPath = path34.join(codexHome, "config.toml");
357
+ if (fs29.existsSync(configPath)) {
358
+ let content = fs29.readFileSync(configPath, "utf8"), parsed = toml2.parse(content);
359
+ if (typeof parsed?.profile == "string" && typeof parsed.profiles?.[parsed.profile]?.model == "string") {
360
+ let profileModel = parsed.profiles[parsed.profile].model.trim();
361
+ if (profileModel) return profileModel;
362
+ }
363
+ if (typeof parsed?.model == "string" && parsed.model.trim())
364
+ return parsed.model.trim();
365
+ }
366
+ }
367
+ } catch {
368
+ }
369
+ if (resolvedHome && resolvedHome.trim()) {
370
+ if (agent === "ANTIGRAVITY") {
371
+ let candidates = [
372
+ path34.join(resolvedHome, ".gemini", "antigravity-cli", "settings.json"),
373
+ path34.join(resolvedHome, ".gemini", "settings.json")
374
+ ];
375
+ for (let candidate of candidates)
376
+ try {
377
+ if (fs29.existsSync(candidate)) {
378
+ let parsed = JSON.parse(fs29.readFileSync(candidate, "utf8"));
379
+ if (typeof parsed?.model == "string" && parsed.model.trim())
380
+ return parsed.model.trim();
381
+ }
382
+ } catch {
383
+ }
384
+ } else if (agent === "CLAUDE") {
385
+ let candidates = [
386
+ path34.join(resolvedHome, ".claude.json"),
387
+ path34.join(resolvedHome, ".claude", "settings.json")
388
+ ];
389
+ for (let candidate of candidates)
390
+ try {
391
+ if (fs29.existsSync(candidate)) {
392
+ let parsed = JSON.parse(fs29.readFileSync(candidate, "utf8"));
393
+ if (typeof parsed?.model == "string" && parsed.model.trim())
394
+ return parsed.model.trim();
395
+ }
396
+ } catch {
397
+ }
398
+ }
399
+ }
400
+ return DEFAULT_AGENT_MODELS[agent] ?? null;
401
+ }
402
+ function detectInstalledAgentModels(env = process.env, homeDir, installedAgents, options) {
403
+ let models = {}, installed = installedAgents ?? detectInstalledAgents(env);
404
+ for (let agent of installed) {
405
+ let model = detectAgentModel(agent, env, homeDir, options);
406
+ model && (models[agent] = model);
407
+ }
408
+ return logger.debug("[detectInstalledAgentModels] Detected models", { models }), models;
409
+ }
324
410
  async function pushDetectedAgents(client, log, capabilityRegistry, detectFn = detectInstalledAgents, replace = !1) {
325
411
  let agents = detectFn();
326
412
  if (agents.length === 0) {
@@ -352,10 +438,10 @@ async function pushDetectedAgents(client, log, capabilityRegistry, detectFn = de
352
438
  });
353
439
  }
354
440
  }
355
- var import_child_process3, fs29, path34, AGENT_BINARIES, COMMON_AGENT_PATHS, init_detect_agents = __esm({
441
+ var import_child_process3, fs29, path34, toml2, AGENT_BINARIES, COMMON_AGENT_PATHS, DEFAULT_AGENT_MODELS, init_detect_agents = __esm({
356
442
  "src/orchestration/detect-agents.ts"() {
357
443
  "use strict";
358
- import_child_process3 = require("child_process"), fs29 = __toESM(require("fs")), path34 = __toESM(require("path"));
444
+ import_child_process3 = require("child_process"), fs29 = __toESM(require("fs")), path34 = __toESM(require("path")), toml2 = __toESM(require("@iarna/toml"));
359
445
  init_env_scrub();
360
446
  init_logger2();
361
447
  AGENT_BINARIES = {
@@ -372,6 +458,12 @@ var import_child_process3, fs29, path34, AGENT_BINARIES, COMMON_AGENT_PATHS, ini
372
458
  "/usr/bin",
373
459
  "/bin"
374
460
  ];
461
+ DEFAULT_AGENT_MODELS = {
462
+ CLAUDE: "claude-opus-5",
463
+ GEMINI: "gemini-2.5-pro",
464
+ CODEX: "gpt-6.1",
465
+ ANTIGRAVITY: "gemini-3.8"
466
+ };
375
467
  }
376
468
  });
377
469
 
@@ -8694,8 +8786,8 @@ function validateSourceCursor(value, options) {
8694
8786
  return row3;
8695
8787
  }
8696
8788
  function createSourceJournal(options) {
8697
- let { id: id5, scope, stream } = options, parse6 = (value) => validateSourceCursor(value, options), read = () => options.read(parse6), required = async () => await read() ?? options.missing(), write = async (row3, assertOwnership) => {
8698
- let validated = parse6(row3);
8789
+ let { id: id5, scope, stream } = options, parse7 = (value) => validateSourceCursor(value, options), read = () => options.read(parse7), required = async () => await read() ?? options.missing(), write = async (row3, assertOwnership) => {
8790
+ let validated = parse7(row3);
8699
8791
  await assertOwnership(), await options.write(validated);
8700
8792
  }, recoverLocked = async (assertOwnership) => {
8701
8793
  let row3 = await read();
@@ -8793,13 +8885,14 @@ function createSourcePair(options) {
8793
8885
  return { ...baseline, ...pending2.length && { pendingFrameEndOffset: Math.min(...pending2) } };
8794
8886
  };
8795
8887
  return Object.freeze({
8796
- open: (initial) => {
8888
+ open: (initial, validateInitial) => {
8797
8889
  let snapshot2 = typeof initial == "number" ? initial : position2(initial);
8798
8890
  return options.locked(async () => {
8799
8891
  await recover();
8800
8892
  let present = (await Promise.all(lanes.map((lane) => lane.load()))).filter((row3) => row3 !== null);
8801
8893
  if (present.length === 1 && (present[0].lastFrame !== null || present[0].entries.length !== 0 || present[0].skippedBytes !== 0 || present[0].projection !== null))
8802
8894
  return options.invalid();
8895
+ present.length || validateInitial?.();
8803
8896
  let baseline = present.length ? earliest(present) : snapshot2, rows = [];
8804
8897
  for (let lane of lanes) rows.push(await lane.open(baseline));
8805
8898
  return earliest(rows);
@@ -10196,7 +10289,7 @@ function decodeSessionRetirement(value, userId, bad3) {
10196
10289
  let toolOutbox = null;
10197
10290
  if (row3.toolOutbox !== null) {
10198
10291
  let location = row3.toolOutbox;
10199
- if (!location || typeof location != "object" || Object.keys(location).sort().join(",") !== "agent,root" || !["codex", "claude"].includes(location.agent) || typeof location.root != "string" || location.root.includes("\0") || Buffer.byteLength(location.root) > 4096 || !path17.isAbsolute(location.root) || path17.resolve(location.root) !== location.root) return bad3();
10292
+ if (!location || typeof location != "object" || Object.keys(location).sort().join(",") !== "agent,root" || !["codex", "claude", "agy"].includes(location.agent) || typeof location.root != "string" || location.root.includes("\0") || Buffer.byteLength(location.root) > 4096 || !path17.isAbsolute(location.root) || path17.resolve(location.root) !== location.root) return bad3();
10200
10293
  toolOutbox = Object.freeze({ agent: location.agent, root: location.root });
10201
10294
  }
10202
10295
  return Object.freeze({ schemaVersion: 1, kind: "SESSION_RETIREMENT", operationId: clientOperationId, input, toolOutbox });
@@ -10991,7 +11084,7 @@ var sourceCursorId = (scope, stream) => stableUuid("codevibe-sync-source-cursor-
10991
11084
  if (!saved) return null;
10992
11085
  await fence();
10993
11086
  let result = await cleanup(saved, fence);
10994
- return await fence(), await this.withStore(async (key, storeFence) => {
11087
+ return await fence(), options.isComplete && !options.isComplete(result) || await this.withStore(async (key, storeFence) => {
10995
11088
  if (!await read(key)) throw new SyncJournalError("SYNC_JOURNAL_MISSING");
10996
11089
  await fence();
10997
11090
  let held = owner;
@@ -11893,13 +11986,14 @@ function toolWindow(scope, id5, value) {
11893
11986
  async function retireToolActivityWindows(options) {
11894
11987
  let scope = { ...options.sessionScope };
11895
11988
  return await options.outbox.withRetirementSources(scope, async (sources) => {
11989
+ if (options.deferIfPaged && sources.hasMore) return { windowsRemoved: 0, operationsRemoved: 0, hasMore: !0 };
11896
11990
  let ids = sources.windows.map((window) => toolWindow(scope, scope.sessionId, window).operationId), operationsRemoved = await options.writer.removeRetiredToolOperations(
11897
11991
  ids,
11898
11992
  options.expectedSessionKeyGen,
11899
11993
  options.confirm,
11900
11994
  sources
11901
11995
  );
11902
- return { windowsRemoved: ids.length, operationsRemoved };
11996
+ return { windowsRemoved: ids.length, operationsRemoved, ...sources.hasMore && { hasMore: !0 } };
11903
11997
  }) ?? { windowsRemoved: 0, operationsRemoved: 0 };
11904
11998
  }
11905
11999
  function createToolActivitySyncTransport(options) {
@@ -12251,6 +12345,18 @@ var ToolActivityLedger = class {
12251
12345
  async markRetired(clientEventId, invocationIds) {
12252
12346
  return this.markSettled(clientEventId, invocationIds, "terminal", !0);
12253
12347
  }
12348
+ /** One durable mutation per bounded retirement page, not per window. */
12349
+ async markRetiredWindows(windows) {
12350
+ let ids = new Set(windows.map((window) => window.clientEventId));
12351
+ await this.mutateAndPersist((next, terminalWindows) => {
12352
+ for (let window of windows) {
12353
+ terminalWindows.add(window.clientEventId);
12354
+ for (let id5 of window.invocationIds) id5 && !next.has(id5) && next.set(id5, { clientEventId: window.clientEventId, byteOffset: 0, state: "terminal" });
12355
+ }
12356
+ for (let [id5, entry5] of next) ids.has(entry5.clientEventId) && entry5.state === "durably-outboxed" && next.set(id5, { ...entry5, state: "terminal" });
12357
+ return !0;
12358
+ }, !0);
12359
+ }
12254
12360
  /** R2 keeps a window settlement independently of occurrence remapping/pruning. */
12255
12361
  async markSettled(clientEventId, invocationIds, disposition, requireDirectorySync = !1) {
12256
12362
  await this.mutateAndPersist((next, terminalWindows) => {
@@ -12464,7 +12570,7 @@ var RESERVED_STATE_FILES = /* @__PURE__ */ new Set(["ledger.json", "legacy-owned
12464
12570
  }
12465
12571
  /** Trusted local namespace persisted inside the encrypted cleanup intent. */
12466
12572
  retirementLocation() {
12467
- if (this.agent !== "codex" && this.agent !== "claude") throw new Error("Invalid tool sync provider");
12573
+ if (!["codex", "claude", "agy"].includes(this.agent)) throw new Error("Invalid tool sync provider");
12468
12574
  return Object.freeze({ agent: this.agent, root: path21.resolve(this.rootDir) });
12469
12575
  }
12470
12576
  entryPath(sessionId, clientEventId) {
@@ -12578,23 +12684,25 @@ var RESERVED_STATE_FILES = /* @__PURE__ */ new Set(["ledger.json", "legacy-owned
12578
12684
  throw new Error("Invalid tool sync generation");
12579
12685
  let { sessionId, sessionGenerationId } = scope;
12580
12686
  return this.withSyncRecovery(sessionId, async (fence) => {
12581
- let dir = this.sessionDir(sessionId), snapshots = [], names = 0, bytes = 0, windows = 0, listing = await import_node_fs8.promises.opendir(dir);
12687
+ let dir = this.sessionDir(sessionId), snapshots = [], bytes = 0, hasMore = !1, listing = await import_node_fs8.promises.opendir(dir);
12582
12688
  for await (let entry5 of listing) {
12583
- if (++names > 1032) throw new Error("Tool sync outbox capacity exceeded");
12584
12689
  if (entry5.name.endsWith(".corrupt")) throw new Error("Tool sync outbox recovery required");
12585
12690
  if (entry5.name.includes(TEMP_INFIX) || RESERVED_STATE_FILES.has(entry5.name) || !entry5.name.endsWith(".json")) continue;
12586
- if (++windows > 256) throw new Error("Tool sync outbox capacity exceeded");
12587
- let file = await readBoundedToolFile(path21.join(dir, entry5.name), 1024 * 1024);
12588
- if (bytes += file.bytes.length, bytes > 32 * 1024 * 1024) throw new Error("Tool sync outbox capacity exceeded");
12589
- let envelope = ToolActivityOutboxEnvelopeSchema.parse(JSON.parse(file.bytes.toString("utf8")));
12691
+ let file = await readBoundedToolFile(path21.join(dir, entry5.name), 1024 * 1024), envelope = ToolActivityOutboxEnvelopeSchema.parse(JSON.parse(file.bytes.toString("utf8")));
12590
12692
  if (envelope.backendSessionId !== sessionId || !/^[A-Za-z0-9_-]{1,128}$/.test(envelope.clientEventId) || entry5.name !== `${envelope.clientEventId}.json`) throw new Error("Tool sync outbox recovery required");
12591
- envelope.syncSessionGenerationId === sessionGenerationId && snapshots.push({
12592
- name: entry5.name,
12593
- dev: file.dev,
12594
- ino: file.ino,
12595
- sha256: (0, import_node_crypto17.createHash)("sha256").update(file.bytes).digest("hex"),
12596
- envelope
12597
- });
12693
+ if (envelope.syncSessionGenerationId === sessionGenerationId) {
12694
+ if (snapshots.length >= 256 || bytes + file.bytes.length > 32 * 1024 * 1024) {
12695
+ hasMore = !0;
12696
+ break;
12697
+ }
12698
+ bytes += file.bytes.length, snapshots.push({
12699
+ name: entry5.name,
12700
+ dev: file.dev,
12701
+ ino: file.ino,
12702
+ sha256: (0, import_node_crypto17.createHash)("sha256").update(file.bytes).digest("hex"),
12703
+ envelope
12704
+ });
12705
+ }
12598
12706
  }
12599
12707
  if (!snapshots.length) return null;
12600
12708
  let ledger = new ToolActivityLedger({ agent: this.agent, sessionId, root: this.rootDir, logger: this.logger });
@@ -12608,10 +12716,9 @@ var RESERVED_STATE_FILES = /* @__PURE__ */ new Set(["ledger.json", "legacy-owned
12608
12716
  };
12609
12717
  return action2({
12610
12718
  windows: snapshots.map((snapshot2) => snapshot2.envelope),
12719
+ hasMore,
12611
12720
  markRetired: async () => {
12612
- await verify();
12613
- for (let { envelope } of snapshots)
12614
- await fence(), await ledger.markRetired(envelope.clientEventId, envelope.invocationIds);
12721
+ await verify(), await ledger.markRetiredWindows(snapshots.map((snapshot2) => snapshot2.envelope));
12615
12722
  },
12616
12723
  prune: async () => {
12617
12724
  await verify();
@@ -14945,7 +15052,18 @@ var AppSyncClient = class _AppSyncClient {
14945
15052
  }), toolOutbox = options.toolOutbox?.retirementLocation() ?? null;
14946
15053
  await this.quiesceDesktopSyncSession(sessionId, quiesce, signal);
14947
15054
  let writer = this.desktopSyncWriter({ root, sessionScope: input }), hasWork = await writer.hasSessionRetirementWork(input.expectedSessionKeyGen) || options.toolOutbox && await options.toolOutbox.withRetirementSources(input, async () => !0);
14948
- return this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), hasWork ? await writer.runSessionRetirement(input, toolOutbox, (record2, fence) => this.finishRecordedSessionRetirement(record2, { root }, fence, signal)) ?? { sourcesRemoved: 0, operationsRemoved: 0 } : { sourcesRemoved: 0, operationsRemoved: 0 };
15055
+ if (this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), !hasWork) return { sourcesRemoved: 0, operationsRemoved: 0 };
15056
+ let result = await writer.runSessionRetirement(
15057
+ input,
15058
+ toolOutbox,
15059
+ (record2, fence) => this.finishRecordedSessionRetirement(record2, { root, deferOversizedTools: !0 }, fence, signal),
15060
+ { isComplete: (result2) => !result2.cleanupDeferred }
15061
+ );
15062
+ return result?.cleanupDeferred && logger.warn("[sync-retirement] cloud session retired; local cleanup page remains durable", {
15063
+ sessionId,
15064
+ sourcesRemoved: result.sourcesRemoved,
15065
+ operationsRemoved: result.operationsRemoved
15066
+ }), result ?? { sourcesRemoved: 0, operationsRemoved: 0 };
14949
15067
  }
14950
15068
  /** No Session fetch, live key lookup, native-process operation or re-homing.
14951
15069
  * The encrypted intent records a completed producer join; fresh cloud proof
@@ -14959,7 +15077,12 @@ var AppSyncClient = class _AppSyncClient {
14959
15077
  try {
14960
15078
  let writer = this.desktopSyncWriter({ root, sessionScope: record2.input });
14961
15079
  await this.quiesceDesktopSyncSession(record2.input.sessionId, async () => {
14962
- }, signal), await writer.runSessionRetirement(record2.input, record2.toolOutbox, (saved, fence) => this.finishRecordedSessionRetirement(saved, { root }, fence, signal), { existingOnly: !0 }), completed++;
15080
+ }, signal), (await writer.runSessionRetirement(
15081
+ record2.input,
15082
+ record2.toolOutbox,
15083
+ (saved, fence) => this.finishRecordedSessionRetirement(saved, { root }, fence, signal),
15084
+ { existingOnly: !0, isComplete: (result2) => !result2.cleanupDeferred }
15085
+ ))?.cleanupDeferred ? deferred++ : completed++;
14963
15086
  } catch (error) {
14964
15087
  this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), deferred++, logger.warn("[sync-retirement] prior-session cleanup retained for recovery", {
14965
15088
  code: error instanceof SyncJournalError ? error.code : "CLEANUP_DEFERRED"
@@ -14990,7 +15113,7 @@ var AppSyncClient = class _AppSyncClient {
14990
15113
  let result = await writer.removeRetiredSources(
14991
15114
  input.expectedSessionKeyGen,
14992
15115
  (request3) => this.confirmDesktopSyncRetirement(request3, signal)
14993
- );
15116
+ ), cleanupDeferred = !1;
14994
15117
  if (record2.toolOutbox) {
14995
15118
  await fence();
14996
15119
  let tools = await retireToolActivityWindows({
@@ -14998,13 +15121,14 @@ var AppSyncClient = class _AppSyncClient {
14998
15121
  writer,
14999
15122
  outbox: new ToolActivityOutbox({ ...record2.toolOutbox, logger }),
15000
15123
  expectedSessionKeyGen: input.expectedSessionKeyGen,
15001
- confirm: (input2) => this.confirmDesktopSyncRetirement(input2, signal)
15124
+ confirm: (input2) => this.confirmDesktopSyncRetirement(input2, signal),
15125
+ deferIfPaged: options.deferOversizedTools
15002
15126
  });
15003
- result.sourcesRemoved += tools.windowsRemoved, result.operationsRemoved += tools.operationsRemoved;
15127
+ result.sourcesRemoved += tools.windowsRemoved, result.operationsRemoved += tools.operationsRemoved, cleanupDeferred = tools.hasMore === !0;
15004
15128
  }
15005
15129
  for (let input2 of await writer.promptResolutions())
15006
15130
  await fence(), this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), await writer.runPromptResolution(input2, async (saved, fence2) => (await fence2(), await this.resolveDesktopSyncPrompt(saved, signal), await fence2(), !0), { existingOnly: !0 });
15007
- return await fence(), this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), result;
15131
+ return await fence(), this.assertSyncAccount(userId), _AppSyncClient.throwIfAborted(signal), { ...result, ...cleanupDeferred && { cleanupDeferred: !0 } };
15008
15132
  }
15009
15133
  /** Wire-only PROMPT_OWNERSHIP transition. It cannot create an Event. Plugin
15010
15134
  * preimage authority does not require the retired Session's encryption key;
@@ -60353,7 +60477,8 @@ ${formatPacket(packet, hash3)}`
60353
60477
  }
60354
60478
 
60355
60479
  // src/orchestration-shell/audit-summary.ts
60356
- var crypto27 = __toESM(require("node:crypto")), MAX_SUMMARY_BYTES = 16384, FIELD_MAX_CHARS = 512, MAX_SEATS_PER_MODEL = 10, MAX_FINDINGS_PER_MODEL = 20, MAX_RESIDUALS_PER_RECORD = 10;
60480
+ var crypto27 = __toESM(require("node:crypto"));
60481
+ var MAX_SUMMARY_BYTES = 16384, FIELD_MAX_CHARS = 512, MAX_SEATS_PER_MODEL = 10, MAX_FINDINGS_PER_MODEL = 20, MAX_RESIDUALS_PER_RECORD = 10;
60357
60482
  var SECTION_BYTE_BUDGETS = {
60358
60483
  section1: 1800,
60359
60484
  section2: 7500,
@@ -60441,7 +60566,7 @@ function boundSummaryModel(model) {
60441
60566
  role: capCodePoints(s.role, 64),
60442
60567
  reviewerModel: capCodePoints(s.reviewerModel, 64),
60443
60568
  reviewerAgent: capCodePoints(s.reviewerAgent, 64),
60444
- modelUsed: capCodePoints(s.modelUsed, 64),
60569
+ modelUsed: s.modelUsed ? capCodePoints(s.modelUsed, 64) : void 0,
60445
60570
  verdict: capCodePoints(s.verdict, 32),
60446
60571
  reasoning: capCodePoints(s.reasoning, FIELD_MAX_CHARS),
60447
60572
  durationSeconds: typeof s.durationSeconds == "number" ? s.durationSeconds : null,
@@ -60462,8 +60587,8 @@ function boundSummaryModel(model) {
60462
60587
  testDetails: capCodePoints(model.verification?.testDetails, FIELD_MAX_CHARS),
60463
60588
  teardownStatus: model.verification?.teardownStatus ?? "unrecorded",
60464
60589
  filesApplied: typeof model.verification?.filesApplied == "number" ? model.verification.filesApplied : void 0,
60465
- completedAt: capCodePoints(model.verification?.completedAt, 64),
60466
- serverAuthorizedAt: capCodePoints(model.verification?.serverAuthorizedAt, 64),
60590
+ completedAt: model.verification?.completedAt ? capCodePoints(model.verification.completedAt, 64) : void 0,
60591
+ serverAuthorizedAt: model.verification?.serverAuthorizedAt ? capCodePoints(model.verification.serverAuthorizedAt, 64) : void 0,
60467
60592
  workspaceApplicationStatus: model.verification?.workspaceApplicationStatus
60468
60593
  }
60469
60594
  };
@@ -61141,11 +61266,13 @@ function compileAuditSummary(args) {
61141
61266
  let displayRound = rec.round + 1;
61142
61267
  rec.historyDegraded && (historyDegraded = !0), rec.omittedFindingsCount && (recordOmittedFindings += rec.omittedFindingsCount), rec.omittedResidualsCount && (recordOmittedResiduals += rec.omittedResidualsCount);
61143
61268
  let dur = typeof rec.durationSeconds == "number" ? rec.durationSeconds : typeof rec.latencyMs == "number" ? rec.latencyMs / 1e3 : null;
61144
- dur !== null ? totalReviewerSeconds += dur : (timingPartial = !0, roundTimingPartial[displayRound] = !0), dur !== null && (roundDurations[displayRound] = Math.max(roundDurations[displayRound] ?? 0, dur)), seats.push({
61269
+ dur !== null ? totalReviewerSeconds += dur : (timingPartial = !0, roundTimingPartial[displayRound] = !0), dur !== null && (roundDurations[displayRound] = Math.max(roundDurations[displayRound] ?? 0, dur));
61270
+ let agentKey = rec.reviewerAgent ? rec.reviewerAgent.toUpperCase() : void 0, detectedDefault = agentKey && args.detectedAgentModels ? args.detectedAgentModels[agentKey] || args.detectedAgentModels[rec.reviewerAgent.toLowerCase()] || args.detectedAgentModels[rec.reviewerAgent] : void 0, displayModel;
61271
+ rec.modelUsed && rec.modelUsed.trim() ? displayModel = rec.modelUsed.trim() : detectedDefault && detectedDefault.trim() ? displayModel = `native default (unverified: ${detectedDefault.trim()})` : displayModel = "native default (unverified)", seats.push({
61145
61272
  round: displayRound,
61146
61273
  seatId: String(rec.seatId),
61147
61274
  role: rec.role,
61148
- reviewerModel: rec.modelUsed || rec.reviewerAgent,
61275
+ reviewerModel: displayModel,
61149
61276
  reviewerAgent: rec.reviewerAgent,
61150
61277
  modelUsed: rec.modelUsed ?? void 0,
61151
61278
  verdict: normalizeVerdictKind(rec.verdict),
@@ -61157,7 +61284,7 @@ function compileAuditSummary(args) {
61157
61284
  findings.push({
61158
61285
  round: displayRound,
61159
61286
  seatId: String(rec.seatId),
61160
- findingId: `F-${displayRound}-${rec.seatId}-${idx + 1}`,
61287
+ findingId: `F-${displayRound}-${displaySeatNumber(rec.seatId)}-${idx + 1}`,
61161
61288
  issue: sc,
61162
61289
  changesMade: "Unavailable (resolution not recorded)"
61163
61290
  });
@@ -61246,13 +61373,15 @@ function compileAuditSummary(args) {
61246
61373
  let maxSeatDur = 0;
61247
61374
  for (let [seatId, s] of gate.seats.entries()) {
61248
61375
  let dur = typeof s.durationSeconds == "number" ? s.durationSeconds : null;
61249
- dur !== null ? (totalReviewerSeconds += dur, maxSeatDur = Math.max(maxSeatDur, dur)) : (timingPartial = !0, roundTimingPartial[gate.roundNumber] = !0), seats.push({
61376
+ dur !== null ? (totalReviewerSeconds += dur, maxSeatDur = Math.max(maxSeatDur, dur)) : (timingPartial = !0, roundTimingPartial[gate.roundNumber] = !0);
61377
+ let agentKey = s.reviewerAgent ? s.reviewerAgent.toUpperCase() : void 0, detectedDefault = agentKey && args.detectedAgentModels ? args.detectedAgentModels[agentKey] || args.detectedAgentModels[s.reviewerAgent?.toLowerCase() ?? ""] || args.detectedAgentModels[s.reviewerAgent ?? ""] : void 0, displayModel;
61378
+ s.modelUsed && s.modelUsed.trim() ? displayModel = s.modelUsed.trim() : s.reviewerModel && s.reviewerModel !== "unknown" && s.reviewerModel !== s.reviewerAgent ? displayModel = s.reviewerModel : detectedDefault && detectedDefault.trim() ? displayModel = `native default (unverified: ${detectedDefault.trim()})` : displayModel = "native default (unverified)", seats.push({
61250
61379
  round: gate.roundNumber,
61251
61380
  seatId: s.seatId,
61252
61381
  role: s.role,
61253
- reviewerModel: s.reviewerModel,
61382
+ reviewerModel: displayModel,
61254
61383
  reviewerAgent: s.reviewerAgent,
61255
- modelUsed: s.modelUsed,
61384
+ modelUsed: s.modelUsed ?? void 0,
61256
61385
  verdict: s.verdict,
61257
61386
  reasoning: s.reasoning,
61258
61387
  durationSeconds: dur,
@@ -61357,16 +61486,16 @@ function renderSummaryMarkdown(summaryModel) {
61357
61486
  else {
61358
61487
  let tableHeader = `| Round | Seat | Role | Agent | Model | Verdict | Duration |
61359
61488
  |-------|------|------|-------|-------|---------|----------|`, tableRows = bounded.seats.map((s) => {
61360
- let durStr = typeof s.durationSeconds == "number" ? `${s.durationSeconds.toFixed(1)}s` : "N/A";
61361
- return `| ${s.round} | ${escapeMarkdownTableCell(s.seatId)} | ${escapeMarkdownTableCell(s.role)} | ${escapeMarkdownTableCell(s.reviewerAgent ?? s.role)} | ${escapeMarkdownTableCell(s.reviewerModel)} | ${escapeMarkdownTableCell(s.verdict)} | ${durStr} |`;
61489
+ let durStr = typeof s.durationSeconds == "number" ? `${s.durationSeconds.toFixed(1)}s` : "N/A", displaySeat = displaySeatNumber(s.seatId);
61490
+ return `| ${s.round} | ${escapeMarkdownTableCell(displaySeat)} | ${escapeMarkdownTableCell(s.role)} | ${escapeMarkdownTableCell(s.reviewerAgent ?? s.role)} | ${escapeMarkdownTableCell(s.reviewerModel)} | ${escapeMarkdownTableCell(s.verdict)} | ${durStr} |`;
61362
61491
  });
61363
61492
  s2 = [tableHeader, ...tableRows].join(`
61364
61493
  `);
61365
61494
  }
61366
61495
  let s3 = "";
61367
61496
  bounded.findings.length === 0 ? s3 = "None recorded." : s3 = bounded.findings.map((f) => {
61368
- let resolution = f.changesMade ? sanitizeMarkdownContent(f.changesMade) : "Unavailable (resolution not recorded)", safeFindingId = String(f.findingId).replace(/[\r\n]+/g, " ").replace(/`/g, "'").trim(), safeSeatId = String(f.seatId).replace(/[\r\n]+/g, " ").replace(/`/g, "'").trim();
61369
- return `- **[Round ${f.round} / Seat ${escapeMarkdownTableCell(safeSeatId)}]** \`${safeFindingId}\`: ${sanitizeMarkdownContent(f.issue)} -> ${resolution}`;
61497
+ let resolution = f.changesMade ? sanitizeMarkdownContent(f.changesMade) : "Unavailable (resolution not recorded)", safeFindingId = String(f.findingId).replace(/[\r\n]+/g, " ").replace(/`/g, "'").trim(), safeSeatId = String(f.seatId).replace(/[\r\n]+/g, " ").replace(/`/g, "'").trim(), displaySeat = displaySeatNumber(safeSeatId);
61498
+ return `- **[Round ${f.round} / Seat ${escapeMarkdownTableCell(displaySeat)}]** \`${safeFindingId}\`: ${sanitizeMarkdownContent(f.issue)} -> ${resolution}`;
61370
61499
  }).join(`
61371
61500
  `);
61372
61501
  let roundTimes = /* @__PURE__ */ new Map(), roundHasPartial = /* @__PURE__ */ new Map();
@@ -64765,7 +64894,8 @@ var QuorumLoop = class _QuorumLoop {
64765
64894
  * Enables reconciliation if a user decision arrives or is replayed after promotion.
64766
64895
  */
64767
64896
  this.completedTaskSummaries = /* @__PURE__ */ new Map();
64768
- this.expectedRosterByTask = /* @__PURE__ */ new Map();
64897
+ this.declaredRosterByTask = /* @__PURE__ */ new Map();
64898
+ this.dispatchedRosterByTask = /* @__PURE__ */ new Map();
64769
64899
  this.taskDegradedMetadataByTask = /* @__PURE__ */ new Map();
64770
64900
  /**
64771
64901
  * A1b — the implementor's own per-round stdout rationale (the
@@ -65325,6 +65455,7 @@ var QuorumLoop = class _QuorumLoop {
65325
65455
  } catch {
65326
65456
  }
65327
65457
  }
65458
+ /** @internal */
65328
65459
  recordCompletedTaskSummary(taskId, info) {
65329
65460
  try {
65330
65461
  this.withCompletedSummariesLock(() => {
@@ -66074,6 +66205,25 @@ var QuorumLoop = class _QuorumLoop {
66074
66205
  }
66075
66206
  return out;
66076
66207
  }
66208
+ getDetectedModelForAgent(agent) {
66209
+ if (!agent) return null;
66210
+ let up = agent.toUpperCase(), low = agent.toLowerCase(), models = this.deps.detectedAgentModels;
66211
+ if (models) {
66212
+ if (models[up]) return models[up];
66213
+ if (models[low]) return models[low];
66214
+ }
66215
+ return null;
66216
+ }
66217
+ getExplicitModelForAgent(agent) {
66218
+ if (!agent) return null;
66219
+ let up = agent.toUpperCase(), low = agent.toLowerCase(), models = this.deps.configuredAgentModels;
66220
+ if (models) {
66221
+ if (models[up]) return models[up];
66222
+ if (models[low]) return models[low];
66223
+ if (models[agent]) return models[agent];
66224
+ }
66225
+ return null;
66226
+ }
66077
66227
  /**
66078
66228
  * #585 auto-continuation (Max) — pick the agent to AUTO-CONTINUE on when the
66079
66229
  * implementor for `taskId` hit a quota wall, or `null` to fall through to the
@@ -66349,8 +66499,8 @@ var QuorumLoop = class _QuorumLoop {
66349
66499
  async handleGateDispatch(payload, envelopeTaskId) {
66350
66500
  let dispatchTaskId = envelopeTaskId || this.latestInFlightStart;
66351
66501
  if (dispatchTaskId && Array.isArray(payload.reviewerSeats) && payload.reviewerSeats.length > 0) {
66352
- let roster = this.expectedRosterByTask.get(dispatchTaskId);
66353
- roster || (roster = /* @__PURE__ */ new Map(), this.expectedRosterByTask.set(dispatchTaskId, roster));
66502
+ let roster = this.declaredRosterByTask.get(dispatchTaskId);
66503
+ roster || (roster = /* @__PURE__ */ new Map(), this.declaredRosterByTask.set(dispatchTaskId, roster));
66354
66504
  for (let seat of payload.reviewerSeats)
66355
66505
  roster.set(String(seat.seatId), String(seat.role || "reviewer").toLowerCase());
66356
66506
  }
@@ -66789,7 +66939,7 @@ var QuorumLoop = class _QuorumLoop {
66789
66939
  if (!stale) return;
66790
66940
  await stale.assertCanDiscard(), logger.info("[QuorumLoop] replacing a stale shadow for a fresh round-0 dispatch (restart)", {
66791
66941
  taskId
66792
- }), await stale.discard(), this.shadowsByTask.get(taskId) === stale && this.shadowsByTask.delete(taskId), this.userNotesByTask.delete(taskId), this.reviewScopeResetTasks.delete(taskId), this.roundHistoryByTask.delete(taskId), this.rationaleByTask.delete(taskId), this.taskDegradedMetadataByTask.delete(taskId), this.expectedRosterByTask.delete(taskId), this.clearSeenGateDispatchRunIdsForTask(taskId), this.activeGateByTaskId.delete(taskId), this.conflictedSeatsByTask.delete(taskId), this.nonApprovedSeatsByTask.delete(taskId);
66942
+ }), await stale.discard(), this.shadowsByTask.get(taskId) === stale && this.shadowsByTask.delete(taskId), this.userNotesByTask.delete(taskId), this.reviewScopeResetTasks.delete(taskId), this.roundHistoryByTask.delete(taskId), this.rationaleByTask.delete(taskId), this.taskDegradedMetadataByTask.delete(taskId), this.declaredRosterByTask.delete(taskId), this.dispatchedRosterByTask.delete(taskId), this.clearSeenGateDispatchRunIdsForTask(taskId), this.activeGateByTaskId.delete(taskId), this.conflictedSeatsByTask.delete(taskId), this.nonApprovedSeatsByTask.delete(taskId);
66793
66943
  let nextFence = (this.restartFenceByTaskId.get(taskId) ?? 0) + 1;
66794
66944
  this.restartFenceByTaskId.set(taskId, nextFence), this.reviewedSnapshotByTask.delete(taskId);
66795
66945
  }
@@ -67733,14 +67883,16 @@ ${section}`);
67733
67883
  let completedInfo = this.getCompletedTaskSummary(taskId);
67734
67884
  if (completedInfo)
67735
67885
  try {
67736
- let summaryModel = compileAuditSummary({
67886
+ let d = decision?.decision?.toLowerCase(), isApprove = (d === "approve" || d === "accept") && decision?.isFinalApproval !== !1, isPendingMerge = completedInfo.workspaceApplicationStatus === "pending_merge_gate", summaryModel = compileAuditSummary({
67737
67887
  taskId,
67738
67888
  sessionId: this.deps.session.sessionId,
67739
67889
  historySnapshot: completedInfo.historySnapshot,
67740
67890
  userDecision: decision,
67741
67891
  filesApplied: completedInfo.filesApplied,
67742
67892
  completedAt: completedInfo.completedAt,
67743
- workspaceApplicationStatus: completedInfo.workspaceApplicationStatus
67893
+ serverAuthorizedAt: isApprove && !isPendingMerge ? decision?.serverRecordedAt ?? void 0 : void 0,
67894
+ workspaceApplicationStatus: completedInfo.workspaceApplicationStatus,
67895
+ detectedAgentModels: this.deps.detectedAgentModels
67744
67896
  }), markdown = renderSummaryMarkdown(summaryModel);
67745
67897
  try {
67746
67898
  this.deps.onTaskAuditSummary?.(summaryModel, markdown);
@@ -67795,17 +67947,23 @@ ${section}`);
67795
67947
  let records = this.roundHistoryByTask.get(taskId) ?? [], taskDegraded = this.taskDegradedMetadataByTask.get(taskId), historyDegraded = !!taskDegraded?.historyDegraded, omittedFindingsCount = taskDegraded?.omittedFindingsCount ?? 0, omittedResidualsCount = taskDegraded?.omittedResidualsCount ?? 0, omittedRounds = taskDegraded?.omittedRounds, truncatedForSize = taskDegraded?.truncatedForSize;
67796
67948
  for (let r of records)
67797
67949
  r.historyDegraded && (historyDegraded = !0), omittedFindingsCount += r.omittedFindingsCount ?? 0, omittedResidualsCount += r.omittedResidualsCount ?? 0;
67798
- let seatCount = this.deps.tier === "MAX" ? 3 : 2, rosterMap = this.expectedRosterByTask.get(taskId), expectedRosterMap = /* @__PURE__ */ new Map();
67799
- if (rosterMap && rosterMap.size > 0)
67800
- for (let [seatId, role] of rosterMap.entries())
67950
+ let declaredRoster = this.declaredRosterByTask.get(taskId), expectedRosterMap = /* @__PURE__ */ new Map();
67951
+ if (declaredRoster && declaredRoster.size > 0)
67952
+ for (let [seatId, role] of declaredRoster.entries())
67801
67953
  expectedRosterMap.set(seatId, role);
67802
- else
67954
+ else {
67803
67955
  for (let r of records)
67804
67956
  expectedRosterMap.set(String(r.seatId), String(r.role || "reviewer").toLowerCase());
67805
- let missingIdx = 0;
67806
- for (; expectedRosterMap.size < seatCount; ) {
67807
- let seatKey2 = `missing-seat-${missingIdx++}`;
67808
- expectedRosterMap.has(seatKey2) || expectedRosterMap.set(seatKey2, "required_seat_unassigned");
67957
+ let dispatched = this.dispatchedRosterByTask.get(taskId);
67958
+ if (dispatched)
67959
+ for (let [seatId, role] of dispatched.entries())
67960
+ expectedRosterMap.set(seatId, role);
67961
+ let minRequiredSeats = this.deps.tier === "FREE" ? 1 : 2, padIdx = 0;
67962
+ for (; expectedRosterMap.size < minRequiredSeats; ) {
67963
+ let syntheticSeat = String(padIdx);
67964
+ expectedRosterMap.has(syntheticSeat) || expectedRosterMap.set(syntheticSeat, "required_seat_unassigned"), padIdx++;
67965
+ }
67966
+ this.deps.tier !== "FREE" && expectedRosterMap.set("unverified_roster_declaration", "required_seat_unassigned");
67809
67967
  }
67810
67968
  let expectedRoster = Array.from(expectedRosterMap.entries()).map(([seatId, role]) => ({ seatId, role }));
67811
67969
  return {
@@ -67862,8 +68020,8 @@ ${section}`);
67862
68020
  ingestReviewSummary(taskId, summary) {
67863
68021
  if (!taskId || !summary || this.isWorkspaceTaskTerminallyRetired(taskId) || this.getCompletedTaskSummary(taskId))
67864
68022
  return;
67865
- let roster = this.expectedRosterByTask.get(taskId);
67866
- if (roster || (roster = /* @__PURE__ */ new Map(), this.expectedRosterByTask.set(taskId, roster)), summary.reviewQuorum && Array.isArray(summary.reviewQuorum.seats))
68023
+ let roster = this.declaredRosterByTask.get(taskId);
68024
+ if (roster || (roster = /* @__PURE__ */ new Map(), this.declaredRosterByTask.set(taskId, roster)), summary.reviewQuorum && Array.isArray(summary.reviewQuorum.seats))
67867
68025
  for (let s of summary.reviewQuorum.seats) {
67868
68026
  if (!s || s.seatId == null || String(s.seatId).trim().length === 0) continue;
67869
68027
  let seatIdStr = String(s.seatId).trim(), roleStr = String(s.role || "").trim().toLowerCase();
@@ -68304,7 +68462,7 @@ ${section}`);
68304
68462
  });
68305
68463
  return;
68306
68464
  }
68307
- if (opts?.preserveReviseContext || (this.userNotesByTask.delete(taskId), this.reviewScopeResetTasks.delete(taskId), this.reviewScopeResetEligibleTasks.delete(taskId), this.roundHistoryByTask.delete(taskId), opts?.taskContinues !== !0 && this.forgetSingleTask(taskId, "discarded"), this.rationaleByTask.delete(taskId), this.taskDegradedMetadataByTask.delete(taskId), this.expectedRosterByTask.delete(taskId), this.activeGateByTaskId.delete(taskId), this.conflictedSeatsByTask.delete(taskId), this.nonApprovedSeatsByTask.delete(taskId), this.restartFenceByTaskId.delete(taskId), appendContextItem(this.deps.session.sessionId, {
68465
+ if (opts?.preserveReviseContext || (this.userNotesByTask.delete(taskId), this.reviewScopeResetTasks.delete(taskId), this.reviewScopeResetEligibleTasks.delete(taskId), this.roundHistoryByTask.delete(taskId), opts?.taskContinues !== !0 && this.forgetSingleTask(taskId, "discarded"), this.rationaleByTask.delete(taskId), this.taskDegradedMetadataByTask.delete(taskId), this.declaredRosterByTask.delete(taskId), this.dispatchedRosterByTask.delete(taskId), this.activeGateByTaskId.delete(taskId), this.conflictedSeatsByTask.delete(taskId), this.nonApprovedSeatsByTask.delete(taskId), this.restartFenceByTaskId.delete(taskId), appendContextItem(this.deps.session.sessionId, {
68308
68466
  kind: "verdict",
68309
68467
  author: { role: "engine" },
68310
68468
  sensitivity: "user",
@@ -68513,7 +68671,7 @@ ${section}`);
68513
68671
  error: err?.message
68514
68672
  }), historySnapshot = null;
68515
68673
  }
68516
- this.userNotesByTask.delete(taskId), this.reviewScopeResetTasks.delete(taskId), this.reviewScopeResetEligibleTasks.delete(taskId), this.roundHistoryByTask.delete(taskId), this.forgetSingleTask(taskId, "apply_failed"), this.rationaleByTask.delete(taskId), this.taskDegradedMetadataByTask.delete(taskId), this.expectedRosterByTask.delete(taskId), this.activeGateByTaskId.delete(taskId), this.conflictedSeatsByTask.delete(taskId), this.nonApprovedSeatsByTask.delete(taskId), this.restartFenceByTaskId.delete(taskId);
68674
+ this.userNotesByTask.delete(taskId), this.reviewScopeResetTasks.delete(taskId), this.reviewScopeResetEligibleTasks.delete(taskId), this.roundHistoryByTask.delete(taskId), this.forgetSingleTask(taskId, "apply_failed"), this.rationaleByTask.delete(taskId), this.taskDegradedMetadataByTask.delete(taskId), this.declaredRosterByTask.delete(taskId), this.dispatchedRosterByTask.delete(taskId), this.activeGateByTaskId.delete(taskId), this.conflictedSeatsByTask.delete(taskId), this.nonApprovedSeatsByTask.delete(taskId), this.restartFenceByTaskId.delete(taskId);
68517
68675
  let shadow = this.shadowsByTask.get(taskId);
68518
68676
  if (!shadow) {
68519
68677
  if (this.singleTaskHistory.get(taskId)?.outcome === "discarded") {
@@ -68735,12 +68893,16 @@ ${section}`);
68735
68893
  }
68736
68894
  discarded && this.shadowsByTask.get(taskId) === shadow && this.shadowsByTask.delete(taskId), discarded && this.terminallyRetiredWorkspaceTasks.add(taskId), this.reviewedSnapshotByTask.delete(taskId);
68737
68895
  try {
68738
- let userDecision = this.lastUserDecisionByTask.get(taskId) ?? null, completedAt = (/* @__PURE__ */ new Date()).toISOString(), summaryModel = compileAuditSummary({
68896
+ let userDecision = this.lastUserDecisionByTask.get(taskId) ?? null, completedAt = (/* @__PURE__ */ new Date()).toISOString(), d = userDecision?.decision?.toLowerCase(), isApprove = d === "approve" || d === "accept", summaryModel = compileAuditSummary({
68739
68897
  taskId,
68740
68898
  sessionId: this.deps.session.sessionId,
68741
68899
  historySnapshot,
68742
68900
  userDecision,
68743
- workspaceApplicationStatus: "pending_merge_gate"
68901
+ completedAt,
68902
+ serverAuthorizedAt: void 0,
68903
+ // pending merge gate — unpromoted
68904
+ workspaceApplicationStatus: "pending_merge_gate",
68905
+ detectedAgentModels: this.deps.detectedAgentModels
68744
68906
  }), markdown = renderSummaryMarkdown(summaryModel);
68745
68907
  try {
68746
68908
  this.deps.onTaskAuditSummary?.(summaryModel, markdown);
@@ -68955,13 +69117,15 @@ ${section}`);
68955
69117
  }), onTaskBoundary(this.deps.session.sessionId).catch(() => {
68956
69118
  }), this.emitProgress({ phase: "promoted", files: appliedPaths.length, taskId }, originEpoch);
68957
69119
  try {
68958
- let userDecision = this.lastUserDecisionByTask.get(taskId) ?? null, completedAt = this.lastWorkspaceOutcome?.completedAt ?? (/* @__PURE__ */ new Date()).toISOString(), filesApplied = appliedPaths.length, summaryModel = compileAuditSummary({
69120
+ let userDecision = this.lastUserDecisionByTask.get(taskId) ?? null, completedAt = this.lastWorkspaceOutcome?.completedAt ?? (/* @__PURE__ */ new Date()).toISOString(), filesApplied = appliedPaths.length, d = userDecision?.decision?.toLowerCase(), isApprove = (d === "approve" || d === "accept") && userDecision?.isFinalApproval !== !1, summaryModel = compileAuditSummary({
68959
69121
  taskId,
68960
69122
  sessionId: this.deps.session.sessionId,
68961
69123
  historySnapshot,
68962
69124
  userDecision,
68963
69125
  filesApplied,
68964
- completedAt
69126
+ completedAt,
69127
+ serverAuthorizedAt: isApprove ? userDecision?.serverRecordedAt ?? void 0 : void 0,
69128
+ detectedAgentModels: this.deps.detectedAgentModels
68965
69129
  }), markdown = renderSummaryMarkdown(summaryModel);
68966
69130
  try {
68967
69131
  this.deps.onTaskAuditSummary?.(summaryModel, markdown);
@@ -69183,8 +69347,8 @@ ${section}`);
69183
69347
  seatId: seat,
69184
69348
  ...dispatchTaskId ? { taskId: dispatchTaskId } : {}
69185
69349
  }), dispatchTaskId) {
69186
- let roster = this.expectedRosterByTask.get(dispatchTaskId);
69187
- roster || (roster = /* @__PURE__ */ new Map(), this.expectedRosterByTask.set(dispatchTaskId, roster)), roster.set(String(seat), String(payload.role || "reviewer"));
69350
+ let roster = this.dispatchedRosterByTask.get(dispatchTaskId);
69351
+ roster || (roster = /* @__PURE__ */ new Map(), this.dispatchedRosterByTask.set(dispatchTaskId, roster)), roster.set(String(seat), String(payload.role || "reviewer"));
69188
69352
  }
69189
69353
  let dispatched = this.dispatchedSeatsByGate.get(payload.gateId) ?? /* @__PURE__ */ new Set(), wasNew = !dispatched.has(seat);
69190
69354
  dispatched.add(seat), this.dispatchedSeatsByGate.set(payload.gateId, dispatched), wasNew && this.emitProgressForTask(dispatchTaskId, originEpoch, {
@@ -69278,7 +69442,7 @@ ${section}`);
69278
69442
  tool_allowlist: [...REVIEWER_TOOL_ALLOWLIST],
69279
69443
  prompt_template: promptText,
69280
69444
  timeout_ms: REVIEWER_TIMEOUT_MS,
69281
- model_hint: null
69445
+ model_hint: this.getExplicitModelForAgent(args.agentKind)
69282
69446
  }, seatSubstrate;
69283
69447
  try {
69284
69448
  seatSubstrate = await this.engageSeatSubstrate(args, key);
@@ -69891,7 +70055,7 @@ ${section}`);
69891
70055
  tool_allowlist: [...REVIEWER_TOOL_ALLOWLIST],
69892
70056
  prompt_template: renderFinalTier2Prompt(diff, bundleSections),
69893
70057
  timeout_ms: REVIEWER_TIMEOUT_MS,
69894
- model_hint: null
70058
+ model_hint: this.getExplicitModelForAgent(agent)
69895
70059
  }, verdict = await this.deps.reviewerRegistry.evaluate(spec, `wave-b-tier2-${args.ownerTaskId}`, {
69896
70060
  ...this.deps.classifyVerdict !== void 0 ? { classifyVerdict: this.deps.classifyVerdict } : {},
69897
70061
  ...substrate !== void 0 ? { substrate, workdir: this.deps.workingDir } : {},
@@ -82571,7 +82735,7 @@ async function runOrchestrationShellSession(args) {
82571
82735
  finalApprovalCancelled ? "CANCEL" : "ABORT"
82572
82736
  ), args.quorumLoop.reportTeamTrackUserResolved(taskId, postAction), args.quorumLoop.reportFinalApprovalCancelled(taskId, postAction);
82573
82737
  try {
82574
- let timestamp5 = gateResolution?.recordedAt || (/* @__PURE__ */ new Date()).toISOString(), gateId = gateResolution?.gateId, decisionClaimId = gateResolution?.decisionClaimId;
82738
+ let timestamp5 = (/* @__PURE__ */ new Date()).toISOString(), serverRecordedAt = gateResolution?.recordedAt, gateId = gateResolution?.gateId, decisionClaimId = gateResolution?.decisionClaimId;
82575
82739
  if (postAction.kind === "final_approval_resolved") {
82576
82740
  let dec = canonicalDecision ? canonicalDecision.trim().toLowerCase() : postAction.decision;
82577
82741
  args.quorumLoop?.recordUserDecision?.(taskId, {
@@ -82579,7 +82743,8 @@ async function runOrchestrationShellSession(args) {
82579
82743
  isFinalApproval: !0,
82580
82744
  gateId,
82581
82745
  decisionClaimId,
82582
- timestamp: timestamp5
82746
+ timestamp: timestamp5,
82747
+ serverRecordedAt
82583
82748
  });
82584
82749
  } else if (postAction.kind === "terminate_gate") {
82585
82750
  let canon = canonicalDecision ? canonicalDecision.trim().toLowerCase() : "", dec = canon === "accept_with_notes" || !canon && postAction.notes ? "accept_with_notes" : canon || "accept";
@@ -82589,14 +82754,16 @@ async function runOrchestrationShellSession(args) {
82589
82754
  notes: postAction.notes ?? void 0,
82590
82755
  gateId,
82591
82756
  decisionClaimId,
82592
- timestamp: timestamp5
82757
+ timestamp: timestamp5,
82758
+ serverRecordedAt
82593
82759
  });
82594
82760
  } else postAction.kind === "abort_task" && args.quorumLoop?.recordUserDecision?.(taskId, {
82595
82761
  decision: "cancel",
82596
82762
  isFinalApproval: !1,
82597
82763
  gateId,
82598
82764
  decisionClaimId,
82599
- timestamp: timestamp5
82765
+ timestamp: timestamp5,
82766
+ serverRecordedAt
82600
82767
  });
82601
82768
  } catch {
82602
82769
  }
@@ -88100,6 +88267,7 @@ var import_uuid18 = require("uuid"), fs65 = __toESM(require("fs"));
88100
88267
 
88101
88268
  // src/orchestration-shell/doctor-cli.ts
88102
88269
  var fs59 = __toESM(require("fs")), path79 = __toESM(require("path")), crypto32 = __toESM(require("crypto")), import_child_process7 = require("child_process");
88270
+ init_detect_agents();
88103
88271
 
88104
88272
  // src/auth/auth-service.ts
88105
88273
  var crypto31 = __toESM(require("crypto")), fs58 = __toESM(require("fs")), http3 = __toESM(require("http")), import_child_process6 = require("child_process");
@@ -88731,13 +88899,16 @@ function probeAgentClis(env = process.env) {
88731
88899
  error: err.message
88732
88900
  };
88733
88901
  }
88902
+ let explicitModel = detectAgentModel(agent, env, { explicitOnly: !0 }), resolvedModel = explicitModel ?? detectAgentModel(agent, env) ?? void 0;
88734
88903
  return {
88735
88904
  agent,
88736
88905
  command,
88737
88906
  name,
88738
88907
  installed: !0,
88739
88908
  version: version || "installed",
88740
- binPath
88909
+ binPath,
88910
+ model: resolvedModel,
88911
+ modelIsConfigured: !!explicitModel
88741
88912
  };
88742
88913
  });
88743
88914
  }
@@ -88982,9 +89153,10 @@ function renderPreflight(agents, auth, connectivity, orphans) {
88982
89153
  console.log(`${colors.bold}CodeVibe Preflight Diagnostics${colors.reset}
88983
89154
  `), console.log(`${colors.bold}Agent CLIs:${colors.reset}`);
88984
89155
  for (let agent of agents)
88985
- if (agent.installed)
88986
- console.log(` [${colors.green}ok${colors.reset}] ${agent.name} (${agent.version ?? "installed"})${agent.binPath ? ` ${colors.dim}${agent.binPath}${colors.reset}` : ""}`);
88987
- else {
89156
+ if (agent.installed) {
89157
+ let modelInfo = agent.model ? agent.modelIsConfigured ? ` [model: ${agent.model}]` : ` [model: native default (unverified: ${agent.model})]` : "";
89158
+ console.log(` [${colors.green}ok${colors.reset}] ${agent.name} (${agent.version ?? "installed"})${modelInfo}${agent.binPath ? ` ${colors.dim}${agent.binPath}${colors.reset}` : ""}`);
89159
+ } else {
88988
89160
  let reason = agent.error ? `(${agent.error})` : "(not in $PATH)";
88989
89161
  console.log(` [${colors.yellow}missing${colors.reset}] ${agent.name} ${colors.dim}${reason}${colors.reset}`);
88990
89162
  }
@@ -93622,7 +93794,7 @@ Run codevibe --help for usage.
93622
93794
  if ((args.resume || args.continue) && tier === "FREE")
93623
93795
  return process.stderr.write(`${RESUME_NEEDS_PAID_TIER2}
93624
93796
  `), 1;
93625
- let mode = await resolveLaunchMode(args, tier), detectedAgents = detectInstalledAgents();
93797
+ let mode = await resolveLaunchMode(args, tier), detectedAgents = detectInstalledAgents(), detectedAgentModels = detectInstalledAgentModels(process.env, void 0, detectedAgents), configuredAgentModels = detectInstalledAgentModels(process.env, void 0, detectedAgents, { explicitOnly: !0 });
93626
93798
  await pushDetectedAgents(
93627
93799
  appsyncClient,
93628
93800
  logger,
@@ -93746,6 +93918,8 @@ ${err.message}
93746
93918
  // CP-1.f LOCK RP-6 — thread the single host-agent probe so the
93747
93919
  // QuorumLoop carries it in `startTask` (race-free gate-row stamp).
93748
93920
  detectedAgents,
93921
+ detectedAgentModels,
93922
+ configuredAgentModels,
93749
93923
  // #585 auto-continuation (Max) — the authoritative resolved tier (the
93750
93924
  // team path is MAX-only, but thread it explicitly for consistency).
93751
93925
  tier,
@@ -93776,6 +93950,8 @@ ${err.message}
93776
93950
  // CP-1.f LOCK RP-6 — thread the single host-agent probe so the
93777
93951
  // QuorumLoop carries it in `startTask` (race-free gate-row stamp).
93778
93952
  detectedAgents,
93953
+ detectedAgentModels,
93954
+ configuredAgentModels,
93779
93955
  // #585 auto-continuation (Max) — the authoritative resolved tier.
93780
93956
  tier,
93781
93957
  // [Gemma classifier · §Wiring] The session's Gemma pipeline (the planner's
@@ -93977,6 +94153,8 @@ function buildAndArmQuorumLoop(args) {
93977
94153
  workingDir: args.workingDir,
93978
94154
  // CP-1.f LOCK RP-6 — race-free request-carried host agents.
93979
94155
  detectedAgents: args.detectedAgents,
94156
+ ...args.detectedAgentModels ? { detectedAgentModels: args.detectedAgentModels } : {},
94157
+ ...args.configuredAgentModels ? { configuredAgentModels: args.configuredAgentModels } : {},
93980
94158
  // #585 auto-continuation (Max) — thread the resolved tier to the loop.
93981
94159
  tier: args.tier,
93982
94160
  // CP-1.f execute-first (#EF-1 / #SR-2) — synchronous halt + fail-closed
@@ -94122,6 +94300,8 @@ async function buildQuorumLoopExecutor(args) {
94122
94300
  holder: quorumLoopHolder,
94123
94301
  // CP-1.f LOCK RP-6 — race-free request-carried host agents.
94124
94302
  detectedAgents: args.detectedAgents,
94303
+ ...args.detectedAgentModels ? { detectedAgentModels: args.detectedAgentModels } : {},
94304
+ ...args.configuredAgentModels ? { configuredAgentModels: args.configuredAgentModels } : {},
94125
94305
  // #585 auto-continuation (Max) — thread the resolved tier to the loop.
94126
94306
  tier: args.tier,
94127
94307
  // [Gemma classifier · §Wiring] Thread the runner so the loop wires the
@@ -94639,6 +94819,8 @@ async function buildTeamLocalExecutor(args) {
94639
94819
  ...args.onTaskAuditSummary ? { onTaskAuditSummary: args.onTaskAuditSummary } : {},
94640
94820
  // CP-1.f LOCK RP-6 — race-free request-carried host agents.
94641
94821
  detectedAgents: args.detectedAgents,
94822
+ ...args.detectedAgentModels ? { detectedAgentModels: args.detectedAgentModels } : {},
94823
+ ...args.configuredAgentModels ? { configuredAgentModels: args.configuredAgentModels } : {},
94642
94824
  // #585 auto-continuation (Max) — thread the resolved tier to the loop.
94643
94825
  tier: args.tier,
94644
94826
  // [Gemma classifier · §Wiring] Thread the runner so the loop wires the