omnius 1.0.238 → 1.0.239

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
@@ -2405,6 +2405,80 @@ function inspectRealProcess(pid) {
2405
2405
  }
2406
2406
  return identity3;
2407
2407
  }
2408
+ function formatProcessLeaseSummary(leases) {
2409
+ const active = leases.filter((l2) => l2.status === "active").length;
2410
+ const stale = leases.filter((l2) => l2.status === "suspect_unverified" || l2.status === "terminating").length;
2411
+ const dead = leases.filter((l2) => l2.status === "dead" || l2.status === "killed").length;
2412
+ const lines = [
2413
+ `[PROCESS LEASES]`,
2414
+ `Active: ${active} | Stale: ${stale} | Dead: ${dead} | Total: ${leases.length}`
2415
+ ];
2416
+ for (const lease of leases.filter((l2) => l2.status !== "dead" && l2.status !== "killed").slice(0, 20)) {
2417
+ const age = Math.round((Date.now() - lease.startedAt) / 1e3);
2418
+ lines.push(` ${lease.leaseId.slice(0, 24).padEnd(24)} pid=${String(lease.pid).padEnd(6)} ${lease.lifecycle}/${lease.status} age=${age}s owner=${lease.ownerId}`);
2419
+ }
2420
+ return lines.join("\n");
2421
+ }
2422
+ function adoptDaemonPidFileLease(pidFilePath, options2) {
2423
+ try {
2424
+ if (!existsSync5(pidFilePath))
2425
+ return null;
2426
+ const pidStr = readFileSync4(pidFilePath, "utf8").trim();
2427
+ const pid = Number(pidStr);
2428
+ if (!Number.isFinite(pid) || pid <= 0)
2429
+ return null;
2430
+ if (!isProcessAlive(pid))
2431
+ return null;
2432
+ const cwd4 = process.platform !== "win32" && existsSync5(`/proc/${pid}/cwd`) ? readlinkSync(`/proc/${pid}/cwd`) : void 0;
2433
+ const cmdline = process.platform !== "win32" && existsSync5(`/proc/${pid}/cmdline`) ? readFileSync4(`/proc/${pid}/cmdline`, "utf8").replace(/\0/g, " ").trim() : void 0;
2434
+ return registerProcessLease({
2435
+ pid,
2436
+ ownerKind: "daemon",
2437
+ ownerId: "daemon",
2438
+ projectRoot: process.cwd(),
2439
+ lifecycle: "daemon",
2440
+ persistent: true,
2441
+ reason: options2?.reason ?? "adopted from daemon pid file",
2442
+ command: cmdline,
2443
+ cwd: cwd4
2444
+ }, options2);
2445
+ } catch {
2446
+ return null;
2447
+ }
2448
+ }
2449
+ function adoptSchedulerLease(record, options2) {
2450
+ try {
2451
+ if (!record.pid || !isProcessAlive(record.pid))
2452
+ return null;
2453
+ return registerProcessLease({
2454
+ pid: record.pid,
2455
+ ownerKind: "scheduler",
2456
+ ownerId: `job:${record.jobId}`,
2457
+ projectRoot: process.cwd(),
2458
+ lifecycle: "scheduler",
2459
+ persistent: true,
2460
+ reason: `adopted from scheduler job ${record.jobId}`
2461
+ }, options2);
2462
+ } catch {
2463
+ return null;
2464
+ }
2465
+ }
2466
+ function adoptInFlightChatLease(record, options2) {
2467
+ try {
2468
+ if (!record.pid || !isProcessAlive(record.pid))
2469
+ return null;
2470
+ return registerProcessLease({
2471
+ pid: record.pid,
2472
+ ownerKind: "chat",
2473
+ ownerId: record.chatId,
2474
+ projectRoot: process.cwd(),
2475
+ lifecycle: "task",
2476
+ reason: `adopted from in-flight chat run ${record.runId}`
2477
+ }, options2);
2478
+ } catch {
2479
+ return null;
2480
+ }
2481
+ }
2408
2482
  function tryAcquireSweeperLock(lockDir, ownerLabel) {
2409
2483
  try {
2410
2484
  mkdirSync4(lockDir, { recursive: false });
@@ -549709,9 +549783,6 @@ __export(dist_exports2, {
549709
549783
  OcrImageAdvancedTool: () => OcrImageAdvancedTool,
549710
549784
  OcrPdfTool: () => OcrPdfTool,
549711
549785
  OpenCodeTool: () => OpenCodeTool,
549712
- PROCESS_LEASE_STALE_MS: () => PROCESS_LEASE_STALE_MS,
549713
- PROCESS_LEASE_SWEEP_INTERVAL_MS: () => PROCESS_LEASE_SWEEP_INTERVAL_MS,
549714
- PROCESS_LEASE_TERM_GRACE_MS: () => PROCESS_LEASE_TERM_GRACE_MS,
549715
549786
  PdfToTextTool: () => PdfToTextTool,
549716
549787
  PhaseRecallTool: () => PhaseRecallTool,
549717
549788
  PlaywrightBrowserTool: () => PlaywrightBrowserTool,
@@ -549777,6 +549848,9 @@ __export(dist_exports2, {
549777
549848
  addProjectConstraint: () => addProjectConstraint,
549778
549849
  addSessionConstraint: () => addSessionConstraint,
549779
549850
  addWorkboardCard: () => addWorkboardCard,
549851
+ adoptDaemonPidFileLease: () => adoptDaemonPidFileLease,
549852
+ adoptInFlightChatLease: () => adoptInFlightChatLease,
549853
+ adoptSchedulerLease: () => adoptSchedulerLease,
549780
549854
  aliasTool: () => aliasTool,
549781
549855
  applyMediaCudaDeviceFilterToEnv: () => applyMediaCudaDeviceFilterToEnv,
549782
549856
  applyPatch: () => applyPatch,
@@ -549863,6 +549937,7 @@ __export(dist_exports2, {
549863
549937
  flattenSlug: () => flattenSlug,
549864
549938
  formatBytes: () => formatBytes,
549865
549939
  formatMessagesForContext: () => formatMessagesForContext,
549940
+ formatProcessLeaseSummary: () => formatProcessLeaseSummary,
549866
549941
  formatProvenanceSummary: () => formatProvenanceSummary,
549867
549942
  formatSecurityNotice: () => formatSecurityNotice,
549868
549943
  formatSnapshotForContext: () => formatSnapshotForContext,
@@ -553161,6 +553236,391 @@ var init_textSanitize = __esm({
553161
553236
  }
553162
553237
  });
553163
553238
 
553239
+ // packages/orchestrator/dist/completionContract.js
553240
+ function normalizeText(value2, max = 500) {
553241
+ const text2 = String(value2 ?? "").trim().replace(/\s+/g, " ");
553242
+ return text2 ? text2.slice(0, max) : "";
553243
+ }
553244
+ function normalizeCompletionKey(value2, fallback = "item") {
553245
+ const key = String(value2 ?? fallback).trim().toLowerCase().replace(/[^a-z0-9_.:-]+/g, "_").replace(/_{2,}/g, "_").replace(/^[_:.-]+|[_:.-]+$/g, "").slice(0, 96);
553246
+ return key || fallback;
553247
+ }
553248
+ function genericField(key, label, description, acceptanceCriteria) {
553249
+ return {
553250
+ key: normalizeCompletionKey(key),
553251
+ label,
553252
+ fieldType: "json",
553253
+ elevation: "required",
553254
+ sourceMode: "derived",
553255
+ description,
553256
+ acceptanceCriteria
553257
+ };
553258
+ }
553259
+ function inferCompletionContract(taskText) {
553260
+ const goalSummary = normalizeText(taskText);
553261
+ const fields = [
553262
+ genericField("claims.evidence_map", "Claim evidence map", "A run-local mapping from each final claim to the observed result that supports it.", "Each material claim is either backed by observed evidence from this run or named as unverified/blocked."),
553263
+ genericField("claims.unverified", "Unverified claims", "Claims that could not be proven from the run's observations.", "Unverified claims are not presented as completed work.")
553264
+ ];
553265
+ const phases = [
553266
+ {
553267
+ key: "execute",
553268
+ label: "Execute",
553269
+ instructions: "Do the requested work while preserving observations needed to evaluate the result.",
553270
+ requirementIds: [],
553271
+ fields: [],
553272
+ gate: {
553273
+ key: "execution_trace",
553274
+ instructions: "Keep enough concrete run output to distinguish facts from assumptions."
553275
+ }
553276
+ },
553277
+ {
553278
+ key: "verify",
553279
+ label: "Verify",
553280
+ instructions: "Derive the needed evidence from the actual request and final claims, then compare those claims to observed results.",
553281
+ requirementIds: [],
553282
+ fields,
553283
+ gate: {
553284
+ key: "claim_evidence_review",
553285
+ instructions: "Judge whether the actual claim is supported by the actual observations."
553286
+ }
553287
+ },
553288
+ {
553289
+ key: "deliver",
553290
+ label: "Deliver",
553291
+ instructions: "Report completed, verified, unverified, and blocked items without overstating what was observed.",
553292
+ requirementIds: [],
553293
+ fields: [],
553294
+ gate: {
553295
+ key: "result_readback",
553296
+ instructions: "Final wording must not exceed the observed evidence."
553297
+ }
553298
+ }
553299
+ ];
553300
+ return {
553301
+ goalSummary,
553302
+ surfaces: [],
553303
+ fields,
553304
+ requirements: [],
553305
+ phases,
553306
+ acceptanceCriteria: [
553307
+ "The final response distinguishes completed work from verified evidence and unverified or blocked claims."
553308
+ ]
553309
+ };
553310
+ }
553311
+ function inferCompletionContractFromTexts(texts, fallbackSummary = "") {
553312
+ const combined = texts.map((text2) => String(text2 ?? "").trim()).filter(Boolean).join("\n\n");
553313
+ return inferCompletionContract(combined || fallbackSummary);
553314
+ }
553315
+ function clip2(value2, max = 500) {
553316
+ return normalizeText(value2, max);
553317
+ }
553318
+ function listLines(items, empty2 = "- none observed") {
553319
+ return items.length > 0 ? items.map((item) => `- ${item}`) : [empty2];
553320
+ }
553321
+ function formatEvidenceEntry(entry) {
553322
+ const parts = [
553323
+ entry.success === true ? "ok" : entry.success === false ? "failed" : "unknown",
553324
+ entry.name ? `tool=${clip2(entry.name, 80)}` : "",
553325
+ typeof entry.turn === "number" ? `turn=${entry.turn}` : "",
553326
+ entry.mutated ? "mutated=true" : "",
553327
+ entry.argsKey ? `args=${clip2(entry.argsKey, 180)}` : "",
553328
+ entry.outputPreview ? `observed=${clip2(entry.outputPreview, 260)}` : ""
553329
+ ].filter(Boolean);
553330
+ return parts.join(" ");
553331
+ }
553332
+ function deriveScenarioSeed(input) {
553333
+ const text2 = [
553334
+ input.taskText,
553335
+ input.contract.goalSummary,
553336
+ input.proposedSummary,
553337
+ input.answerText
553338
+ ].map((part) => String(part ?? "").trim()).filter(Boolean).join("\n");
553339
+ const normalized = normalizeCompletionKey(text2.slice(0, 140), "completion_scenario");
553340
+ return normalized || "completion_scenario";
553341
+ }
553342
+ function buildCompletionScenarioDecomposition(input) {
553343
+ const proposedClaimText = [
553344
+ input.proposedSummary ? `task_complete summary:
553345
+ ${String(input.proposedSummary).trim()}` : "",
553346
+ input.answerText ? `assistant visible answer:
553347
+ ${String(input.answerText).trim()}` : ""
553348
+ ].filter(Boolean).join("\n\n").slice(0, 4e3);
553349
+ const observedEvidence = (input.log ?? []).slice(-40).map(formatEvidenceEntry);
553350
+ const unresolvedSignals = [
553351
+ ...(input.openLoops ?? []).map((item) => `open loop: ${clip2(item, 260)}`),
553352
+ ...(input.recentFailures ?? []).map((item) => `recent failure: ${clip2(item, 260)}`),
553353
+ ...(input.planStatus ?? []).filter((item) => item.status || item.reconciled || item.rationale).map((item) => {
553354
+ const state = [item.status, item.reconciled].filter(Boolean).join("/");
553355
+ const suffix = item.rationale ? ` (${clip2(item.rationale, 180)})` : "";
553356
+ return `plan ${state || "observed"}: ${clip2(item.content, 220)}${suffix}`;
553357
+ })
553358
+ ];
553359
+ const modifiedFiles = (input.modifiedFiles ?? []).slice(0, 30).map((file) => {
553360
+ const meta = [
553361
+ file.status ? `status=${clip2(file.status, 40)}` : "",
553362
+ typeof file.bytes === "number" ? `bytes=${file.bytes}` : ""
553363
+ ].filter(Boolean).join(" ");
553364
+ return `${clip2(file.path, 220)}${meta ? ` (${meta})` : ""}`;
553365
+ });
553366
+ const scenarioSeed = deriveScenarioSeed(input);
553367
+ const lines = [];
553368
+ lines.push(`[COMPLETION META-DECOMPOSITION]`);
553369
+ lines.push(`Scenario seed: ${scenarioSeed}`);
553370
+ lines.push(``);
553371
+ lines.push(`Original request / goal text:`);
553372
+ lines.push(clip2(input.taskText || input.contract.goalSummary, 1200) || "(not provided)");
553373
+ lines.push(``);
553374
+ lines.push(`Proposed completion claim text:`);
553375
+ lines.push(proposedClaimText || "(no proposed completion text yet)");
553376
+ lines.push(``);
553377
+ lines.push(`Observed run evidence:`);
553378
+ lines.push(...listLines(observedEvidence, "- no tool evidence recorded"));
553379
+ lines.push(``);
553380
+ lines.push(`Unresolved or caution signals:`);
553381
+ lines.push(...listLines(unresolvedSignals, "- none recorded"));
553382
+ lines.push(``);
553383
+ lines.push(`Modified artifact digest:`);
553384
+ lines.push(...listLines(modifiedFiles, "- no modified artifacts listed"));
553385
+ lines.push(``);
553386
+ lines.push(`Reviewer decomposition task:`);
553387
+ lines.push(`- Invent a situation-specific completion scenario from the request, proposed claims, and observed run data above.`);
553388
+ lines.push(`- Enumerate the material claims in the proposed completion text, including implied claims about created state, external effects, recipient-visible outcomes, runtime behavior, research facts, or absence of blockers when those claims appear in the text.`);
553389
+ lines.push(`- For each claim, derive what would make it true from the claim's semantics, the user's request, and this run's observations.`);
553390
+ lines.push(`- Map the claim to the observed evidence, contradictions, missing observations, and unresolved loops shown above.`);
553391
+ lines.push(`- If an unsupported claim is material, propose the smallest next observation or correction; if the final wording already marks it unverified or blocked, treat that honesty as part of the evidence review.`);
553392
+ return {
553393
+ scenarioSeed,
553394
+ prompt: lines.join("\n"),
553395
+ proposedClaimText,
553396
+ observedEvidence,
553397
+ unresolvedSignals
553398
+ };
553399
+ }
553400
+ function formatCompletionContract(contract, scenario) {
553401
+ const lines = [];
553402
+ lines.push(`[COMPLETION CONTRACT]`);
553403
+ lines.push(`Goal: ${contract.goalSummary || "(no goal text)"}`);
553404
+ lines.push(``);
553405
+ lines.push(`Completion review policy:`);
553406
+ lines.push(`- Derive material claims from the current request and proposed final answer.`);
553407
+ lines.push(`- Compare those claims to observed tool results from this run.`);
553408
+ lines.push(`- Treat missing, ambiguous, or failed observations as unverified rather than complete.`);
553409
+ lines.push(`- Use the current request, proposed claims, and recorded observations as the source of truth.`);
553410
+ lines.push(``);
553411
+ lines.push(`Flow: execute -> scenario decomposition -> evidence review -> delivery readback.`);
553412
+ if (scenario) {
553413
+ lines.push(``);
553414
+ lines.push(buildCompletionScenarioDecomposition({ contract, ...scenario }).prompt);
553415
+ }
553416
+ return lines.join("\n");
553417
+ }
553418
+ var init_completionContract = __esm({
553419
+ "packages/orchestrator/dist/completionContract.js"() {
553420
+ "use strict";
553421
+ }
553422
+ });
553423
+
553424
+ // packages/orchestrator/dist/completionLedger.js
553425
+ import { mkdirSync as mkdirSync44, readFileSync as readFileSync59, writeFileSync as writeFileSync38 } from "node:fs";
553426
+ import { dirname as dirname26 } from "node:path";
553427
+ function nowIso2(now = /* @__PURE__ */ new Date()) {
553428
+ return now instanceof Date ? now.toISOString() : new Date(now).toISOString();
553429
+ }
553430
+ function cleanText(value2, max = 600) {
553431
+ return String(value2 ?? "").replace(/\s+/g, " ").trim().slice(0, max);
553432
+ }
553433
+ function nextId2(prefix, count) {
553434
+ return `${prefix}_${String(count + 1).padStart(4, "0")}`;
553435
+ }
553436
+ function createCompletionLedger(input) {
553437
+ const ts = nowIso2(input.now);
553438
+ return {
553439
+ runId: input.runId,
553440
+ goal: cleanText(input.goal, 2e3),
553441
+ createdAtIso: ts,
553442
+ updatedAtIso: ts,
553443
+ proposedClaims: [],
553444
+ evidence: [],
553445
+ critiques: [],
553446
+ unresolved: [],
553447
+ status: "open"
553448
+ };
553449
+ }
553450
+ function deriveClaimsFromProposedText(input) {
553451
+ const raw = String(input.text ?? "").trim();
553452
+ if (!raw)
553453
+ return [];
553454
+ const segments = raw.replace(/\b(?:done|completed|verified)\s*:\s*/gi, "").split(/(?:\n+|;\s+|,\s+(?=(?:and\s+)?(?:sent|built|created|updated|published|verified|tested|fixed|added|removed|deployed|wrote)\b)|\.\s+)/i).map((part) => cleanText(part, 300)).filter((part) => part.length > 0);
553455
+ const unique2 = Array.from(new Set(segments.length > 0 ? segments : [cleanText(raw, 300)]));
553456
+ const existingIds = new Set((input.existing ?? []).map((claim) => claim.id));
553457
+ return unique2.map((text2, index) => {
553458
+ const base3 = normalizeCompletionKey(text2, `claim_${index + 1}`).slice(0, 64);
553459
+ let id = base3 || `claim_${index + 1}`;
553460
+ let suffix = 2;
553461
+ while (existingIds.has(id)) {
553462
+ id = `${base3}_${suffix++}`;
553463
+ }
553464
+ existingIds.add(id);
553465
+ return {
553466
+ id,
553467
+ text: text2,
553468
+ source: input.source,
553469
+ materiality: "high",
553470
+ evidenceRequirement: "Observed evidence from this run supports the claim or the final response marks it unverified/blocked.",
553471
+ evidenceIds: [],
553472
+ status: "unverified"
553473
+ };
553474
+ });
553475
+ }
553476
+ function recordCompletionEvidence(ledger, evidence) {
553477
+ const entry = {
553478
+ id: evidence.id ?? nextId2("ev", ledger.evidence.length),
553479
+ kind: evidence.kind,
553480
+ observedAtIso: evidence.observedAtIso ?? nowIso2(),
553481
+ summary: cleanText(evidence.summary, 1200),
553482
+ toolName: evidence.toolName,
553483
+ success: evidence.success,
553484
+ rawRef: evidence.rawRef
553485
+ };
553486
+ return {
553487
+ ...ledger,
553488
+ evidence: [...ledger.evidence, entry],
553489
+ updatedAtIso: entry.observedAtIso
553490
+ };
553491
+ }
553492
+ function recordToolEvidence(ledger, input) {
553493
+ const summary = [
553494
+ input.name,
553495
+ input.success === true ? "succeeded" : input.success === false ? "failed" : "observed",
553496
+ input.argsKey ? `args=${cleanText(input.argsKey, 180)}` : "",
553497
+ input.outputPreview ? `output=${cleanText(input.outputPreview, 700)}` : ""
553498
+ ].filter(Boolean).join(" ");
553499
+ return recordCompletionEvidence(ledger, {
553500
+ kind: "tool_result",
553501
+ toolName: input.name,
553502
+ success: input.success,
553503
+ summary,
553504
+ rawRef: input.rawRef
553505
+ });
553506
+ }
553507
+ function addCompletionClaims(ledger, claims) {
553508
+ const byId = new Map(ledger.proposedClaims.map((claim) => [claim.id, claim]));
553509
+ for (const claim of claims)
553510
+ byId.set(claim.id, claim);
553511
+ return {
553512
+ ...ledger,
553513
+ proposedClaims: Array.from(byId.values()),
553514
+ updatedAtIso: nowIso2()
553515
+ };
553516
+ }
553517
+ function reconcileClaimsWithEvidence(ledger) {
553518
+ const successfulEvidence = ledger.evidence.filter((entry) => entry.success !== false);
553519
+ const failedEvidence = ledger.evidence.filter((entry) => entry.success === false);
553520
+ const claims = ledger.proposedClaims.map((claim) => {
553521
+ const claimTerms = cleanText(claim.text, 300).toLowerCase().split(/[^a-z0-9]+/).filter((part) => part.length >= 4);
553522
+ const matches = successfulEvidence.filter((entry) => {
553523
+ const haystack = `${entry.toolName ?? ""} ${entry.summary}`.toLowerCase();
553524
+ return claimTerms.some((term) => haystack.includes(term));
553525
+ });
553526
+ const contradictions = failedEvidence.filter((entry) => {
553527
+ const haystack = `${entry.toolName ?? ""} ${entry.summary}`.toLowerCase();
553528
+ return claimTerms.some((term) => haystack.includes(term));
553529
+ });
553530
+ if (contradictions.length > 0 && matches.length === 0) {
553531
+ return { ...claim, evidenceIds: contradictions.map((entry) => entry.id), status: "contradicted" };
553532
+ }
553533
+ if (matches.length > 0) {
553534
+ return { ...claim, evidenceIds: matches.map((entry) => entry.id), status: "supported" };
553535
+ }
553536
+ return { ...claim, evidenceIds: [], status: "unverified" };
553537
+ });
553538
+ return {
553539
+ ...ledger,
553540
+ proposedClaims: claims,
553541
+ updatedAtIso: nowIso2()
553542
+ };
553543
+ }
553544
+ function recordCompletionCritique(ledger, input) {
553545
+ const critique = {
553546
+ id: input.id ?? nextId2("critique", ledger.critiques.length),
553547
+ verdict: input.verdict,
553548
+ rationale: cleanText(input.rationale, 1200),
553549
+ feedback: input.feedback ? cleanText(input.feedback, 3e3) : void 0,
553550
+ recordedAtIso: input.recordedAtIso ?? nowIso2(),
553551
+ evidenceSequence: ledger.evidence.length
553552
+ };
553553
+ return {
553554
+ ...ledger,
553555
+ critiques: [...ledger.critiques, critique],
553556
+ status: input.verdict === "approve" ? "approved" : input.verdict,
553557
+ updatedAtIso: critique.recordedAtIso
553558
+ };
553559
+ }
553560
+ function buildCriticPacketFromLedger(ledger) {
553561
+ const latestCritique = ledger.critiques.at(-1);
553562
+ const evidenceSinceCritique = latestCritique ? ledger.evidence.slice(latestCritique.evidenceSequence) : [];
553563
+ const lines = [];
553564
+ lines.push("[COMPLETION LEDGER]");
553565
+ lines.push(`Run: ${ledger.runId}`);
553566
+ lines.push(`Goal: ${ledger.goal || "(not recorded)"}`);
553567
+ lines.push(`Status: ${ledger.status}`);
553568
+ lines.push("");
553569
+ lines.push("Claims:");
553570
+ if (ledger.proposedClaims.length === 0)
553571
+ lines.push("- none recorded");
553572
+ for (const claim of ledger.proposedClaims) {
553573
+ lines.push(`- [${claim.status}] ${claim.id}: ${claim.text}`);
553574
+ lines.push(` evidence: ${claim.evidenceIds.length > 0 ? claim.evidenceIds.join(", ") : "none"}`);
553575
+ lines.push(` requirement: ${claim.evidenceRequirement}`);
553576
+ }
553577
+ lines.push("");
553578
+ lines.push("Evidence:");
553579
+ if (ledger.evidence.length === 0)
553580
+ lines.push("- none recorded");
553581
+ for (const evidence of ledger.evidence.slice(-40)) {
553582
+ const status = evidence.success === true ? "ok" : evidence.success === false ? "failed" : "unknown";
553583
+ lines.push(`- ${evidence.id} [${status}] ${evidence.kind}${evidence.toolName ? `/${evidence.toolName}` : ""}: ${evidence.summary}`);
553584
+ }
553585
+ if (latestCritique) {
553586
+ lines.push("");
553587
+ lines.push("Prior critique:");
553588
+ lines.push(`- verdict: ${latestCritique.verdict}`);
553589
+ lines.push(`- rationale: ${latestCritique.rationale}`);
553590
+ if (latestCritique.feedback)
553591
+ lines.push(`- feedback: ${latestCritique.feedback}`);
553592
+ lines.push("");
553593
+ lines.push("Evidence recorded after prior critique:");
553594
+ if (evidenceSinceCritique.length === 0)
553595
+ lines.push("- none recorded");
553596
+ for (const evidence of evidenceSinceCritique) {
553597
+ const status = evidence.success === true ? "ok" : evidence.success === false ? "failed" : "unknown";
553598
+ lines.push(`- ${evidence.id} [${status}] ${evidence.summary}`);
553599
+ }
553600
+ }
553601
+ if (ledger.unresolved.length > 0) {
553602
+ lines.push("");
553603
+ lines.push("Unresolved:");
553604
+ for (const item of ledger.unresolved.slice(-20))
553605
+ lines.push(`- ${item.text}`);
553606
+ }
553607
+ return lines.join("\n");
553608
+ }
553609
+ function saveCompletionLedger(filePath, ledger) {
553610
+ mkdirSync44(dirname26(filePath), { recursive: true });
553611
+ writeFileSync38(filePath, `${JSON.stringify(ledger, null, 2)}
553612
+ `, "utf8");
553613
+ }
553614
+ function loadCompletionLedger(filePath) {
553615
+ return JSON.parse(readFileSync59(filePath, "utf8"));
553616
+ }
553617
+ var init_completionLedger = __esm({
553618
+ "packages/orchestrator/dist/completionLedger.js"() {
553619
+ "use strict";
553620
+ init_completionContract();
553621
+ }
553622
+ });
553623
+
553164
553624
  // packages/orchestrator/dist/ollama-pool-cleanup.js
553165
553625
  var ollama_pool_cleanup_exports = {};
553166
553626
  __export(ollama_pool_cleanup_exports, {
@@ -553820,7 +554280,7 @@ var init_ollama_pool_cleanup = __esm({
553820
554280
 
553821
554281
  // packages/orchestrator/dist/ollama-pool.js
553822
554282
  import { spawn as spawn23, exec as exec2 } from "node:child_process";
553823
- import { existsSync as existsSync76, readFileSync as readFileSync59, readdirSync as readdirSync23, statfsSync as statfsSync3, statSync as statSync29 } from "node:fs";
554283
+ import { existsSync as existsSync76, readFileSync as readFileSync60, readdirSync as readdirSync23, statfsSync as statfsSync3, statSync as statSync29 } from "node:fs";
553824
554284
  import { homedir as homedir29 } from "node:os";
553825
554285
  import { join as join89 } from "node:path";
553826
554286
  import { createServer as createServer3 } from "node:net";
@@ -553870,7 +554330,7 @@ function listOllamaPids() {
553870
554330
  try {
553871
554331
  return readdirSync23("/proc", { withFileTypes: true }).filter((d2) => d2.isDirectory() && /^\d+$/.test(d2.name)).map((d2) => d2.name).filter((pid) => {
553872
554332
  try {
553873
- const comm = readFileSync59(`/proc/${pid}/comm`, "utf8").trim();
554333
+ const comm = readFileSync60(`/proc/${pid}/comm`, "utf8").trim();
553874
554334
  return comm === "ollama";
553875
554335
  } catch {
553876
554336
  return false;
@@ -553882,7 +554342,7 @@ function listOllamaPids() {
553882
554342
  }
553883
554343
  function readProcEnvValue(pid, key) {
553884
554344
  try {
553885
- const raw = readFileSync59(`/proc/${pid}/environ`, "utf8");
554345
+ const raw = readFileSync60(`/proc/${pid}/environ`, "utf8");
553886
554346
  for (const entry of raw.split("\0")) {
553887
554347
  const idx = entry.indexOf("=");
553888
554348
  if (idx <= 0)
@@ -553898,11 +554358,11 @@ function readProcEnvValue(pid, key) {
553898
554358
  }
553899
554359
  function inferHomeFromProcUid(pid) {
553900
554360
  try {
553901
- const status = readFileSync59(`/proc/${pid}/status`, "utf8");
554361
+ const status = readFileSync60(`/proc/${pid}/status`, "utf8");
553902
554362
  const uid = status.match(/^Uid:\s+(\d+)/m)?.[1];
553903
554363
  if (!uid)
553904
554364
  return null;
553905
- const passwd = readFileSync59("/etc/passwd", "utf8");
554365
+ const passwd = readFileSync60("/etc/passwd", "utf8");
553906
554366
  for (const line of passwd.split("\n")) {
553907
554367
  const parts = line.split(":");
553908
554368
  if (parts.length >= 7 && parts[2] === uid)
@@ -553928,7 +554388,7 @@ function detectPeerOmniusOllamaPool() {
553928
554388
  if (e2.name === selfPid || e2.name === selfPpid)
553929
554389
  continue;
553930
554390
  try {
553931
- const cmdline = readFileSync59(`/proc/${e2.name}/cmdline`, "utf8");
554391
+ const cmdline = readFileSync60(`/proc/${e2.name}/cmdline`, "utf8");
553932
554392
  if (!cmdline.includes("node"))
553933
554393
  continue;
553934
554394
  if (!/[/\\]omnius[/\\]dist[/\\]index\.js|[/\\]omnius[/\\]/i.test(cmdline))
@@ -553941,12 +554401,12 @@ function detectPeerOmniusOllamaPool() {
553941
554401
  return false;
553942
554402
  for (const e2 of entries) {
553943
554403
  try {
553944
- const cmd = readFileSync59(`/proc/${e2.name}/cmdline`, "utf8");
554404
+ const cmd = readFileSync60(`/proc/${e2.name}/cmdline`, "utf8");
553945
554405
  if (!cmd.includes("ollama"))
553946
554406
  continue;
553947
554407
  if (!cmd.split("\0").includes("serve"))
553948
554408
  continue;
553949
- const status = readFileSync59(`/proc/${e2.name}/status`, "utf8");
554409
+ const status = readFileSync60(`/proc/${e2.name}/status`, "utf8");
553950
554410
  const ppid = status.match(/^PPid:\s+(\d+)/m)?.[1];
553951
554411
  if (ppid && peerNodePids.has(ppid))
553952
554412
  return true;
@@ -554077,7 +554537,7 @@ function snapshotDisk(path12) {
554077
554537
  }
554078
554538
  function snapshotNetwork() {
554079
554539
  try {
554080
- const raw = readFileSync59("/proc/net/dev", "utf8");
554540
+ const raw = readFileSync60("/proc/net/dev", "utf8");
554081
554541
  let rxBytes = 0;
554082
554542
  let txBytes = 0;
554083
554543
  for (const line of raw.split("\n")) {
@@ -555627,8 +556087,8 @@ var init_artifact_inspector = __esm({
555627
556087
  });
555628
556088
 
555629
556089
  // packages/orchestrator/dist/lesson-bank.js
555630
- import { existsSync as existsSync78, mkdirSync as mkdirSync44, appendFileSync as appendFileSync4, readFileSync as readFileSync60 } from "node:fs";
555631
- import { join as join90, dirname as dirname26 } from "node:path";
556090
+ import { existsSync as existsSync78, mkdirSync as mkdirSync45, appendFileSync as appendFileSync4, readFileSync as readFileSync61 } from "node:fs";
556091
+ import { join as join90, dirname as dirname27 } from "node:path";
555632
556092
  import { createHash as createHash25 } from "node:crypto";
555633
556093
  function tokenize4(text2) {
555634
556094
  if (!text2)
@@ -555665,7 +556125,7 @@ function lessonBankPath(workingDir) {
555665
556125
  }
555666
556126
  function bank(lesson, workingDir) {
555667
556127
  const path12 = lessonBankPath(workingDir);
555668
- mkdirSync44(dirname26(path12), { recursive: true });
556128
+ mkdirSync45(dirname27(path12), { recursive: true });
555669
556129
  appendFileSync4(path12, JSON.stringify(lesson) + "\n", "utf-8");
555670
556130
  }
555671
556131
  function readAll(workingDir) {
@@ -555673,7 +556133,7 @@ function readAll(workingDir) {
555673
556133
  if (!existsSync78(path12))
555674
556134
  return [];
555675
556135
  try {
555676
- const raw = readFileSync60(path12, "utf-8");
556136
+ const raw = readFileSync61(path12, "utf-8");
555677
556137
  const out = [];
555678
556138
  for (const line of raw.split(/\r?\n/)) {
555679
556139
  const trimmed = line.trim();
@@ -555730,8 +556190,8 @@ var init_lesson_bank = __esm({
555730
556190
  });
555731
556191
 
555732
556192
  // packages/orchestrator/dist/intervention-replay.js
555733
- import { existsSync as existsSync79, mkdirSync as mkdirSync45, readFileSync as readFileSync61, writeFileSync as writeFileSync38, readdirSync as readdirSync24 } from "node:fs";
555734
- import { join as join91, dirname as dirname27 } from "node:path";
556193
+ import { existsSync as existsSync79, mkdirSync as mkdirSync46, readFileSync as readFileSync62, writeFileSync as writeFileSync39, readdirSync as readdirSync24 } from "node:fs";
556194
+ import { join as join91, dirname as dirname28 } from "node:path";
555735
556195
  function checkpointDir2(workingDir) {
555736
556196
  return workingDir ? join91(workingDir, ".omnius", "checkpoints") : join91(process.env["HOME"] || ".", ".omnius", "checkpoints");
555737
556197
  }
@@ -555748,8 +556208,8 @@ function writeCheckpoint(args) {
555748
556208
  notes: args.notes
555749
556209
  };
555750
556210
  const path12 = checkpointPath(args.workingDir, args.turn);
555751
- mkdirSync45(dirname27(path12), { recursive: true });
555752
- writeFileSync38(path12, JSON.stringify(snap), "utf-8");
556211
+ mkdirSync46(dirname28(path12), { recursive: true });
556212
+ writeFileSync39(path12, JSON.stringify(snap), "utf-8");
555753
556213
  } catch {
555754
556214
  }
555755
556215
  }
@@ -555789,13 +556249,13 @@ var init_intervention_replay = __esm({
555789
556249
  });
555790
556250
 
555791
556251
  // packages/orchestrator/dist/world-state-disk-scan.js
555792
- import { existsSync as existsSync80, readFileSync as readFileSync62, readdirSync as readdirSync25, statSync as statSync31 } from "node:fs";
556252
+ import { existsSync as existsSync80, readFileSync as readFileSync63, readdirSync as readdirSync25, statSync as statSync31 } from "node:fs";
555793
556253
  import { join as join92, relative as relative8, basename as basename20 } from "node:path";
555794
556254
  function loadIgnoreFile(path12) {
555795
556255
  if (!existsSync80(path12))
555796
556256
  return [];
555797
556257
  try {
555798
- const lines = readFileSync62(path12, "utf-8").split(/\r?\n/);
556258
+ const lines = readFileSync63(path12, "utf-8").split(/\r?\n/);
555799
556259
  const out = [];
555800
556260
  for (const raw of lines) {
555801
556261
  const line = raw.trim();
@@ -556145,8 +556605,8 @@ var init_world_state_plan_reconciler = __esm({
556145
556605
  });
556146
556606
 
556147
556607
  // packages/orchestrator/dist/world-state-drift-detector.js
556148
- import { existsSync as existsSync82, readFileSync as readFileSync63, statSync as statSync33 } from "node:fs";
556149
- import { dirname as dirname28, isAbsolute as isAbsolute7, join as join94, resolve as pathResolve } from "node:path";
556608
+ import { existsSync as existsSync82, readFileSync as readFileSync64, statSync as statSync33 } from "node:fs";
556609
+ import { dirname as dirname29, isAbsolute as isAbsolute7, join as join94, resolve as pathResolve } from "node:path";
556150
556610
  function parseImports(source) {
556151
556611
  const out = [];
556152
556612
  const lines = source.split(/\r?\n/);
@@ -556303,7 +556763,7 @@ function loadProjectAliases(workingDir) {
556303
556763
  if (!existsSync82(path12))
556304
556764
  continue;
556305
556765
  try {
556306
- const raw = readFileSync63(path12, "utf-8");
556766
+ const raw = readFileSync64(path12, "utf-8");
556307
556767
  const parsed = JSON.parse(stripJsonComments(raw));
556308
556768
  const co = parsed?.compilerOptions;
556309
556769
  const paths = co?.paths;
@@ -556344,7 +556804,7 @@ function resolveImportPath2(importingFile, source, workingDir, aliases) {
556344
556804
  }
556345
556805
  if (bestAlias)
556346
556806
  resolvedSpec = aliases[bestAlias] + source.slice(bestAlias.length);
556347
- const importerDir = dirname28(importingFile);
556807
+ const importerDir = dirname29(importingFile);
556348
556808
  const base3 = resolvedSpec.startsWith(".") ? pathResolve(importerDir, resolvedSpec) : resolvedSpec.startsWith("/") ? resolvedSpec : pathResolve(workingDir, resolvedSpec);
556349
556809
  const candidates = [];
556350
556810
  for (const ext of FILE_EXTENSIONS)
@@ -556392,7 +556852,7 @@ function detectDrift(files, opts) {
556392
556852
  const exportsCache = /* @__PURE__ */ new Map();
556393
556853
  const readSource = (path12) => {
556394
556854
  try {
556395
- const buf = readFileSync63(path12);
556855
+ const buf = readFileSync64(path12);
556396
556856
  if (buf.length > maxBytes)
556397
556857
  return buf.slice(0, maxBytes).toString("utf-8");
556398
556858
  return buf.toString("utf-8");
@@ -556806,6 +557266,11 @@ function renderCriticPrompt(inputs) {
556806
557266
  }
556807
557267
  lines.push(``);
556808
557268
  }
557269
+ if (inputs.workboardSynthesisContext && inputs.workboardSynthesisContext.trim().length > 0) {
557270
+ lines.push(`## Workboard synthesis context (multi-agent board)`);
557271
+ lines.push(inputs.workboardSynthesisContext.trim().slice(0, 3e3));
557272
+ lines.push(``);
557273
+ }
556809
557274
  lines.push(`## Files modified (${inputs.diff.length} total)`);
556810
557275
  if (inputs.diff.length === 0) {
556811
557276
  lines.push(`(no file changes detected — this run produced no on-disk artifacts)`);
@@ -557002,7 +557467,7 @@ var init_backward_pass_critic = __esm({
557002
557467
  });
557003
557468
 
557004
557469
  // packages/orchestrator/dist/backward-pass-runner.js
557005
- import { existsSync as existsSync83, readFileSync as readFileSync64, statSync as statSync34 } from "node:fs";
557470
+ import { existsSync as existsSync83, readFileSync as readFileSync65, statSync as statSync34 } from "node:fs";
557006
557471
  import { execSync as execSync45 } from "node:child_process";
557007
557472
  import { isAbsolute as isAbsolute8, join as join95, relative as relative9 } from "node:path";
557008
557473
  function collectDiff(opts) {
@@ -557062,7 +557527,7 @@ function collectDiff(opts) {
557062
557527
  }
557063
557528
  function readPreview(absPath, maxBytes) {
557064
557529
  try {
557065
- const buf = readFileSync64(absPath);
557530
+ const buf = readFileSync65(absPath);
557066
557531
  if (buf.length === 0)
557067
557532
  return "";
557068
557533
  const sniff = buf.slice(0, Math.min(8192, buf.length));
@@ -557106,7 +557571,8 @@ async function runBackwardPass(opts) {
557106
557571
  openLoops: opts.openLoops,
557107
557572
  systemPromptDigest: opts.systemPromptDigest,
557108
557573
  cycle: opts.cycle,
557109
- maxCycles: opts.maxCycles
557574
+ maxCycles: opts.maxCycles,
557575
+ workboardSynthesisContext: opts.workboardSynthesisContext
557110
557576
  };
557111
557577
  const prompt = renderCriticPrompt(inputs);
557112
557578
  const promptBytes = Buffer.byteLength(prompt, "utf-8");
@@ -559162,7 +559628,7 @@ var init_hooks = __esm({
559162
559628
  });
559163
559629
 
559164
559630
  // packages/orchestrator/dist/todo-context-chunker.js
559165
- import { mkdirSync as mkdirSync48, writeFileSync as writeFileSync41, readFileSync as readFileSync67, existsSync as existsSync86, readdirSync as readdirSync26 } from "node:fs";
559631
+ import { mkdirSync as mkdirSync49, writeFileSync as writeFileSync42, readFileSync as readFileSync68, existsSync as existsSync86, readdirSync as readdirSync26 } from "node:fs";
559166
559632
  import { join as join98 } from "node:path";
559167
559633
  function chunkDir(workingDir) {
559168
559634
  return join98(workingDir, ".omnius", "todo-chunks");
@@ -559378,16 +559844,16 @@ async function runTodoChunker(opts) {
559378
559844
  function persistTodoChunk(workingDir, chunk) {
559379
559845
  const dir = chunkDir(workingDir);
559380
559846
  if (!existsSync86(dir)) {
559381
- mkdirSync48(dir, { recursive: true });
559847
+ mkdirSync49(dir, { recursive: true });
559382
559848
  }
559383
- writeFileSync41(chunkPath(workingDir, chunk.todoId), JSON.stringify(chunk, null, 2), "utf-8");
559849
+ writeFileSync42(chunkPath(workingDir, chunk.todoId), JSON.stringify(chunk, null, 2), "utf-8");
559384
559850
  }
559385
559851
  function loadTodoChunk(workingDir, todoId) {
559386
559852
  const p2 = chunkPath(workingDir, todoId);
559387
559853
  if (!existsSync86(p2))
559388
559854
  return null;
559389
559855
  try {
559390
- return JSON.parse(readFileSync67(p2, "utf-8"));
559856
+ return JSON.parse(readFileSync68(p2, "utf-8"));
559391
559857
  } catch {
559392
559858
  return null;
559393
559859
  }
@@ -559952,191 +560418,6 @@ var init_specDecomposer = __esm({
559952
560418
  }
559953
560419
  });
559954
560420
 
559955
- // packages/orchestrator/dist/completionContract.js
559956
- function normalizeText(value2, max = 500) {
559957
- const text2 = String(value2 ?? "").trim().replace(/\s+/g, " ");
559958
- return text2 ? text2.slice(0, max) : "";
559959
- }
559960
- function normalizeCompletionKey(value2, fallback = "item") {
559961
- const key = String(value2 ?? fallback).trim().toLowerCase().replace(/[^a-z0-9_.:-]+/g, "_").replace(/_{2,}/g, "_").replace(/^[_:.-]+|[_:.-]+$/g, "").slice(0, 96);
559962
- return key || fallback;
559963
- }
559964
- function genericField(key, label, description, acceptanceCriteria) {
559965
- return {
559966
- key: normalizeCompletionKey(key),
559967
- label,
559968
- fieldType: "json",
559969
- elevation: "required",
559970
- sourceMode: "derived",
559971
- description,
559972
- acceptanceCriteria
559973
- };
559974
- }
559975
- function inferCompletionContract(taskText) {
559976
- const goalSummary = normalizeText(taskText);
559977
- const fields = [
559978
- genericField("claims.evidence_map", "Claim evidence map", "A run-local mapping from each final claim to the observed result that supports it.", "Each material claim is either backed by observed evidence from this run or named as unverified/blocked."),
559979
- genericField("claims.unverified", "Unverified claims", "Claims that could not be proven from the run's observations.", "Unverified claims are not presented as completed work.")
559980
- ];
559981
- const phases = [
559982
- {
559983
- key: "execute",
559984
- label: "Execute",
559985
- instructions: "Do the requested work while preserving observations needed to evaluate the result.",
559986
- requirementIds: [],
559987
- fields: [],
559988
- gate: {
559989
- key: "execution_trace",
559990
- instructions: "Keep enough concrete run output to distinguish facts from assumptions."
559991
- }
559992
- },
559993
- {
559994
- key: "verify",
559995
- label: "Verify",
559996
- instructions: "Derive the needed evidence from the actual request and final claims, then compare those claims to observed results.",
559997
- requirementIds: [],
559998
- fields,
559999
- gate: {
560000
- key: "claim_evidence_review",
560001
- instructions: "Judge whether the actual claim is supported by the actual observations."
560002
- }
560003
- },
560004
- {
560005
- key: "deliver",
560006
- label: "Deliver",
560007
- instructions: "Report completed, verified, unverified, and blocked items without overstating what was observed.",
560008
- requirementIds: [],
560009
- fields: [],
560010
- gate: {
560011
- key: "result_readback",
560012
- instructions: "Final wording must not exceed the observed evidence."
560013
- }
560014
- }
560015
- ];
560016
- return {
560017
- goalSummary,
560018
- surfaces: [],
560019
- fields,
560020
- requirements: [],
560021
- phases,
560022
- acceptanceCriteria: [
560023
- "The final response distinguishes completed work from verified evidence and unverified or blocked claims."
560024
- ]
560025
- };
560026
- }
560027
- function inferCompletionContractFromTexts(texts, fallbackSummary = "") {
560028
- const combined = texts.map((text2) => String(text2 ?? "").trim()).filter(Boolean).join("\n\n");
560029
- return inferCompletionContract(combined || fallbackSummary);
560030
- }
560031
- function clip2(value2, max = 500) {
560032
- return normalizeText(value2, max);
560033
- }
560034
- function listLines(items, empty2 = "- none observed") {
560035
- return items.length > 0 ? items.map((item) => `- ${item}`) : [empty2];
560036
- }
560037
- function formatEvidenceEntry(entry) {
560038
- const parts = [
560039
- entry.success === true ? "ok" : entry.success === false ? "failed" : "unknown",
560040
- entry.name ? `tool=${clip2(entry.name, 80)}` : "",
560041
- typeof entry.turn === "number" ? `turn=${entry.turn}` : "",
560042
- entry.mutated ? "mutated=true" : "",
560043
- entry.argsKey ? `args=${clip2(entry.argsKey, 180)}` : "",
560044
- entry.outputPreview ? `observed=${clip2(entry.outputPreview, 260)}` : ""
560045
- ].filter(Boolean);
560046
- return parts.join(" ");
560047
- }
560048
- function deriveScenarioSeed(input) {
560049
- const text2 = [
560050
- input.taskText,
560051
- input.contract.goalSummary,
560052
- input.proposedSummary,
560053
- input.answerText
560054
- ].map((part) => String(part ?? "").trim()).filter(Boolean).join("\n");
560055
- const normalized = normalizeCompletionKey(text2.slice(0, 140), "completion_scenario");
560056
- return normalized || "completion_scenario";
560057
- }
560058
- function buildCompletionScenarioDecomposition(input) {
560059
- const proposedClaimText = [
560060
- input.proposedSummary ? `task_complete summary:
560061
- ${String(input.proposedSummary).trim()}` : "",
560062
- input.answerText ? `assistant visible answer:
560063
- ${String(input.answerText).trim()}` : ""
560064
- ].filter(Boolean).join("\n\n").slice(0, 4e3);
560065
- const observedEvidence = (input.log ?? []).slice(-40).map(formatEvidenceEntry);
560066
- const unresolvedSignals = [
560067
- ...(input.openLoops ?? []).map((item) => `open loop: ${clip2(item, 260)}`),
560068
- ...(input.recentFailures ?? []).map((item) => `recent failure: ${clip2(item, 260)}`),
560069
- ...(input.planStatus ?? []).filter((item) => item.status || item.reconciled || item.rationale).map((item) => {
560070
- const state = [item.status, item.reconciled].filter(Boolean).join("/");
560071
- const suffix = item.rationale ? ` (${clip2(item.rationale, 180)})` : "";
560072
- return `plan ${state || "observed"}: ${clip2(item.content, 220)}${suffix}`;
560073
- })
560074
- ];
560075
- const modifiedFiles = (input.modifiedFiles ?? []).slice(0, 30).map((file) => {
560076
- const meta = [
560077
- file.status ? `status=${clip2(file.status, 40)}` : "",
560078
- typeof file.bytes === "number" ? `bytes=${file.bytes}` : ""
560079
- ].filter(Boolean).join(" ");
560080
- return `${clip2(file.path, 220)}${meta ? ` (${meta})` : ""}`;
560081
- });
560082
- const scenarioSeed = deriveScenarioSeed(input);
560083
- const lines = [];
560084
- lines.push(`[COMPLETION META-DECOMPOSITION]`);
560085
- lines.push(`Scenario seed: ${scenarioSeed}`);
560086
- lines.push(``);
560087
- lines.push(`Original request / goal text:`);
560088
- lines.push(clip2(input.taskText || input.contract.goalSummary, 1200) || "(not provided)");
560089
- lines.push(``);
560090
- lines.push(`Proposed completion claim text:`);
560091
- lines.push(proposedClaimText || "(no proposed completion text yet)");
560092
- lines.push(``);
560093
- lines.push(`Observed run evidence:`);
560094
- lines.push(...listLines(observedEvidence, "- no tool evidence recorded"));
560095
- lines.push(``);
560096
- lines.push(`Unresolved or caution signals:`);
560097
- lines.push(...listLines(unresolvedSignals, "- none recorded"));
560098
- lines.push(``);
560099
- lines.push(`Modified artifact digest:`);
560100
- lines.push(...listLines(modifiedFiles, "- no modified artifacts listed"));
560101
- lines.push(``);
560102
- lines.push(`Reviewer decomposition task:`);
560103
- lines.push(`- Invent a situation-specific completion scenario from the request, proposed claims, and observed run data above.`);
560104
- lines.push(`- Enumerate the material claims in the proposed completion text, including implied claims about created state, external effects, recipient-visible outcomes, runtime behavior, research facts, or absence of blockers when those claims appear in the text.`);
560105
- lines.push(`- For each claim, derive what would make it true from the claim's semantics, the user's request, and this run's observations.`);
560106
- lines.push(`- Map the claim to the observed evidence, contradictions, missing observations, and unresolved loops shown above.`);
560107
- lines.push(`- If an unsupported claim is material, propose the smallest next observation or correction; if the final wording already marks it unverified or blocked, treat that honesty as part of the evidence review.`);
560108
- return {
560109
- scenarioSeed,
560110
- prompt: lines.join("\n"),
560111
- proposedClaimText,
560112
- observedEvidence,
560113
- unresolvedSignals
560114
- };
560115
- }
560116
- function formatCompletionContract(contract, scenario) {
560117
- const lines = [];
560118
- lines.push(`[COMPLETION CONTRACT]`);
560119
- lines.push(`Goal: ${contract.goalSummary || "(no goal text)"}`);
560120
- lines.push(``);
560121
- lines.push(`Completion review policy:`);
560122
- lines.push(`- Derive material claims from the current request and proposed final answer.`);
560123
- lines.push(`- Compare those claims to observed tool results from this run.`);
560124
- lines.push(`- Treat missing, ambiguous, or failed observations as unverified rather than complete.`);
560125
- lines.push(`- Use the current request, proposed claims, and recorded observations as the source of truth.`);
560126
- lines.push(``);
560127
- lines.push(`Flow: execute -> scenario decomposition -> evidence review -> delivery readback.`);
560128
- if (scenario) {
560129
- lines.push(``);
560130
- lines.push(buildCompletionScenarioDecomposition({ contract, ...scenario }).prompt);
560131
- }
560132
- return lines.join("\n");
560133
- }
560134
- var init_completionContract = __esm({
560135
- "packages/orchestrator/dist/completionContract.js"() {
560136
- "use strict";
560137
- }
560138
- });
560139
-
560140
560421
  // packages/orchestrator/dist/modelProfile.js
560141
560422
  function resolveModelProfile(model) {
560142
560423
  const m2 = model.toLowerCase();
@@ -560811,6 +561092,82 @@ context_fabric: included=${included.length} dropped=${dropped.length} truncated=
560811
561092
  }
560812
561093
  });
560813
561094
 
561095
+ // packages/orchestrator/dist/contextEngine.js
561096
+ function estimateTokens3(messages2) {
561097
+ const chars = messages2.reduce((sum, message2) => sum + message2.content.length + message2.role.length + (message2.name?.length ?? 0), 0);
561098
+ return Math.ceil(chars / 4);
561099
+ }
561100
+ function evidenceMessage(event) {
561101
+ const status = event.success === true ? "ok" : event.success === false ? "failed" : "unknown";
561102
+ const parts = [
561103
+ `tool=${event.name}`,
561104
+ `status=${status}`,
561105
+ typeof event.turn === "number" ? `turn=${event.turn}` : "",
561106
+ event.evidenceId ? `evidence=${event.evidenceId}` : "",
561107
+ event.outputPreview ? `observed=${event.outputPreview}` : ""
561108
+ ].filter(Boolean);
561109
+ return { role: "system", content: `[RUN EVIDENCE] ${parts.join(" ")}` };
561110
+ }
561111
+ function createDefaultContextEngine() {
561112
+ return new DefaultContextEngine();
561113
+ }
561114
+ var DefaultContextEngine;
561115
+ var init_contextEngine = __esm({
561116
+ "packages/orchestrator/dist/contextEngine.js"() {
561117
+ "use strict";
561118
+ DefaultContextEngine = class {
561119
+ async build(input) {
561120
+ return this.render(input, false);
561121
+ }
561122
+ async compact(input) {
561123
+ return this.render(input, true);
561124
+ }
561125
+ render(input, allowCompaction) {
561126
+ const evidence = (input.toolEvents ?? []).map(evidenceMessage);
561127
+ const hints = (input.memoryHints ?? []).filter((hint) => hint.trim().length > 0).slice(-8).map((hint) => ({ role: "system", content: `[MEMORY HINT] ${hint.trim()}` }));
561128
+ const contract = input.runState?.completionContract ? [{ role: "system", content: input.runState.completionContract }] : [];
561129
+ const beforeMessages = [...evidence, ...hints, ...contract, ...input.messages];
561130
+ const before = estimateTokens3(beforeMessages);
561131
+ const budget = input.runState?.tokenBudget;
561132
+ let compactedMessages = input.messages;
561133
+ let compacted = false;
561134
+ let evidenceDropped = 0;
561135
+ if (allowCompaction && budget && before > budget) {
561136
+ const overhead = estimateTokens3([...evidence, ...hints, ...contract]);
561137
+ const retained = [];
561138
+ let used = overhead;
561139
+ for (const message2 of [...input.messages].reverse()) {
561140
+ const cost = estimateTokens3([message2]);
561141
+ if (used + cost > budget)
561142
+ continue;
561143
+ retained.push(message2);
561144
+ used += cost;
561145
+ }
561146
+ compactedMessages = retained.reverse();
561147
+ compacted = compactedMessages.length !== input.messages.length;
561148
+ evidenceDropped = 0;
561149
+ }
561150
+ const allMessages = [...evidence, ...hints, ...contract, ...compactedMessages];
561151
+ const after = estimateTokens3(allMessages);
561152
+ return {
561153
+ systemMessages: allMessages.filter((m2) => m2.role === "system"),
561154
+ conversationMessages: allMessages.filter((m2) => m2.role !== "system"),
561155
+ compacted,
561156
+ diagnostics: {
561157
+ surface: input.surface,
561158
+ tokenEstimateBefore: before,
561159
+ tokenEstimateAfter: after,
561160
+ compacted,
561161
+ compactionStrategy: compacted ? "drop_oldest_non_evidence" : "none",
561162
+ evidenceRetained: evidence.length,
561163
+ evidenceDropped
561164
+ }
561165
+ };
561166
+ }
561167
+ };
561168
+ }
561169
+ });
561170
+
560814
561171
  // packages/orchestrator/dist/preflightSnapshot.js
560815
561172
  var preflightSnapshot_exports = {};
560816
561173
  __export(preflightSnapshot_exports, {
@@ -560818,7 +561175,7 @@ __export(preflightSnapshot_exports, {
560818
561175
  formatPreflightStatus: () => formatPreflightStatus,
560819
561176
  freeDiskBytes: () => freeDiskBytes
560820
561177
  });
560821
- import { existsSync as existsSync87, readFileSync as readFileSync68, statSync as statSync35 } from "node:fs";
561178
+ import { existsSync as existsSync87, readFileSync as readFileSync69, statSync as statSync35 } from "node:fs";
560822
561179
  import { execSync as execSync47 } from "node:child_process";
560823
561180
  import { homedir as homedir30, platform as platform3, arch as arch2, totalmem as totalmem3, freemem as freemem3, hostname as hostname3 } from "node:os";
560824
561181
  import { join as join99 } from "node:path";
@@ -560832,7 +561189,7 @@ function capturePreflightSnapshot(workingDir) {
560832
561189
  continue;
560833
561190
  let raw;
560834
561191
  try {
560835
- raw = readFileSync68(expanded, "utf8");
561192
+ raw = readFileSync69(expanded, "utf8");
560836
561193
  } catch {
560837
561194
  continue;
560838
561195
  }
@@ -560850,7 +561207,7 @@ function capturePreflightSnapshot(workingDir) {
560850
561207
  continue;
560851
561208
  let raw;
560852
561209
  try {
560853
- raw = readFileSync68(projectPath, "utf8");
561210
+ raw = readFileSync69(projectPath, "utf8");
560854
561211
  } catch {
560855
561212
  continue;
560856
561213
  }
@@ -561053,7 +561410,7 @@ __export(postActionVerifier_exports, {
561053
561410
  classifyShellIntent: () => classifyShellIntent,
561054
561411
  verifyShellOutcome: () => verifyShellOutcome
561055
561412
  });
561056
- import { existsSync as existsSync88, readFileSync as readFileSync69, readdirSync as readdirSync27, statSync as statSync36 } from "node:fs";
561413
+ import { existsSync as existsSync88, readFileSync as readFileSync70, readdirSync as readdirSync27, statSync as statSync36 } from "node:fs";
561057
561414
  import { join as join100 } from "node:path";
561058
561415
  function classifyShellIntent(cmd) {
561059
561416
  const stripped = cmd.replace(/^cd\s+\S+\s*&&\s*/, "").trim();
@@ -561146,7 +561503,7 @@ function checkManifestInvariant(cwd4, fallbackBucket) {
561146
561503
  continue;
561147
561504
  let declared;
561148
561505
  try {
561149
- declared = pattern.parseDeps(readFileSync69(manifestPath2, "utf8"));
561506
+ declared = pattern.parseDeps(readFileSync70(manifestPath2, "utf8"));
561150
561507
  } catch {
561151
561508
  continue;
561152
561509
  }
@@ -562330,6 +562687,7 @@ var init_agenticRunner = __esm({
562330
562687
  "packages/orchestrator/dist/agenticRunner.js"() {
562331
562688
  "use strict";
562332
562689
  init_textSanitize();
562690
+ init_completionLedger();
562333
562691
  init_dist6();
562334
562692
  init_ollama_pool();
562335
562693
  init_personality();
@@ -562355,6 +562713,7 @@ var init_agenticRunner = __esm({
562355
562713
  init_contextTree();
562356
562714
  init_codeGraphLink();
562357
562715
  init_dist5();
562716
+ init_dist5();
562358
562717
  init_tool_batching();
562359
562718
  init_hooks();
562360
562719
  init_todo_context_chunker();
@@ -562365,6 +562724,7 @@ var init_agenticRunner = __esm({
562365
562724
  init_modelProfile();
562366
562725
  init_failureHandoff();
562367
562726
  init_context_fabric();
562727
+ init_contextEngine();
562368
562728
  TOOL_SUBSETS = {
562369
562729
  web: ["web_search", "web_fetch", "web_crawl"],
562370
562730
  code: [
@@ -562441,6 +562801,7 @@ var init_agenticRunner = __esm({
562441
562801
  backend;
562442
562802
  tools = /* @__PURE__ */ new Map();
562443
562803
  options;
562804
+ _onTypedEvent;
562444
562805
  handlers = [];
562445
562806
  pendingUserMessages = [];
562446
562807
  aborted = false;
@@ -562691,6 +563052,7 @@ var init_agenticRunner = __esm({
562691
563052
  // Reset whenever a completion is allowed.
562692
563053
  _completionHoldState = { count: 0, lastKey: "" };
562693
563054
  _completionIncompleteVerification = null;
563055
+ _completionLedger = null;
562694
563056
  // ── WO-AM-01/04/10: Associative memory stores ──
562695
563057
  // Episode store: every tool call → persistent episode with importance + decay
562696
563058
  // Temporal KG: entities + relations with temporal validity (valid_from/valid_until)
@@ -562811,6 +563173,8 @@ var init_agenticRunner = __esm({
562811
563173
  _lastPprSig = null;
562812
563174
  _lastPprMemoryLines = [];
562813
563175
  _pprSkipCount = 0;
563176
+ // WO-07: Durable Multi-Agent Kanban — workboard integration
563177
+ _workboard = null;
562814
563178
  // Phase 2 — tool subset expansion and usage tracking.
562815
563179
  // Tools promoted from deferred → inline by tool_search (or by subset
562816
563180
  // expansion). They stay inline for the rest of the run unless idle past
@@ -562841,6 +563205,10 @@ var init_agenticRunner = __esm({
562841
563205
  _lastContextPressureSnapshot = null;
562842
563206
  _lastActiveForgettingReport = null;
562843
563207
  _lastContextConsolidationTurn = -1e3;
563208
+ /** WO-CE-BOUNDARY: Context engine instance for structured context assembly */
563209
+ _contextEngine;
563210
+ /** WO-CE-BOUNDARY: Collected tool events for context engine input */
563211
+ _toolEvents = [];
562844
563212
  /** WO-AM-10: Process pending episode embeddings in background batches */
562845
563213
  async processPendingEmbeddings() {
562846
563214
  if (this._pendingEmbeddings.length === 0 || !this._episodeStore)
@@ -562875,6 +563243,126 @@ var init_agenticRunner = __esm({
562875
563243
  }
562876
563244
  // Never block tools: we rely on guidance and repetition handling rather than
562877
563245
  // modifying the available tool set.
563246
+ // ── WO-07: Durable Multi-Agent Kanban integration ──
563247
+ /** Get or create the workboard for this run. Lazily initialized. */
563248
+ _workboardDir() {
563249
+ return this.options.workboardDir || this._workingDirectory || process.cwd();
563250
+ }
563251
+ getOrCreateWorkboard() {
563252
+ if (this._workboard)
563253
+ return this._workboard;
563254
+ const dir = this._workboardDir();
563255
+ const runId = this._sessionId;
563256
+ const existing = loadWorkboardSnapshot(dir, runId);
563257
+ if (existing) {
563258
+ this._workboard = existing;
563259
+ return existing;
563260
+ }
563261
+ try {
563262
+ this._workboard = createWorkboard(dir, {
563263
+ runId,
563264
+ owner: this.options.subAgent ? "sub-agent" : "agent",
563265
+ title: (this._taskState.goal || "").slice(0, 120) || void 0
563266
+ });
563267
+ } catch {
563268
+ this._workboard = loadWorkboardSnapshot(dir, runId);
563269
+ }
563270
+ return this._workboard;
563271
+ }
563272
+ /**
563273
+ * Build a compact workboard context string for injection into the
563274
+ * system prompt. Returns null when no active board exists or when
563275
+ * the board has no active cards worth surfacing (short-lived tasks).
563276
+ * Injects for sub-agents and long-running admin tasks.
563277
+ */
563278
+ injectWorkboardContext() {
563279
+ if (this._workboard || this.options.subAgent) {
563280
+ const dir = this._workboardDir();
563281
+ const snapshot = readActiveWorkboardSnapshot(dir, this._sessionId);
563282
+ if (!snapshot)
563283
+ return null;
563284
+ const activeCards = snapshot.cards.filter((c8) => c8.status === "in_progress" || c8.status === "open" || c8.status === "needs_changes");
563285
+ if (activeCards.length === 0 && snapshot.cards.every((c8) => c8.status === "verified" || c8.status === "completed"))
563286
+ return null;
563287
+ const synthesis = buildWorkboardSynthesisContext(snapshot);
563288
+ const parts = [];
563289
+ if (synthesis.verifiedCards.length > 0) {
563290
+ parts.push(`Verified: ${synthesis.verifiedCards.length}`);
563291
+ }
563292
+ if (synthesis.unresolvedBlockers.length > 0) {
563293
+ parts.push(`Blockers: ${synthesis.unresolvedBlockers.length}`);
563294
+ }
563295
+ if (activeCards.length > 0) {
563296
+ parts.push(`Active: ${activeCards.length}`);
563297
+ }
563298
+ if (snapshot.cards.length > 0) {
563299
+ const compact3 = compactWorkboardSnapshot(snapshot, 12);
563300
+ parts.push(`
563301
+ ${formatWorkboardCompact(snapshot, 12)}`);
563302
+ }
563303
+ return parts.length > 0 ? `<workboard-status>
563304
+ ${parts.join("\n")}
563305
+ </workboard-status>` : null;
563306
+ }
563307
+ return null;
563308
+ }
563309
+ /**
563310
+ * Record evidence from a tool call against the active workboard.
563311
+ * Matches by card assignee when the card is in progress.
563312
+ * Non-fatal: failures to attach evidence are silently caught.
563313
+ */
563314
+ recordWorkboardToolCall(toolName, args, success, output) {
563315
+ const board = this._workboard ?? this.getOrCreateWorkboard();
563316
+ if (!board)
563317
+ return;
563318
+ if (toolName === "task_complete" || toolName === "workboard_create")
563319
+ return;
563320
+ const dir = this._workboardDir();
563321
+ try {
563322
+ const evidenceSummary = `${toolName} ${success ? "ok" : "fail"}`;
563323
+ const evidenceContent = (success ? typeof output === "string" ? output : "" : "").slice(0, 1e3);
563324
+ const evidence = {
563325
+ kind: "tool_result",
563326
+ summary: evidenceSummary,
563327
+ tool: toolName,
563328
+ content: evidenceContent,
563329
+ command: typeof args["command"] === "string" ? args["command"]?.slice(0, 200) : void 0,
563330
+ ref: typeof args["path"] === "string" ? args["path"]?.slice(0, 200) : void 0
563331
+ };
563332
+ const actor = this.options.subAgent ? "sub-agent" : "agent";
563333
+ for (const card of board.cards) {
563334
+ if (card.status !== "in_progress" && card.status !== "open")
563335
+ continue;
563336
+ if (card.assignee && card.assignee !== actor && card.assignee !== "any")
563337
+ continue;
563338
+ if (toolName === "shell" && !card.evidenceRequirements.some((r2) => r2.toLowerCase().includes("shell") || r2.toLowerCase().includes("build") || r2.toLowerCase().includes("test")))
563339
+ continue;
563340
+ if (toolName === "file_write" && !card.evidenceRequirements.some((r2) => r2.toLowerCase().includes("file") || r2.toLowerCase().includes("write") || r2.toLowerCase().includes("implement")))
563341
+ continue;
563342
+ if (toolName === "file_read" && !card.evidenceRequirements.some((r2) => r2.toLowerCase().includes("read") || r2.toLowerCase().includes("explor") || r2.toLowerCase().includes("understand")))
563343
+ continue;
563344
+ attachWorkboardEvidence(dir, {
563345
+ runId: this._sessionId,
563346
+ cardId: card.id,
563347
+ actor,
563348
+ evidence
563349
+ });
563350
+ }
563351
+ } catch {
563352
+ }
563353
+ }
563354
+ /** Persist the workboard snapshot before run teardown. */
563355
+ _saveWorkboard() {
563356
+ if (!this._workboard)
563357
+ return;
563358
+ try {
563359
+ const dir = this._workboardDir();
563360
+ const refreshed = readActiveWorkboardSnapshot(dir, this._sessionId);
563361
+ if (refreshed)
563362
+ this._workboard = refreshed;
563363
+ } catch {
563364
+ }
563365
+ }
562878
563366
  // -- Session Checkpointing (Priority 5) --
562879
563367
  _sessionId = `session-${Date.now()}`;
562880
563368
  _workingDirectory = "";
@@ -562919,10 +563407,15 @@ var init_agenticRunner = __esm({
562919
563407
  // runner skips cross-task handoff inheritance from the parent's
562920
563408
  // session.
562921
563409
  subAgent: options2?.subAgent ?? false,
563410
+ workboardDir: options2?.workboardDir ?? "",
562922
563411
  skipCrossTaskHandoff: options2?.skipCrossTaskHandoff ?? false
562923
563412
  };
562924
563413
  this._adversaryMode = this.options.adversaryMode;
562925
563414
  this._streamingExecutor.setConcurrencyResolver((name10, args) => this.resolveToolConcurrencySafe(name10, args));
563415
+ this._contextEngine = createDefaultContextEngine();
563416
+ if (options2?.onTypedEvent) {
563417
+ this._onTypedEvent = options2.onTypedEvent;
563418
+ }
562926
563419
  }
562927
563420
  /** Update context window size (e.g. after querying Ollama /api/show) */
562928
563421
  setContextWindowSize(size) {
@@ -562952,6 +563445,16 @@ var init_agenticRunner = __esm({
562952
563445
  } catch {
562953
563446
  }
562954
563447
  }
563448
+ _saveCompletionLedgerSafe() {
563449
+ if (!this._completionLedger)
563450
+ return;
563451
+ try {
563452
+ const dir = _pathJoin(this.omniusStateDir(), "completion-ledgers");
563453
+ _fsMkdirSync(dir, { recursive: true });
563454
+ saveCompletionLedger(_pathJoin(dir, `${this._sessionId}.json`), this._completionLedger);
563455
+ } catch {
563456
+ }
563457
+ }
562955
563458
  _initializeCompletionContract(task, context2) {
562956
563459
  this._completionContractSeedText = [task, context2 ?? ""].map((text2) => String(text2 || "").trim()).filter(Boolean).join("\n\n");
562957
563460
  this._completionContract = inferCompletionContractFromTexts([this._completionContractSeedText], task);
@@ -563017,6 +563520,38 @@ var init_agenticRunner = __esm({
563017
563520
  }));
563018
563521
  }
563019
563522
  // -------------------------------------------------------------------------
563523
+ // WO-CE-BOUNDARY: Context Engine integration (Work Order #02)
563524
+ // -------------------------------------------------------------------------
563525
+ /** Infer the surface identifier from runner configuration and dynamic context. */
563526
+ _inferSurface() {
563527
+ const ctx3 = this._stickyDynamicContext || this.options.dynamicContext || "";
563528
+ if (/Admin Capability/i.test(ctx3) || /telegram-admin/i.test(ctx3))
563529
+ return "telegram-admin";
563530
+ if (/Telegram|telegram|Voice Soul/i.test(ctx3) || this.options.stateDir)
563531
+ return "telegram-public";
563532
+ if (/api/i.test(ctx3))
563533
+ return "api";
563534
+ if (/background/i.test(ctx3))
563535
+ return "background";
563536
+ return "tui";
563537
+ }
563538
+ /**
563539
+ * Build structured context via the context engine.
563540
+ * Converts the runner's internal messages + tool events into
563541
+ * the engine's output format (system messages separated from
563542
+ * conversation, evidence injected, completion contracts placed).
563543
+ */
563544
+ async buildContext(input) {
563545
+ return this._contextEngine.build(input);
563546
+ }
563547
+ /**
563548
+ * Compact structured context via the context engine.
563549
+ * Same as buildContext but allows token-budget-aware compaction.
563550
+ */
563551
+ async compactContext(input) {
563552
+ return this._contextEngine.compact(input);
563553
+ }
563554
+ // -------------------------------------------------------------------------
563020
563555
  // Structured Context Assembly — C = A(c_instr, c_know, c_tools, c_mem, c_state, c_query)
563021
563556
  // Reference: "A Survey of Context Engineering for LLMs" (arXiv:2507.xxxxx)
563022
563557
  // -------------------------------------------------------------------------
@@ -563198,6 +563733,19 @@ ${graphSummary}`,
563198
563733
  }
563199
563734
  } catch {
563200
563735
  }
563736
+ try {
563737
+ const wbCtx = this.injectWorkboardContext();
563738
+ if (wbCtx) {
563739
+ sections.push({
563740
+ label: "c_workboard",
563741
+ content: `
563742
+
563743
+ ${wbCtx}`,
563744
+ tokenEstimate: Math.ceil(wbCtx.length / 4)
563745
+ });
563746
+ }
563747
+ } catch {
563748
+ }
563201
563749
  const assembled = sections.map((s2) => s2.content).join("");
563202
563750
  const totalTokenEstimate = sections.reduce((sum, s2) => sum + s2.tokenEstimate, 0);
563203
563751
  return {
@@ -564080,6 +564628,18 @@ ${context2 ?? ""}`;
564080
564628
  * a different path (eg. surface to user). max cycles enforced here.
564081
564629
  */
564082
564630
  async _runBackwardPassReview(turn, toolCallLog, proposedSummary = "") {
564631
+ if (this._completionLedger && proposedSummary) {
564632
+ const _newClaims = deriveClaimsFromProposedText({
564633
+ text: proposedSummary,
564634
+ source: "task_complete_summary",
564635
+ existing: this._completionLedger.proposedClaims
564636
+ });
564637
+ if (_newClaims.length > 0) {
564638
+ this._completionLedger = addCompletionClaims(this._completionLedger, _newClaims);
564639
+ this._completionLedger = reconcileClaimsWithEvidence(this._completionLedger);
564640
+ this._saveCompletionLedgerSafe();
564641
+ }
564642
+ }
564083
564643
  const optOverride = this.options.backwardPassReview;
564084
564644
  const raw = (process.env["OMNIUS_BACKWARD_PASS"] || "on").toLowerCase();
564085
564645
  const envDisabled = raw === "off" || raw === "0" || raw === "false";
@@ -564221,6 +564781,13 @@ ${context2 ?? ""}`;
564221
564781
  })),
564222
564782
  modifiedFiles: modifiedFileDigest
564223
564783
  }).prompt;
564784
+ let _ledgerScenarioDecomposition = completionScenarioDecomposition;
564785
+ if (this._completionLedger) {
564786
+ const _packet = buildCriticPacketFromLedger(this._completionLedger);
564787
+ if (_packet) {
564788
+ _ledgerScenarioDecomposition = [completionScenarioDecomposition, _packet].join("\n\n");
564789
+ }
564790
+ }
564224
564791
  const reviewReconciliation = lastCritique ? {
564225
564792
  previousVerdict: lastCritique.verdict,
564226
564793
  previousRationale: lastCritique.rationale,
@@ -564244,9 +564811,16 @@ ${context2 ?? ""}`;
564244
564811
  recentFailures,
564245
564812
  finalSummary: proposedSummary,
564246
564813
  toolEvidence: criticToolEvidence,
564247
- completionScenarioDecomposition,
564814
+ completionScenarioDecomposition: _ledgerScenarioDecomposition,
564248
564815
  reviewReconciliation,
564249
564816
  openLoops,
564817
+ workboardSynthesisContext: this._workboard ? (() => {
564818
+ try {
564819
+ return buildWorkboardSynthesisContext(this._workboard).excludedUnverifiedCardIds.length > 0 ? `Verified: ${this._workboard.cards.filter((c8) => c8.status === "verified").length}, Unverified remaining: ${this._workboard.cards.filter((c8) => c8.status !== "verified").length}, Blockers: ${this._workboard.cards.filter((c8) => c8.status === "blocked" || c8.status === "needs_changes").length}` : void 0;
564820
+ } catch {
564821
+ return void 0;
564822
+ }
564823
+ })() : void 0,
564250
564824
  callable,
564251
564825
  maxFiles: parseInt(process.env["OMNIUS_BACKWARD_PASS_MAX_FILES"] || "60", 10) || 60,
564252
564826
  maxFilePreviewBytes: parseInt(process.env["OMNIUS_BACKWARD_PASS_MAX_FILE_PREVIEW"] || "8000", 10) || 8e3,
@@ -564289,10 +564863,25 @@ ${context2 ?? ""}`;
564289
564863
  });
564290
564864
  void turn;
564291
564865
  if (result.verdict.verdict === "approve") {
564866
+ if (this._completionLedger) {
564867
+ this._completionLedger = recordCompletionCritique(this._completionLedger, {
564868
+ verdict: "approve",
564869
+ rationale: result.verdict.rationale
564870
+ });
564871
+ this._saveCompletionLedgerSafe();
564872
+ }
564292
564873
  this._lastBackwardPassCritique = null;
564293
564874
  return { proceed: true };
564294
564875
  }
564295
564876
  const feedback = result.feedbackMessage;
564877
+ if (this._completionLedger) {
564878
+ this._completionLedger = recordCompletionCritique(this._completionLedger, {
564879
+ verdict: result.verdict.verdict === "blocked" ? "blocked" : "request_changes",
564880
+ rationale: result.verdict.rationale,
564881
+ feedback
564882
+ });
564883
+ this._saveCompletionLedgerSafe();
564884
+ }
564296
564885
  this._lastBackwardPassCritique = {
564297
564886
  verdict: result.verdict.verdict,
564298
564887
  rationale: result.verdict.rationale,
@@ -566845,6 +567434,7 @@ Respond with your assessment, then take action.`;
566845
567434
  this._completionContract = null;
566846
567435
  this._completionContractSeedText = "";
566847
567436
  this._completionIncompleteVerification = null;
567437
+ this._completionLedger = null;
566848
567438
  this._lastWorldStateTurn = -1;
566849
567439
  this._fileWritesSinceLastWorldState = 0;
566850
567440
  this._resetVisualEvidenceState();
@@ -566984,6 +567574,10 @@ Respond with your assessment, then take action.`;
566984
567574
  });
566985
567575
  this._hookManager.runSessionHook("session_start", this._sessionId);
566986
567576
  this._initializeCompletionContract(task, context2);
567577
+ this._completionLedger = createCompletionLedger({
567578
+ runId: this._sessionId,
567579
+ goal: cleanedTask
567580
+ });
566987
567581
  this._sessionStartMs = Date.now();
566988
567582
  if (process.env["OMNIUS_DISABLE_PREFLIGHT"] !== "1") {
566989
567583
  try {
@@ -567554,6 +568148,12 @@ TASK: ${scrubbedTask}` : scrubbedTask;
567554
568148
  content: "Task aborted by user",
567555
568149
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
567556
568150
  });
568151
+ this._onTypedEvent?.({
568152
+ type: "run_failed",
568153
+ runId: this._sessionId ?? "unknown",
568154
+ error: "Task aborted by user",
568155
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
568156
+ });
567557
568157
  break;
567558
568158
  }
567559
568159
  }
@@ -567563,6 +568163,12 @@ TASK: ${scrubbedTask}` : scrubbedTask;
567563
568163
  content: "Task aborted by user",
567564
568164
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
567565
568165
  });
568166
+ this._onTypedEvent?.({
568167
+ type: "run_failed",
568168
+ runId: this._sessionId ?? "unknown",
568169
+ error: "Task aborted by user",
568170
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
568171
+ });
567566
568172
  break;
567567
568173
  }
567568
568174
  const REG35_CHECKPOINT_EVERY = 10;
@@ -568772,6 +569378,28 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
568772
569378
  messages2.push(...compacted);
568773
569379
  compacted = messages2;
568774
569380
  }
569381
+ if (turn > 0 && this._toolEvents.length > 0) {
569382
+ try {
569383
+ const _limits = this.contextLimits();
569384
+ const ceCompactInput = {
569385
+ goal: this._taskState.originalGoal || this._taskState.goal || task,
569386
+ surface: this._inferSurface(),
569387
+ messages: compacted.map((m2) => ({
569388
+ role: m2.role === "tool" ? "tool" : m2.role === "system" ? "system" : m2.role === "assistant" ? "assistant" : "user",
569389
+ content: typeof m2.content === "string" ? m2.content : JSON.stringify(m2.content)
569390
+ })),
569391
+ toolEvents: this._toolEvents,
569392
+ memoryHints: [],
569393
+ runState: {
569394
+ runId: this._sessionId,
569395
+ tokenBudget: _limits.compactionThreshold,
569396
+ completionContract: this._completionContract ? formatCompletionContract(this._completionContract) : void 0
569397
+ }
569398
+ };
569399
+ await this._contextEngine.compact(ceCompactInput);
569400
+ } catch {
569401
+ }
569402
+ }
568775
569403
  if (turn > 0 && turn % 3 === 0 && this._temporalGraph && this._episodeStore) {
568776
569404
  let shouldRetrieve = true;
568777
569405
  try {
@@ -568878,6 +569506,34 @@ ${memoryLines.join("\n")}`
568878
569506
  this.proactivePrune(compacted, turn);
568879
569507
  this.microcompact(compacted, recentToolResults);
568880
569508
  this._insertContextFrame(compacted, await this._buildTurnContextFrame(turn, compacted, recentToolResults, environmentBlock));
569509
+ {
569510
+ const _limits = this.contextLimits();
569511
+ const ceInput = {
569512
+ goal: this._taskState.originalGoal || this._taskState.goal || task,
569513
+ surface: this._inferSurface(),
569514
+ messages: compacted.map((m2) => ({
569515
+ role: m2.role === "tool" ? "tool" : m2.role === "system" ? "system" : m2.role === "assistant" ? "assistant" : "user",
569516
+ content: typeof m2.content === "string" ? m2.content : JSON.stringify(m2.content)
569517
+ })),
569518
+ toolEvents: this._toolEvents,
569519
+ memoryHints: [],
569520
+ runState: {
569521
+ runId: this._sessionId,
569522
+ tokenBudget: _limits.compactionThreshold,
569523
+ completionContract: this._completionContract ? formatCompletionContract(this._completionContract) : void 0
569524
+ }
569525
+ };
569526
+ try {
569527
+ const ceOutput = await this._contextEngine.build(ceInput);
569528
+ if (ceOutput.diagnostics.evidenceRetained > 0 || ceInput.runState?.completionContract || ceInput.memoryHints?.length) {
569529
+ const engineExtra = ceOutput.systemMessages.filter((m2) => !ceInput.messages.some((im) => im.content === m2.content));
569530
+ if (engineExtra.length > 0) {
569531
+ compacted.unshift(...engineExtra.map((m2) => ({ role: "system", content: m2.content })));
569532
+ }
569533
+ }
569534
+ } catch {
569535
+ }
569536
+ }
568881
569537
  const { maxOutputTokens: effectiveMaxTokens } = this.contextLimits();
568882
569538
  const chatRequest = {
568883
569539
  messages: compacted,
@@ -568966,15 +569622,28 @@ ${memoryLines.join("\n")}`
568966
569622
  content: `Backend error: ${reqErr.message}`,
568967
569623
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
568968
569624
  });
569625
+ this._onTypedEvent?.({
569626
+ type: "run_failed",
569627
+ runId: this._sessionId ?? "unknown",
569628
+ error: reqErr.message,
569629
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
569630
+ });
568969
569631
  break;
568970
569632
  }
568971
569633
  if (this.handleMaxTokensError(reqErr, chatRequest)) {
568972
569634
  try {
568973
569635
  response = this.options.streamEnabled && this.hasStreamingSupport() ? await this.streamingRequest(chatRequest, turn) : await this.backend.chatCompletion(chatRequest);
568974
569636
  } catch (retryErr) {
569637
+ const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
568975
569638
  this.emit({
568976
569639
  type: "error",
568977
- content: `Retry with reduced max_tokens also failed: ${retryErr instanceof Error ? retryErr.message : String(retryErr)}`,
569640
+ content: `Retry with reduced max_tokens also failed: ${retryMsg}`,
569641
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
569642
+ });
569643
+ this._onTypedEvent?.({
569644
+ type: "run_failed",
569645
+ runId: this._sessionId ?? "unknown",
569646
+ error: retryMsg,
568978
569647
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
568979
569648
  });
568980
569649
  break;
@@ -568995,6 +569664,12 @@ ${memoryLines.join("\n")}`
568995
569664
  content: `Model not available. Use /model to select a different model.`,
568996
569665
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
568997
569666
  });
569667
+ this._onTypedEvent?.({
569668
+ type: "run_failed",
569669
+ runId: this._sessionId ?? "unknown",
569670
+ error: `Model not found: ${errMsg}`,
569671
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
569672
+ });
568998
569673
  break;
568999
569674
  }
569000
569675
  let imageRecovered = false;
@@ -569060,6 +569735,13 @@ ${memoryLines.join("\n")}`
569060
569735
  if (resolvedParsedTool.name === "task_complete") {
569061
569736
  completed = true;
569062
569737
  summary = String(parsed.args?.summary ?? content);
569738
+ this._onTypedEvent?.({
569739
+ type: "completion_requested",
569740
+ runId: this._sessionId ?? "unknown",
569741
+ summary: summary.slice(0, 500),
569742
+ sourcePath: this.options.streamEnabled ? "stream" : "batch",
569743
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
569744
+ });
569063
569745
  }
569064
569746
  toolCallCount++;
569065
569747
  continue;
@@ -569076,6 +569758,12 @@ ${memoryLines.join("\n")}`
569076
569758
  content: `Prompt-injected tool mode also failed: ${msg2}`,
569077
569759
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
569078
569760
  });
569761
+ this._onTypedEvent?.({
569762
+ type: "run_failed",
569763
+ runId: this._sessionId ?? "unknown",
569764
+ error: msg2,
569765
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
569766
+ });
569079
569767
  break;
569080
569768
  }
569081
569769
  }
@@ -569085,6 +569773,12 @@ ${memoryLines.join("\n")}`
569085
569773
  content: `Backend unavailable — stopping task. Fix the issue and retry.`,
569086
569774
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
569087
569775
  });
569776
+ this._onTypedEvent?.({
569777
+ type: "run_failed",
569778
+ runId: this._sessionId ?? "unknown",
569779
+ error: `Backend unavailable: ${errMsg}`,
569780
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
569781
+ });
569088
569782
  break;
569089
569783
  }
569090
569784
  }
@@ -570696,6 +571390,14 @@ ${criticGuidance}`;
570696
571390
  currentLogEntry.mutatedFiles = realMutationPaths;
570697
571391
  currentLogEntry.outputPreview = (result.success ? result.llmContent ?? result.output ?? output : result.error ?? result.output ?? output).toString().slice(0, 500);
570698
571392
  }
571393
+ this._toolEvents.push({
571394
+ name: tc.name,
571395
+ success: result.success,
571396
+ outputPreview: (result.output ?? result.error ?? output ?? "").toString().slice(0, 300),
571397
+ turn
571398
+ });
571399
+ if (this._toolEvents.length > 200)
571400
+ this._toolEvents = this._toolEvents.slice(-200);
570699
571401
  const runtimeEvidenceEvents = this._recordEvidenceEventsFromResult(result, tc.name, tc.arguments ?? {}, turn, _toolLogTailIdx);
570700
571402
  if (runtimeEvidenceEvents.length > 0 && currentLogEntry) {
570701
571403
  const evidencePreview = runtimeEvidenceEvents.map((event) => `${event.surface}/${event.action}:${event.verification?.status ?? "unknown"}`).join(", ");
@@ -570710,6 +571412,7 @@ Evidence: ${evidencePreview}`.slice(0, 500);
570710
571412
  turn,
570711
571413
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
570712
571414
  });
571415
+ this.recordWorkboardToolCall(tc.name, tc.arguments, result.success, result.output || output);
570713
571416
  this._taskState.toolCallCount++;
570714
571417
  if (realFileMutation) {
570715
571418
  this._lastFileWriteTurn = turn;
@@ -571021,6 +571724,35 @@ Then use file_read on individual FILES inside it.`);
571021
571724
  lastFailureHandoffTurn = turn;
571022
571725
  }
571023
571726
  }
571727
+ if (this._completionLedger && tc.name !== "task_complete") {
571728
+ this._completionLedger = recordToolEvidence(this._completionLedger, {
571729
+ name: tc.name,
571730
+ success: result.success,
571731
+ outputPreview: (result.success ? result.llmContent ?? result.output ?? output : result.error ?? result.output ?? output).toString().slice(0, 500),
571732
+ argsKey: tc.arguments ? JSON.stringify(tc.arguments).slice(0, 300) : ""
571733
+ });
571734
+ if (realFileMutation && realMutationPaths.length > 0) {
571735
+ for (const filePath2 of realMutationPaths) {
571736
+ this._completionLedger = recordCompletionEvidence(this._completionLedger, {
571737
+ kind: "file_change",
571738
+ toolName: tc.name,
571739
+ success: true,
571740
+ summary: `file change: ${filePath2}`,
571741
+ rawRef: `file://${filePath2}`
571742
+ });
571743
+ }
571744
+ }
571745
+ this._saveCompletionLedgerSafe();
571746
+ }
571747
+ this._onTypedEvent?.({
571748
+ type: "tool_call_finished",
571749
+ runId: this._sessionId ?? "unknown",
571750
+ toolName: tc.name,
571751
+ callId: tc.id,
571752
+ success: result.success === true,
571753
+ outputPreview: (result.output ?? result.error ?? "").toString().slice(0, 500),
571754
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
571755
+ });
571024
571756
  return { tc, output, success: result.success };
571025
571757
  };
571026
571758
  const rawToolCalls = msg.toolCalls;
@@ -571104,6 +571836,13 @@ ${sr.result.output}`;
571104
571836
  }
571105
571837
  completed = true;
571106
571838
  summary = extractTaskCompleteSummary(matchTc.arguments);
571839
+ this._onTypedEvent?.({
571840
+ type: "completion_requested",
571841
+ runId: this._sessionId ?? "unknown",
571842
+ summary: (summary ?? "").slice(0, 500),
571843
+ sourcePath: this.options.streamEnabled ? "stream" : "batch",
571844
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
571845
+ });
571107
571846
  if (summary && !this._assistantTextEmitted) {
571108
571847
  this.emit({
571109
571848
  type: "assistant_text",
@@ -571165,6 +571904,13 @@ ${sr.result.output}`;
571165
571904
  }
571166
571905
  completed = true;
571167
571906
  summary = extractTaskCompleteSummary(r2.tc.arguments);
571907
+ this._onTypedEvent?.({
571908
+ type: "completion_requested",
571909
+ runId: this._sessionId ?? "unknown",
571910
+ summary: (summary ?? "").slice(0, 500),
571911
+ sourcePath: this.options.streamEnabled ? "stream" : "batch",
571912
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
571913
+ });
571168
571914
  if (summary && !this._assistantTextEmitted) {
571169
571915
  this.emit({
571170
571916
  type: "assistant_text",
@@ -571263,6 +572009,13 @@ ${sr.result.output}`;
571263
572009
  }
571264
572010
  completed = true;
571265
572011
  summary = extractTaskCompleteSummary(r2.tc.arguments);
572012
+ this._onTypedEvent?.({
572013
+ type: "completion_requested",
572014
+ runId: this._sessionId ?? "unknown",
572015
+ summary: (summary ?? "").slice(0, 500),
572016
+ sourcePath: this.options.streamEnabled ? "stream" : "batch",
572017
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
572018
+ });
571266
572019
  if (summary && !this._assistantTextEmitted) {
571267
572020
  this.emit({
571268
572021
  type: "assistant_text",
@@ -571482,6 +572235,13 @@ Call task_complete(summary="...") NOW with whatever you have.`
571482
572235
  }
571483
572236
  completed = true;
571484
572237
  summary = content;
572238
+ this._onTypedEvent?.({
572239
+ type: "completion_requested",
572240
+ runId: this._sessionId ?? "unknown",
572241
+ summary: content.slice(0, 500),
572242
+ sourcePath: this.options.streamEnabled ? "stream" : "batch",
572243
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
572244
+ });
571485
572245
  break;
571486
572246
  }
571487
572247
  if (isThinkOnly) {
@@ -571677,6 +572437,28 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
571677
572437
  messages2.length = 0;
571678
572438
  messages2.push(...compacted);
571679
572439
  }
572440
+ if (this._toolEvents.length > 0) {
572441
+ try {
572442
+ const _limits = this.contextLimits();
572443
+ const _ceInput = {
572444
+ goal: this._taskState.originalGoal || this._taskState.goal || task,
572445
+ surface: this._inferSurface(),
572446
+ messages: messages2.map((m2) => ({
572447
+ role: m2.role === "tool" ? "tool" : m2.role === "system" ? "system" : m2.role === "assistant" ? "assistant" : "user",
572448
+ content: typeof m2.content === "string" ? m2.content : JSON.stringify(m2.content)
572449
+ })),
572450
+ toolEvents: this._toolEvents,
572451
+ memoryHints: [],
572452
+ runState: {
572453
+ runId: this._sessionId,
572454
+ tokenBudget: _limits.compactionThreshold,
572455
+ completionContract: this._completionContract ? formatCompletionContract(this._completionContract) : void 0
572456
+ }
572457
+ };
572458
+ const _ceOut = await this._contextEngine.compact(_ceInput);
572459
+ } catch {
572460
+ }
572461
+ }
571680
572462
  const restartTurnCap = this.options.maxTurns && this.options.maxTurns > 0 ? this.options.maxTurns : Number.MAX_SAFE_INTEGER;
571681
572463
  for (let turn = 0; turn < restartTurnCap; turn++) {
571682
572464
  this._maybeApplyThinkGuard();
@@ -571688,6 +572470,12 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
571688
572470
  content: "Task aborted by user",
571689
572471
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
571690
572472
  });
572473
+ this._onTypedEvent?.({
572474
+ type: "run_failed",
572475
+ runId: this._sessionId ?? "unknown",
572476
+ error: "Task aborted by user",
572477
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
572478
+ });
571691
572479
  break;
571692
572480
  }
571693
572481
  }
@@ -571697,6 +572485,12 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
571697
572485
  content: "Task aborted by user",
571698
572486
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
571699
572487
  });
572488
+ this._onTypedEvent?.({
572489
+ type: "run_failed",
572490
+ runId: this._sessionId ?? "unknown",
572491
+ error: "Task aborted by user",
572492
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
572493
+ });
571700
572494
  break;
571701
572495
  }
571702
572496
  this._runReg61Check(turn, toolCallLog, messages2, `bf-cycle ${bruteForceCycle}`);
@@ -571761,15 +572555,28 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
571761
572555
  content: "Task aborted by user",
571762
572556
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
571763
572557
  });
572558
+ this._onTypedEvent?.({
572559
+ type: "run_failed",
572560
+ runId: this._sessionId ?? "unknown",
572561
+ error: "Task aborted by user",
572562
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
572563
+ });
571764
572564
  break;
571765
572565
  }
571766
572566
  if (this.handleMaxTokensError(reqErr, chatRequest)) {
571767
572567
  try {
571768
572568
  response = this.options.streamEnabled && this.hasStreamingSupport() ? await this.streamingRequest(chatRequest, turn) : await this.backend.chatCompletion(chatRequest);
571769
572569
  } catch (retryErr) {
572570
+ const bfRetryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
571770
572571
  this.emit({
571771
572572
  type: "error",
571772
- content: `Retry with reduced max_tokens also failed: ${retryErr instanceof Error ? retryErr.message : String(retryErr)}`,
572573
+ content: `Retry with reduced max_tokens also failed: ${bfRetryMsg}`,
572574
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
572575
+ });
572576
+ this._onTypedEvent?.({
572577
+ type: "run_failed",
572578
+ runId: this._sessionId ?? "unknown",
572579
+ error: bfRetryMsg,
571773
572580
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
571774
572581
  });
571775
572582
  break;
@@ -571789,6 +572596,12 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
571789
572596
  content: `Backend unavailable — stopping task.`,
571790
572597
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
571791
572598
  });
572599
+ this._onTypedEvent?.({
572600
+ type: "run_failed",
572601
+ runId: this._sessionId ?? "unknown",
572602
+ error: errMsg2,
572603
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
572604
+ });
571792
572605
  break;
571793
572606
  }
571794
572607
  response = recovered;
@@ -572005,6 +572818,14 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
572005
572818
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
572006
572819
  });
572007
572820
  this._trackDecomp2(tc, result, turn);
572821
+ if (this._completionLedger && tc.name !== "task_complete") {
572822
+ this._completionLedger = recordToolEvidence(this._completionLedger, {
572823
+ name: tc.name,
572824
+ success: result.success,
572825
+ outputPreview: output.slice(0, 500),
572826
+ argsKey: bfArgsKey.slice(0, 300)
572827
+ });
572828
+ }
572008
572829
  const enoentTools2 = /* @__PURE__ */ new Set([
572009
572830
  "file_read",
572010
572831
  "list_directory",
@@ -572063,6 +572884,13 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
572063
572884
  }
572064
572885
  completed = true;
572065
572886
  summary = extractTaskCompleteSummary(tc.arguments);
572887
+ this._onTypedEvent?.({
572888
+ type: "completion_requested",
572889
+ runId: this._sessionId ?? "unknown",
572890
+ summary: (summary ?? "").slice(0, 500),
572891
+ sourcePath: this.options.streamEnabled ? "stream" : "batch",
572892
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
572893
+ });
572066
572894
  if (summary && !this._assistantTextEmitted) {
572067
572895
  this.emit({
572068
572896
  type: "assistant_text",
@@ -572114,6 +572942,13 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
572114
572942
  }
572115
572943
  completed = true;
572116
572944
  summary = content;
572945
+ this._onTypedEvent?.({
572946
+ type: "completion_requested",
572947
+ runId: this._sessionId ?? "unknown",
572948
+ summary: content.slice(0, 500),
572949
+ sourcePath: this.options.streamEnabled ? "stream" : "batch",
572950
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
572951
+ });
572117
572952
  break;
572118
572953
  }
572119
572954
  }
@@ -572162,7 +572997,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
572162
572997
  if (this._completionIncompleteVerification && !summary) {
572163
572998
  summary = this._completionIncompleteVerification.summary;
572164
572999
  }
572165
- const runStatus = completed ? "completed" : this._completionIncompleteVerification ? "incomplete_verification" : "incomplete";
573000
+ const runStatus = completed ? "completed" : this._completionLedger?.status === "blocked" || this._completionLedger?.status === "request_changes" ? "incomplete_verification" : this._completionIncompleteVerification ? "incomplete_verification" : "incomplete";
572166
573001
  this._emitMASTSummary("run-end");
572167
573002
  this.emit({
572168
573003
  type: "complete",
@@ -572170,6 +573005,13 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
572170
573005
  success: completed,
572171
573006
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
572172
573007
  });
573008
+ this._onTypedEvent?.({
573009
+ type: "run_finished",
573010
+ runId: this._sessionId ?? "unknown",
573011
+ status: runStatus,
573012
+ success: completed,
573013
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
573014
+ });
572173
573015
  if (this._errorPatterns.size > 0) {
572174
573016
  try {
572175
573017
  const fs11 = await import("node:fs");
@@ -572778,6 +573620,7 @@ Full content available via: repl_exec(code="data = retrieve('${handleId}')") or
572778
573620
  } catch {
572779
573621
  }
572780
573622
  }
573623
+ this._saveWorkboard();
572781
573624
  this._hookManager.runSessionHook("session_end", this._sessionId);
572782
573625
  try {
572783
573626
  const fs11 = await import("node:fs");
@@ -577278,7 +578121,7 @@ var init_constraint_learner = __esm({
577278
578121
  });
577279
578122
 
577280
578123
  // packages/orchestrator/dist/nexusBackend.js
577281
- import { existsSync as existsSync89, statSync as statSync37, openSync, readSync, closeSync, unlinkSync as unlinkSync17, writeFileSync as writeFileSync42 } from "node:fs";
578124
+ import { existsSync as existsSync89, statSync as statSync37, openSync, readSync, closeSync, unlinkSync as unlinkSync17, writeFileSync as writeFileSync43 } from "node:fs";
577282
578125
  import { watch as fsWatch } from "node:fs";
577283
578126
  import { join as join101 } from "node:path";
577284
578127
  import { tmpdir as tmpdir19 } from "node:os";
@@ -577484,7 +578327,7 @@ ${suffix}` } : m2);
577484
578327
  */
577485
578328
  async *chatCompletionStream(request) {
577486
578329
  const streamFile = join101(tmpdir19(), `nexus-stream-${randomBytes20(6).toString("hex")}.jsonl`);
577487
- writeFileSync42(streamFile, "", "utf8");
578330
+ writeFileSync43(streamFile, "", "utf8");
577488
578331
  const effectiveThink = this.effectiveThink(request);
577489
578332
  const daemonArgs = {
577490
578333
  model: this.model,
@@ -578001,7 +578844,7 @@ var init_cascadeBackend = __esm({
578001
578844
 
578002
578845
  // packages/orchestrator/dist/steeringIntake.js
578003
578846
  import { randomUUID as randomUUID16 } from "node:crypto";
578004
- import { appendFileSync as appendFileSync6, existsSync as existsSync90, mkdirSync as mkdirSync49, readFileSync as readFileSync70 } from "node:fs";
578847
+ import { appendFileSync as appendFileSync6, existsSync as existsSync90, mkdirSync as mkdirSync50, readFileSync as readFileSync71 } from "node:fs";
578005
578848
  import { join as join102 } from "node:path";
578006
578849
  import { z as z16 } from "zod";
578007
578850
  function createSteeringIngress(input) {
@@ -578129,7 +578972,7 @@ function extractMidTaskSteeringInput(value2) {
578129
578972
  function appendSteeringLedgerEntry(repoRoot, entry) {
578130
578973
  try {
578131
578974
  const dir = join102(repoRoot, ".omnius", "context");
578132
- mkdirSync49(dir, { recursive: true });
578975
+ mkdirSync50(dir, { recursive: true });
578133
578976
  appendFileSync6(join102(dir, LEDGER_FILE), `${JSON.stringify(entry)}
578134
578977
  `, "utf-8");
578135
578978
  } catch {
@@ -578268,7 +579111,7 @@ function readRecentSteeringEntries(repoRoot, limit) {
578268
579111
  const file = join102(repoRoot, ".omnius", "context", LEDGER_FILE);
578269
579112
  if (!existsSync90(file))
578270
579113
  return [];
578271
- const lines = readFileSync70(file, "utf-8").split("\n").filter(Boolean).slice(-100);
579114
+ const lines = readFileSync71(file, "utf-8").split("\n").filter(Boolean).slice(-100);
578272
579115
  const parsedEntries = [];
578273
579116
  for (const line of lines) {
578274
579117
  try {
@@ -578374,283 +579217,6 @@ Constrain your context. Clarify your target. Focus your tools. Flow will follow.
578374
579217
  }
578375
579218
  });
578376
579219
 
578377
- // packages/orchestrator/dist/contextEngine.js
578378
- function estimateTokens3(messages2) {
578379
- const chars = messages2.reduce((sum, message2) => sum + message2.content.length + message2.role.length + (message2.name?.length ?? 0), 0);
578380
- return Math.ceil(chars / 4);
578381
- }
578382
- function evidenceMessage(event) {
578383
- const status = event.success === true ? "ok" : event.success === false ? "failed" : "unknown";
578384
- const parts = [
578385
- `tool=${event.name}`,
578386
- `status=${status}`,
578387
- typeof event.turn === "number" ? `turn=${event.turn}` : "",
578388
- event.evidenceId ? `evidence=${event.evidenceId}` : "",
578389
- event.outputPreview ? `observed=${event.outputPreview}` : ""
578390
- ].filter(Boolean);
578391
- return { role: "system", content: `[RUN EVIDENCE] ${parts.join(" ")}` };
578392
- }
578393
- function createDefaultContextEngine() {
578394
- return new DefaultContextEngine();
578395
- }
578396
- var DefaultContextEngine;
578397
- var init_contextEngine = __esm({
578398
- "packages/orchestrator/dist/contextEngine.js"() {
578399
- "use strict";
578400
- DefaultContextEngine = class {
578401
- async build(input) {
578402
- return this.render(input, false);
578403
- }
578404
- async compact(input) {
578405
- return this.render(input, true);
578406
- }
578407
- render(input, allowCompaction) {
578408
- const systemMessages = input.messages.filter((message2) => message2.role === "system");
578409
- const conversationMessages = input.messages.filter((message2) => message2.role !== "system");
578410
- const evidence = (input.toolEvents ?? []).map(evidenceMessage);
578411
- const hints = (input.memoryHints ?? []).filter((hint) => hint.trim().length > 0).slice(-8).map((hint) => ({ role: "system", content: `[MEMORY HINT] ${hint.trim()}` }));
578412
- const contract = input.runState?.completionContract ? [{ role: "system", content: input.runState.completionContract }] : [];
578413
- const beforeMessages = [...systemMessages, ...contract, ...hints, ...evidence, ...conversationMessages];
578414
- const before = estimateTokens3(beforeMessages);
578415
- const budget = input.runState?.tokenBudget;
578416
- let compactedConversation = conversationMessages;
578417
- let compacted = false;
578418
- let evidenceDropped = 0;
578419
- if (allowCompaction && budget && before > budget) {
578420
- const retained = [];
578421
- let used = estimateTokens3([...systemMessages, ...contract, ...hints, ...evidence]);
578422
- for (const message2 of [...conversationMessages].reverse()) {
578423
- const cost = estimateTokens3([message2]);
578424
- if (used + cost > budget)
578425
- continue;
578426
- retained.push(message2);
578427
- used += cost;
578428
- }
578429
- compactedConversation = retained.reverse();
578430
- compacted = compactedConversation.length !== conversationMessages.length;
578431
- evidenceDropped = 0;
578432
- }
578433
- const renderedSystem = [...systemMessages, ...contract, ...hints, ...evidence];
578434
- const after = estimateTokens3([...renderedSystem, ...compactedConversation]);
578435
- return {
578436
- systemMessages: renderedSystem,
578437
- conversationMessages: compactedConversation,
578438
- compacted,
578439
- diagnostics: {
578440
- surface: input.surface,
578441
- tokenEstimateBefore: before,
578442
- tokenEstimateAfter: after,
578443
- compacted,
578444
- compactionStrategy: compacted ? "drop_oldest_non_evidence" : "none",
578445
- evidenceRetained: evidence.length,
578446
- evidenceDropped
578447
- }
578448
- };
578449
- }
578450
- };
578451
- }
578452
- });
578453
-
578454
- // packages/orchestrator/dist/completionLedger.js
578455
- import { mkdirSync as mkdirSync50, readFileSync as readFileSync71, writeFileSync as writeFileSync43 } from "node:fs";
578456
- import { dirname as dirname31 } from "node:path";
578457
- function nowIso2(now = /* @__PURE__ */ new Date()) {
578458
- return now instanceof Date ? now.toISOString() : new Date(now).toISOString();
578459
- }
578460
- function cleanText(value2, max = 600) {
578461
- return String(value2 ?? "").replace(/\s+/g, " ").trim().slice(0, max);
578462
- }
578463
- function nextId2(prefix, count) {
578464
- return `${prefix}_${String(count + 1).padStart(4, "0")}`;
578465
- }
578466
- function createCompletionLedger(input) {
578467
- const ts = nowIso2(input.now);
578468
- return {
578469
- runId: input.runId,
578470
- goal: cleanText(input.goal, 2e3),
578471
- createdAtIso: ts,
578472
- updatedAtIso: ts,
578473
- proposedClaims: [],
578474
- evidence: [],
578475
- critiques: [],
578476
- unresolved: [],
578477
- status: "open"
578478
- };
578479
- }
578480
- function deriveClaimsFromProposedText(input) {
578481
- const raw = String(input.text ?? "").trim();
578482
- if (!raw)
578483
- return [];
578484
- const segments = raw.replace(/\b(?:done|completed|verified)\s*:\s*/gi, "").split(/(?:\n+|;\s+|,\s+(?=(?:and\s+)?(?:sent|built|created|updated|published|verified|tested|fixed|added|removed|deployed|wrote)\b)|\.\s+)/i).map((part) => cleanText(part, 300)).filter((part) => part.length > 0);
578485
- const unique2 = Array.from(new Set(segments.length > 0 ? segments : [cleanText(raw, 300)]));
578486
- const existingIds = new Set((input.existing ?? []).map((claim) => claim.id));
578487
- return unique2.map((text2, index) => {
578488
- const base3 = normalizeCompletionKey(text2, `claim_${index + 1}`).slice(0, 64);
578489
- let id = base3 || `claim_${index + 1}`;
578490
- let suffix = 2;
578491
- while (existingIds.has(id)) {
578492
- id = `${base3}_${suffix++}`;
578493
- }
578494
- existingIds.add(id);
578495
- return {
578496
- id,
578497
- text: text2,
578498
- source: input.source,
578499
- materiality: "high",
578500
- evidenceRequirement: "Observed evidence from this run supports the claim or the final response marks it unverified/blocked.",
578501
- evidenceIds: [],
578502
- status: "unverified"
578503
- };
578504
- });
578505
- }
578506
- function recordCompletionEvidence(ledger, evidence) {
578507
- const entry = {
578508
- id: evidence.id ?? nextId2("ev", ledger.evidence.length),
578509
- kind: evidence.kind,
578510
- observedAtIso: evidence.observedAtIso ?? nowIso2(),
578511
- summary: cleanText(evidence.summary, 1200),
578512
- toolName: evidence.toolName,
578513
- success: evidence.success,
578514
- rawRef: evidence.rawRef
578515
- };
578516
- return {
578517
- ...ledger,
578518
- evidence: [...ledger.evidence, entry],
578519
- updatedAtIso: entry.observedAtIso
578520
- };
578521
- }
578522
- function recordToolEvidence(ledger, input) {
578523
- const summary = [
578524
- input.name,
578525
- input.success === true ? "succeeded" : input.success === false ? "failed" : "observed",
578526
- input.argsKey ? `args=${cleanText(input.argsKey, 180)}` : "",
578527
- input.outputPreview ? `output=${cleanText(input.outputPreview, 700)}` : ""
578528
- ].filter(Boolean).join(" ");
578529
- return recordCompletionEvidence(ledger, {
578530
- kind: "tool_result",
578531
- toolName: input.name,
578532
- success: input.success,
578533
- summary,
578534
- rawRef: input.rawRef
578535
- });
578536
- }
578537
- function addCompletionClaims(ledger, claims) {
578538
- const byId = new Map(ledger.proposedClaims.map((claim) => [claim.id, claim]));
578539
- for (const claim of claims)
578540
- byId.set(claim.id, claim);
578541
- return {
578542
- ...ledger,
578543
- proposedClaims: Array.from(byId.values()),
578544
- updatedAtIso: nowIso2()
578545
- };
578546
- }
578547
- function reconcileClaimsWithEvidence(ledger) {
578548
- const successfulEvidence = ledger.evidence.filter((entry) => entry.success !== false);
578549
- const failedEvidence = ledger.evidence.filter((entry) => entry.success === false);
578550
- const claims = ledger.proposedClaims.map((claim) => {
578551
- const claimTerms = cleanText(claim.text, 300).toLowerCase().split(/[^a-z0-9]+/).filter((part) => part.length >= 4);
578552
- const matches = successfulEvidence.filter((entry) => {
578553
- const haystack = `${entry.toolName ?? ""} ${entry.summary}`.toLowerCase();
578554
- return claimTerms.some((term) => haystack.includes(term));
578555
- });
578556
- const contradictions = failedEvidence.filter((entry) => {
578557
- const haystack = `${entry.toolName ?? ""} ${entry.summary}`.toLowerCase();
578558
- return claimTerms.some((term) => haystack.includes(term));
578559
- });
578560
- if (contradictions.length > 0 && matches.length === 0) {
578561
- return { ...claim, evidenceIds: contradictions.map((entry) => entry.id), status: "contradicted" };
578562
- }
578563
- if (matches.length > 0) {
578564
- return { ...claim, evidenceIds: matches.map((entry) => entry.id), status: "supported" };
578565
- }
578566
- return { ...claim, evidenceIds: [], status: "unverified" };
578567
- });
578568
- return {
578569
- ...ledger,
578570
- proposedClaims: claims,
578571
- updatedAtIso: nowIso2()
578572
- };
578573
- }
578574
- function recordCompletionCritique(ledger, input) {
578575
- const critique = {
578576
- id: input.id ?? nextId2("critique", ledger.critiques.length),
578577
- verdict: input.verdict,
578578
- rationale: cleanText(input.rationale, 1200),
578579
- feedback: input.feedback ? cleanText(input.feedback, 3e3) : void 0,
578580
- recordedAtIso: input.recordedAtIso ?? nowIso2(),
578581
- evidenceSequence: ledger.evidence.length
578582
- };
578583
- return {
578584
- ...ledger,
578585
- critiques: [...ledger.critiques, critique],
578586
- status: input.verdict === "approve" ? "approved" : input.verdict,
578587
- updatedAtIso: critique.recordedAtIso
578588
- };
578589
- }
578590
- function buildCriticPacketFromLedger(ledger) {
578591
- const latestCritique = ledger.critiques.at(-1);
578592
- const evidenceSinceCritique = latestCritique ? ledger.evidence.slice(latestCritique.evidenceSequence) : [];
578593
- const lines = [];
578594
- lines.push("[COMPLETION LEDGER]");
578595
- lines.push(`Run: ${ledger.runId}`);
578596
- lines.push(`Goal: ${ledger.goal || "(not recorded)"}`);
578597
- lines.push(`Status: ${ledger.status}`);
578598
- lines.push("");
578599
- lines.push("Claims:");
578600
- if (ledger.proposedClaims.length === 0)
578601
- lines.push("- none recorded");
578602
- for (const claim of ledger.proposedClaims) {
578603
- lines.push(`- [${claim.status}] ${claim.id}: ${claim.text}`);
578604
- lines.push(` evidence: ${claim.evidenceIds.length > 0 ? claim.evidenceIds.join(", ") : "none"}`);
578605
- lines.push(` requirement: ${claim.evidenceRequirement}`);
578606
- }
578607
- lines.push("");
578608
- lines.push("Evidence:");
578609
- if (ledger.evidence.length === 0)
578610
- lines.push("- none recorded");
578611
- for (const evidence of ledger.evidence.slice(-40)) {
578612
- const status = evidence.success === true ? "ok" : evidence.success === false ? "failed" : "unknown";
578613
- lines.push(`- ${evidence.id} [${status}] ${evidence.kind}${evidence.toolName ? `/${evidence.toolName}` : ""}: ${evidence.summary}`);
578614
- }
578615
- if (latestCritique) {
578616
- lines.push("");
578617
- lines.push("Prior critique:");
578618
- lines.push(`- verdict: ${latestCritique.verdict}`);
578619
- lines.push(`- rationale: ${latestCritique.rationale}`);
578620
- if (latestCritique.feedback)
578621
- lines.push(`- feedback: ${latestCritique.feedback}`);
578622
- lines.push("");
578623
- lines.push("Evidence recorded after prior critique:");
578624
- if (evidenceSinceCritique.length === 0)
578625
- lines.push("- none recorded");
578626
- for (const evidence of evidenceSinceCritique) {
578627
- const status = evidence.success === true ? "ok" : evidence.success === false ? "failed" : "unknown";
578628
- lines.push(`- ${evidence.id} [${status}] ${evidence.summary}`);
578629
- }
578630
- }
578631
- if (ledger.unresolved.length > 0) {
578632
- lines.push("");
578633
- lines.push("Unresolved:");
578634
- for (const item of ledger.unresolved.slice(-20))
578635
- lines.push(`- ${item.text}`);
578636
- }
578637
- return lines.join("\n");
578638
- }
578639
- function saveCompletionLedger(filePath, ledger) {
578640
- mkdirSync50(dirname31(filePath), { recursive: true });
578641
- writeFileSync43(filePath, `${JSON.stringify(ledger, null, 2)}
578642
- `, "utf8");
578643
- }
578644
- function loadCompletionLedger(filePath) {
578645
- return JSON.parse(readFileSync71(filePath, "utf8"));
578646
- }
578647
- var init_completionLedger = __esm({
578648
- "packages/orchestrator/dist/completionLedger.js"() {
578649
- "use strict";
578650
- init_completionContract();
578651
- }
578652
- });
578653
-
578654
579220
  // packages/orchestrator/dist/runEvents.js
578655
579221
  function text(value2, max = 500) {
578656
579222
  const out = String(value2 ?? "").replace(/\s+/g, " ").trim();
@@ -645287,6 +645853,60 @@ var init_telegram_social_state = __esm({
645287
645853
  }
645288
645854
  });
645289
645855
 
645856
+ // packages/cli/src/tui/telegram-vision-router.ts
645857
+ function deriveVisualEvidencePlan(request) {
645858
+ const prompt = request.prompt.toLowerCase();
645859
+ const detail = request.requestedDetail ?? "auto";
645860
+ const needsText = /\b(text|read|ocr|extract|label|word|number|what does it say|transcript|character|letter|digit|spell|transcribe|copy|quote|type|what is written)\b/i.test(prompt);
645861
+ const needsScene = /\b(what|who|where|describe|scene|object|person|identify|tell me about|explain|see|show|happening|look like|recogniz)\b/i.test(prompt) && !needsText;
645862
+ const needsUI = /\b(ui|button|menu|dialog|window|interface|screen|dashboard|form|field|input|select|option|dropdown)\b/i.test(prompt);
645863
+ switch (detail) {
645864
+ case "low":
645865
+ return { stages: [{ kind: "low_fidelity_observation", required: true }], reason: "low detail requested" };
645866
+ case "text":
645867
+ return { stages: [{ kind: "low_fidelity_observation", required: false }, { kind: "ocr", required: true }, { kind: "auxiliary_vision", required: false }], reason: "text extraction requested" };
645868
+ case "full":
645869
+ return { stages: [{ kind: "low_fidelity_observation", required: false }, { kind: "ocr", required: needsText || needsUI }, { kind: "auxiliary_vision", required: true }], reason: "full detail requested" };
645870
+ default:
645871
+ const stages = [{ kind: "low_fidelity_observation", required: false }];
645872
+ if (needsText || needsUI) stages.push({ kind: "ocr", required: true });
645873
+ if (needsScene || needsUI) stages.push({ kind: "auxiliary_vision", required: !needsText && !needsUI });
645874
+ return { stages, reason: needsText ? "text evidence needed" : needsScene ? "scene analysis needed" : needsUI ? "UI/document analysis needed" : "auto" };
645875
+ }
645876
+ }
645877
+ async function executeVisualEvidencePlan(resolution, plan, executor) {
645878
+ const stages = [];
645879
+ for (const stage of plan.stages) {
645880
+ const start2 = Date.now();
645881
+ try {
645882
+ const result = await executor(stage.kind, resolution.path, "auto");
645883
+ stages.push({ ...stage, completed: true, output: result.output, durationMs: result.durationMs });
645884
+ } catch (err) {
645885
+ stages.push({
645886
+ ...stage,
645887
+ completed: false,
645888
+ error: err instanceof Error ? err.message : String(err),
645889
+ durationMs: Date.now() - start2
645890
+ });
645891
+ if (stage.required) break;
645892
+ }
645893
+ }
645894
+ const succeeded = stages.filter((s2) => s2.completed);
645895
+ const finalSummary = succeeded.map((s2) => `${s2.kind}: ${(s2.output ?? "").slice(0, 200)}`).join("\n") || "No evidence extracted";
645896
+ return {
645897
+ resolution,
645898
+ stages,
645899
+ finalSummary,
645900
+ confidence: succeeded.length >= plan.stages.length ? "high" : succeeded.length > 0 ? "medium" : "low",
645901
+ unresolvedGaps: stages.filter((s2) => !s2.completed).map((s2) => `${s2.kind} stage failed: ${s2.error || "unknown"}`)
645902
+ };
645903
+ }
645904
+ var init_telegram_vision_router = __esm({
645905
+ "packages/cli/src/tui/telegram-vision-router.ts"() {
645906
+ "use strict";
645907
+ }
645908
+ });
645909
+
645290
645910
  // packages/cli/src/tui/vision-ingress.ts
645291
645911
  var vision_ingress_exports = {};
645292
645912
  __export(vision_ingress_exports, {
@@ -647569,6 +648189,7 @@ var init_telegram_bridge = __esm({
647569
648189
  init_telegram_reflection_extraction();
647570
648190
  init_telegram_social_state();
647571
648191
  init_dist();
648192
+ init_telegram_vision_router();
647572
648193
  TELEGRAM_TOOL_ACTION_GROUPS = [
647573
648194
  "read",
647574
648195
  "message",
@@ -651666,6 +652287,19 @@ ${mediaContext}` : ""
651666
652287
  error: `Path is outside this Telegram chat's media/workspace scope or does not exist: ${raw || "(empty)"}`
651667
652288
  };
651668
652289
  }
652290
+ resolveVisualMedia(rawValue, chatId, currentMsg, kind = "media") {
652291
+ const result = this.resolveTelegramScopedMediaPath(rawValue, chatId, currentMsg, kind);
652292
+ if (!result.ok) return { ok: false, error: result.error };
652293
+ const mediaEntries = this.recentTelegramMediaEntries(chatId, 60).filter((entry) => this.telegramMediaEntryMatchesKind(entry, kind));
652294
+ const matchingEntry = mediaEntries.find((entry) => resolve56(entry.localPath) === resolve56(result.path));
652295
+ const sourceMessageId = matchingEntry?.messageId ?? currentMsg?.replyToMessageId;
652296
+ const chatKey = chatId !== void 0 ? `chat:${chatId}` : "unknown";
652297
+ const mediaKind = kind === "media" ? matchingEntry && telegramCachedMediaIsImage(matchingEntry) ? "image" : matchingEntry && telegramCachedMediaIsPdf(matchingEntry) ? "pdf" : matchingEntry && telegramCachedMediaIsAudio(matchingEntry) ? "audio" : matchingEntry && telegramCachedMediaIsVideo(matchingEntry) ? "video" : "media" : kind;
652298
+ return {
652299
+ ok: true,
652300
+ resolution: { path: result.path, sourceMessageId, chatKey, mediaKind, safeAlias: basename35(result.path) }
652301
+ };
652302
+ }
651669
652303
  telegramIdentityMediaKind(args) {
651670
652304
  const action = String(args["action"] || "").toLowerCase();
651671
652305
  const relation = String(args["relation"] || "").toLowerCase();
@@ -656366,88 +657000,106 @@ ${conversationStream}`
656366
657000
  }
656367
657001
  async runTelegramChatCompletion(msg, toolContext, mediaContext, onToken) {
656368
657002
  const config = this.agentConfig;
656369
- const backend = new OllamaAgenticBackend(
656370
- config.backendUrl,
656371
- config.model,
656372
- config.apiKey
656373
- );
656374
- const request = telegramThinkSuppressedRequest({
656375
- messages: this.buildTelegramChatMessages(msg, toolContext, mediaContext),
656376
- tools: [],
656377
- temperature: 0.4,
656378
- maxTokens: 1500,
656379
- timeoutMs: Math.max(config.timeoutMs ?? 3e5, 12e4),
656380
- responseFormat: TELEGRAM_CHAT_REPLY_RESPONSE_FORMAT
656381
- });
656382
- let accumulated = "";
656383
- let streamError;
656384
- const sessionKey = this.sessionKeyForMessage(msg);
656385
- const inferenceId = this.registerTelegramInference("chat-fast-path", sessionKey, config.model);
656386
- const streamable = backend;
656387
- const stream = typeof streamable.chatCompletionStream === "function" ? streamable.chatCompletionStream(request) : null;
656388
- try {
656389
- if (stream && typeof stream[Symbol.asyncIterator] === "function") {
656390
- try {
656391
- let lastTokenEmitMs = 0;
656392
- for await (const chunk of stream) {
656393
- if (chunk.type !== "content") continue;
656394
- const piece = chunk.content;
656395
- if (!piece) continue;
656396
- if (chunk.thinking) {
656397
- this.bumpTelegramInferenceTokens(inferenceId, 0, 1);
656398
- if (this.telegramThinkingVisible) {
656399
- const preview = piece.slice(0, 120);
656400
- this.tuiWrite(() => renderTelegramSubAgentEvent(
656401
- msg.username,
656402
- `chat-fast-path thinking: ${JSON.stringify(preview)}`
656403
- ));
656404
- }
656405
- } else {
656406
- this.bumpTelegramInferenceTokens(inferenceId, 1, 0);
656407
- accumulated += piece;
656408
- const now = Date.now();
656409
- if (now - lastTokenEmitMs > 120) {
656410
- lastTokenEmitMs = now;
656411
- const partial = extractPartialTelegramReplyJson(accumulated);
656412
- if (partial !== null) void onToken(partial);
657003
+ return runWithOmniusContext({
657004
+ runId: `chat-${msg.messageId}`,
657005
+ surface: "telegram",
657006
+ projectRoot: this.repoRoot,
657007
+ ownerKind: "chat",
657008
+ ownerId: String(msg.chatId),
657009
+ telegram: {
657010
+ chatId: msg.chatId,
657011
+ chatType: msg.chatType,
657012
+ messageId: msg.messageId,
657013
+ threadId: msg.messageThreadId,
657014
+ userId: msg.fromUserId,
657015
+ username: msg.username || msg.firstName,
657016
+ sessionKey: this.sessionKeyForMessage(msg),
657017
+ toolContext
657018
+ }
657019
+ }, async () => {
657020
+ const backend = new OllamaAgenticBackend(
657021
+ config.backendUrl,
657022
+ config.model,
657023
+ config.apiKey
657024
+ );
657025
+ const request = telegramThinkSuppressedRequest({
657026
+ messages: this.buildTelegramChatMessages(msg, toolContext, mediaContext),
657027
+ tools: [],
657028
+ temperature: 0.4,
657029
+ maxTokens: 1500,
657030
+ timeoutMs: Math.max(config.timeoutMs ?? 3e5, 12e4),
657031
+ responseFormat: TELEGRAM_CHAT_REPLY_RESPONSE_FORMAT
657032
+ });
657033
+ let accumulated = "";
657034
+ let streamError;
657035
+ const sessionKey = this.sessionKeyForMessage(msg);
657036
+ const inferenceId = this.registerTelegramInference("chat-fast-path", sessionKey, config.model);
657037
+ const streamable = backend;
657038
+ const stream = typeof streamable.chatCompletionStream === "function" ? streamable.chatCompletionStream(request) : null;
657039
+ try {
657040
+ if (stream && typeof stream[Symbol.asyncIterator] === "function") {
657041
+ try {
657042
+ let lastTokenEmitMs = 0;
657043
+ for await (const chunk of stream) {
657044
+ if (chunk.type !== "content") continue;
657045
+ const piece = chunk.content;
657046
+ if (!piece) continue;
657047
+ if (chunk.thinking) {
657048
+ this.bumpTelegramInferenceTokens(inferenceId, 0, 1);
657049
+ if (this.telegramThinkingVisible) {
657050
+ const preview = piece.slice(0, 120);
657051
+ this.tuiWrite(() => renderTelegramSubAgentEvent(
657052
+ msg.username,
657053
+ `chat-fast-path thinking: ${JSON.stringify(preview)}`
657054
+ ));
657055
+ }
657056
+ } else {
657057
+ this.bumpTelegramInferenceTokens(inferenceId, 1, 0);
657058
+ accumulated += piece;
657059
+ const now = Date.now();
657060
+ if (now - lastTokenEmitMs > 120) {
657061
+ lastTokenEmitMs = now;
657062
+ const partial = extractPartialTelegramReplyJson(accumulated);
657063
+ if (partial !== null) void onToken(partial);
657064
+ }
656413
657065
  }
656414
657066
  }
656415
- }
656416
- const finalPartial = extractPartialTelegramReplyJson(accumulated);
656417
- if (finalPartial !== null) {
656418
- try {
656419
- await onToken(finalPartial);
656420
- } catch {
657067
+ const finalPartial = extractPartialTelegramReplyJson(accumulated);
657068
+ if (finalPartial !== null) {
657069
+ try {
657070
+ await onToken(finalPartial);
657071
+ } catch {
657072
+ }
656421
657073
  }
657074
+ } catch (err) {
657075
+ streamError = err;
657076
+ accumulated = "";
656422
657077
  }
656423
- } catch (err) {
656424
- streamError = err;
656425
- accumulated = "";
656426
657078
  }
656427
- }
656428
- if (!accumulated.trim()) {
656429
- let result;
656430
- try {
656431
- result = await backend.chatCompletion(request);
656432
- } catch (err) {
656433
- if (streamError) {
656434
- const streamMsg = streamError instanceof Error ? streamError.message : String(streamError);
656435
- const retryMsg = err instanceof Error ? err.message : String(err);
656436
- throw new Error(`streaming failed (${streamMsg}); non-stream retry failed (${retryMsg})`);
657079
+ if (!accumulated.trim()) {
657080
+ let result;
657081
+ try {
657082
+ result = await backend.chatCompletion(request);
657083
+ } catch (err) {
657084
+ if (streamError) {
657085
+ const streamMsg = streamError instanceof Error ? streamError.message : String(streamError);
657086
+ const retryMsg = err instanceof Error ? err.message : String(err);
657087
+ throw new Error(`streaming failed (${streamMsg}); non-stream retry failed (${retryMsg})`);
657088
+ }
657089
+ throw err;
656437
657090
  }
656438
- throw err;
657091
+ this.updateTelegramInferenceFinal(inferenceId, result);
657092
+ accumulated = result.choices[0]?.message?.content ?? "";
657093
+ const fullExtracted = extractPartialTelegramReplyJson(accumulated);
657094
+ if (fullExtracted) await onToken(fullExtracted);
656439
657095
  }
656440
- this.updateTelegramInferenceFinal(inferenceId, result);
656441
- accumulated = result.choices[0]?.message?.content ?? "";
656442
- const fullExtracted = extractPartialTelegramReplyJson(accumulated);
656443
- if (fullExtracted) await onToken(fullExtracted);
657096
+ } finally {
657097
+ this.deregisterTelegramInference(inferenceId);
656444
657098
  }
656445
- } finally {
656446
- this.deregisterTelegramInference(inferenceId);
656447
- }
656448
- const extracted = extractFinalTelegramReplyJson(accumulated);
656449
- if (extracted) return extracted;
656450
- return stripTelegramHiddenThinking(accumulated).trim();
657099
+ const extracted = extractFinalTelegramReplyJson(accumulated);
657100
+ if (extracted) return extracted;
657101
+ return stripTelegramHiddenThinking(accumulated).trim();
657102
+ });
656451
657103
  }
656452
657104
  retainTelegramVisibleReplyDraft(subAgent, draft, streamToolNames = subAgent.currentStreamToolNames) {
656453
657105
  if (subAgent.visibleReplyText) return;
@@ -656530,7 +657182,21 @@ ${conversationStream}`
656530
657182
  // approval on, persistence via unlimited maxTurns above. Both keep
656531
657183
  // brute-force re-engagement and Adversary turn-extension OFF, which is
656532
657184
  // how Telegram avoids the 60+ turn self-talk loops.
656533
- ...isAdminDM ? TELEGRAM_ADMIN_EVIDENCE_OPTIONS : TELEGRAM_PUBLIC_FAST_OPTIONS
657185
+ ...isAdminDM ? TELEGRAM_ADMIN_EVIDENCE_OPTIONS : TELEGRAM_PUBLIC_FAST_OPTIONS,
657186
+ // ── WO #03 (Typed Gateway Event Stream): structured event feed ──
657187
+ onTypedEvent: (event) => {
657188
+ if (event.type === "run_finished") {
657189
+ subAgent.runnerCompleted = event.success;
657190
+ subAgent.runnerStatus = event.status;
657191
+ subAgent.completionBoundarySeen = event.status === "completed";
657192
+ }
657193
+ if (event.type === "completion_incomplete_verification") {
657194
+ subAgent.completionBoundarySeen = false;
657195
+ }
657196
+ if (event.type === "completion_accepted") {
657197
+ subAgent.completionBoundarySeen = true;
657198
+ }
657199
+ }
656534
657200
  });
656535
657201
  runner.setWorkingDirectory(repoRoot);
656536
657202
  subAgent.runner = runner;
@@ -656760,7 +657426,23 @@ ${creativeWorkspace}` : ""}`;
656760
657426
  mediaContext,
656761
657427
  additionalContext
656762
657428
  };
656763
- const result = await runner.run(userPrompt, systemCtx);
657429
+ const result = await runWithOmniusContext({
657430
+ runId: subAgent.viewId,
657431
+ surface: "telegram",
657432
+ projectRoot: repoRoot,
657433
+ ownerKind: "chat",
657434
+ ownerId: String(msg.chatId),
657435
+ telegram: {
657436
+ chatId: msg.chatId,
657437
+ chatType: msg.chatType,
657438
+ messageId: msg.messageId,
657439
+ threadId: msg.messageThreadId,
657440
+ userId: msg.fromUserId,
657441
+ username: msg.username || msg.firstName,
657442
+ sessionKey: sessionContext.sessionKey,
657443
+ toolContext: ctx3
657444
+ }
657445
+ }, () => runner.run(userPrompt, systemCtx));
656764
657446
  subAgent.runnerCompleted = result.completed;
656765
657447
  subAgent.runnerStatus = result.status;
656766
657448
  subAgent.runnerTurns = result.turns;
@@ -658993,15 +659675,23 @@ Scoped workspace: ${scopedRoot}`,
658993
659675
  },
658994
659676
  async execute(args) {
658995
659677
  const start2 = performance.now();
658996
- const resolved = bridge.resolveTelegramScopedMediaPath(args["image"], chatId, currentMsg, "image");
658997
- if (!resolved.ok) {
658998
- return { success: false, output: "", error: resolved.error, durationMs: performance.now() - start2 };
658999
- }
659000
- const detail = normalizeTelegramImageAnalyzeDetail(args["detail"]);
659001
659678
  const question = String(args["question"] ?? args["prompt"] ?? currentMsg?.text ?? "").trim();
659679
+ const detail = normalizeTelegramImageAnalyzeDetail(args["detail"]);
659680
+ const request = {
659681
+ prompt: question,
659682
+ mediaRef: args["image"],
659683
+ surface: "telegram",
659684
+ requestedDetail: detail
659685
+ };
659686
+ const plan = deriveVisualEvidencePlan(request);
659687
+ const mediaResult = bridge.resolveVisualMedia(args["image"], chatId, currentMsg, "image");
659688
+ if (!mediaResult.ok) {
659689
+ return { success: false, output: "", error: mediaResult.error, durationMs: performance.now() - start2 };
659690
+ }
659691
+ const resolution = mediaResult.resolution;
659002
659692
  const stageLines = [
659003
- `Telegram image analysis: media=${basename35(resolved.path)} detail=${detail}`,
659004
- "Stage ladder: low_fidelity_image_read -> basic OCR probe -> advanced OCR when text density/under-extraction warrants it -> Moondream vision when visual QA/captioning is warranted."
659693
+ `Telegram image analysis: media=${resolution.safeAlias} detail=${detail}`,
659694
+ `Evidence plan: ${plan.reason}`
659005
659695
  ];
659006
659696
  const llmParts = [];
659007
659697
  const runStage = async (name10, reason, fn) => {
@@ -659017,75 +659707,75 @@ ${result.llmContent ?? result.output ?? ""}${result.success ? "" : `
659017
659707
  ERROR: ${result.error || "stage failed"}`}`);
659018
659708
  return result;
659019
659709
  };
659020
- const imageRead = await runStage(
659021
- "low_fidelity_image_read",
659022
- "Always start with scoped image metadata and a multimodal image payload for the model.",
659023
- () => new ImageReadTool(repoRoot).execute({
659024
- path: resolved.path,
659025
- ocr: false,
659026
- max_size_kb: typeof args["max_size_kb"] === "number" ? args["max_size_kb"] : 10240
659027
- })
659028
- );
659029
- const textRequested = detail === "text" || detail === "full";
659030
- const visualRequested = detail === "visual" || detail === "full";
659031
- const shouldRunTextProbe = detail !== "visual";
659032
- let textStage = null;
659033
- let textSignal = telegramTextExtractionSignal("");
659034
- if (shouldRunTextProbe) {
659035
- textStage = await runStage(
659036
- "ocr",
659037
- "After low-fidelity intake, basic OCR measures whether text extraction is sufficient before any heavier escalation.",
659038
- () => new OCRTool(repoRoot).execute({
659039
- path: resolved.path,
659040
- language: typeof args["language"] === "string" ? args["language"] : "eng"
659041
- })
659042
- );
659043
- textSignal = telegramTextExtractionSignal(textStage.output ?? "");
659044
- stageLines.push(
659045
- `
659710
+ const executor = async (kind, path12, _execDetail) => {
659711
+ switch (kind) {
659712
+ case "low_fidelity_observation": {
659713
+ const result = await runStage(
659714
+ "low_fidelity_observation",
659715
+ "Always start with scoped image metadata and a multimodal image payload for the model.",
659716
+ () => new ImageReadTool(repoRoot).execute({
659717
+ path: path12,
659718
+ ocr: false,
659719
+ max_size_kb: typeof args["max_size_kb"] === "number" ? args["max_size_kb"] : 10240
659720
+ })
659721
+ );
659722
+ return { output: result.output ?? "", durationMs: result.durationMs };
659723
+ }
659724
+ case "ocr": {
659725
+ const textRequested = detail === "text" || detail === "full";
659726
+ const ocrResult = await runStage(
659727
+ "ocr",
659728
+ "After low-fidelity intake, basic OCR measures whether text extraction is sufficient before any heavier escalation.",
659729
+ () => new OCRTool(repoRoot).execute({
659730
+ path: path12,
659731
+ language: typeof args["language"] === "string" ? args["language"] : "eng"
659732
+ })
659733
+ );
659734
+ let textSignal = telegramTextExtractionSignal(ocrResult.output ?? "");
659735
+ stageLines.push(
659736
+ `
659046
659737
  Text extraction signal: chars=${textSignal.chars}, lines=${textSignal.lines}, longest_line=${textSignal.longestLine}, dense=${textSignal.dense ? "yes" : "no"}.`
659047
- );
659048
- llmParts.push(`Text extraction signal: ${JSON.stringify(textSignal)}`);
659049
- const shouldUseAdvancedOcr = detail === "full" || textSignal.dense || textRequested && !textSignal.present;
659050
- if (shouldUseAdvancedOcr) {
659051
- textStage = await runStage(
659052
- "ocr_image_advanced",
659053
- textSignal.dense ? "Basic OCR observed dense text, so multi-pass OCR is warranted." : "The request emphasized text extraction and basic intake did not provide enough text.",
659054
- () => new OcrImageAdvancedTool(repoRoot).execute({
659055
- image: resolved.path,
659056
- language: typeof args["language"] === "string" ? args["language"] : "eng"
659057
- })
659058
- );
659059
- const advancedSignal = telegramTextExtractionSignal(textStage.output ?? "");
659060
- stageLines.push(
659061
- `
659738
+ );
659739
+ llmParts.push(`Text extraction signal: ${JSON.stringify(textSignal)}`);
659740
+ const shouldUseAdvancedOcr = detail === "full" || textSignal.dense || textRequested && !textSignal.present;
659741
+ if (shouldUseAdvancedOcr) {
659742
+ const advancedResult = await runStage(
659743
+ "ocr_image_advanced",
659744
+ textSignal.dense ? "Basic OCR observed dense text, so multi-pass OCR is warranted." : "The request emphasized text extraction and basic intake did not provide enough text.",
659745
+ () => new OcrImageAdvancedTool(repoRoot).execute({
659746
+ image: path12,
659747
+ language: typeof args["language"] === "string" ? args["language"] : "eng"
659748
+ })
659749
+ );
659750
+ const advancedSignal = telegramTextExtractionSignal(advancedResult.output ?? "");
659751
+ stageLines.push(
659752
+ `
659062
659753
  Advanced text extraction signal: chars=${advancedSignal.chars}, lines=${advancedSignal.lines}, longest_line=${advancedSignal.longestLine}, dense=${advancedSignal.dense ? "yes" : "no"}.`
659063
- );
659064
- llmParts.push(`Advanced text extraction signal: ${JSON.stringify(advancedSignal)}`);
659065
- if (advancedSignal.present || !textSignal.present) textSignal = advancedSignal;
659754
+ );
659755
+ llmParts.push(`Advanced text extraction signal: ${JSON.stringify(advancedSignal)}`);
659756
+ return { output: advancedResult.output ?? ocrResult.output ?? "", durationMs: ocrResult.durationMs + advancedResult.durationMs };
659757
+ }
659758
+ return { output: ocrResult.output ?? "", durationMs: ocrResult.durationMs };
659759
+ }
659760
+ case "auxiliary_vision": {
659761
+ const result = await runStage(
659762
+ "auxiliary_vision",
659763
+ question ? "A visual question is present, so Moondream visual QA is warranted after lower-cost intake." : "Text extraction did not provide enough content or visual detail was requested, so Moondream captioning is warranted.",
659764
+ () => new VisionTool(repoRoot).execute({
659765
+ image: path12,
659766
+ action: question ? "query" : "caption",
659767
+ ...question ? { prompt: question } : {},
659768
+ length: "normal"
659769
+ })
659770
+ );
659771
+ return { output: result.output ?? "", durationMs: result.durationMs };
659772
+ }
659773
+ default:
659774
+ throw new Error(`Unknown evidence stage kind: ${kind}`);
659066
659775
  }
659067
- } else {
659068
- stageLines.push("\n## OCR skipped\nReason: Visual detail was explicitly requested and text extraction was not needed.");
659069
- llmParts.push("## OCR skipped\nReason: Visual detail was explicitly requested and text extraction was not needed.");
659070
- }
659071
- const shouldRunVision = visualRequested || Boolean(question && detail !== "text") || !textSignal.present && detail !== "text";
659072
- let visionStage = null;
659073
- if (shouldRunVision) {
659074
- visionStage = await runStage(
659075
- "vision_moondream",
659076
- question ? "A visual question is present, so Moondream visual QA is warranted after lower-cost intake." : "Text extraction did not provide enough content or visual detail was requested, so Moondream captioning is warranted.",
659077
- () => new VisionTool(repoRoot).execute({
659078
- image: resolved.path,
659079
- action: question ? "query" : "caption",
659080
- ...question ? { prompt: question } : {},
659081
- length: "normal"
659082
- })
659083
- );
659084
- } else {
659085
- stageLines.push("\n## vision_moondream skipped\nReason: OCR/text extraction produced sufficient evidence for the requested detail.");
659086
- llmParts.push("## vision_moondream skipped\nReason: OCR/text extraction produced sufficient evidence for the requested detail.");
659087
- }
659088
- const anySuccess = imageRead.success || Boolean(textStage?.success) || Boolean(visionStage?.success);
659776
+ };
659777
+ const packet = await executeVisualEvidencePlan(resolution, plan, executor);
659778
+ const anySuccess = packet.stages.some((s2) => s2.completed);
659089
659779
  const output = stageLines.join("\n");
659090
659780
  return {
659091
659781
  success: anySuccess,
@@ -681600,12 +682290,13 @@ async function handleV1Run(req3, res) {
681600
682290
  const _rca1EffectiveTimeoutS = timeout2 && timeout2 > 0 ? timeout2 : activeProfile?.limits?.timeout_s && activeProfile.limits.timeout_s > 0 ? activeProfile.limits.timeout_s : 1800;
681601
682291
  const _rca1DeadlineAtMs = Date.now() + (_rca1EffectiveTimeoutS + 60) * 1e3;
681602
682292
  if (job.pid > 0) {
682293
+ const runCtx = getOmniusRunContext();
681603
682294
  registerProcessLease({
681604
682295
  leaseId: runLeaseId,
681605
682296
  pid: job.pid,
681606
682297
  pgid: process.platform === "win32" ? void 0 : job.pid,
681607
- ownerKind: "api_run",
681608
- ownerId: id,
682298
+ ownerKind: runCtx?.ownerKind ?? "api_run",
682299
+ ownerId: runCtx?.ownerId ?? id,
681609
682300
  projectRoot: cwd4,
681610
682301
  lifecycle: "run",
681611
682302
  persistent: false,
@@ -683899,12 +684590,13 @@ ${historyLines}
683899
684590
  detached: true
683900
684591
  });
683901
684592
  if (child.pid) {
684593
+ const chatCtx = getOmniusRunContext();
683902
684594
  registerProcessLease({
683903
684595
  leaseId: chatLeaseId,
683904
684596
  pid: child.pid,
683905
684597
  pgid: process.platform === "win32" ? void 0 : child.pid,
683906
- ownerKind: "chat_run",
683907
- ownerId: inFlightRunId,
684598
+ ownerKind: chatCtx?.ownerKind ?? "chat_run",
684599
+ ownerId: chatCtx?.ownerId ?? inFlightRunId,
683908
684600
  projectRoot: cwdPath,
683909
684601
  lifecycle: "run",
683910
684602
  persistent: false,
@@ -689586,7 +690278,14 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
689586
690278
  }
689587
690279
  }
689588
690280
  resetSessionLock();
689589
- const promise = runner.run(effectiveTask, systemContext).then((result) => {
690281
+ const promise = Promise.resolve(runWithOmniusContext({
690282
+ runId: sessionId,
690283
+ surface: "tui",
690284
+ projectRoot: repoRoot,
690285
+ ownerKind: "tui",
690286
+ ownerId: `session:${sessionId}`
690287
+ }, async () => {
690288
+ const result = await runner.run(effectiveTask, systemContext);
689590
690289
  const tokens = {
689591
690290
  total: result.totalTokens,
689592
690291
  estimated: result.estimatedTokens
@@ -689969,7 +690668,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
689969
690668
  }
689970
690669
  _checkinPoller = null;
689971
690670
  }
689972
- });
690671
+ }));
689973
690672
  return {
689974
690673
  runner,
689975
690674
  promise,
@@ -691150,12 +691849,18 @@ Respond to the scoped Telegram target when complete.`);
691150
691849
  runner.setWorkingDirectory(repoRoot);
691151
691850
  runner.registerTools(buildSubAgentTools(repoRoot, currentConfig).map(adaptTool6));
691152
691851
  runner.registerTool(createTaskCompleteTool(modelTier, repoRoot));
691153
- const result = await runner.run(
691852
+ const result = await runWithOmniusContext({
691853
+ runId: `bg-${Date.now()}`,
691854
+ surface: "background",
691855
+ projectRoot: repoRoot,
691856
+ ownerKind: "tui",
691857
+ ownerId: `session:${process.env["OMNIUS_SESSION_ID"] || "terminal"}`
691858
+ }, () => runner.run(
691154
691859
  prompt,
691155
691860
  `Working directory: ${repoRoot}
691156
691861
 
691157
691862
  This is an independent background session started from /background.`
691158
- );
691863
+ ));
691159
691864
  return [
691160
691865
  result.completed ? "completed" : "incomplete",
691161
691866
  `${result.turns} turns, ${result.toolCalls} tool calls`,
@@ -696998,6 +697703,7 @@ import { dirname as dirname50, join as join164 } from "node:path";
696998
697703
 
696999
697704
  // packages/cli/src/cli.ts
697000
697705
  init_typed_node_events();
697706
+ init_dist5();
697001
697707
  init_dist8();
697002
697708
  import { createInterface } from "node:readline";
697003
697709
  function createCli(options2) {
@@ -697049,7 +697755,13 @@ function createCli(options2) {
697049
697755
  return;
697050
697756
  }
697051
697757
  try {
697052
- const result = await runner.run(input);
697758
+ const result = await runWithOmniusContext({
697759
+ runId: `cli-${Date.now()}`,
697760
+ surface: "tui",
697761
+ projectRoot: options2.projectRoot,
697762
+ ownerKind: "cli",
697763
+ ownerId: `cli:${process.pid}`
697764
+ }, () => runner.run(input));
697053
697765
  console.log("");
697054
697766
  console.log(`[agent] Task completed: ${result.completed ? "success" : "incomplete"}`);
697055
697767
  if (result.summary) {