omnius 1.0.571 → 1.0.572

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
@@ -567847,6 +567847,36 @@ function clip2(value2, max = 500) {
567847
567847
  function listLines(items, empty2 = "- none observed") {
567848
567848
  return items.length > 0 ? items.map((item) => `- ${item}`) : [empty2];
567849
567849
  }
567850
+ function formatWorkspaceInventorySummary(inventory) {
567851
+ if (!inventory)
567852
+ return ["- no bounded workspace inventory was provided"];
567853
+ const files = (inventory.files ?? []).slice(0, 40).map((file) => `${file.path}${file.bytes !== void 0 ? ` (bytes=${file.bytes}` : ""}${file.mtimeMs !== void 0 ? `${file.bytes !== void 0 ? ", " : " ("}mtimeMs=${file.mtimeMs})` : file.bytes !== void 0 ? ")" : ""}`);
567854
+ const dirs = (inventory.dirs ?? []).slice(0, 40).map((dir) => `dir:${dir}`);
567855
+ const summary = [
567856
+ `workspace_root=${inventory.root}`,
567857
+ `files=${inventory.files.length}${inventory.truncated ? "+" : ""}`,
567858
+ `dirs=${(inventory.dirs ?? []).length}`,
567859
+ `requested_max=${inventory.maxFiles}x${inventory.maxDirs}`
567860
+ ];
567861
+ if (!inventory.truncated)
567862
+ summary.push(`inventory_complete=${inventory.files.length > 0 || (inventory.dirs ?? []).length > 0 ? "yes" : "no"}`);
567863
+ const out = [
567864
+ `Generated at: ${inventory.generatedAtIso}`,
567865
+ summary.join("; ")
567866
+ ];
567867
+ if (files.length > 0) {
567868
+ out.push("Representative files:");
567869
+ out.push(...files.map((item) => `- ${item}`));
567870
+ }
567871
+ if (dirs.length > 0) {
567872
+ out.push("Representative directories:");
567873
+ out.push(...dirs.map((item) => `- ${item}`));
567874
+ }
567875
+ if (inventory.truncated) {
567876
+ out.push("- inventory_truncated: run a fresh scan with higher limits to inspect additional paths");
567877
+ }
567878
+ return out;
567879
+ }
567850
567880
  function formatEvidenceEntry(entry) {
567851
567881
  const parts = [
567852
567882
  entry.success === true ? "ok" : entry.success === false ? "failed" : "unknown",
@@ -567892,6 +567922,7 @@ ${String(input.answerText).trim()}` : ""
567892
567922
  ].filter(Boolean).join(" ");
567893
567923
  return `${clip2(file.path, 220)}${meta ? ` (${meta})` : ""}`;
567894
567924
  });
567925
+ const workspaceInventory = formatWorkspaceInventorySummary(input.workspaceInventory);
567895
567926
  const scenarioSeed = deriveScenarioSeed(input);
567896
567927
  const lines = [];
567897
567928
  lines.push(`[COMPLETION META-DECOMPOSITION]`);
@@ -567903,11 +567934,14 @@ ${String(input.answerText).trim()}` : ""
567903
567934
  lines.push(`Proposed completion claim text:`);
567904
567935
  lines.push(proposedClaimText || "(no proposed completion text yet)");
567905
567936
  lines.push(``);
567937
+ lines.push(`Open loops and remaining blockers:`);
567938
+ lines.push(...listLines(unresolvedSignals, "- no open loop / blocker signals currently reported"));
567939
+ lines.push(``);
567906
567940
  lines.push(`Observed run evidence:`);
567907
567941
  lines.push(...listLines(observedEvidence, "- no tool evidence recorded"));
567908
567942
  lines.push(``);
567909
- lines.push(`Unresolved or caution signals:`);
567910
- lines.push(...listLines(unresolvedSignals, "- none recorded"));
567943
+ lines.push(`Workspace inventory (bounded to prevent scan drift):`);
567944
+ lines.push(...workspaceInventory);
567911
567945
  lines.push(``);
567912
567946
  lines.push(`Modified artifact digest:`);
567913
567947
  lines.push(...listLines(modifiedFiles, "- no modified artifacts listed"));
@@ -567953,6 +567987,52 @@ var init_completionContract = __esm({
567953
567987
  // packages/orchestrator/dist/completionLedger.js
567954
567988
  import { mkdirSync as mkdirSync51, readFileSync as readFileSync66, writeFileSync as writeFileSync42 } from "node:fs";
567955
567989
  import { dirname as dirname29 } from "node:path";
567990
+ function setClaimDiscoveryState(ledger, state) {
567991
+ return {
567992
+ ...ledger,
567993
+ claimDiscovery: {
567994
+ ...state,
567995
+ generatedAtIso: nowIso3(),
567996
+ resolvedEvidenceHandles: state.resolvedEvidenceHandles ?? []
567997
+ },
567998
+ updatedAtIso: nowIso3()
567999
+ };
568000
+ }
568001
+ function claimDiscoveryStateFromSurvey(input) {
568002
+ const normalizedInventory = input.boundedInventory;
568003
+ const paths = [...new Set((Array.isArray(input.candidatePaths) ? input.candidatePaths : []).map((value2) => normalizeEvidencePath(value2)).filter(Boolean).slice(0, 16))];
568004
+ const reasons = /* @__PURE__ */ Object.create(null);
568005
+ for (const [rawPath, rawReason] of Object.entries(input.pathReasons ?? {})) {
568006
+ const path16 = normalizeEvidencePath(rawPath);
568007
+ const reason = cleanText(rawReason, 220);
568008
+ if (path16)
568009
+ reasons[path16] = reason || "candidate selected from bounded workspace inventory";
568010
+ }
568011
+ const openDeltas = paths.map((path16) => ({
568012
+ path: path16,
568013
+ reason: reasons[path16] || "candidate selected from bounded workspace inventory"
568014
+ }));
568015
+ const unresolved = Array.isArray(input.unresolvedQuestions) ? input.unresolvedQuestions.map((item) => cleanText(item, 260)).filter(Boolean) : [];
568016
+ const blockers = Array.isArray(input.survivingBlockers) ? input.survivingBlockers.map((item) => cleanText(item, 220)).filter(Boolean) : [];
568017
+ const hasBlockers = blockers.length > 0;
568018
+ const hasQuestions = unresolved.length > 0;
568019
+ const resolvedStatus = paths.length === 0 ? hasBlockers || hasQuestions ? "blocked" : "skipped" : hasBlockers || hasQuestions ? "blocked" : "active";
568020
+ return {
568021
+ status: resolvedStatus,
568022
+ generatedAtIso: nowIso3(),
568023
+ request: cleanText(input.request, 600),
568024
+ context: cleanText(input.context, 480),
568025
+ boundedInventory: normalizedInventory,
568026
+ candidatePaths: paths,
568027
+ pathReasons: reasons,
568028
+ unresolvedQuestions: unresolved.slice(0, 10),
568029
+ openDeltas,
568030
+ survivingBlockers: blockers.slice(0, 8),
568031
+ evidenceHandles: [...new Set(paths.map((path16) => `workspace:${path16}`))],
568032
+ resolvedEvidenceHandles: [],
568033
+ requiresEvidence: typeof input.requiresEvidence === "boolean" ? input.requiresEvidence : true
568034
+ };
568035
+ }
567956
568036
  function nowIso3(now2 = /* @__PURE__ */ new Date()) {
567957
568037
  return now2 instanceof Date ? now2.toISOString() : new Date(now2).toISOString();
567958
568038
  }
@@ -568002,6 +568082,180 @@ function formatEvidenceSummary(summary) {
568002
568082
  function nextId2(prefix, count) {
568003
568083
  return `${prefix}_${String(count + 1).padStart(4, "0")}`;
568004
568084
  }
568085
+ function extractWorkspaceTokens(text2) {
568086
+ const raw = String(text2 ?? "").toLowerCase().replace(/["'`]/g, " ").replace(/[^\w./@-]+/g, " ");
568087
+ return raw.split(/\s+/).filter((value2) => value2.length >= 4);
568088
+ }
568089
+ function extractPathFragments(text2) {
568090
+ const out = [];
568091
+ const pathPattern = /(?:[\w.-]+\/[\w./-]+\.[A-Za-z0-9]+|[\w.-]+\.(?:ts|tsx|js|jsx|mjs|cjs|py|go|rs|cpp|c|h|hpp|java|kt|json|yml|yaml|toml|md|mdx|sh|bash|cxx|swift|rb|php)|[\w./-]+\.[A-Za-z0-9]+)/g;
568092
+ for (const hit of text2.matchAll(pathPattern)) {
568093
+ const value2 = String(hit[0] ?? "").trim();
568094
+ if (!value2)
568095
+ continue;
568096
+ const normalized = value2.replace(/^\.\/+/, "");
568097
+ if (normalized.length > 2)
568098
+ out.push(normalized);
568099
+ }
568100
+ return [...new Set(out)].slice(0, 12);
568101
+ }
568102
+ function tokenizeClaims(text2) {
568103
+ return String(text2 ?? "").split(/[.\n\r!?;]+/).map((item) => item.trim()).filter((item) => item.length > 6).filter((item) => item.length < 260).slice(0, 30);
568104
+ }
568105
+ function estimateClaimMateriality(text2) {
568106
+ const normalized = text2.toLowerCase();
568107
+ if (/\b(blocker|critical|security|production|release|deploy|migrate|migration|regression|customer|public)\b/.test(normalized)) {
568108
+ return "high";
568109
+ }
568110
+ if (/\b(implement|fix|refactor|resolve|wire|integrat|add|remove|change|update)\b/.test(normalized)) {
568111
+ return "medium";
568112
+ }
568113
+ return "low";
568114
+ }
568115
+ function classifyClaimAttainedState(text2) {
568116
+ const normalized = text2.toLowerCase();
568117
+ if (/\b(block|blocked|blocker|cannot verify|unverified|not verified|hold)\b/.test(normalized)) {
568118
+ return "blocked";
568119
+ }
568120
+ if (/\b(simulat|dry.?run|mock|unit test|paper|offline|software.?in.?loop)\b/.test(normalized)) {
568121
+ return "simulation_only";
568122
+ }
568123
+ if (/\b(hil|hardware.?in.?the.?loop|hardware.?test|on.?device|real.?hardware|physical)\b/.test(normalized)) {
568124
+ return "hardware_verified";
568125
+ }
568126
+ if (/\b(integrat|integrated|bridge|transport|serial|can|hardware|device|physical)\b/.test(normalized)) {
568127
+ return "hardware_integrated";
568128
+ }
568129
+ return "unproven";
568130
+ }
568131
+ function deriveClaimRisks(text2) {
568132
+ const normalized = text2.toLowerCase();
568133
+ if (/\b(start|running|daemon|process|service|alive|ready)\b/.test(normalized)) {
568134
+ return {
568135
+ riskCategory: "process_liveness",
568136
+ requiresIndependentEvidence: true,
568137
+ requiredCheck: "Independent runtime state/health check with process or endpoint probe."
568138
+ };
568139
+ }
568140
+ if (/\b(instal|pip|npm|pnpm|apt|brew|cargo|go install|pip install|docker pull)\b/.test(normalized)) {
568141
+ return {
568142
+ riskCategory: "installation",
568143
+ requiresIndependentEvidence: true,
568144
+ requiredCheck: "Independent command query/inspection proving the toolchain exists after the installation claim."
568145
+ };
568146
+ }
568147
+ if (/\b(fixed|repair|resolved|passed|test pass|fix|bug|regression)\b/.test(normalized)) {
568148
+ return {
568149
+ riskCategory: "fix_confirmation",
568150
+ requiresIndependentEvidence: true,
568151
+ requiredCheck: "Re-run the same failure path or equivalent check and capture the successful evidence."
568152
+ };
568153
+ }
568154
+ if (/\b(simulat|dry.?run|mock|fake|virtual)\b/.test(normalized)) {
568155
+ return {
568156
+ riskCategory: "reality",
568157
+ requiresIndependentEvidence: false,
568158
+ requiredCheck: "Label and preserve as simulation-only unless hardware-path evidence exists."
568159
+ };
568160
+ }
568161
+ return {
568162
+ riskCategory: "coverage",
568163
+ requiresIndependentEvidence: false,
568164
+ requiredCheck: "Collect evidence per claim from supported tool outputs and source observations."
568165
+ };
568166
+ }
568167
+ function claimEvidenceNeeds(text2) {
568168
+ const normalized = text2.toLowerCase();
568169
+ const needs = [];
568170
+ const kind = /\b(test|verify|validate|coverage|run|build|lint|check|execute)\b/.test(normalized) ? "tool_result" : /\b(create|write|modify|edit|delete|remove|add|updated|implemented|fix)\b/.test(normalized) ? "file_change" : "runtime_observation";
568171
+ needs.push({
568172
+ handle: `${kind}:in_scope`,
568173
+ evidenceKind: kind,
568174
+ rationale: `Evidence supporting the in-scope portion of: ${cleanText(text2, 120)}`
568175
+ });
568176
+ if (/\b(runtime|process|service|daemon|endpoint|server)\b/.test(normalized)) {
568177
+ needs.push({
568178
+ handle: "verification:post-change",
568179
+ evidenceKind: "runtime_observation",
568180
+ rationale: "Observed runtime confirmation after the claimed change."
568181
+ });
568182
+ }
568183
+ if (/\b(serial|hardware|device|controller|transport)\b/.test(normalized)) {
568184
+ needs.push({
568185
+ handle: "delivery:hardware-path",
568186
+ evidenceKind: "delivery",
568187
+ rationale: "Hardware-path or transport evidence that clarifies simulation/hardware status."
568188
+ });
568189
+ }
568190
+ return needs;
568191
+ }
568192
+ function findInventoryMatches(statement, workspaceInventory) {
568193
+ if (!workspaceInventory)
568194
+ return [];
568195
+ const tokens = extractWorkspaceTokens(statement);
568196
+ const candidatePaths = workspaceInventory.files.map((entry) => entry.path);
568197
+ const seen = /* @__PURE__ */ new Set();
568198
+ const matches = [];
568199
+ const literalPathHints = extractPathFragments(statement);
568200
+ for (const hint of literalPathHints) {
568201
+ const normalized = hint.toLowerCase();
568202
+ const exact = candidatePaths.find((path16) => path16.toLowerCase() === normalized);
568203
+ if (exact)
568204
+ seen.add(exact);
568205
+ }
568206
+ for (const path16 of candidatePaths) {
568207
+ if (matches.length >= 5 || seen.size >= 8)
568208
+ break;
568209
+ const lower = path16.toLowerCase();
568210
+ const tokenHits = tokens.filter((token) => lower.includes(token));
568211
+ if (tokenHits.length >= 2 || tokenHits.length >= 1 && literalPathHints.length === 0) {
568212
+ if (!seen.has(path16)) {
568213
+ seen.add(path16);
568214
+ }
568215
+ }
568216
+ }
568217
+ for (const path16 of seen)
568218
+ matches.push(path16);
568219
+ if (literalPathHints.length > 0 && matches.length === 0) {
568220
+ for (const path16 of candidatePaths) {
568221
+ for (const hint of literalPathHints) {
568222
+ if (path16.toLowerCase().includes(hint.toLowerCase())) {
568223
+ matches.push(path16);
568224
+ break;
568225
+ }
568226
+ }
568227
+ if (matches.length >= 6)
568228
+ break;
568229
+ }
568230
+ }
568231
+ return matches.slice(0, 6);
568232
+ }
568233
+ function claimDiscoveryControllerSignals(stage2) {
568234
+ if (!stage2)
568235
+ return [];
568236
+ const openDeltas = (stage2.openDeltas ?? []).slice(0, 10);
568237
+ const evidenceHandles = stage2.evidenceHandles ?? [];
568238
+ const resolvedEvidenceHandles = stage2.resolvedEvidenceHandles ?? [];
568239
+ const survivingBlockers = stage2.survivingBlockers ?? [];
568240
+ const unresolvedQuestions = stage2.unresolvedQuestions ?? [];
568241
+ const boundedInventory = stage2.boundedInventory;
568242
+ const boundedDirs = boundedInventory?.dirs ?? [];
568243
+ const resolvedCount = Math.min(evidenceHandles.length, new Set(resolvedEvidenceHandles).size);
568244
+ const unresolvedEvidenceCount = Math.max(evidenceHandles.length - resolvedCount, 0);
568245
+ return [
568246
+ "[COMPLETION CLAIM DISCOVERY]",
568247
+ `status=${stage2.status ?? "skipped"} generated_at=${stage2.generatedAtIso ?? ""}`,
568248
+ `requires_evidence=${stage2.requiresEvidence ? "true" : "false"}`,
568249
+ `bounded_inventory=${boundedInventory ? `${boundedInventory.root}|files=${boundedInventory.files.length}|dirs=${boundedDirs.length}|truncated=${Boolean(boundedInventory.truncated)}` : "none"}`,
568250
+ `candidate_paths=${(stage2.candidatePaths ?? []).join(",") || "none"}`,
568251
+ `open_deltas=${openDeltas.map((delta) => `${delta.path} :: ${delta.reason}`.replace(/\s+/g, " ")).join(" | ") || "none"}`,
568252
+ `open_delta_count=${openDeltas.length} unresolved_evidence_count=${unresolvedEvidenceCount}`,
568253
+ `surviving_blockers=${survivingBlockers.join(" | ") || "none"}`,
568254
+ `unresolved_questions=${unresolvedQuestions.join(" | ") || "none"}`,
568255
+ `evidence_handles=${evidenceHandles.join(",") || "none"}`,
568256
+ `resolved_evidence_handles=${resolvedEvidenceHandles.join(",") || "none"}`
568257
+ ];
568258
+ }
568005
568259
  function createCompletionLedger(input) {
568006
568260
  const ts = nowIso3(input.now);
568007
568261
  return {
@@ -568018,28 +568272,68 @@ function createCompletionLedger(input) {
568018
568272
  };
568019
568273
  }
568020
568274
  function deriveClaimsFromProposedText(input) {
568021
- const raw = String(input.text ?? "").trim();
568022
- if (!raw)
568275
+ return deriveStructuredClaims({
568276
+ taskText: input.taskText,
568277
+ proposedSummary: input.text,
568278
+ source: input.source,
568279
+ existing: input.existing,
568280
+ workspaceInventory: input.workspaceInventory,
568281
+ maxClaims: 12
568282
+ });
568283
+ }
568284
+ function deriveStructuredClaims(input) {
568285
+ const proposed = String(input.proposedSummary ?? "").trim();
568286
+ const task = String(input.taskText ?? "").trim();
568287
+ const baseText = [proposed, task].filter(Boolean).join("\n");
568288
+ const statements = tokenizeClaims(baseText);
568289
+ if (statements.length === 0)
568023
568290
  return [];
568024
568291
  const existingIds = new Set((input.existing ?? []).map((claim) => claim.id));
568025
- const text2 = cleanText(raw, 1200);
568026
- const base3 = normalizeCompletionKey(text2, "claim").slice(0, 64);
568027
- let id2 = base3 || "claim";
568028
- let suffix = 2;
568029
- while (existingIds.has(id2)) {
568030
- id2 = `${base3}_${suffix++}`;
568031
- }
568032
- return [
568033
- {
568292
+ const maxClaims = Math.max(1, Math.min(32, input.maxClaims ?? 12));
568293
+ const seen = /* @__PURE__ */ new Set();
568294
+ const claims = [];
568295
+ for (const statementRaw of statements) {
568296
+ if (claims.length >= maxClaims)
568297
+ break;
568298
+ const text2 = cleanText(statementRaw, 220);
568299
+ if (!text2)
568300
+ continue;
568301
+ const base3 = normalizeCompletionKey(text2, "claim").slice(0, 64) || "claim";
568302
+ let id2 = base3;
568303
+ let suffix = 2;
568304
+ while (existingIds.has(id2) || seen.has(id2)) {
568305
+ id2 = `${base3}_${suffix++}`;
568306
+ }
568307
+ const risk = deriveClaimRisks(text2);
568308
+ const needs = claimEvidenceNeeds(text2);
568309
+ const evidenceHandles = [
568310
+ ...needs.map((need) => need.handle),
568311
+ ...findInventoryMatches(text2, input.workspaceInventory).map((path16) => `workspace:${path16}`)
568312
+ ];
568313
+ const workspaceSignals = findInventoryMatches(text2, input.workspaceInventory);
568314
+ const sourceSignals = [
568315
+ input.taskText ? "task" : "proposed_text",
568316
+ ...extractPathFragments(statementRaw).slice(0, 2)
568317
+ ].filter(Boolean);
568318
+ claims.push({
568034
568319
  id: id2,
568035
568320
  text: text2,
568036
- source: input.source,
568037
- materiality: "high",
568038
- evidenceRequirement: "Explicit evidenceIds must be attached by the caller, or the claim remains unverified for critic review.",
568321
+ source: input.source ?? "derived",
568322
+ materiality: estimateClaimMateriality(statementRaw),
568323
+ evidenceRequirement: "Attach explicit evidenceIds that match the listed evidence handles and state.",
568324
+ attainedState: classifyClaimAttainedState(text2),
568325
+ riskCategory: risk.riskCategory,
568326
+ requiresIndependentEvidence: risk.requiresIndependentEvidence,
568327
+ requiredCheck: risk.requiredCheck,
568328
+ evidenceNeeds: needs,
568329
+ sourceSignals,
568330
+ workspaceSignals,
568039
568331
  evidenceIds: [],
568040
568332
  status: "unverified"
568041
- }
568042
- ];
568333
+ });
568334
+ seen.add(id2);
568335
+ }
568336
+ return claims;
568043
568337
  }
568044
568338
  function recordCompletionEvidence(ledger, evidence) {
568045
568339
  const targetPaths = cleanTargetPaths(evidence.targetPaths);
@@ -568138,14 +568432,42 @@ function buildCriticPacketFromLedger(ledger) {
568138
568432
  lines.push(`Run: ${ledger.runId}`);
568139
568433
  lines.push(`Goal: ${ledger.goal || "(not recorded)"}`);
568140
568434
  lines.push(`Status: ${ledger.status}`);
568435
+ lines.push(`Claims discovered: ${ledger.proposedClaims.length}`);
568436
+ if (ledger.claimDiscovery) {
568437
+ lines.push("");
568438
+ lines.push("Claim Discovery:");
568439
+ lines.push(` status=${ledger.claimDiscovery.status}`);
568440
+ lines.push(` generated_at=${ledger.claimDiscovery.generatedAtIso}`);
568441
+ lines.push(` candidate_paths=${ledger.claimDiscovery.candidatePaths.join(",") || "none"}`);
568442
+ lines.push(` open_deltas=${ledger.claimDiscovery.openDeltas.map((delta) => `${delta.path} :: ${delta.reason}`).slice(0, 10).join(" | ") || "none"}`);
568443
+ lines.push(` surviving_blockers=${ledger.claimDiscovery.survivingBlockers.join(" | ") || "none"}`);
568444
+ lines.push(` unresolved_questions=${ledger.claimDiscovery.unresolvedQuestions.join(" | ") || "none"}`);
568445
+ lines.push(` evidence_handles=${ledger.claimDiscovery.evidenceHandles.join(",") || "none"}`);
568446
+ lines.push(` resolved_evidence_handles=${ledger.claimDiscovery.resolvedEvidenceHandles.join(",") || "none"}`);
568447
+ }
568141
568448
  lines.push("");
568142
568449
  lines.push("Claims:");
568143
568450
  if (ledger.proposedClaims.length === 0)
568144
568451
  lines.push("- none recorded");
568145
568452
  for (const claim of ledger.proposedClaims) {
568146
- lines.push(`- [${claim.status}] ${claim.id}: ${claim.text}`);
568453
+ const handles = claim.evidenceNeeds.length === 0 ? "none" : claim.evidenceNeeds.map((need) => need.handle).join(", ");
568454
+ lines.push(`- [${claim.status}] ${claim.id} (${claim.attainedState}): ${claim.text}`);
568455
+ lines.push(` source: ${claim.source} materiality:${claim.materiality}`);
568147
568456
  lines.push(` evidence: ${claim.evidenceIds.length > 0 ? claim.evidenceIds.join(", ") : "none"}`);
568148
- lines.push(` requirement: ${claim.evidenceRequirement}`);
568457
+ lines.push(` evidence_handles: ${handles}`);
568458
+ if (claim.workspaceSignals.length > 0) {
568459
+ lines.push(` workspace_signals: ${claim.workspaceSignals.join(", ")}`);
568460
+ }
568461
+ if (claim.sourceSignals.length > 0) {
568462
+ lines.push(` source_signals: ${claim.sourceSignals.join(", ")}`);
568463
+ }
568464
+ lines.push(` requirement: ${claim.evidenceRequirement} ${claim.requiresIndependentEvidence ? "[independent evidence required]" : ""}`);
568465
+ if (claim.riskCategory && claim.riskCategory !== "unknown") {
568466
+ lines.push(` risk: ${claim.riskCategory}`);
568467
+ if (claim.requiredCheck) {
568468
+ lines.push(` required_check: ${claim.requiredCheck}`);
568469
+ }
568470
+ }
568149
568471
  }
568150
568472
  lines.push("");
568151
568473
  lines.push("Evidence:");
@@ -568232,6 +568554,27 @@ function evidenceTargetPaths(entry) {
568232
568554
  }
568233
568555
  return cleanTargetPaths(paths);
568234
568556
  }
568557
+ function claimDiscoveryResolvedHandles(ledger, state) {
568558
+ if (!state)
568559
+ return [];
568560
+ const inspected = /* @__PURE__ */ new Set();
568561
+ const candidatePaths = [...state.candidatePaths].map((value2) => normalizeEvidencePath(value2)).filter(Boolean).map((path16) => path16.replace(/^\/+/, ""));
568562
+ for (const entry of ledger.evidence) {
568563
+ if (entry.success !== true)
568564
+ continue;
568565
+ for (const rawPath of evidenceTargetPaths(entry)) {
568566
+ const path16 = normalizeEvidencePath(rawPath);
568567
+ if (!path16)
568568
+ continue;
568569
+ const normalized = path16.replace(/^\/+/, "");
568570
+ const matched = candidatePaths.find((candidate) => pathsEquivalent(candidate, normalized));
568571
+ if (matched) {
568572
+ inspected.add(`workspace:${matched}`);
568573
+ }
568574
+ }
568575
+ }
568576
+ return [...inspected];
568577
+ }
568235
568578
  function pathsEquivalent(a2, b) {
568236
568579
  const left = normalizeEvidencePath(a2);
568237
568580
  const right = normalizeEvidencePath(b);
@@ -568803,18 +569146,41 @@ function clean3(value2, max) {
568803
569146
  return String(value2 ?? "").replace(/\s+/g, " ").trim().slice(0, max);
568804
569147
  }
568805
569148
  function selectedEvidence(ledger) {
568806
- if (!ledger)
568807
- return { evidenceIds: [], artifactHashes: [] };
569149
+ if (!ledger) {
569150
+ return {
569151
+ evidenceIds: [],
569152
+ commandReceipts: [],
569153
+ artifactHashes: []
569154
+ };
569155
+ }
568808
569156
  const candidates = ledger.evidence.filter((entry) => entry.success === true && (entry.role === "verification" || entry.role === "mutation")).slice(-16);
568809
569157
  const artifacts = /* @__PURE__ */ new Map();
569158
+ const commandReceipts = [];
568810
569159
  for (const entry of candidates) {
568811
569160
  for (const item of entry.receipt?.artifactHashes ?? []) {
568812
569161
  if (item.path && item.sha256)
568813
569162
  artifacts.set(item.path, item.sha256);
568814
569163
  }
569164
+ if (entry.receipt) {
569165
+ const receipt = entry.receipt;
569166
+ commandReceipts.push({
569167
+ evidenceId: entry.id,
569168
+ toolName: entry.toolName ?? "unknown",
569169
+ role: entry.role ?? "unknown",
569170
+ command: receipt.command ?? "",
569171
+ canonicalCommand: receipt.canonicalCommand ?? "",
569172
+ cwd: receipt.cwd ?? "",
569173
+ exitCode: receipt.exitCode ?? null,
569174
+ timedOut: Boolean(receipt.timedOut),
569175
+ startedAtIso: receipt.startedAtIso ?? "",
569176
+ finishedAtIso: receipt.finishedAtIso ?? "",
569177
+ artifactHashes: entry.receipt.artifactHashes?.length ? entry.receipt.artifactHashes : []
569178
+ });
569179
+ }
568815
569180
  }
568816
569181
  return {
568817
569182
  evidenceIds: candidates.map((entry) => entry.id),
569183
+ commandReceipts,
568818
569184
  artifactHashes: [...artifacts.entries()].map(([path16, sha2567]) => ({
568819
569185
  path: path16,
568820
569186
  sha256: sha2567
@@ -568842,6 +569208,7 @@ function buildCompletionFinalizationRecord(input) {
568842
569208
  summary: clean3(input.summary, 4e3),
568843
569209
  committedAtIso,
568844
569210
  evidenceIds: evidence.evidenceIds,
569211
+ commandReceipts: evidence.commandReceipts,
568845
569212
  artifactHashes: evidence.artifactHashes,
568846
569213
  projections: {
568847
569214
  ledger: "pending",
@@ -577895,16 +578262,90 @@ var init_consolidation_runtime = __esm({
577895
578262
  });
577896
578263
 
577897
578264
  // packages/orchestrator/dist/completion-evidence-gate.js
578265
+ function normalizedEvidenceText(text2) {
578266
+ return String(text2 ?? "").toLowerCase();
578267
+ }
577898
578268
  function classifyCompletionClaim(text2) {
577899
- void text2;
578269
+ const normalized = normalizedEvidenceText(text2);
578270
+ if (!normalized) {
578271
+ return {
578272
+ category: null,
578273
+ requiresIndependentEvidence: false,
578274
+ requiredCheck: ""
578275
+ };
578276
+ }
578277
+ const processLiveness = /\b(daemon|service|process|server|port|listener|runtime|pid|socket|endpoint)\b/.test(normalized) && /\b(start(ed|ing)?|run(ning)?|up|ready|alive|online|boot(ed|ing)?|initialized|listening)\b/.test(normalized);
578278
+ if (processLiveness) {
578279
+ return {
578280
+ category: "process_liveness",
578281
+ requiresIndependentEvidence: true,
578282
+ requiredCheck: "Independent runtime verification (process/pid/health/port check) after the claimed state change."
578283
+ };
578284
+ }
578285
+ if (/\b(instal|npm|pnpm|yarn|pip\s+install|go\s+install|cargo\s+install|apt\s+get|brew\s+install|dnf|yum|apk add|make\s+install)\b/.test(normalized)) {
578286
+ return {
578287
+ category: "installation",
578288
+ requiresIndependentEvidence: true,
578289
+ requiredCheck: "Independent command-level availability check for the installed artifact after change."
578290
+ };
578291
+ }
578292
+ const fixHint = /(fix|fixed|resolved|repair|patched|correct|address|addressed)\b/.test(normalized);
578293
+ const fixTarget = /(bug|regression|failure|error|issue|test|build|lint|crash|exception|pass|coverage)\b/.test(normalized);
578294
+ if (fixHint && fixTarget) {
578295
+ return {
578296
+ category: "fix_confirmation",
578297
+ requiresIndependentEvidence: true,
578298
+ requiredCheck: "Rerun the original failing command path and capture a passing result as evidence."
578299
+ };
578300
+ }
578301
+ if (/(simulat|dry.?run|mock|mocked|virtual|paper|emulat)\b/.test(normalized)) {
578302
+ return {
578303
+ category: "reality",
578304
+ requiresIndependentEvidence: false,
578305
+ requiredCheck: "Mark as simulation-only unless paired with a grounded hardware/live execution claim."
578306
+ };
578307
+ }
577900
578308
  return {
577901
578309
  category: null,
577902
578310
  requiresIndependentEvidence: false,
577903
578311
  requiredCheck: ""
577904
578312
  };
577905
578313
  }
577906
- function detectExitCodeMisread(text2) {
577907
- void text2;
578314
+ function detectExitCodeMisread(input) {
578315
+ const source = typeof input === "string" ? {
578316
+ statement: input,
578317
+ command: "",
578318
+ output: "",
578319
+ exitCode: null,
578320
+ canonicalCommand: ""
578321
+ } : {
578322
+ statement: input.statement ?? "",
578323
+ command: input.command ?? input.canonicalCommand ?? "",
578324
+ output: input.output ?? "",
578325
+ exitCode: typeof input.exitCode === "number" && Number.isFinite(input.exitCode) ? input.exitCode : null,
578326
+ canonicalCommand: ""
578327
+ };
578328
+ const statement = normalizedEvidenceText(source.statement);
578329
+ const command = normalizedEvidenceText(source.command);
578330
+ const output = normalizedEvidenceText(source.output);
578331
+ const exitCode = source.exitCode;
578332
+ if (exitCode !== null && exitCode !== 0 && /\b(success|pass(?:ed|es)?|succeed(?:ed|s)?|ok|completed|done|finished|verified)\b/.test(statement)) {
578333
+ return true;
578334
+ }
578335
+ if (/\|\|\s*(true|:|exit\s+0)/.test(command))
578336
+ return true;
578337
+ if (/\bset\s*\+e\b/.test(command))
578338
+ return true;
578339
+ if (/;\s*\(\s*/.test(command))
578340
+ return true;
578341
+ if (command.includes("|") && !/\bset\s+-o\s+pipefail\b/.test(statement + " " + command)) {
578342
+ return true;
578343
+ }
578344
+ if (/\b\S+\s&\s*$/.test(command.trim()))
578345
+ return true;
578346
+ if (/\bexit(ed|ion)?\s+code\s*[1-9]\d*/.test(statement + " " + output)) {
578347
+ return true;
578348
+ }
577908
578349
  return false;
577909
578350
  }
577910
578351
  function auditCompletionClaims(claims) {
@@ -581059,8 +581500,8 @@ var init_evidenceLedger = __esm({
581059
581500
  }
581060
581501
  /**
581061
581502
  * Return a bounded, read-only projection for components that need to make a
581062
- * routing decision from observed workspace state (for example Feature Loop
581063
- * survey grounding). Callers cannot mutate ledger entries through this
581503
+ * routing decision from observed workspace state (for example claim-discovery
581504
+ * grounding). Callers cannot mutate ledger entries through this
581064
581505
  * result, preserving the ledger as the single freshness authority.
581065
581506
  */
581066
581507
  snapshot(maxEntries = 24) {
@@ -586977,7 +587418,7 @@ var init_longhaul_integration = __esm({
586977
587418
  }
586978
587419
  /**
586979
587420
  * WO-6 (spec §2.5): seed the locked contract from the planner's
586980
- * `LockedContract` at PLAN time. The Feature Loop calls this after the
587421
+ * `LockedContract` at PLAN time. The claim-discovery planner path calls this after the
586981
587422
  * planner emits its artefact, so the breaker's "regenerate from the locked
586982
587423
  * contract" guidance has a real target from the first boundary unit — without
586983
587424
  * waiting for coherent code to accumulate one. Idempotent + fault-tolerant.
@@ -589248,515 +589689,6 @@ var init_git_progress = __esm({
589248
589689
  }
589249
589690
  });
589250
589691
 
589251
- // packages/orchestrator/dist/featurePlanner.js
589252
- import fs7 from "node:fs";
589253
- import path9 from "node:path";
589254
- function classifyKind(survey) {
589255
- const files = survey.files ?? [];
589256
- const newSym = (survey.newSymbols ?? []).length;
589257
- const req3 = survey.request.toLowerCase();
589258
- if (/\b(investigat|why does|how does|trace|understand|root cause|diagnos|explain)\b/.test(req3) && newSym === 0 && files.length <= 2) {
589259
- return "investigation";
589260
- }
589261
- if (/\b(bug|fix|broken|regression|crash|incorrect|fails?|misbehav)/.test(req3) && newSym === 0) {
589262
- return "bugfix";
589263
- }
589264
- if (/\b(refactor|restructure|rename|clean up|simplif|migrate|consolidate)\b/.test(req3) && newSym === 0) {
589265
- return "refactor";
589266
- }
589267
- if (/\b(wir|connect|integrate|hook up|plumb|bridge|glue)\b/.test(req3) && files.length >= 2) {
589268
- return "wiring";
589269
- }
589270
- if (newSym > 0 || /\b(new|create|add|implement|build|introduce|scaffold)\b/.test(req3)) {
589271
- return "new-module";
589272
- }
589273
- return "new-module";
589274
- }
589275
- function guessKind(name10) {
589276
- if (/^(I[A-Z]|.*Interface|.*Contract|.*Spec|.*Event|.*Meta|.*Config|.*State)$/.test(name10)) {
589277
- return "interface";
589278
- }
589279
- if (/^(T|Type|.*Type)$/.test(name10))
589280
- return "type";
589281
- if (/^(E|Enum|.*Kind|.*Status|.*Mode)$/.test(name10))
589282
- return "enum";
589283
- if (/^[A-Z]/.test(name10))
589284
- return "class";
589285
- return "function";
589286
- }
589287
- function buildLockedContract(kind, survey) {
589288
- const symbols = [];
589289
- if (kind === "refactor") {
589290
- for (const name10 of survey.existingSymbols ?? []) {
589291
- symbols.push({ name: name10, kind: guessKind(name10), fields: [] });
589292
- }
589293
- } else if (kind === "new-module") {
589294
- for (const name10 of survey.newSymbols ?? []) {
589295
- symbols.push({ name: name10, kind: guessKind(name10), fields: [] });
589296
- }
589297
- }
589298
- return { symbols };
589299
- }
589300
- function decomposeFeature(survey, kind) {
589301
- const units = [];
589302
- const evidenceRefs = featureEvidenceRefs(survey);
589303
- const unresolvedQuestion = survey.unresolvedQuestions?.[0] ?? (evidenceRefs.length === 0 ? "Which current files, symbols, and tests govern this unit? Inspect them before proposing a mutation." : void 0);
589304
- const returnContract = "Return the direct result with cited observations, relevant/changed paths, verification or blocker, and the next parent decision.";
589305
- const withGrounding = (unit) => ({
589306
- ...unit,
589307
- evidenceRefs,
589308
- ...unresolvedQuestion ? { unresolvedQuestion } : {},
589309
- returnContract
589310
- });
589311
- if (kind === "new-module") {
589312
- const syms = survey.newSymbols ?? [];
589313
- if (syms.length === 0) {
589314
- units.push(withGrounding({
589315
- label: "Establish the module boundary and implement the evidenced unit",
589316
- size: "large",
589317
- detail: "Do not scaffold from the request alone. First identify the owning entry point, adjacent contract, and test surface from current evidence."
589318
- }));
589319
- } else {
589320
- for (const name10 of syms) {
589321
- units.push({
589322
- ...withGrounding({
589323
- label: `Implement ${name10} within its evidenced owner`,
589324
- size: "small",
589325
- detail: "Confirm the symbol's owning module and contract before editing; do not infer a file path from the feature label."
589326
- }),
589327
- expectedSymbols: [name10]
589328
- });
589329
- }
589330
- }
589331
- } else if (kind === "refactor") {
589332
- units.push(withGrounding({
589333
- label: "Refactor only the evidenced public surface",
589334
- size: survey.files.length > 1 ? "large" : "small"
589335
- }));
589336
- } else if (kind === "bugfix") {
589337
- units.push(withGrounding({
589338
- label: "Reproduce the evidenced failure, make the smallest justified fix, and verify it",
589339
- size: "small"
589340
- }));
589341
- } else if (kind === "wiring") {
589342
- units.push(withGrounding({
589343
- label: "Connect the evidenced module boundaries",
589344
- size: survey.files.length > 2 ? "large" : "small"
589345
- }));
589346
- } else {
589347
- units.push(withGrounding({
589348
- label: "Investigate the evidence gap and report the next justified action",
589349
- size: "small"
589350
- }));
589351
- }
589352
- return units;
589353
- }
589354
- function featureEvidenceRefs(survey) {
589355
- const declared = (survey.evidence ?? []).map((item) => item.ref.trim()).filter(Boolean).slice(0, 6);
589356
- if (declared.length > 0)
589357
- return declared;
589358
- return survey.files.map((file) => `survey:file:${file.path}`).filter(Boolean).slice(0, 6);
589359
- }
589360
- function buildFeatureUnitRequest(input) {
589361
- const evidence = (input.survey.evidence ?? []).filter((item) => !input.unit.evidenceRefs?.length || input.unit.evidenceRefs.includes(item.ref)).slice(0, 6);
589362
- const fallbackEvidence = evidence.length > 0 ? evidence : input.survey.files.slice(0, 6).map((file) => ({
589363
- ref: `survey:file:${file.path}`,
589364
- detail: `${file.path}${file.role ? ` — ${file.role}` : ""}`,
589365
- freshness: "unknown"
589366
- }));
589367
- const lines = [
589368
- "[FEATURE UNIT EVIDENCE BRIEF]",
589369
- `Parent request: ${input.parentRequest.slice(0, 900)}`,
589370
- `Requested unit: ${input.unit.label}`,
589371
- `Why now: this unit was selected from the current feature survey, not from a task label alone.`,
589372
- "Evidence:",
589373
- ...fallbackEvidence.length > 0 ? fallbackEvidence.map((item) => `- [${item.freshness ?? "unknown"}] ${item.ref}: ${item.detail.slice(0, 360)}`) : ["- No current code observation is available; discovery is required before mutation."],
589374
- input.unit.unresolvedQuestion ? `Open question: ${input.unit.unresolvedQuestion}` : null,
589375
- "Scope: stay within this unit and directly implicated code; do not broaden the feature without returning to the parent.",
589376
- `Return contract: ${input.unit.returnContract ?? "Return evidence, verification or blocker, and the next parent decision."}`,
589377
- "",
589378
- "Work protocol: inspect the cited files/contracts first. Only mutate after a fresh observation identifies the exact target; if the evidence does not support a target, report the gap instead of fabricating one."
589379
- ];
589380
- return lines.filter((line) => Boolean(line)).join("\n");
589381
- }
589382
- function renderSpecMarkdown(input) {
589383
- const { kind, survey, lockedContract, completionContract, decomposition, prose } = input;
589384
- const lines = [];
589385
- lines.push(`# Feature Plan — ${kind}`);
589386
- lines.push("");
589387
- lines.push(`**Request:** ${survey.request}`);
589388
- lines.push("");
589389
- lines.push(`**Node kind:** \`${kind}\` (selected by CLASSIFY over the survey signals)`);
589390
- lines.push("");
589391
- if (prose) {
589392
- lines.push(`## 1. Intent`);
589393
- lines.push("");
589394
- lines.push(prose.trim());
589395
- lines.push("");
589396
- }
589397
- lines.push(`## 2. Survey (codebase as-is)`);
589398
- lines.push("");
589399
- if (survey.files.length > 0) {
589400
- for (const f2 of survey.files) {
589401
- const refs = f2.lineRefs?.length ? `:${f2.lineRefs.join(",")}` : "";
589402
- lines.push(`- \`${f2.path}${refs}\`${f2.role ? ` — ${f2.role}` : ""}`);
589403
- }
589404
- } else {
589405
- lines.push("- (no files enumerated in survey)");
589406
- }
589407
- if (survey.evidence?.length) {
589408
- for (const item of survey.evidence.slice(0, 8)) {
589409
- lines.push(`- evidence [${item.freshness ?? "unknown"}] ${item.ref}: ${item.detail}`);
589410
- }
589411
- }
589412
- if (survey.unresolvedQuestions?.length) {
589413
- lines.push(`- unresolved: ${survey.unresolvedQuestions.join("; ")}`);
589414
- }
589415
- lines.push(`- new symbols: ${(survey.newSymbols ?? []).join(", ") || "none"}`);
589416
- lines.push(`- public surface changes: ${survey.publicSurfaceChanges ? "yes" : "no"}`);
589417
- lines.push(`- tests exist: ${survey.testsExist ? "yes" : "no"}`);
589418
- lines.push("");
589419
- lines.push(`## 3. Locked contract (executable gate)`);
589420
- lines.push("");
589421
- if (lockedContract.symbols.length === 0) {
589422
- lines.push("- (no locked symbols for this kind — disciplined but permissive)");
589423
- } else {
589424
- for (const s2 of lockedContract.symbols) {
589425
- lines.push(`- \`${s2.kind} ${s2.name}\``);
589426
- }
589427
- }
589428
- lines.push("");
589429
- lines.push(`## 4. Definition of done (CompletionContract)`);
589430
- lines.push("");
589431
- lines.push(`- goal: ${completionContract.goalSummary || "(none)"}`);
589432
- for (const p2 of completionContract.phases ?? []) {
589433
- lines.push(`- phase: ${p2.label}`);
589434
- }
589435
- lines.push("");
589436
- lines.push(`## 5. Decomposition (SPLIT seed)`);
589437
- lines.push("");
589438
- for (const u of decomposition) {
589439
- lines.push(`- [${u.size}] ${u.label}${u.expectedSymbols?.length ? ` (symbols: ${u.expectedSymbols.join(", ")})` : ""}${u.evidenceRefs?.length ? ` [evidence: ${u.evidenceRefs.join(", ")}]` : ""}`);
589440
- }
589441
- lines.push("");
589442
- lines.push(`## 6. Verification bar`);
589443
- lines.push("");
589444
- lines.push("- planner emits real artefacts (this file + locked contract + completion contract)");
589445
- lines.push("- approval gate blocks before any source edit");
589446
- lines.push("- WO-6 executor gate activates on locked symbols");
589447
- lines.push("- recursion + eviction keep context bounded");
589448
- lines.push("- scope token re-prompts on out-of-scope work");
589449
- lines.push("");
589450
- lines.push(`## 7. Handoff notes`);
589451
- lines.push("");
589452
- lines.push("- Compose, do not rebuild: this plan reuses spec-gate + completionContract primitives.");
589453
- lines.push("- Fail-closed: if planning errors, the run falls back to the general agentic loop.");
589454
- lines.push("");
589455
- return lines.join("\n");
589456
- }
589457
- async function planFeature(survey, options2 = {}) {
589458
- const kind = classifyKind(survey);
589459
- const lockedContract = buildLockedContract(kind, survey);
589460
- const completionContract = inferCompletionContractFromTexts([survey.request, ...survey.rawTexts ?? [], ...survey.signals ?? []], survey.request);
589461
- const decomposition = decomposeFeature(survey, kind);
589462
- let prose = "";
589463
- try {
589464
- if (options2.proseGenerator) {
589465
- prose = await options2.proseGenerator({ request: survey.request, kind, survey });
589466
- }
589467
- } catch {
589468
- prose = "";
589469
- }
589470
- const specMarkdown = renderSpecMarkdown({
589471
- kind,
589472
- survey,
589473
- lockedContract,
589474
- completionContract,
589475
- decomposition,
589476
- prose
589477
- });
589478
- return { kind, specMarkdown, lockedContract, completionContract, decomposition };
589479
- }
589480
- function persistPlannerArtefacts(rootId, artefact, stateDir) {
589481
- try {
589482
- const dir = path9.join(stateDir, "feature-tree", rootId);
589483
- fs7.mkdirSync(dir, { recursive: true });
589484
- fs7.writeFileSync(path9.join(dir, "spec.md"), artefact.specMarkdown, "utf8");
589485
- fs7.writeFileSync(path9.join(dir, "locked-contract.json"), JSON.stringify(artefact.lockedContract, null, 2), "utf8");
589486
- fs7.writeFileSync(path9.join(dir, "completion-contract.json"), JSON.stringify(artefact.completionContract, null, 2), "utf8");
589487
- } catch {
589488
- }
589489
- }
589490
- var init_featurePlanner = __esm({
589491
- "packages/orchestrator/dist/featurePlanner.js"() {
589492
- "use strict";
589493
- init_completionContract();
589494
- }
589495
- });
589496
-
589497
- // packages/orchestrator/dist/featureApprovalGate.js
589498
- function mintScopeToken(input) {
589499
- return {
589500
- rootId: input.rootId,
589501
- files: [...input.files ?? []],
589502
- symbols: input.lockedContract.symbols.map((s2) => s2.name),
589503
- nodeKinds: input.nodeKinds ?? ["new-module", "refactor", "bugfix", "wiring", "investigation"],
589504
- depthCap: input.depthCap
589505
- };
589506
- }
589507
- function isWithinScope(input) {
589508
- const { token } = input;
589509
- if (typeof input.depth === "number" && input.depth > token.depthCap) {
589510
- return false;
589511
- }
589512
- if (input.nodeKind && !token.nodeKinds.includes(input.nodeKind)) {
589513
- return false;
589514
- }
589515
- if (input.newSymbol && !token.symbols.includes(input.newSymbol)) {
589516
- return false;
589517
- }
589518
- if (input.file) {
589519
- const file = input.file;
589520
- const allowed = token.files.some((f2) => {
589521
- if (f2 === file)
589522
- return true;
589523
- if (f2.endsWith("/") && file.startsWith(f2))
589524
- return true;
589525
- if (f2.includes("*") && globMatch(f2, file))
589526
- return true;
589527
- return false;
589528
- });
589529
- if (!allowed)
589530
- return false;
589531
- }
589532
- return true;
589533
- }
589534
- function globMatch(pattern, value2) {
589535
- const re = new RegExp("^" + pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$");
589536
- return re.test(value2);
589537
- }
589538
- async function requestApproval(req3, ask2, options2 = {}) {
589539
- let decision2;
589540
- try {
589541
- const raw = await ask2(req3);
589542
- decision2 = raw === "approve" || raw === "edit" || raw === "reject" ? raw : "reject";
589543
- } catch {
589544
- decision2 = "reject";
589545
- }
589546
- if (decision2 === "approve") {
589547
- const token = mintScopeToken({
589548
- rootId: req3.rootId,
589549
- lockedContract: req3.lockedContract,
589550
- decomposition: req3.decomposition,
589551
- depthCap: req3.depthCap,
589552
- files: options2.files,
589553
- nodeKinds: options2.nodeKinds
589554
- });
589555
- return { decision: decision2, token };
589556
- }
589557
- return { decision: decision2 };
589558
- }
589559
- var init_featureApprovalGate = __esm({
589560
- "packages/orchestrator/dist/featureApprovalGate.js"() {
589561
- "use strict";
589562
- }
589563
- });
589564
-
589565
- // packages/orchestrator/dist/featureNode.js
589566
- import fs8 from "node:fs";
589567
- import path10 from "node:path";
589568
- function treePath(stateDir, rootId) {
589569
- return path10.join(stateDir, "feature-tree", `${rootId}.json`);
589570
- }
589571
- function saveFeatureTree(stateDir, rootId, nodes) {
589572
- try {
589573
- const file = treePath(stateDir, rootId);
589574
- fs8.mkdirSync(path10.dirname(file), { recursive: true });
589575
- fs8.writeFileSync(file, JSON.stringify(nodes, null, 2), "utf8");
589576
- } catch {
589577
- }
589578
- }
589579
- function loadFeatureTree(stateDir, rootId) {
589580
- try {
589581
- const file = treePath(stateDir, rootId);
589582
- if (!fs8.existsSync(file))
589583
- return null;
589584
- const raw = JSON.parse(fs8.readFileSync(file, "utf8"));
589585
- return raw && typeof raw === "object" ? raw : null;
589586
- } catch {
589587
- return null;
589588
- }
589589
- }
589590
- function newNodeId(depth, seed) {
589591
- const h = String(Math.abs(hashString2(seed)) % 1e9).padStart(9, "0");
589592
- return `fn-d${depth}-${h}`;
589593
- }
589594
- function hashString2(s2) {
589595
- let h = 0;
589596
- for (let i2 = 0; i2 < s2.length; i2++)
589597
- h = h * 31 + s2.charCodeAt(i2) | 0;
589598
- return h;
589599
- }
589600
- async function evictNode(node, ctx3, transcript) {
589601
- try {
589602
- await runTodoChunker({
589603
- inputs: {
589604
- todoId: node.id,
589605
- todoContent: node.request,
589606
- turnRange: [0, 0],
589607
- transcript: transcript || node.request,
589608
- toolCalls: [],
589609
- workingDirectory: ctx3.workingDirectory,
589610
- sessionId: ctx3.sessionId
589611
- },
589612
- callable: ctx3.summarizer ?? (async () => "")
589613
- });
589614
- } catch {
589615
- }
589616
- }
589617
- async function execUnit(unit, node, ctx3, contract, maxRegenerate) {
589618
- let result = await ctx3.executeUnit(unit, node);
589619
- if (!result.ok)
589620
- return false;
589621
- const expected = unit.expectedSymbols ?? [];
589622
- if (expected.length === 0) {
589623
- return true;
589624
- }
589625
- for (let attempt = 0; attempt <= maxRegenerate; attempt++) {
589626
- if (!result.path || result.source === void 0)
589627
- return false;
589628
- const verdict = evaluateExecutorStep({
589629
- unit: { path: result.path, source: result.source },
589630
- contract,
589631
- expectedSymbols: expected
589632
- });
589633
- if (verdict.decision === "accept")
589634
- return true;
589635
- if (verdict.decision === "replan")
589636
- return false;
589637
- result = await ctx3.executeUnit(unit, node);
589638
- if (!result.ok)
589639
- return false;
589640
- }
589641
- return false;
589642
- }
589643
- async function runFeatureNode(node, ctx3, options2, tree2 = {}) {
589644
- const maxRegenerate = options2.maxRegenerate ?? 2;
589645
- tree2[node.id] = node;
589646
- try {
589647
- const artefact = await planFeature(options2.survey, {
589648
- proseGenerator: options2.proseGenerator
589649
- });
589650
- node.kind = artefact.kind;
589651
- if (ctx3.onPlan) {
589652
- try {
589653
- await ctx3.onPlan(artefact);
589654
- } catch {
589655
- }
589656
- }
589657
- persistPlannerArtefacts(ctx3.rootId, artefact, ctx3.stateDir);
589658
- const mustAsk = node.depth === 0 || !node.scopeToken;
589659
- if (mustAsk && ctx3.askApproval) {
589660
- node.status = "awaiting_approval";
589661
- const outcome = await requestApproval({
589662
- rootId: ctx3.rootId,
589663
- request: node.request,
589664
- specMarkdown: artefact.specMarkdown,
589665
- lockedContract: artefact.lockedContract,
589666
- decomposition: artefact.decomposition,
589667
- depthCap: ctx3.depthCap
589668
- }, ctx3.askApproval, { files: options2.survey.files.map((f2) => f2.path) });
589669
- if (outcome.decision !== "approve") {
589670
- node.status = outcome.decision === "edit" ? "planned" : "rejected";
589671
- saveFeatureTree(ctx3.stateDir, ctx3.rootId, tree2);
589672
- return node;
589673
- }
589674
- node.scopeToken = outcome.token;
589675
- }
589676
- node.status = "approved";
589677
- node.status = "executing";
589678
- let allOk = true;
589679
- for (const unit of artefact.decomposition) {
589680
- if (unit.size === "large" && node.depth < ctx3.depthCap) {
589681
- const childId = newNodeId(node.depth + 1, unit.label + node.id);
589682
- const childRequest = buildFeatureUnitRequest({
589683
- unit,
589684
- parentRequest: node.request,
589685
- survey: options2.survey
589686
- });
589687
- const child = {
589688
- id: childId,
589689
- parentId: node.id,
589690
- depth: node.depth + 1,
589691
- request: childRequest,
589692
- kind: artefact.kind,
589693
- status: "planned",
589694
- scopeToken: node.scopeToken,
589695
- children: []
589696
- };
589697
- node.children.push(childId);
589698
- const childSurvey = {
589699
- ...options2.survey,
589700
- request: child.request
589701
- };
589702
- const childCtx = {
589703
- ...ctx3,
589704
- // children inherit the token; re-prompt only if they exceed scope
589705
- askApproval: (req3) => isWithinScope({
589706
- token: node.scopeToken,
589707
- depth: node.depth + 1,
589708
- nodeKind: artefact.kind
589709
- }) ? "approve" : ctx3.askApproval(req3)
589710
- };
589711
- const res = await runFeatureNode(child, childCtx, { ...options2, survey: childSurvey }, tree2);
589712
- if (res.status !== "completed")
589713
- allOk = false;
589714
- await evictNode(child, ctx3, child.request);
589715
- } else {
589716
- const ok3 = await execUnit(unit, node, ctx3, artefact.lockedContract, maxRegenerate);
589717
- if (!ok3)
589718
- allOk = false;
589719
- }
589720
- }
589721
- if (allOk) {
589722
- node.status = "completed";
589723
- } else {
589724
- node.status = "failed";
589725
- }
589726
- saveFeatureTree(ctx3.stateDir, ctx3.rootId, tree2);
589727
- return node;
589728
- } catch {
589729
- if (ctx3.runGeneralLoop) {
589730
- await ctx3.runGeneralLoop(node.request);
589731
- node.status = "completed";
589732
- } else {
589733
- node.status = "failed";
589734
- }
589735
- saveFeatureTree(ctx3.stateDir, ctx3.rootId, tree2);
589736
- return node;
589737
- }
589738
- }
589739
- function createRootFeatureNode(request) {
589740
- return {
589741
- id: newNodeId(0, request),
589742
- parentId: null,
589743
- depth: 0,
589744
- request,
589745
- kind: "new-module",
589746
- status: "planned",
589747
- children: []
589748
- };
589749
- }
589750
- var init_featureNode = __esm({
589751
- "packages/orchestrator/dist/featureNode.js"() {
589752
- "use strict";
589753
- init_featurePlanner();
589754
- init_featureApprovalGate();
589755
- init_spec_gate();
589756
- init_todo_context_chunker();
589757
- }
589758
- });
589759
-
589760
589692
  // packages/orchestrator/dist/preflightSnapshot.js
589761
589693
  var preflightSnapshot_exports = {};
589762
589694
  __export(preflightSnapshot_exports, {
@@ -590875,6 +590807,142 @@ function stripShellQuotedSegments(command) {
590875
590807
  }
590876
590808
  return out;
590877
590809
  }
590810
+ function extractClaimPathFragments(text2) {
590811
+ const out = [];
590812
+ const pathPattern = /\b(?:[\w.-]+\/[\w./-]+(?:\.[A-Za-z0-9]+)?|[\w.-]+\.[A-Za-z0-9]+)\b/g;
590813
+ for (const match of text2.matchAll(pathPattern)) {
590814
+ const value2 = sanitizeDelegationText(String(match[0] ?? ""), 260).trim();
590815
+ if (!value2)
590816
+ continue;
590817
+ out.push(value2);
590818
+ }
590819
+ return [...new Set(out)];
590820
+ }
590821
+ function normalizeClaimPathSignal(raw) {
590822
+ const normalized = raw.replace(/["'`]+/g, "").replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/").trim().toLowerCase();
590823
+ if (!normalized)
590824
+ return "";
590825
+ if (normalized.length < 4)
590826
+ return "";
590827
+ if (normalized.includes(".."))
590828
+ return "";
590829
+ if (/[\\s]/.test(normalized))
590830
+ return "";
590831
+ return normalized;
590832
+ }
590833
+ function isLikelyPathSignal(value2) {
590834
+ if (!value2)
590835
+ return false;
590836
+ return value2.includes("/") || /\.[a-z0-9]+$/i.test(value2);
590837
+ }
590838
+ function collectClaimPathSignals(text2) {
590839
+ const direct = extractClaimPathFragments(text2).map((value2) => normalizeClaimPathSignal(value2)).filter(isLikelyPathSignal);
590840
+ const quoted = [...text2.matchAll(/["'`](.*?)["'`]/g)].map((match) => normalizeClaimPathSignal(String(match[1] ?? ""))).filter((value2) => isLikelyPathSignal(value2));
590841
+ return [.../* @__PURE__ */ new Set([...direct, ...quoted])];
590842
+ }
590843
+ function matchHintToInventoryPath(path16, hint) {
590844
+ const normalizedPath = normalizeClaimPathSignal(path16);
590845
+ const normalizedHint = normalizeClaimPathSignal(hint);
590846
+ if (!normalizedPath || !normalizedHint)
590847
+ return false;
590848
+ if (normalizedPath === normalizedHint)
590849
+ return true;
590850
+ if (normalizedPath.endsWith(`/${normalizedHint}`))
590851
+ return true;
590852
+ if (normalizedPath.endsWith(normalizedHint))
590853
+ return true;
590854
+ if (normalizedHint.includes("/") && normalizedPath.includes(normalizedHint))
590855
+ return true;
590856
+ const base3 = normalizedPath.split("/").at(-1) ?? "";
590857
+ return base3 === normalizedHint;
590858
+ }
590859
+ function claimDiscoveryFallbackCandidates(files, maxCandidates) {
590860
+ const ranked = [];
590861
+ const nowMs = Date.now();
590862
+ const maxAgeMs = 30 * 24 * 60 * 60 * 1e3;
590863
+ for (const raw of files) {
590864
+ const rawPath = String(raw.path ?? "").trim();
590865
+ if (!rawPath || rawPath.startsWith(".omnius/"))
590866
+ continue;
590867
+ const normalized = rawPath.replace(/\s+/g, " ").trim().replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/").toLowerCase();
590868
+ if (normalized.length < 4 || normalized.includes(".."))
590869
+ continue;
590870
+ const chunks = normalized.split("/").filter(Boolean);
590871
+ const depth = chunks.length || 1;
590872
+ const reasons = [];
590873
+ let score = 0;
590874
+ score += Math.max(1, 12 - Math.min(depth, 10));
590875
+ reasons.push("generic workspace proximity");
590876
+ if (raw.bytes !== void 0) {
590877
+ if (raw.bytes > 5e5)
590878
+ score -= 3;
590879
+ else if (raw.bytes > 8e4)
590880
+ score -= 1;
590881
+ if (raw.bytes > 5e5)
590882
+ reasons.push("large artifact");
590883
+ else if (raw.bytes > 8e4)
590884
+ reasons.push("moderate artifact");
590885
+ else
590886
+ reasons.push("light payload");
590887
+ }
590888
+ if (raw.mtimeMs !== void 0 && raw.mtimeMs > 0) {
590889
+ const age = nowMs - raw.mtimeMs;
590890
+ if (age >= 0 && age < maxAgeMs) {
590891
+ score += 2;
590892
+ reasons.push("recently modified");
590893
+ } else if (age < 0) {
590894
+ score += 1;
590895
+ reasons.push("fresh metadata");
590896
+ } else {
590897
+ reasons.push("older artifact");
590898
+ }
590899
+ }
590900
+ const pathSignal = chunks.join("/");
590901
+ if (!pathSignal)
590902
+ continue;
590903
+ ranked.push({
590904
+ path: pathSignal,
590905
+ score,
590906
+ reasons: [...new Set(reasons)].slice(0, 3)
590907
+ });
590908
+ }
590909
+ ranked.sort((left, right) => right.score !== left.score ? right.score - left.score : left.path.localeCompare(right.path));
590910
+ const fallback = [];
590911
+ for (const entry of ranked) {
590912
+ if (fallback.length >= maxCandidates)
590913
+ break;
590914
+ const canonical2 = entry.path.replace(/\\/g, "/").replace(/\/+/g, "/").replace(/^\.\//, "").trim().toLowerCase();
590915
+ if (canonical2.length < 4 || canonical2.includes(".."))
590916
+ continue;
590917
+ if (fallback.some((candidate) => candidate.path === canonical2))
590918
+ continue;
590919
+ fallback.push({
590920
+ path: canonical2,
590921
+ reasons: entry.reasons.length > 0 ? entry.reasons : ["generic workspace candidate"]
590922
+ });
590923
+ }
590924
+ return fallback;
590925
+ }
590926
+ function extractClaimTaskTokens(text2) {
590927
+ return String(text2 ?? "").toLowerCase().replace(/["'`]/g, " ").replace(/[^\w./-]+/g, " ").split(/\s+/).map((value2) => value2.trim()).filter((value2) => value2.length >= 4 && value2.length <= 80 && /[a-z0-9]/i.test(value2)).slice(0, 80);
590928
+ }
590929
+ function isMeaningfulClaimTaskToken(token) {
590930
+ if (!token)
590931
+ return false;
590932
+ const normalized = token.toLowerCase();
590933
+ if (normalized.length < 4 || normalized.length > 80)
590934
+ return false;
590935
+ if (!/[a-z0-9]/i.test(normalized))
590936
+ return false;
590937
+ if (CLAIM_TASK_STOPWORDS.has(normalized))
590938
+ return false;
590939
+ return true;
590940
+ }
590941
+ function chunkHasSymbolMatch(token, text2) {
590942
+ const haystack = text2.toLowerCase().replace(/[^a-z0-9]+/g, " ");
590943
+ const tokens = haystack.split(" ").filter(Boolean);
590944
+ return tokens.includes(token);
590945
+ }
590878
590946
  function isCompilerLikeVerifierCommand(command) {
590879
590947
  const normalized = command.toLowerCase();
590880
590948
  return /\b(?:pio|platformio|tsc|gcc|g\+\+|clang\+\+?|clang|cargo\s+(?:build|check)|go\s+(?:build|test)|javac|gradle|mvn|msbuild|dotnet\s+build|python(?:3)?\s+-m\s+(?:py_compile|compileall)|mypy|pyright)\b/.test(normalized);
@@ -591617,7 +591685,7 @@ function classifyThinkOutcome(raw) {
591617
591685
  }
591618
591686
  return null;
591619
591687
  }
591620
- var PRESERVE_MODEL_VISIBLE_HISTORY, TOOL_SUBSETS, TOOL_AUTO_DEMOTE_TURNS, LEGACY_ACTION_REASON_KEYS, SYSTEM_PROMPT, SYSTEM_PROMPT_MEDIUM, SYSTEM_PROMPT_SMALL, VISUAL_TOOLS, AUDIO_TOOLS, SOCIAL_TOOLS, SPATIAL_TOOLS, CODE_TOOLS, AgenticRunner, OllamaAgenticBackend;
591688
+ var PRESERVE_MODEL_VISIBLE_HISTORY, TOOL_SUBSETS, TOOL_AUTO_DEMOTE_TURNS, LEGACY_ACTION_REASON_KEYS, CLAIM_TASK_STOPWORDS, SYSTEM_PROMPT, SYSTEM_PROMPT_MEDIUM, SYSTEM_PROMPT_SMALL, VISUAL_TOOLS, AUDIO_TOOLS, SOCIAL_TOOLS, SPATIAL_TOOLS, CODE_TOOLS, AgenticRunner, OllamaAgenticBackend;
591621
591689
  var init_agenticRunner = __esm({
591622
591690
  "packages/orchestrator/dist/agenticRunner.js"() {
591623
591691
  "use strict";
@@ -591699,8 +591767,6 @@ var init_agenticRunner = __esm({
591699
591767
  init_prompt_cache();
591700
591768
  init_compile_error_fix_loop();
591701
591769
  init_git_progress();
591702
- init_featurePlanner();
591703
- init_featureNode();
591704
591770
  PRESERVE_MODEL_VISIBLE_HISTORY = /* @__PURE__ */ Symbol("omnius.preserveModelVisibleHistory");
591705
591771
  TOOL_SUBSETS = {
591706
591772
  web: ["web_search", "web_fetch", "web_crawl"],
@@ -591727,6 +591793,79 @@ var init_agenticRunner = __esm({
591727
591793
  };
591728
591794
  TOOL_AUTO_DEMOTE_TURNS = 10;
591729
591795
  LEGACY_ACTION_REASON_KEYS = /* @__PURE__ */ new Set(["action_reason", "actionReason"]);
591796
+ CLAIM_TASK_STOPWORDS = /* @__PURE__ */ new Set([
591797
+ "this",
591798
+ "that",
591799
+ "these",
591800
+ "those",
591801
+ "there",
591802
+ "where",
591803
+ "from",
591804
+ "with",
591805
+ "what",
591806
+ "when",
591807
+ "then",
591808
+ "help",
591809
+ "please",
591810
+ "request",
591811
+ "about",
591812
+ "their",
591813
+ "would",
591814
+ "could",
591815
+ "should",
591816
+ "might",
591817
+ "issue",
591818
+ "issues",
591819
+ "bug",
591820
+ "problem",
591821
+ "problems",
591822
+ "task",
591823
+ "tasks",
591824
+ "run",
591825
+ "build",
591826
+ "make",
591827
+ "need",
591828
+ "needs",
591829
+ "also",
591830
+ "only",
591831
+ "same",
591832
+ "other",
591833
+ "code",
591834
+ "file",
591835
+ "files",
591836
+ "repo",
591837
+ "project",
591838
+ "workspace",
591839
+ "read",
591840
+ "fix",
591841
+ "add",
591842
+ "remove",
591843
+ "create",
591844
+ "review",
591845
+ "check",
591846
+ "report",
591847
+ "inspect",
591848
+ "update",
591849
+ "implement",
591850
+ "setup",
591851
+ "install",
591852
+ "deploy",
591853
+ "run",
591854
+ "get",
591855
+ "set",
591856
+ "open",
591857
+ "close",
591858
+ "start",
591859
+ "stop",
591860
+ "turn",
591861
+ "off",
591862
+ "on",
591863
+ "enable",
591864
+ "disable",
591865
+ "add",
591866
+ "new",
591867
+ "old"
591868
+ ]);
591730
591869
  SYSTEM_PROMPT = loadPrompt("agentic/system-large.md");
591731
591870
  SYSTEM_PROMPT_MEDIUM = loadPrompt("agentic/system-medium.md");
591732
591871
  SYSTEM_PROMPT_SMALL = loadPrompt("agentic/system-small.md");
@@ -592024,8 +592163,6 @@ var init_agenticRunner = __esm({
592024
592163
  _wideExplorationCooldownUntilTurn = -1;
592025
592164
  /** REG-44: how many times the stuck detector has fired (for adaptive cooldown). */
592026
592165
  _reg44FireCount = 0;
592027
- /** Guard against re-entering the feature loop. */
592028
- _inFeatureLoop = false;
592029
592166
  // REG-45: sticky cross-turn escalation. The dispatch-time reflection
592030
592167
  // surface (REG-26) only fires when the agent re-emits the exact same
592031
592168
  // failed stem. If the agent thrashes on OTHER tools (wide-exploration
@@ -592145,6 +592282,7 @@ var init_agenticRunner = __esm({
592145
592282
  */
592146
592283
  _completionCaveat = null;
592147
592284
  _completionLedger = null;
592285
+ _claimDiscoveryInitialized = false;
592148
592286
  _staleEditFamilies = /* @__PURE__ */ new Map();
592149
592287
  /** Semantic retry counter for blocked full-file writes (payload-independent). */
592150
592288
  _blockedFullWriteAttempts = /* @__PURE__ */ new Map();
@@ -593518,7 +593656,9 @@ ${parts.join("\n")}
593518
593656
  success: input.status === "completed",
593519
593657
  output: `terminal_receipt=${record.id}
593520
593658
  marker=${markerPath}
593521
- evidence=${record.evidenceIds.join(",") || "none"}`
593659
+ evidence=${record.evidenceIds.join(",") || "none"}
593660
+ command_receipts=${record.commandReceipts.length}
593661
+ ` + (record.commandReceipts.length > 0 ? `command_receipts_summary=${record.commandReceipts.map((entry) => `${entry.canonicalCommand || entry.command || "n/a"}:${entry.exitCode}`).join(" | ")}` : "command_receipts_summary=none")
593522
593662
  });
593523
593663
  commitTerminalTrajectoryProjection(stateDir, record, input.trajectoryPayload);
593524
593664
  const committed = {
@@ -593610,6 +593750,7 @@ evidence=${record.evidenceIds.join(",") || "none"}`
593610
593750
  disableAdversaryCritic,
593611
593751
  disableStepCritic: disableAdversaryCritic,
593612
593752
  modelTier: options2?.modelTier ?? "large",
593753
+ claimDiscovery: options2?.claimDiscovery,
593613
593754
  referenceContractModules: options2?.referenceContractModules ?? [],
593614
593755
  contextWindowSize: options2?.contextWindowSize ?? 0,
593615
593756
  recursionDepth: options2?.recursionDepth ?? 0,
@@ -597037,7 +597178,7 @@ ${extras.join("\n")}`;
597037
597178
  const paths = args["edits"].map((edit) => edit && typeof edit === "object" ? edit["path"] : null).filter((p3) => typeof p3 === "string" && p3.trim().length > 0);
597038
597179
  return [...new Set(paths)];
597039
597180
  }
597040
- const p2 = args?.["path"] ?? args?.["file_path"] ?? args?.["file"] ?? args?.["filename"] ?? args?.["filepath"] ?? args?.["filePath"];
597181
+ const p2 = args?.["path"] ?? args?.["file_path"] ?? args?.["file"] ?? args?.["filename"] ?? args?.["filepath"] ?? args?.["filePath"] ?? args?.["input"] ?? args?.["target"];
597041
597182
  return typeof p2 === "string" && p2.trim().length > 0 ? [p2.trim()] : [];
597042
597183
  }
597043
597184
  _isRealProjectMutation(toolName, result) {
@@ -597178,6 +597319,9 @@ ${modelVisible}` : modelVisible || result.error || displayOutput || "";
597178
597319
  metrics: input.result.completionEvidenceMetrics,
597179
597320
  receipt
597180
597321
  });
597322
+ if (this._completionLedger?.claimDiscovery) {
597323
+ this._refreshClaimDiscoveryStateFromEvidence();
597324
+ }
597181
597325
  if (realFileMutation && realMutationPaths.length > 0) {
597182
597326
  for (const filePath of realMutationPaths) {
597183
597327
  this._completionLedger = recordCompletionEvidence(this._completionLedger, {
@@ -597194,6 +597338,50 @@ ${modelVisible}` : modelVisible || result.error || displayOutput || "";
597194
597338
  }
597195
597339
  this._saveCompletionLedgerSafe();
597196
597340
  }
597341
+ _refreshClaimDiscoveryStateFromEvidence() {
597342
+ if (!this._completionLedger?.claimDiscovery)
597343
+ return;
597344
+ const state = this._completionLedger.claimDiscovery;
597345
+ const evidenceHandles = state.evidenceHandles ?? [];
597346
+ const survivingBlockers = state.survivingBlockers ?? [];
597347
+ const unresolvedQuestions = state.unresolvedQuestions ?? [];
597348
+ const openDeltas = state.openDeltas ?? [];
597349
+ const resolved = claimDiscoveryResolvedHandles(this._completionLedger, state);
597350
+ const unresolvedEvidence = evidenceHandles.filter((handle2) => !resolved.includes(handle2));
597351
+ const unresolvedHandleSet = new Set(unresolvedEvidence);
597352
+ const unresolvedOpenDeltas = openDeltas.filter((delta) => {
597353
+ const normalizedDeltaPath = this._normalizeEvidencePath(delta.path).replace(/^\/+/, "");
597354
+ const handle2 = `workspace:${normalizedDeltaPath}`;
597355
+ return unresolvedHandleSet.has(handle2);
597356
+ });
597357
+ const hasBlockers = survivingBlockers.length > 0;
597358
+ const hasCandidates = state.candidatePaths.length > 0;
597359
+ const hasOpenQuestions = unresolvedQuestions.length > 0;
597360
+ const hasOpenEvidence = unresolvedEvidence.length > 0;
597361
+ let status;
597362
+ if (!hasCandidates) {
597363
+ status = hasBlockers || hasOpenQuestions ? "blocked" : "skipped";
597364
+ } else if (hasOpenEvidence || hasOpenQuestions || hasBlockers) {
597365
+ status = hasOpenQuestions || hasBlockers ? "blocked" : "active";
597366
+ } else {
597367
+ status = "complete";
597368
+ }
597369
+ const updated = {
597370
+ ...this._completionLedger,
597371
+ claimDiscovery: {
597372
+ ...state,
597373
+ openDeltas: unresolvedOpenDeltas,
597374
+ resolvedEvidenceHandles: resolved,
597375
+ evidenceHandles,
597376
+ survivingBlockers,
597377
+ unresolvedQuestions,
597378
+ status
597379
+ }
597380
+ };
597381
+ this._completionLedger = updated;
597382
+ this._saveCompletionLedgerSafe();
597383
+ return updated.claimDiscovery;
597384
+ }
597197
597385
  _completionArtifactHashes(paths) {
597198
597386
  const unique3 = [...new Set(paths.map((path16) => this._normalizeEvidencePath(path16)).filter(Boolean))].slice(0, 20);
597199
597387
  const out = [];
@@ -597946,15 +598134,18 @@ ${readOnlyLines.join("\n")}` : "Successful read-only evidence: none"
597946
598134
  }
597947
598135
  const timeoutMs = parseInt(process.env["OMNIUS_COMPLETION_VERIFY_TIMEOUT_MS"] || "180000", 10) || 18e4;
597948
598136
  const wd = this._workingDirectory || process.cwd();
598137
+ const hasPipe = cmd.includes("|");
598138
+ const startedAtIso = (/* @__PURE__ */ new Date()).toISOString();
597949
598139
  this.emit({
597950
598140
  type: "status",
597951
598141
  content: `completion verify gate: running '${cmd}' (cwd=${wd})`,
597952
598142
  turn,
597953
598143
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
597954
598144
  });
597955
- const { exitCode, outTail } = await new Promise((resolve84) => {
598145
+ const { exitCode, outTail, timedOut, finishedAtIso } = await new Promise((resolve84) => {
597956
598146
  const chunks = [];
597957
598147
  let settled = false;
598148
+ let hitTimeout = false;
597958
598149
  const child = _spawn(cmd, {
597959
598150
  cwd: wd,
597960
598151
  shell: true,
@@ -597970,6 +598161,7 @@ ${readOnlyLines.join("\n")}` : "Successful read-only evidence: none"
597970
598161
  child.stderr?.on("data", onData);
597971
598162
  const killTimer = setTimeout(() => {
597972
598163
  try {
598164
+ hitTimeout = true;
597973
598165
  child.kill("SIGKILL");
597974
598166
  } catch {
597975
598167
  }
@@ -597980,11 +598172,31 @@ ${readOnlyLines.join("\n")}` : "Successful read-only evidence: none"
597980
598172
  return;
597981
598173
  settled = true;
597982
598174
  clearTimeout(killTimer);
597983
- resolve84({ exitCode: code8, outTail: chunks.join("").slice(-4e3) });
598175
+ resolve84({
598176
+ exitCode: code8,
598177
+ outTail: chunks.join("").slice(-4e3),
598178
+ timedOut: hitTimeout,
598179
+ finishedAtIso: (/* @__PURE__ */ new Date()).toISOString()
598180
+ });
597984
598181
  };
597985
598182
  child.on("error", () => finish(1));
597986
598183
  child.on("close", (code8) => finish(code8 ?? 1));
597987
598184
  });
598185
+ const commandReceipt = {
598186
+ schema: "omnius.command-evidence-receipt.v1",
598187
+ command: cmd,
598188
+ canonicalCommand: "",
598189
+ cwd: wd,
598190
+ exitCode,
598191
+ pipefail: hasPipe,
598192
+ timedOut,
598193
+ startedAtIso,
598194
+ finishedAtIso,
598195
+ artifactHashes: this._completionArtifactHashes([
598196
+ ...this._taskState.modifiedFiles.keys()
598197
+ ])
598198
+ };
598199
+ commandReceipt.canonicalCommand = canonicalVerificationIdentity(cmd, commandReceipt) ?? normalizeShellCommand(cmd) ?? cmd;
597988
598200
  if (this._completionLedger) {
597989
598201
  this._completionLedger = recordCompletionEvidence(this._completionLedger, {
597990
598202
  kind: "tool_result",
@@ -597992,9 +598204,11 @@ ${readOnlyLines.join("\n")}` : "Successful read-only evidence: none"
597992
598204
  success: exitCode === 0,
597993
598205
  summary: `completion verify command exited ${exitCode}: ${cmd}
597994
598206
  ${outTail || "(no output captured)"}`,
598207
+ receipt: commandReceipt,
597995
598208
  role: "verification",
597996
598209
  family: "completion_verify"
597997
598210
  });
598211
+ this._refreshClaimDiscoveryResolvedHandles();
597998
598212
  this._saveCompletionLedgerSafe();
597999
598213
  }
598000
598214
  const compileGuidance = this._observeCompileVerifierResult({
@@ -598052,7 +598266,8 @@ ${compileGuidance}` : ""
598052
598266
  const _newClaims = deriveClaimsFromProposedText({
598053
598267
  text: proposedSummary,
598054
598268
  source: "task_complete_summary",
598055
- existing: this._completionLedger.proposedClaims
598269
+ existing: this._completionLedger.proposedClaims,
598270
+ workspaceInventory: this._completionLedger.claimDiscovery?.boundedInventory
598056
598271
  });
598057
598272
  if (_newClaims.length > 0) {
598058
598273
  this._completionLedger = addCompletionClaims(this._completionLedger, _newClaims);
@@ -598062,7 +598277,10 @@ ${compileGuidance}` : ""
598062
598277
  try {
598063
598278
  const _audit = auditCompletionClaims(this._completionLedger.proposedClaims.map((c9) => ({
598064
598279
  text: c9.text,
598065
- status: c9.status
598280
+ status: c9.status,
598281
+ riskCategory: c9.riskCategory === "unknown" || c9.riskCategory === "coverage" ? null : c9.riskCategory,
598282
+ requiresIndependentEvidence: c9.requiresIndependentEvidence,
598283
+ requiredCheck: c9.requiredCheck
598066
598284
  })));
598067
598285
  if (!_audit.ok) {
598068
598286
  const _checks = _audit.blockers.map((b) => `• [${b.category}] "${b.claim}" → ${b.requiredCheck}`).join("\n");
@@ -598286,8 +598504,9 @@ ${_checks}`
598286
598504
  verdict: "approve",
598287
598505
  rationale: result.verdict.rationale
598288
598506
  });
598289
- this._saveCompletionLedgerSafe();
598290
598507
  }
598508
+ this._saveCompletionLedgerSafe();
598509
+ this._refreshClaimDiscoveryResolvedHandles();
598291
598510
  this._lastBackwardPassCritique = null;
598292
598511
  return { proceed: true };
598293
598512
  }
@@ -598357,6 +598576,9 @@ ${_checks}`
598357
598576
  }
598358
598577
  return { proceed: false, feedback };
598359
598578
  }
598579
+ _refreshClaimDiscoveryResolvedHandles() {
598580
+ this._refreshClaimDiscoveryStateFromEvidence();
598581
+ }
598360
598582
  /**
598361
598583
  * WO-META-TRACK — Hannover-style turn-counter reminder.
598362
598584
  *
@@ -602241,6 +602463,7 @@ ${notice}`;
602241
602463
  runId: this.currentArtifactRunId(),
602242
602464
  goal: record.content
602243
602465
  }) : null;
602466
+ this._claimDiscoveryInitialized = false;
602244
602467
  if (this._completionLedger) {
602245
602468
  this._completionLedger.taskEpoch = this._taskEpoch;
602246
602469
  }
@@ -603270,111 +603493,210 @@ ${rawTask}`;
603270
603493
  return next;
603271
603494
  }
603272
603495
  /**
603273
- * Feature Loop used to classify and split from the raw user sentence. Build
603274
- * a small, model-selected survey first instead: the model sees only an
603275
- * inventory of paths (not invented contents), chooses candidate files, and
603276
- * names the facts that still require file_read before any unit can mutate.
603277
- * Returning null deliberately falls back to the ordinary tool loop rather
603278
- * than recreating the old task-label-only Feature Loop.
603496
+ * Claim-discovery uses task + bounded workspace inventory before any mutation.
603497
+ * It remains task-centered and product-agnostic: no protocol-specific
603498
+ * heuristics, no model-inferred domain taxonomy, no filename-category
603499
+ * inference. Candidate grounding is deterministic from task + bounded inventory
603500
+ * signals only.
603279
603501
  */
603280
- async _resolveFeatureSurvey(task, context2, turn) {
603281
- if (process.env["OMNIUS_FEATURE_SURVEY_GROUNDING"] === "0")
603282
- return null;
603502
+ async _resolveClaimDiscoverySurvey(task, turn) {
603503
+ if (process.env["OMNIUS_FEATURE_SURVEY_GROUNDING"] === "0") {
603504
+ return claimDiscoveryStateFromSurvey({
603505
+ request: task,
603506
+ boundedInventory: {
603507
+ root: this.authoritativeWorkingDirectory(),
603508
+ files: [],
603509
+ dirs: [],
603510
+ truncated: true,
603511
+ maxFiles: 0,
603512
+ maxDirs: 0,
603513
+ generatedAtIso: (/* @__PURE__ */ new Date()).toISOString()
603514
+ },
603515
+ candidatePaths: [],
603516
+ pathReasons: {},
603517
+ unresolvedQuestions: [],
603518
+ survivingBlockers: [
603519
+ "Claim discovery is currently disabled by OMNIUS_FEATURE_SURVEY_GROUNDING=0."
603520
+ ],
603521
+ requiresEvidence: false
603522
+ });
603523
+ }
603283
603524
  const root = this.authoritativeWorkingDirectory();
603284
- let workspaceFiles = [];
603285
- try {
603286
- workspaceFiles = scanWorkspace({ root, maxFiles: 320, maxDirs: 800 }).files.map((file) => ({ rel: file.rel, bytes: file.bytes }));
603525
+ const maxFiles = Math.max(80, Math.min(420, Number.parseInt(process.env["OMNIUS_CLAIM_DISCOVERY_MAX_FILES"] || "240", 10) || 240));
603526
+ const maxDirs = Math.max(60, Math.min(1200, Number.parseInt(process.env["OMNIUS_CLAIM_DISCOVERY_MAX_DIRS"] || "300", 10) || 300));
603527
+ let boundedInventory = null;
603528
+ try {
603529
+ const workspace = scanWorkspace({ root, maxFiles, maxDirs });
603530
+ const files = workspace.files.slice(0, maxFiles).map((file) => ({
603531
+ path: file.rel,
603532
+ bytes: file.bytes,
603533
+ mtimeMs: file.mtimeMs
603534
+ })).filter((file) => !file.path.startsWith(".omnius/"));
603535
+ boundedInventory = {
603536
+ root,
603537
+ files,
603538
+ dirs: workspace.dirs.slice(0, maxDirs).map((dir) => dir.rel),
603539
+ truncated: workspace.truncated,
603540
+ maxFiles,
603541
+ maxDirs,
603542
+ generatedAtIso: (/* @__PURE__ */ new Date()).toISOString()
603543
+ };
603287
603544
  } catch {
603288
- return null;
603289
- }
603290
- if (workspaceFiles.length === 0)
603291
- return null;
603292
- const allowedPaths = new Set(workspaceFiles.map((file) => file.rel));
603293
- const ledgerEvidence = this._evidenceLedger.snapshot(12).map((entry) => ({
603294
- ref: `read:${entry.path}`,
603295
- detail: `${entry.path} was read at turn ${entry.lastReadTurn}${entry.stale ? " and is now stale" : ""}.`,
603296
- freshness: entry.stale ? "stale" : "fresh"
603297
- }));
603298
- const inventory = workspaceFiles.slice(0, 320).map((file) => `${file.rel} (${file.bytes} bytes)`).join("\n");
603299
- const prompt = [
603300
- "You are Omnius's feature survey grounder. Return JSON only; do not provide chain-of-thought.",
603301
- "You have file-existence metadata, not source contents. Select only candidate paths from the provided inventory and state what must be inspected before any mutation. Do not claim code behavior, APIs, or test results from a filename.",
603302
- "Schema:",
603303
- JSON.stringify({
603304
- candidate_paths: ["exact allowed relative path, 1-8 items"],
603305
- path_reasons: { "path": "why this is a candidate, based only on request/inventory" },
603306
- unresolved_questions: ["specific source fact to inspect before edit"],
603307
- new_symbols: ["only explicitly requested symbols, if any"],
603308
- existing_symbols: ["only symbols named in supplied context, if any"],
603309
- tests_exist: false,
603310
- public_surface_changes: false
603311
- }),
603312
- `Task:
603313
- ${sanitizeDelegationText(task, 1400)}`,
603314
- context2 ? `Parent context (may be stale; verify):
603315
- ${sanitizeDelegationText(context2, 1200)}` : "",
603316
- ledgerEvidence.length ? `Fresh/stale reads already observed:
603317
- ${ledgerEvidence.map((item) => `- [${item.freshness}] ${item.ref}: ${item.detail}`).join("\n")}` : "No source files have been read in this run yet.",
603318
- `Allowed workspace inventory:
603319
- ${inventory}`
603320
- ].filter(Boolean).join("\n\n");
603321
- try {
603322
- this._emitModelResolutionTelemetry("feature_survey_grounding", turn);
603323
- const backend = this._auxInferenceBackend({
603324
- dumpStage: "feature_survey_grounding"
603325
- });
603326
- const response = await backend.chatCompletion({
603327
- messages: [
603328
- {
603329
- role: "system",
603330
- content: "Return only valid JSON matching the requested schema. Never invent a path or infer file content from its name."
603331
- },
603332
- { role: "user", content: prompt }
603545
+ return claimDiscoveryStateFromSurvey({
603546
+ request: task,
603547
+ boundedInventory: {
603548
+ root,
603549
+ files: [],
603550
+ dirs: [],
603551
+ truncated: true,
603552
+ maxFiles,
603553
+ maxDirs,
603554
+ generatedAtIso: (/* @__PURE__ */ new Date()).toISOString()
603555
+ },
603556
+ candidatePaths: [],
603557
+ pathReasons: {},
603558
+ unresolvedQuestions: [
603559
+ "Workspace scan failed for bounded inventory grounding; retry with explicit target paths."
603333
603560
  ],
603334
- tools: [],
603335
- temperature: 0.1,
603336
- maxTokens: 900,
603337
- timeoutMs: Math.max(5e3, Math.min(this.options.requestTimeoutMs, 25e3)),
603338
- think: false
603561
+ survivingBlockers: [
603562
+ "Claim discovery cannot anchor evidence without a successful workspace inventory scan."
603563
+ ],
603564
+ requiresEvidence: false
603339
603565
  });
603340
- const raw = response.choices?.[0]?.message?.content ?? "";
603341
- const json = raw.match(/```(?:json)?\s*([\s\S]*?)```/)?.[1] ?? raw.match(/\{[\s\S]*\}/)?.[0] ?? "";
603342
- const parsed = JSON.parse(json);
603343
- const requestedPaths = Array.isArray(parsed["candidate_paths"]) ? parsed["candidate_paths"].map((value2) => String(value2).trim()).filter((value2) => allowedPaths.has(value2)).slice(0, 8) : [];
603344
- if (requestedPaths.length === 0)
603345
- return null;
603346
- const reasons = parsed["path_reasons"] && typeof parsed["path_reasons"] === "object" ? parsed["path_reasons"] : {};
603347
- const stringList3 = (value2, cap, maxChars) => Array.isArray(value2) ? value2.map((item) => sanitizeDelegationText(item, maxChars)).filter(Boolean).slice(0, cap) : [];
603348
- const selectedEvidence2 = requestedPaths.map((file) => ({
603349
- ref: `workspace:${file}`,
603350
- detail: sanitizeDelegationText(reasons[file], 280) || "Selected from the workspace inventory; source contents remain uninspected.",
603351
- freshness: "unknown"
603352
- }));
603353
- const unresolvedQuestions = stringList3(parsed["unresolved_questions"], 6, 260);
603354
- if (unresolvedQuestions.length === 0) {
603355
- unresolvedQuestions.push("Read the selected source and its nearest tests/callers to establish the exact implementation contract before editing.");
603356
- }
603357
- return {
603566
+ }
603567
+ if (!boundedInventory || boundedInventory.files.length === 0) {
603568
+ return claimDiscoveryStateFromSurvey({
603358
603569
  request: task,
603359
- files: requestedPaths.map((path16) => ({
603360
- path: path16,
603361
- role: sanitizeDelegationText(reasons[path16], 180) || "candidate selected from workspace inventory"
603362
- })),
603363
- signals: [
603364
- "Feature survey candidates were generated from the current workspace inventory.",
603365
- ...unresolvedQuestions
603570
+ boundedInventory: boundedInventory ?? {
603571
+ root,
603572
+ files: [],
603573
+ dirs: [],
603574
+ truncated: true,
603575
+ maxFiles,
603576
+ maxDirs,
603577
+ generatedAtIso: (/* @__PURE__ */ new Date()).toISOString()
603578
+ },
603579
+ candidatePaths: [],
603580
+ pathReasons: {},
603581
+ unresolvedQuestions: [
603582
+ "Bounded workspace inventory was empty; provide concrete target artifacts before claiming completion."
603366
603583
  ],
603367
- rawTexts: [task, context2 ?? ""],
603368
- evidence: [...ledgerEvidence, ...selectedEvidence2].slice(0, 14),
603369
- unresolvedQuestions,
603370
- newSymbols: stringList3(parsed["new_symbols"], 8, 120),
603371
- existingSymbols: stringList3(parsed["existing_symbols"], 8, 120),
603372
- testsExist: parsed["tests_exist"] === true,
603373
- publicSurfaceChanges: parsed["public_surface_changes"] === true
603374
- };
603375
- } catch {
603376
- return null;
603584
+ survivingBlockers: ["No bounded inventory files were discoverable."],
603585
+ requiresEvidence: false
603586
+ });
603587
+ }
603588
+ const boundedInventoryPaths = boundedInventory.files.map((file) => file.path);
603589
+ const allowedPaths = new Set(boundedInventoryPaths);
603590
+ const pathReasons = /* @__PURE__ */ Object.create(null);
603591
+ const normalizedTask = sanitizeDelegationText(task, 1500);
603592
+ const taskTokens = extractClaimTaskTokens(task);
603593
+ const meaningfulTaskTokens = taskTokens.filter(isMeaningfulClaimTaskToken);
603594
+ const explicitPathHints = collectClaimPathSignals(task).map((token) => token.toLowerCase()).slice(0, 80);
603595
+ const unmatchedHints = new Set(explicitPathHints);
603596
+ const scored = [];
603597
+ for (const path16 of boundedInventoryPaths) {
603598
+ const lowerPath = path16.toLowerCase();
603599
+ const lowerBase = (path16.split("/").at(-1) ?? "").toLowerCase();
603600
+ const chunks = lowerPath.split("/").filter(Boolean);
603601
+ let score = 0;
603602
+ const reasons = [];
603603
+ for (const hint of explicitPathHints) {
603604
+ if (!matchHintToInventoryPath(path16, hint))
603605
+ continue;
603606
+ unmatchedHints.delete(hint);
603607
+ score += 120;
603608
+ reasons.push(`explicit path hint "${hint}" matches path`);
603609
+ }
603610
+ for (const token of meaningfulTaskTokens) {
603611
+ const lowerToken = token.toLowerCase();
603612
+ if (lowerToken.length < 4)
603613
+ continue;
603614
+ if (chunks.some((chunk) => chunk === lowerToken)) {
603615
+ score += 40;
603616
+ reasons.push(`segment token match (${lowerToken})`);
603617
+ } else if (lowerPath.includes(lowerToken)) {
603618
+ score += 14;
603619
+ reasons.push(`path includes task token (${lowerToken})`);
603620
+ } else if (chunkHasSymbolMatch(lowerToken, lowerBase)) {
603621
+ score += 6;
603622
+ reasons.push(`base symbol overlap (${lowerToken})`);
603623
+ }
603624
+ }
603625
+ if (score > 0) {
603626
+ scored.push({
603627
+ path: path16,
603628
+ score,
603629
+ reasons: [...new Set(reasons)].slice(0, 3)
603630
+ });
603631
+ }
603632
+ }
603633
+ scored.sort((left, right) => right.score !== left.score ? right.score - left.score : left.path.localeCompare(right.path));
603634
+ const rankedCandidates = scored.filter((entry) => entry.score > 0).map((entry) => entry.path).slice(0, 12);
603635
+ const explicitCandidates = explicitPathHints.flatMap((token) => boundedInventoryPaths.filter((path16) => matchHintToInventoryPath(path16, token))).filter((path16) => allowedPaths.has(path16)).slice(0, 12);
603636
+ const candidateSeeds = explicitCandidates.length > 0 ? explicitCandidates : rankedCandidates;
603637
+ const candidatePaths = [.../* @__PURE__ */ new Set([...candidateSeeds, ...rankedCandidates])].slice(0, 8);
603638
+ const shouldUseFallbackCandidates = explicitPathHints.length === 0 && candidatePaths.length === 0;
603639
+ const fallbackCandidates = shouldUseFallbackCandidates ? claimDiscoveryFallbackCandidates(boundedInventory.files, Math.max(4, Math.min(8, maxFiles ? Math.min(8, maxFiles) : 8))) : [];
603640
+ let finalCandidatePaths = candidatePaths.length > 0 ? candidatePaths : fallbackCandidates.map((entry) => entry.path);
603641
+ if (candidatePaths.length === 0 && fallbackCandidates.length > 0) {
603642
+ for (const candidate of fallbackCandidates) {
603643
+ if (!pathReasons[candidate.path]) {
603644
+ pathReasons[candidate.path] = candidate.reasons.join("; ");
603645
+ }
603646
+ }
603647
+ }
603648
+ if (finalCandidatePaths.length === 0 && boundedInventory.files.length > 0) {
603649
+ const boundedPaths = boundedInventory.files.map((file) => String(file.path ?? "")).map((path16) => path16.trim()).filter((path16) => path16.length >= 4 && path16.length <= 800).filter((path16) => !path16.startsWith(".omnius/"));
603650
+ const candidateWithDir = boundedPaths.filter((path16) => path16.includes("/")).slice(0, 4);
603651
+ finalCandidatePaths = (candidateWithDir.length > 0 ? candidateWithDir : boundedPaths).slice(0, 4);
603652
+ for (const candidate of finalCandidatePaths) {
603653
+ if (!pathReasons[candidate]) {
603654
+ pathReasons[candidate] = "selected from bounded inventory fallback";
603655
+ }
603656
+ }
603377
603657
  }
603658
+ if (finalCandidatePaths.length === 0) {
603659
+ const hasUnmatchedHints = unmatchedHints.size > 0;
603660
+ const unresolvedQuestions2 = hasUnmatchedHints ? [
603661
+ normalizedTask.length < 5 ? "Task text is too short to anchor evidence safely." : `No grounded candidate source path was identified for explicit task hints (${[...unmatchedHints].slice(0, 4).join(", ")}).`,
603662
+ "Read from declared artifacts before claiming completion."
603663
+ ] : [];
603664
+ const survivingBlockers2 = unmatchedHints.size > 0 ? [
603665
+ `No bounded inventory artifact matched explicit task hints: ${[...unmatchedHints].slice(0, 4).join(", ")}`
603666
+ ] : [];
603667
+ return claimDiscoveryStateFromSurvey({
603668
+ request: task,
603669
+ boundedInventory,
603670
+ candidatePaths: [],
603671
+ pathReasons: {},
603672
+ unresolvedQuestions: unresolvedQuestions2,
603673
+ survivingBlockers: survivingBlockers2,
603674
+ requiresEvidence: explicitPathHints.length > 0
603675
+ });
603676
+ }
603677
+ for (const candidate of finalCandidatePaths) {
603678
+ const details = scored.find((entry) => entry.path === candidate);
603679
+ if (!pathReasons[candidate]) {
603680
+ pathReasons[candidate] = details && details.reasons.length > 0 ? details.reasons.join("; ") : unmatchedHints.size > 0 ? "selected from explicit task hints plus inventory" : meaningfulTaskTokens.length === 0 ? "selected from bounded inventory fallback" : "selected from bounded request signals and inventory";
603681
+ }
603682
+ }
603683
+ const unresolvedQuestions = unmatchedHints.size > 0 ? [
603684
+ `Unresolved explicit task hints remain unmatched: ${[...unmatchedHints].slice(0, 3).join(", ")}.`,
603685
+ "If task intent changed, restate target artifacts in the user message."
603686
+ ] : [];
603687
+ const survivingBlockers = unmatchedHints.size > 0 ? [
603688
+ `Unmatched explicit task hints: ${[...unmatchedHints].slice(0, 3).join(", ")}`
603689
+ ] : [];
603690
+ const shouldRequireEvidence = finalCandidatePaths.length > 0 && (explicitPathHints.length > 0 || rankedCandidates.length > 0);
603691
+ return claimDiscoveryStateFromSurvey({
603692
+ request: task,
603693
+ boundedInventory,
603694
+ candidatePaths: finalCandidatePaths,
603695
+ pathReasons,
603696
+ unresolvedQuestions,
603697
+ survivingBlockers,
603698
+ requiresEvidence: shouldRequireEvidence
603699
+ });
603378
603700
  }
603379
603701
  /**
603380
603702
  * Rebuild the one current checkpoint at the context boundary. This shared
@@ -603701,6 +604023,7 @@ Respond with the assessment and take the selected evidence-backed action.`;
603701
604023
  this._completionIncompleteVerification = null;
603702
604024
  this._completionCaveat = null;
603703
604025
  this._completionLedger = null;
604026
+ this._claimDiscoveryInitialized = false;
603704
604027
  this._focusTerminalLedgerRecorded = false;
603705
604028
  this._resetTaskScopedVerifierState();
603706
604029
  this._staleEditFamilies.clear();
@@ -604001,6 +604324,7 @@ Respond with the assessment and take the selected evidence-backed action.`;
604001
604324
  runId: this._activeRunId || this._sessionId,
604002
604325
  goal: userGoal
604003
604326
  });
604327
+ this._claimDiscoveryInitialized = false;
604004
604328
  this._completionLedger.taskEpoch = this._taskEpoch;
604005
604329
  } else {
604006
604330
  this._completionContract = null;
@@ -604685,6 +605009,44 @@ ${dynamicProjectContext}`
604685
605009
  });
604686
605010
  return true;
604687
605011
  };
605012
+ const holdClaimDiscoveryTaskComplete = (turn) => {
605013
+ const ledger = this._completionLedger;
605014
+ if (!ledger?.claimDiscovery)
605015
+ return false;
605016
+ this._refreshClaimDiscoveryStateFromEvidence();
605017
+ const state = this._completionLedger?.claimDiscovery;
605018
+ if (!state)
605019
+ return false;
605020
+ const evidenceHandles = state.evidenceHandles ?? [];
605021
+ const unresolvedQuestions = state.unresolvedQuestions ?? [];
605022
+ const resolved = claimDiscoveryResolvedHandles(ledger, state);
605023
+ const unresolved = evidenceHandles.filter((handle2) => !resolved.includes(handle2));
605024
+ const blockers = state.survivingBlockers ?? [];
605025
+ const openDeltas = state.openDeltas ?? [];
605026
+ const hasOpenDiscoveryWork = unresolved.length > 0 || blockers.length > 0 || unresolvedQuestions.length > 0;
605027
+ const shouldHold = (state.status === "active" || state.status === "blocked") && hasOpenDiscoveryWork && state.requiresEvidence !== false;
605028
+ if (!shouldHold) {
605029
+ return false;
605030
+ }
605031
+ const feedback = [
605032
+ "[COMPLETION BLOCKED — evidence discovery incomplete]",
605033
+ `Open claim-discovery deltas: ${openDeltas.map((item) => `${item.path} :: ${item.reason}`).join(" | ") || "none"}`,
605034
+ `Outstanding evidence handles: ${unresolved.join(" | ") || "none"}`,
605035
+ ...blockers.length > 0 ? [`Surviving blockers: ${blockers.join(" | ")}`] : [],
605036
+ state.unresolvedQuestions.length > 0 ? `Outstanding question(s): ${state.unresolvedQuestions.slice(0, 4).join(" | ")}` : ""
605037
+ ].filter(Boolean).join("\n");
605038
+ lastCompletionGateReason = unresolved.length > 0 ? `claim discovery evidence pending (${unresolved.length})` : "claim discovery is still waiting on blockers/questions";
605039
+ lastCompletionGateFeedback = feedback;
605040
+ lastCompletionGateCode = "claim_discovery";
605041
+ messages2.push({ role: "system", content: feedback });
605042
+ this.emit({
605043
+ type: "status",
605044
+ content: `task_complete held by claim discovery gate: ${lastCompletionGateReason}`,
605045
+ turn,
605046
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
605047
+ });
605048
+ return true;
605049
+ };
604688
605050
  const completionHoldEscapeMax = (() => {
604689
605051
  const raw = Number(process.env["OMNIUS_COMPLETION_HOLD_MAX"]);
604690
605052
  return Number.isFinite(raw) && raw >= 1 ? Math.floor(raw) : 3;
@@ -604733,7 +605095,7 @@ ${lastCompletionGateFeedback.trim().slice(0, 4e3)}` : ""
604733
605095
  lastCompletionGateCode = "";
604734
605096
  return true;
604735
605097
  }
604736
- const held = holdDeliveryCoverageTaskComplete(turn) || holdCompileFixLoopTaskComplete(turn) || holdUnresolvedVerificationTaskComplete(turn) || holdNoProgressTaskComplete(args, turn) || holdProvenanceTaskComplete(args, turn);
605098
+ const held = holdDeliveryCoverageTaskComplete(turn) || holdCompileFixLoopTaskComplete(turn) || holdUnresolvedVerificationTaskComplete(turn) || holdNoProgressTaskComplete(args, turn) || holdProvenanceTaskComplete(args, turn) || holdClaimDiscoveryTaskComplete(turn);
604737
605099
  if (!held) {
604738
605100
  this._completionHoldState.count = 0;
604739
605101
  this._completionHoldState.lastKey = "";
@@ -604828,94 +605190,41 @@ ${lastCompletionGateFeedback.trim().slice(0, 4e3)}` : ""
604828
605190
  };
604829
605191
  let executeSingle = async () => null;
604830
605192
  const turnCap = this.options.maxTurns && this.options.maxTurns > 0 ? this.options.maxTurns : Number.MAX_SAFE_INTEGER;
604831
- const _featureLoopHandled = process.env["OMNIUS_FEATURE_LOOP"] === "1" && !this._inFeatureLoop && !this.options.subAgent;
604832
- if (_featureLoopHandled) {
604833
- try {
604834
- const _survey = await this._resolveFeatureSurvey(task, context2, 0);
604835
- if (!_survey) {
604836
- this.emit({
604837
- type: "status",
604838
- content: "[FEATURE LOOP] deferred: no model-grounded workspace survey was available; continuing with the normal discovery loop",
604839
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
604840
- });
604841
- } else {
604842
- const _kind = classifyKind(_survey);
604843
- if (_kind === "investigation") {
604844
- this.emit({
604845
- type: "status",
604846
- content: "[FEATURE LOOP] survey classified this as investigation; continuing with the normal evidence-gathering loop",
604847
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
604848
- });
604849
- } else {
604850
- this._inFeatureLoop = true;
604851
- this.emit({
604852
- type: "status",
604853
- content: `[FEATURE LOOP] evidence-grounded survey classified "${_kind}" – entering recursive driver...`,
604854
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
604855
- });
604856
- const _root = createRootFeatureNode(task);
604857
- const _startMs = Date.now();
604858
- const _resultNode = await runFeatureNode(_root, {
604859
- rootId: _root.id,
604860
- stateDir: this.omniusStateDir(),
604861
- workingDirectory: this.authoritativeWorkingDirectory() || process.cwd(),
604862
- sessionId: this._sessionId,
604863
- depthCap: 4,
604864
- askApproval: async () => "approve",
604865
- executeUnit: async (unit, node) => {
604866
- const _unitRequest = buildFeatureUnitRequest({
604867
- unit,
604868
- parentRequest: node.request,
604869
- survey: _survey
604870
- });
604871
- const _sub = await this.run(_unitRequest, unit.detail || "Feature unit request is grounded in the parent survey; verify the cited source before mutation.", unit.label);
604872
- return { ok: _sub.status === "completed" };
604873
- },
604874
- runGeneralLoop: async (request) => {
604875
- await this.run(request, void 0, request);
604876
- },
604877
- onPlan: async (artefact) => {
604878
- if (this._longHaul && artefact.lockedContract?.symbols?.length) {
604879
- this._longHaul.seedLockedContract(artefact.lockedContract);
604880
- this.emit({
604881
- type: "status",
604882
- content: `[FEATURE LOOP] seeded ${artefact.lockedContract.symbols.length} locked symbols into WO-6 contract`,
604883
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
604884
- });
604885
- }
604886
- }
604887
- }, { survey: _survey });
604888
- this._inFeatureLoop = false;
604889
- const _completed = _resultNode.status === "completed";
604890
- const _durMs = Date.now() - _startMs;
604891
- this.emit({
604892
- type: _completed ? "complete" : "error",
604893
- content: `[FEATURE LOOP] ${_completed ? "completed" : "failed"} after ${_durMs}ms — ${_resultNode.children.length} child nodes`,
604894
- success: _completed,
604895
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
604896
- });
604897
- return {
604898
- status: _completed ? "completed" : "incomplete",
604899
- completed: _completed,
604900
- turns: 0,
604901
- toolCalls: 0,
604902
- totalTokens: 0,
604903
- promptTokens: 0,
604904
- completionTokens: 0,
604905
- estimatedTokens: 0,
604906
- summary: `[FEATURE LOOP] ${_completed ? "completed" : "failed"}: ${task.slice(0, 200)}`,
604907
- durationMs: _durMs
604908
- };
604909
- }
604910
- }
604911
- } catch (e2) {
604912
- this._inFeatureLoop = false;
604913
- this.emit({
604914
- type: "status",
604915
- content: `[FEATURE LOOP] error, falling back to general loop: ${e2}`,
604916
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
604917
- });
605193
+ const _claimDiscoveryEnabled = (() => {
605194
+ if (typeof this.options.claimDiscovery === "boolean") {
605195
+ return this.options.claimDiscovery;
604918
605196
  }
605197
+ const parse3 = (raw) => {
605198
+ if (raw === void 0)
605199
+ return void 0;
605200
+ const lowered = raw.toLowerCase();
605201
+ if (raw === "1" || lowered === "true" || lowered === "on")
605202
+ return true;
605203
+ if (raw === "0" || lowered === "false" || lowered === "off")
605204
+ return false;
605205
+ return void 0;
605206
+ };
605207
+ const explicit = parse3(process.env["OMNIUS_CLAIM_DISCOVERY"]);
605208
+ if (explicit !== void 0)
605209
+ return explicit;
605210
+ const legacy = parse3(process.env["OMNIUS_FEATURE_LOOP"]);
605211
+ return legacy ?? true;
605212
+ })();
605213
+ const _claimDiscoveryNeedsInit = _claimDiscoveryEnabled && !this._claimDiscoveryInitialized && !this.options.subAgent && this._completionLedger !== null;
605214
+ if (_claimDiscoveryNeedsInit && this._completionLedger) {
605215
+ this._claimDiscoveryInitialized = true;
605216
+ const _survey = await this._resolveClaimDiscoverySurvey(task, 0);
605217
+ this._completionLedger = setClaimDiscoveryState(this._completionLedger, _survey);
605218
+ messages2.push({
605219
+ role: "system",
605220
+ content: "[CLAIM DISCOVERY] Grounding signals (compact):\n" + claimDiscoveryControllerSignals(this._completionLedger.claimDiscovery).join("\n")
605221
+ });
605222
+ this.emit({
605223
+ type: "status",
605224
+ content: `[CLAIM DISCOVERY] initialized from bounded inventory: ${this._completionLedger.claimDiscovery?.candidatePaths.length ?? 0} candidate path(s), status=${this._completionLedger.claimDiscovery?.status ?? "skipped"}`,
605225
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
605226
+ });
605227
+ this._saveCompletionLedgerSafe();
604919
605228
  }
604920
605229
  if (process.env["OMNIUS_DISABLE_TEXT_ECHO_GUARD"] !== "1") {
604921
605230
  const restoredCollapsed = this._textEchoGuard.collapseEchoes(messages2);
@@ -615134,6 +615443,9 @@ ${trimmedNew}`;
615134
615443
  `next_claim_inspection=${coverage?.nextInspection?.replace(/\s+/g, " ").slice(0, 420) || "none"}`,
615135
615444
  `evidence_handles=${evidenceHandles.join(",") || "none"}`
615136
615445
  ];
615446
+ if (this._completionLedger?.claimDiscovery) {
615447
+ lines.push(...claimDiscoveryControllerSignals(this._completionLedger.claimDiscovery));
615448
+ }
615137
615449
  const tier = this.options.modelTier ?? "large";
615138
615450
  const directive = this._focusSupervisor?.snapshot().directive;
615139
615451
  if (directive && tier === "small") {
@@ -622530,8 +622842,8 @@ var init_skill_fork = __esm({
622530
622842
  });
622531
622843
 
622532
622844
  // packages/orchestrator/dist/missionArtifacts.js
622533
- import * as fs9 from "node:fs";
622534
- import * as path11 from "node:path";
622845
+ import * as fs7 from "node:fs";
622846
+ import * as path9 from "node:path";
622535
622847
  function createValidationContract(missionId, assertions) {
622536
622848
  return {
622537
622849
  missionId,
@@ -622711,33 +623023,33 @@ function checkMilestoneComplete(state, manifest, milestoneId) {
622711
623023
  return true;
622712
623024
  }
622713
623025
  function writeFeaturesManifest(missionDir, manifest) {
622714
- fs9.mkdirSync(missionDir, { recursive: true });
622715
- const filePath = path11.join(missionDir, "features.json");
622716
- fs9.writeFileSync(filePath, JSON.stringify(manifest, null, 2), "utf-8");
623026
+ fs7.mkdirSync(missionDir, { recursive: true });
623027
+ const filePath = path9.join(missionDir, "features.json");
623028
+ fs7.writeFileSync(filePath, JSON.stringify(manifest, null, 2), "utf-8");
622717
623029
  }
622718
623030
  function writeValidationContract(missionDir, contract) {
622719
- fs9.mkdirSync(missionDir, { recursive: true });
622720
- const filePath = path11.join(missionDir, "validation-contract.md");
622721
- fs9.writeFileSync(filePath, renderValidationContract(contract), "utf-8");
623031
+ fs7.mkdirSync(missionDir, { recursive: true });
623032
+ const filePath = path9.join(missionDir, "validation-contract.md");
623033
+ fs7.writeFileSync(filePath, renderValidationContract(contract), "utf-8");
622722
623034
  }
622723
623035
  function writeValidationState(missionDir, state) {
622724
- fs9.mkdirSync(missionDir, { recursive: true });
622725
- const filePath = path11.join(missionDir, "validation-state.json");
622726
- fs9.writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
623036
+ fs7.mkdirSync(missionDir, { recursive: true });
623037
+ const filePath = path9.join(missionDir, "validation-state.json");
623038
+ fs7.writeFileSync(filePath, JSON.stringify(state, null, 2), "utf-8");
622727
623039
  }
622728
623040
  function readFeaturesManifest(missionDir) {
622729
- const filePath = path11.join(missionDir, "features.json");
622730
- const content = fs9.readFileSync(filePath, "utf-8");
623041
+ const filePath = path9.join(missionDir, "features.json");
623042
+ const content = fs7.readFileSync(filePath, "utf-8");
622731
623043
  return JSON.parse(content);
622732
623044
  }
622733
623045
  function readValidationState(missionDir) {
622734
- const filePath = path11.join(missionDir, "validation-state.json");
622735
- const content = fs9.readFileSync(filePath, "utf-8");
623046
+ const filePath = path9.join(missionDir, "validation-state.json");
623047
+ const content = fs7.readFileSync(filePath, "utf-8");
622736
623048
  return JSON.parse(content);
622737
623049
  }
622738
623050
  function readValidationContract(missionDir) {
622739
- const filePath = path11.join(missionDir, "validation-contract.md");
622740
- const content = fs9.readFileSync(filePath, "utf-8");
623051
+ const filePath = path9.join(missionDir, "validation-contract.md");
623052
+ const content = fs7.readFileSync(filePath, "utf-8");
622741
623053
  const assertions = [];
622742
623054
  const lines = content.split("\n");
622743
623055
  let inTable = false;
@@ -623075,8 +623387,8 @@ var init_adversarialHandoffs = __esm({
623075
623387
  });
623076
623388
 
623077
623389
  // packages/orchestrator/dist/autoValidators.js
623078
- import * as fs10 from "node:fs";
623079
- import * as path12 from "node:path";
623390
+ import * as fs8 from "node:fs";
623391
+ import * as path10 from "node:path";
623080
623392
  function generateScrutinyValidatorSkill() {
623081
623393
  return `# Scrutiny Validator
623082
623394
 
@@ -623193,22 +623505,22 @@ function combineValidatorResults(missionId, milestoneId, scrutiny, userTesting)
623193
623505
  };
623194
623506
  }
623195
623507
  function writeValidatorResults(missionDir, results) {
623196
- fs10.mkdirSync(missionDir, { recursive: true });
623197
- const filePath = path12.join(missionDir, "validator-results.json");
623198
- fs10.writeFileSync(filePath, JSON.stringify(results, null, 2), "utf-8");
623508
+ fs8.mkdirSync(missionDir, { recursive: true });
623509
+ const filePath = path10.join(missionDir, "validator-results.json");
623510
+ fs8.writeFileSync(filePath, JSON.stringify(results, null, 2), "utf-8");
623199
623511
  }
623200
623512
  function readValidatorResults(missionDir) {
623201
- const filePath = path12.join(missionDir, "validator-results.json");
623202
- const content = fs10.readFileSync(filePath, "utf-8");
623513
+ const filePath = path10.join(missionDir, "validator-results.json");
623514
+ const content = fs8.readFileSync(filePath, "utf-8");
623203
623515
  return JSON.parse(content);
623204
623516
  }
623205
623517
  function writeValidatorSkill(missionDir, skillName, content) {
623206
- const dir = path12.join(missionDir, "skills", "auto-injected");
623207
- if (!fs10.existsSync(dir)) {
623208
- fs10.mkdirSync(dir, { recursive: true });
623518
+ const dir = path10.join(missionDir, "skills", "auto-injected");
623519
+ if (!fs8.existsSync(dir)) {
623520
+ fs8.mkdirSync(dir, { recursive: true });
623209
623521
  }
623210
- const filePath = path12.join(dir, `${skillName}.md`);
623211
- fs10.writeFileSync(filePath, content, "utf-8");
623522
+ const filePath = path10.join(dir, `${skillName}.md`);
623523
+ fs8.writeFileSync(filePath, content, "utf-8");
623212
623524
  }
623213
623525
  var init_autoValidators = __esm({
623214
623526
  "packages/orchestrator/dist/autoValidators.js"() {
@@ -623217,8 +623529,8 @@ var init_autoValidators = __esm({
623217
623529
  });
623218
623530
 
623219
623531
  // packages/orchestrator/dist/serviceManifest.js
623220
- import * as fs11 from "node:fs";
623221
- import * as path13 from "node:path";
623532
+ import * as fs9 from "node:fs";
623533
+ import * as path11 from "node:path";
623222
623534
  function quoteScalar(value2) {
623223
623535
  return JSON.stringify(value2);
623224
623536
  }
@@ -623349,8 +623661,8 @@ function getCommand(manifest, name10) {
623349
623661
  return cmd.command;
623350
623662
  }
623351
623663
  function writeServicesManifest(missionDir, manifest) {
623352
- fs11.mkdirSync(missionDir, { recursive: true });
623353
- const filePath = path13.join(missionDir, "services.yaml");
623664
+ fs9.mkdirSync(missionDir, { recursive: true });
623665
+ const filePath = path11.join(missionDir, "services.yaml");
623354
623666
  const lines = [
623355
623667
  `missionId: ${manifest.missionId}`,
623356
623668
  `createdAt: ${manifest.createdAt}`,
@@ -623398,11 +623710,11 @@ function writeServicesManifest(missionDir, manifest) {
623398
623710
  lines.push(` min: ${manifest.ports.range.min}`);
623399
623711
  lines.push(` max: ${manifest.ports.range.max}`);
623400
623712
  lines.push(` offLimits: [${manifest.ports.offLimits.join(", ")}]`);
623401
- fs11.writeFileSync(filePath, lines.join("\n"), "utf-8");
623713
+ fs9.writeFileSync(filePath, lines.join("\n"), "utf-8");
623402
623714
  }
623403
623715
  function readServicesManifest(missionDir) {
623404
- const filePath = path13.join(missionDir, "services.yaml");
623405
- const content = fs11.readFileSync(filePath, "utf-8");
623716
+ const filePath = path11.join(missionDir, "services.yaml");
623717
+ const content = fs9.readFileSync(filePath, "utf-8");
623406
623718
  const services = [];
623407
623719
  const commands = [];
623408
623720
  let missionId = "";
@@ -624839,6 +625151,549 @@ var init_conversational_scrutiny = __esm({
624839
625151
  }
624840
625152
  });
624841
625153
 
625154
+ // packages/orchestrator/dist/featurePlanner.js
625155
+ import fs10 from "node:fs";
625156
+ import path12 from "node:path";
625157
+ function classifyKind(survey) {
625158
+ const files = survey.files ?? [];
625159
+ const newSym = (survey.newSymbols ?? []).length;
625160
+ const req3 = survey.request.toLowerCase();
625161
+ if (/\b(investigat|why does|how does|trace|understand|root cause|diagnos|explain)\b/.test(req3) && newSym === 0 && files.length <= 2) {
625162
+ return "investigation";
625163
+ }
625164
+ if (/\b(bug|fix|broken|regression|crash|incorrect|fails?|misbehav)/.test(req3) && newSym === 0) {
625165
+ return "bugfix";
625166
+ }
625167
+ if (/\b(refactor|restructure|rename|clean up|simplif|migrate|consolidate)\b/.test(req3) && newSym === 0) {
625168
+ return "refactor";
625169
+ }
625170
+ if (/\b(wir|connect|integrate|hook up|plumb|bridge|glue)\b/.test(req3) && files.length >= 2) {
625171
+ return "wiring";
625172
+ }
625173
+ if (newSym > 0 || /\b(new|create|add|implement|build|introduce|scaffold)\b/.test(req3)) {
625174
+ return "new-module";
625175
+ }
625176
+ return "new-module";
625177
+ }
625178
+ function guessKind(name10) {
625179
+ if (/^(I[A-Z]|.*Interface|.*Contract|.*Spec|.*Event|.*Meta|.*Config|.*State)$/.test(name10)) {
625180
+ return "interface";
625181
+ }
625182
+ if (/^(T|Type|.*Type)$/.test(name10))
625183
+ return "type";
625184
+ if (/^(E|Enum|.*Kind|.*Status|.*Mode)$/.test(name10))
625185
+ return "enum";
625186
+ if (/^[A-Z]/.test(name10))
625187
+ return "class";
625188
+ return "function";
625189
+ }
625190
+ function buildLockedContract(kind, survey) {
625191
+ const symbols = [];
625192
+ if (kind === "refactor") {
625193
+ for (const name10 of survey.existingSymbols ?? []) {
625194
+ symbols.push({ name: name10, kind: guessKind(name10), fields: [] });
625195
+ }
625196
+ } else if (kind === "new-module") {
625197
+ for (const name10 of survey.newSymbols ?? []) {
625198
+ symbols.push({ name: name10, kind: guessKind(name10), fields: [] });
625199
+ }
625200
+ }
625201
+ return { symbols };
625202
+ }
625203
+ function decomposeFeature(survey, kind) {
625204
+ const units = [];
625205
+ const evidenceRefs = claimEvidenceRefs(survey);
625206
+ const unresolvedQuestion = survey.unresolvedQuestions?.[0] ?? (evidenceRefs.length === 0 ? "Which current files, symbols, and tests govern this unit? Inspect them before proposing a mutation." : void 0);
625207
+ const returnContract = "Return the direct result with cited observations, relevant/changed paths, verification or blocker, and the next parent decision.";
625208
+ const withGrounding = (unit) => ({
625209
+ ...unit,
625210
+ evidenceRefs,
625211
+ ...unresolvedQuestion ? { unresolvedQuestion } : {},
625212
+ returnContract
625213
+ });
625214
+ if (kind === "new-module") {
625215
+ const syms = survey.newSymbols ?? [];
625216
+ if (syms.length === 0) {
625217
+ units.push(withGrounding({
625218
+ label: "Establish the module boundary and implement the evidenced unit",
625219
+ size: "large",
625220
+ detail: "Do not scaffold from the request alone. First identify the owning entry point, adjacent contract, and test surface from current evidence."
625221
+ }));
625222
+ } else {
625223
+ for (const name10 of syms) {
625224
+ units.push({
625225
+ ...withGrounding({
625226
+ label: `Implement ${name10} within its evidenced owner`,
625227
+ size: "small",
625228
+ detail: "Confirm the symbol's owning module and contract before editing; do not infer a file path from the request label."
625229
+ }),
625230
+ expectedSymbols: [name10]
625231
+ });
625232
+ }
625233
+ }
625234
+ } else if (kind === "refactor") {
625235
+ units.push(withGrounding({
625236
+ label: "Refactor only the evidenced public surface",
625237
+ size: survey.files.length > 1 ? "large" : "small"
625238
+ }));
625239
+ } else if (kind === "bugfix") {
625240
+ units.push(withGrounding({
625241
+ label: "Reproduce the evidenced failure, make the smallest justified fix, and verify it",
625242
+ size: "small"
625243
+ }));
625244
+ } else if (kind === "wiring") {
625245
+ units.push(withGrounding({
625246
+ label: "Connect the evidenced module boundaries",
625247
+ size: survey.files.length > 2 ? "large" : "small"
625248
+ }));
625249
+ } else {
625250
+ units.push(withGrounding({
625251
+ label: "Investigate the evidence gap and report the next justified action",
625252
+ size: "small"
625253
+ }));
625254
+ }
625255
+ return units;
625256
+ }
625257
+ function claimEvidenceRefs(survey) {
625258
+ const declared = (survey.evidence ?? []).map((item) => item.ref.trim()).filter(Boolean).slice(0, 6);
625259
+ if (declared.length > 0)
625260
+ return declared;
625261
+ return survey.files.map((file) => `survey:file:${file.path}`).filter(Boolean).slice(0, 6);
625262
+ }
625263
+ function buildFeatureUnitRequest(input) {
625264
+ const evidence = (input.survey.evidence ?? []).filter((item) => !input.unit.evidenceRefs?.length || input.unit.evidenceRefs.includes(item.ref)).slice(0, 6);
625265
+ const fallbackEvidence = evidence.length > 0 ? evidence : input.survey.files.slice(0, 6).map((file) => ({
625266
+ ref: `survey:file:${file.path}`,
625267
+ detail: `${file.path}${file.role ? ` — ${file.role}` : ""}`,
625268
+ freshness: "unknown"
625269
+ }));
625270
+ const explicitOpenDeltas = [
625271
+ ...input.unit.unresolvedQuestion ? [input.unit.unresolvedQuestion] : [],
625272
+ ...input.survey.unresolvedQuestions ?? []
625273
+ ].slice(0, 6);
625274
+ const lines = [
625275
+ "[CLAIM UNIT EVIDENCE BRIEF]",
625276
+ `Parent request: ${input.parentRequest.slice(0, 900)}`,
625277
+ `Requested unit: ${input.unit.label}`,
625278
+ `Why now: this unit was selected from the current claim discovery survey, not from a task label alone.`,
625279
+ `Open deltas: ${explicitOpenDeltas.length > 0 ? explicitOpenDeltas.join(" | ") : "none"}`,
625280
+ `Surviving blockers: ${input.unit.unresolvedQuestion ? "blocker carried from planner: open question" : "none"}`,
625281
+ `Evidence handles: ${fallbackEvidence.map((item) => item.ref).join(", ")}`,
625282
+ "Evidence:",
625283
+ ...fallbackEvidence.length > 0 ? fallbackEvidence.map((item) => `- [${item.freshness ?? "unknown"}] ${item.ref}: ${item.detail.slice(0, 360)}`) : ["- No current code observation is available; discovery is required before mutation."],
625284
+ `Open question: ${input.unit.unresolvedQuestion ?? "none"}`,
625285
+ "Scope: stay within this unit and directly implicated code; do not broaden the claim without returning to the parent.",
625286
+ `Return contract: ${input.unit.returnContract ?? "Return evidence, verification or blocker, and the next parent decision."}`,
625287
+ "",
625288
+ "Work protocol: inspect the cited files/contracts first. Only mutate after a fresh observation identifies the exact target; if the evidence does not support a target, report the gap instead of fabricating one."
625289
+ ];
625290
+ return lines.filter((line) => Boolean(line)).join("\n");
625291
+ }
625292
+ function renderSpecMarkdown(input) {
625293
+ const { kind, survey, lockedContract, completionContract, decomposition, prose } = input;
625294
+ const lines = [];
625295
+ lines.push(`# Claim Discovery Plan — ${kind}`);
625296
+ lines.push("");
625297
+ lines.push(`**Request:** ${survey.request}`);
625298
+ lines.push("");
625299
+ lines.push(`**Node kind:** \`${kind}\` (selected by CLASSIFY over the survey signals)`);
625300
+ lines.push("");
625301
+ if (prose) {
625302
+ lines.push(`## 1. Intent`);
625303
+ lines.push("");
625304
+ lines.push(prose.trim());
625305
+ lines.push("");
625306
+ }
625307
+ lines.push(`## 2. Survey (codebase as-is)`);
625308
+ lines.push("");
625309
+ if (survey.files.length > 0) {
625310
+ for (const f2 of survey.files) {
625311
+ const refs = f2.lineRefs?.length ? `:${f2.lineRefs.join(",")}` : "";
625312
+ lines.push(`- \`${f2.path}${refs}\`${f2.role ? ` — ${f2.role}` : ""}`);
625313
+ }
625314
+ } else {
625315
+ lines.push("- (no files enumerated in survey)");
625316
+ }
625317
+ if (survey.evidence?.length) {
625318
+ for (const item of survey.evidence.slice(0, 8)) {
625319
+ lines.push(`- evidence [${item.freshness ?? "unknown"}] ${item.ref}: ${item.detail}`);
625320
+ }
625321
+ }
625322
+ if (survey.unresolvedQuestions?.length) {
625323
+ lines.push(`- unresolved: ${survey.unresolvedQuestions.join("; ")}`);
625324
+ }
625325
+ lines.push(`- new symbols: ${(survey.newSymbols ?? []).join(", ") || "none"}`);
625326
+ lines.push(`- public surface changes: ${survey.publicSurfaceChanges ? "yes" : "no"}`);
625327
+ lines.push(`- tests exist: ${survey.testsExist ? "yes" : "no"}`);
625328
+ lines.push("");
625329
+ lines.push(`## 3. Locked contract (executable gate)`);
625330
+ lines.push("");
625331
+ if (lockedContract.symbols.length === 0) {
625332
+ lines.push("- (no locked symbols for this kind — disciplined but permissive)");
625333
+ } else {
625334
+ for (const s2 of lockedContract.symbols) {
625335
+ lines.push(`- \`${s2.kind} ${s2.name}\``);
625336
+ }
625337
+ }
625338
+ lines.push("");
625339
+ lines.push(`## 4. Definition of done (CompletionContract)`);
625340
+ lines.push("");
625341
+ lines.push(`- goal: ${completionContract.goalSummary || "(none)"}`);
625342
+ for (const p2 of completionContract.phases ?? []) {
625343
+ lines.push(`- phase: ${p2.label}`);
625344
+ }
625345
+ lines.push("");
625346
+ lines.push(`## 5. Decomposition (SPLIT seed)`);
625347
+ lines.push("");
625348
+ for (const u of decomposition) {
625349
+ lines.push(`- [${u.size}] ${u.label}${u.expectedSymbols?.length ? ` (symbols: ${u.expectedSymbols.join(", ")})` : ""}${u.evidenceRefs?.length ? ` [evidence: ${u.evidenceRefs.join(", ")}]` : ""}`);
625350
+ }
625351
+ lines.push("");
625352
+ lines.push(`## 6. Verification bar`);
625353
+ lines.push("");
625354
+ lines.push("- planner emits real artefacts (this file + locked contract + completion contract)");
625355
+ lines.push("- approval gate blocks before any source edit");
625356
+ lines.push("- WO-6 executor gate activates on locked symbols");
625357
+ lines.push("- recursion + eviction keep context bounded");
625358
+ lines.push("- scope token re-prompts on out-of-scope work");
625359
+ lines.push("");
625360
+ lines.push(`## 7. Handoff notes`);
625361
+ lines.push("");
625362
+ lines.push("- Compose, do not rebuild: this plan reuses spec-gate + completionContract primitives.");
625363
+ lines.push("- Fail-closed: if planning errors, the run falls back to the general agentic loop.");
625364
+ lines.push("");
625365
+ return lines.join("\n");
625366
+ }
625367
+ async function planFeature(survey, options2 = {}) {
625368
+ const kind = classifyKind(survey);
625369
+ const lockedContract = buildLockedContract(kind, survey);
625370
+ const completionContract = inferCompletionContractFromTexts([survey.request, ...survey.rawTexts ?? [], ...survey.signals ?? []], survey.request);
625371
+ const decomposition = decomposeFeature(survey, kind);
625372
+ let prose = "";
625373
+ try {
625374
+ if (options2.proseGenerator) {
625375
+ prose = await options2.proseGenerator({ request: survey.request, kind, survey });
625376
+ }
625377
+ } catch {
625378
+ prose = "";
625379
+ }
625380
+ const specMarkdown = renderSpecMarkdown({
625381
+ kind,
625382
+ survey,
625383
+ lockedContract,
625384
+ completionContract,
625385
+ decomposition,
625386
+ prose
625387
+ });
625388
+ return { kind, specMarkdown, lockedContract, completionContract, decomposition };
625389
+ }
625390
+ function persistPlannerArtefacts(rootId, artefact, stateDir, survey) {
625391
+ try {
625392
+ const dir = path12.join(stateDir, "feature-tree", rootId);
625393
+ fs10.mkdirSync(dir, { recursive: true });
625394
+ fs10.writeFileSync(path12.join(dir, "spec.md"), artefact.specMarkdown, "utf8");
625395
+ fs10.writeFileSync(path12.join(dir, "locked-contract.json"), JSON.stringify(artefact.lockedContract, null, 2), "utf8");
625396
+ fs10.writeFileSync(path12.join(dir, "completion-contract.json"), JSON.stringify(artefact.completionContract, null, 2), "utf8");
625397
+ if (survey) {
625398
+ fs10.writeFileSync(path12.join(dir, "claim-discovery-survey.json"), JSON.stringify({
625399
+ request: survey.request,
625400
+ requestSource: "bound_workspace_inventory",
625401
+ files: survey.files,
625402
+ unresolvedQuestions: survey.unresolvedQuestions ?? [],
625403
+ evidenceRefs: survey.evidence?.map((item) => item.ref) ?? [],
625404
+ signals: survey.signals ?? [],
625405
+ requiredVerificationCommands: survey.requiredVerificationCommands ?? [],
625406
+ testsExist: survey.testsExist ?? false,
625407
+ publicSurfaceChanges: survey.publicSurfaceChanges ?? false,
625408
+ newSymbols: survey.newSymbols ?? [],
625409
+ existingSymbols: survey.existingSymbols ?? []
625410
+ }, null, 2), "utf8");
625411
+ }
625412
+ } catch {
625413
+ }
625414
+ }
625415
+ var classifyClaimKind, buildClaimPlan, buildClaimUnitRequest, buildClaimLockedContract;
625416
+ var init_featurePlanner = __esm({
625417
+ "packages/orchestrator/dist/featurePlanner.js"() {
625418
+ "use strict";
625419
+ init_completionContract();
625420
+ classifyClaimKind = classifyKind;
625421
+ buildClaimPlan = planFeature;
625422
+ buildClaimUnitRequest = buildFeatureUnitRequest;
625423
+ buildClaimLockedContract = buildLockedContract;
625424
+ }
625425
+ });
625426
+
625427
+ // packages/orchestrator/dist/featureApprovalGate.js
625428
+ function mintScopeToken(input) {
625429
+ return {
625430
+ rootId: input.rootId,
625431
+ files: [...input.files ?? []],
625432
+ symbols: input.lockedContract.symbols.map((s2) => s2.name),
625433
+ nodeKinds: input.nodeKinds ?? ["new-module", "refactor", "bugfix", "wiring", "investigation"],
625434
+ depthCap: input.depthCap
625435
+ };
625436
+ }
625437
+ function isWithinScope(input) {
625438
+ const { token } = input;
625439
+ if (typeof input.depth === "number" && input.depth > token.depthCap) {
625440
+ return false;
625441
+ }
625442
+ if (input.nodeKind && !token.nodeKinds.includes(input.nodeKind)) {
625443
+ return false;
625444
+ }
625445
+ if (input.newSymbol && !token.symbols.includes(input.newSymbol)) {
625446
+ return false;
625447
+ }
625448
+ if (input.file) {
625449
+ const file = input.file;
625450
+ const allowed = token.files.some((f2) => {
625451
+ if (f2 === file)
625452
+ return true;
625453
+ if (f2.endsWith("/") && file.startsWith(f2))
625454
+ return true;
625455
+ if (f2.includes("*") && globMatch(f2, file))
625456
+ return true;
625457
+ return false;
625458
+ });
625459
+ if (!allowed)
625460
+ return false;
625461
+ }
625462
+ return true;
625463
+ }
625464
+ function globMatch(pattern, value2) {
625465
+ const re = new RegExp("^" + pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$");
625466
+ return re.test(value2);
625467
+ }
625468
+ async function requestApproval(req3, ask2, options2 = {}) {
625469
+ let decision2;
625470
+ try {
625471
+ const raw = await ask2(req3);
625472
+ decision2 = raw === "approve" || raw === "edit" || raw === "reject" ? raw : "reject";
625473
+ } catch {
625474
+ decision2 = "reject";
625475
+ }
625476
+ if (decision2 === "approve") {
625477
+ const token = mintScopeToken({
625478
+ rootId: req3.rootId,
625479
+ lockedContract: req3.lockedContract,
625480
+ decomposition: req3.decomposition,
625481
+ depthCap: req3.depthCap,
625482
+ files: options2.files,
625483
+ nodeKinds: options2.nodeKinds
625484
+ });
625485
+ return { decision: decision2, token };
625486
+ }
625487
+ return { decision: decision2 };
625488
+ }
625489
+ var mintClaimScopeToken, isWithinClaimScope, requestClaimApproval;
625490
+ var init_featureApprovalGate = __esm({
625491
+ "packages/orchestrator/dist/featureApprovalGate.js"() {
625492
+ "use strict";
625493
+ mintClaimScopeToken = mintScopeToken;
625494
+ isWithinClaimScope = isWithinScope;
625495
+ requestClaimApproval = requestApproval;
625496
+ }
625497
+ });
625498
+
625499
+ // packages/orchestrator/dist/featureNode.js
625500
+ import fs11 from "node:fs";
625501
+ import path13 from "node:path";
625502
+ function treePath(stateDir, rootId) {
625503
+ return path13.join(stateDir, "feature-tree", `${rootId}.json`);
625504
+ }
625505
+ function saveFeatureTree(stateDir, rootId, nodes) {
625506
+ try {
625507
+ const file = treePath(stateDir, rootId);
625508
+ fs11.mkdirSync(path13.dirname(file), { recursive: true });
625509
+ fs11.writeFileSync(file, JSON.stringify(nodes, null, 2), "utf8");
625510
+ } catch {
625511
+ }
625512
+ }
625513
+ function loadFeatureTree(stateDir, rootId) {
625514
+ try {
625515
+ const file = treePath(stateDir, rootId);
625516
+ if (!fs11.existsSync(file))
625517
+ return null;
625518
+ const raw = JSON.parse(fs11.readFileSync(file, "utf8"));
625519
+ return raw && typeof raw === "object" ? raw : null;
625520
+ } catch {
625521
+ return null;
625522
+ }
625523
+ }
625524
+ function newNodeId(depth, seed) {
625525
+ const h = String(Math.abs(hashString2(seed)) % 1e9).padStart(9, "0");
625526
+ return `fn-d${depth}-${h}`;
625527
+ }
625528
+ function hashString2(s2) {
625529
+ let h = 0;
625530
+ for (let i2 = 0; i2 < s2.length; i2++)
625531
+ h = h * 31 + s2.charCodeAt(i2) | 0;
625532
+ return h;
625533
+ }
625534
+ async function evictNode(node, ctx3, transcript) {
625535
+ try {
625536
+ await runTodoChunker({
625537
+ inputs: {
625538
+ todoId: node.id,
625539
+ todoContent: node.request,
625540
+ turnRange: [0, 0],
625541
+ transcript: transcript || node.request,
625542
+ toolCalls: [],
625543
+ workingDirectory: ctx3.workingDirectory,
625544
+ sessionId: ctx3.sessionId
625545
+ },
625546
+ callable: ctx3.summarizer ?? (async () => "")
625547
+ });
625548
+ } catch {
625549
+ }
625550
+ }
625551
+ async function execUnit(unit, node, ctx3, contract, maxRegenerate) {
625552
+ let result = await ctx3.executeUnit(unit, node);
625553
+ if (!result.ok)
625554
+ return false;
625555
+ const expected = unit.expectedSymbols ?? [];
625556
+ if (expected.length === 0) {
625557
+ return true;
625558
+ }
625559
+ for (let attempt = 0; attempt <= maxRegenerate; attempt++) {
625560
+ if (!result.path || result.source === void 0)
625561
+ return false;
625562
+ const verdict = evaluateExecutorStep({
625563
+ unit: { path: result.path, source: result.source },
625564
+ contract,
625565
+ expectedSymbols: expected
625566
+ });
625567
+ if (verdict.decision === "accept")
625568
+ return true;
625569
+ if (verdict.decision === "replan")
625570
+ return false;
625571
+ result = await ctx3.executeUnit(unit, node);
625572
+ if (!result.ok)
625573
+ return false;
625574
+ }
625575
+ return false;
625576
+ }
625577
+ async function runFeatureNode(node, ctx3, options2, tree2 = {}) {
625578
+ const maxRegenerate = options2.maxRegenerate ?? 2;
625579
+ tree2[node.id] = node;
625580
+ try {
625581
+ const artefact = await planFeature(options2.survey, {
625582
+ proseGenerator: options2.proseGenerator
625583
+ });
625584
+ node.kind = artefact.kind;
625585
+ if (ctx3.onPlan) {
625586
+ try {
625587
+ await ctx3.onPlan(artefact);
625588
+ } catch {
625589
+ }
625590
+ }
625591
+ persistPlannerArtefacts(ctx3.rootId, artefact, ctx3.stateDir, options2.survey);
625592
+ const mustAsk = node.depth === 0 || !node.scopeToken;
625593
+ if (mustAsk && ctx3.askApproval) {
625594
+ node.status = "awaiting_approval";
625595
+ const outcome = await requestApproval({
625596
+ rootId: ctx3.rootId,
625597
+ request: node.request,
625598
+ specMarkdown: artefact.specMarkdown,
625599
+ lockedContract: artefact.lockedContract,
625600
+ decomposition: artefact.decomposition,
625601
+ depthCap: ctx3.depthCap
625602
+ }, ctx3.askApproval, { files: options2.survey.files.map((f2) => f2.path) });
625603
+ if (outcome.decision !== "approve") {
625604
+ node.status = outcome.decision === "edit" ? "planned" : "rejected";
625605
+ saveFeatureTree(ctx3.stateDir, ctx3.rootId, tree2);
625606
+ return node;
625607
+ }
625608
+ node.scopeToken = outcome.token;
625609
+ }
625610
+ node.status = "approved";
625611
+ node.status = "executing";
625612
+ let allOk = true;
625613
+ for (const unit of artefact.decomposition) {
625614
+ if (unit.size === "large" && node.depth < ctx3.depthCap) {
625615
+ const childId = newNodeId(node.depth + 1, unit.label + node.id);
625616
+ const childRequest = buildFeatureUnitRequest({
625617
+ unit,
625618
+ parentRequest: node.request,
625619
+ survey: options2.survey
625620
+ });
625621
+ const child = {
625622
+ id: childId,
625623
+ parentId: node.id,
625624
+ depth: node.depth + 1,
625625
+ request: childRequest,
625626
+ kind: artefact.kind,
625627
+ status: "planned",
625628
+ scopeToken: node.scopeToken,
625629
+ children: []
625630
+ };
625631
+ node.children.push(childId);
625632
+ const childSurvey = {
625633
+ ...options2.survey,
625634
+ request: child.request
625635
+ };
625636
+ const childCtx = {
625637
+ ...ctx3,
625638
+ // children inherit the token; re-prompt only if they exceed scope
625639
+ askApproval: (req3) => isWithinScope({
625640
+ token: node.scopeToken,
625641
+ depth: node.depth + 1,
625642
+ nodeKind: artefact.kind
625643
+ }) ? "approve" : ctx3.askApproval(req3)
625644
+ };
625645
+ const res = await runFeatureNode(child, childCtx, { ...options2, survey: childSurvey }, tree2);
625646
+ if (res.status !== "completed")
625647
+ allOk = false;
625648
+ await evictNode(child, ctx3, child.request);
625649
+ } else {
625650
+ const ok3 = await execUnit(unit, node, ctx3, artefact.lockedContract, maxRegenerate);
625651
+ if (!ok3)
625652
+ allOk = false;
625653
+ }
625654
+ }
625655
+ if (allOk) {
625656
+ node.status = "completed";
625657
+ } else {
625658
+ node.status = "failed";
625659
+ }
625660
+ saveFeatureTree(ctx3.stateDir, ctx3.rootId, tree2);
625661
+ return node;
625662
+ } catch {
625663
+ if (ctx3.runGeneralLoop) {
625664
+ await ctx3.runGeneralLoop(node.request);
625665
+ node.status = "completed";
625666
+ } else {
625667
+ node.status = "failed";
625668
+ }
625669
+ saveFeatureTree(ctx3.stateDir, ctx3.rootId, tree2);
625670
+ return node;
625671
+ }
625672
+ }
625673
+ function createRootFeatureNode(request) {
625674
+ return {
625675
+ id: newNodeId(0, request),
625676
+ parentId: null,
625677
+ depth: 0,
625678
+ request,
625679
+ kind: "new-module",
625680
+ status: "planned",
625681
+ children: []
625682
+ };
625683
+ }
625684
+ var runClaimNode, createClaimRootNode;
625685
+ var init_featureNode = __esm({
625686
+ "packages/orchestrator/dist/featureNode.js"() {
625687
+ "use strict";
625688
+ init_featurePlanner();
625689
+ init_featureApprovalGate();
625690
+ init_spec_gate();
625691
+ init_todo_context_chunker();
625692
+ runClaimNode = runFeatureNode;
625693
+ createClaimRootNode = createRootFeatureNode;
625694
+ }
625695
+ });
625696
+
624842
625697
  // packages/orchestrator/dist/causalAblation.js
624843
625698
  function _identifyAblationTargets(messages2, dimension) {
624844
625699
  const targets = [];
@@ -625364,6 +626219,9 @@ __export(dist_exports3, {
625364
626219
  buildAgentDeploymentPatternSummary: () => buildAgentDeploymentPatternSummary,
625365
626220
  buildAgentNotification: () => buildAgentNotification,
625366
626221
  buildAgentTypeSummary: () => buildAgentTypeSummary,
626222
+ buildClaimLockedContract: () => buildClaimLockedContract,
626223
+ buildClaimPlan: () => buildClaimPlan,
626224
+ buildClaimUnitRequest: () => buildClaimUnitRequest,
625367
626225
  buildCompletionFinalizationRecord: () => buildCompletionFinalizationRecord,
625368
626226
  buildCompletionScenarioDecomposition: () => buildCompletionScenarioDecomposition,
625369
626227
  buildCoordinatorPrompt: () => buildCoordinatorPrompt,
@@ -625390,6 +626248,7 @@ __export(dist_exports3, {
625390
626248
  chooseCheapModelRoute: () => chooseCheapModelRoute,
625391
626249
  claimAssertion: () => claimAssertion,
625392
626250
  classifyBreadth: () => classifyBreadth,
626251
+ classifyClaimKind: () => classifyClaimKind,
625393
626252
  classifyCompletionClaim: () => classifyCompletionClaim,
625394
626253
  classifyHandoff: () => classifyHandoff,
625395
626254
  classifyKind: () => classifyKind,
@@ -625424,6 +626283,7 @@ __export(dist_exports3, {
625424
626283
  countDefinitions: () => countDefinitions,
625425
626284
  createAppState: () => createAppState,
625426
626285
  createChildAbortController: () => createChildAbortController,
626286
+ createClaimRootNode: () => createClaimRootNode,
625427
626287
  createCompletionLedger: () => createCompletionLedger,
625428
626288
  createDefaultContextEngine: () => createDefaultContextEngine,
625429
626289
  createFeaturesManifest: () => createFeaturesManifest,
@@ -625517,6 +626377,7 @@ __export(dist_exports3, {
625517
626377
  isSuccessfulRunFinished: () => isSuccessfulRunFinished,
625518
626378
  isTerminalRunEvent: () => isTerminalRunEvent,
625519
626379
  isTerminalTaskStatus: () => isTerminalTaskStatus,
626380
+ isWithinClaimScope: () => isWithinClaimScope,
625520
626381
  isWithinScope: () => isWithinScope,
625521
626382
  legacyAgenticEventToRunEvent: () => legacyAgenticEventToRunEvent,
625522
626383
  listContextWindowDumps: () => listContextWindowDumps,
@@ -625533,6 +626394,7 @@ __export(dist_exports3, {
625533
626394
  measureContextSNR: () => measureContextSNR,
625534
626395
  memoryCosine: () => cosine4,
625535
626396
  mergeDigests: () => mergeDigests,
626397
+ mintClaimScopeToken: () => mintClaimScopeToken,
625536
626398
  mintScopeToken: () => mintScopeToken,
625537
626399
  normalizeCompletionKey: () => normalizeCompletionKey,
625538
626400
  normalizeMemoryCompilationPlanAudit: () => normalizeMemoryCompilationPlanAudit,
@@ -625551,6 +626413,7 @@ __export(dist_exports3, {
625551
626413
  persistAgentTaskSidecar: () => persistAgentTaskSidecar,
625552
626414
  persistPlannerArtefacts: () => persistPlannerArtefacts,
625553
626415
  planAgentDeploymentPattern: () => planAgentDeploymentPattern,
626416
+ planClaim: () => buildClaimPlan,
625554
626417
  planConsolidation: () => planConsolidation,
625555
626418
  planFeature: () => planFeature,
625556
626419
  prepareCompletionFinalization: () => prepareCompletionFinalization,
@@ -625598,6 +626461,7 @@ __export(dist_exports3, {
625598
626461
  renderValidationContract: () => renderValidationContract,
625599
626462
  renderWorkerSkill: () => renderWorkerSkill,
625600
626463
  requestApproval: () => requestApproval,
626464
+ requestClaimApproval: () => requestClaimApproval,
625601
626465
  resetPluginRegistry: () => resetPluginRegistry,
625602
626466
  resolveAgentTools: () => resolveAgentTools,
625603
626467
  resolveDefaultPoolConfig: () => resolveDefaultPoolConfig,
@@ -625605,6 +626469,7 @@ __export(dist_exports3, {
625605
626469
  resolveModelProfile: () => resolveModelProfile,
625606
626470
  restoreAgentTasks: () => restoreAgentTasks,
625607
626471
  retentionStrength: () => retentionStrength,
626472
+ runClaimNode: () => runClaimNode,
625608
626473
  runFeatureNode: () => runFeatureNode,
625609
626474
  runMemoryCompilerReplay: () => runMemoryCompilerReplay,
625610
626475
  runMemoryCompilerReplaySuite: () => runMemoryCompilerReplaySuite,
@@ -772018,6 +772883,8 @@ async function runCommand2(opts, config) {
772018
772883
  await runBackground(opts.task, mergedConfig, opts);
772019
772884
  } else if (opts.json) {
772020
772885
  await runJson(opts.task, mergedConfig, opts.repoPath);
772886
+ } else if (opts.verbose) {
772887
+ await runConsole(opts.task, mergedConfig, opts.repoPath);
772021
772888
  } else {
772022
772889
  await runWithTUI(opts.task, mergedConfig, opts.repoPath);
772023
772890
  if (shouldForceSingleRunExit()) process.exit(0);
@@ -772117,6 +772984,95 @@ async function runJson(task, config, repoPath2) {
772117
772984
  if (result.exitCode !== 0) process.exit(result.exitCode);
772118
772985
  if (shouldForceJsonExit()) process.exit(0);
772119
772986
  }
772987
+ async function runConsole(task, config, repoPath2) {
772988
+ const startTime = Date.now();
772989
+ const origWrite = process.stdout.write.bind(process.stdout);
772990
+ const origStderr = process.stderr.write.bind(process.stderr);
772991
+ process.stdout.write = (() => true);
772992
+ process.stderr.write = (() => true);
772993
+ let runnerResult = null;
772994
+ let toolCount = 0;
772995
+ const fmtArgs = (args) => {
772996
+ if (args === void 0 || args === null) return "";
772997
+ if (typeof args !== "object") return ` (${String(args)})`;
772998
+ const entries = Object.entries(args);
772999
+ if (entries.length === 0) return "";
773000
+ const parts = entries.map(([k, v]) => {
773001
+ let s2;
773002
+ if (typeof v === "string") {
773003
+ s2 = v.length > 200 ? `${v.slice(0, 197)}…` : v;
773004
+ } else if (v === void 0 || v === null) {
773005
+ s2 = String(v);
773006
+ } else {
773007
+ try {
773008
+ s2 = JSON.stringify(v);
773009
+ } catch {
773010
+ s2 = String(v);
773011
+ }
773012
+ if (s2.length > 200) s2 = `${s2.slice(0, 197)}…`;
773013
+ }
773014
+ return `${k}=${s2}`;
773015
+ });
773016
+ return ` (${parts.join(", ")})`;
773017
+ };
773018
+ const emit2 = (line) => {
773019
+ origWrite(line + "\n");
773020
+ };
773021
+ try {
773022
+ emit2(`▶ Task: ${task}`);
773023
+ await runWithTUI(task, config, repoPath2, {
773024
+ onToolCall: (tool, args) => {
773025
+ toolCount += 1;
773026
+ emit2(`[${toolCount}] 🔧 ${tool}${fmtArgs(args)}`);
773027
+ },
773028
+ onToolResult: (tool, output, success) => {
773029
+ const redacted = getSecretRedactor().redactText(output || "");
773030
+ const capped = redacted && redacted.length > 400 ? redacted.slice(0, 380) + `… [+${redacted.length - 380} chars]` : redacted;
773031
+ const mark = success ? "✓" : "✗";
773032
+ emit2(` ${mark} ${tool} → ${capped || "(no output)"}`);
773033
+ },
773034
+ onStatus: (content) => {
773035
+ if (content && content.trim()) {
773036
+ emit2(`ℹ ${content.trim()}`);
773037
+ }
773038
+ },
773039
+ onAssistantText: (text2) => {
773040
+ const clean6 = sanitizeAgentOutputForUser(text2).trim();
773041
+ if (clean6) emit2(`💬 ${clean6.replace(/\n/g, "\n ")}`);
773042
+ },
773043
+ onRunResult: (result) => {
773044
+ runnerResult = {
773045
+ status: result.status,
773046
+ completed: result.completed,
773047
+ summary: result.summary,
773048
+ turns: result.turns,
773049
+ toolCalls: result.toolCalls
773050
+ };
773051
+ }
773052
+ });
773053
+ } catch (err) {
773054
+ process.stdout.write = origWrite;
773055
+ process.stderr.write = origStderr;
773056
+ emit2(`✗ Error: ${err instanceof Error ? err.message : String(err)}`);
773057
+ if (config.verbose && err instanceof Error && err.stack) {
773058
+ emit2(err.stack);
773059
+ }
773060
+ process.exit(1);
773061
+ }
773062
+ process.stdout.write = origWrite;
773063
+ process.stderr.write = origStderr;
773064
+ const durationMs = Date.now() - startTime;
773065
+ const rr = runnerResult;
773066
+ const status = rr?.completed ? "completed" : rr?.status ?? "completed";
773067
+ emit2("");
773068
+ emit2(
773069
+ `✓ Done — status: ${status} | ${rr?.turns ?? "?"} turns | ${toolCount} tool calls | ${(durationMs / 1e3).toFixed(1)}s`
773070
+ );
773071
+ if (rr?.summary) {
773072
+ emit2(`Summary: ${rr.summary.slice(0, 400)}`);
773073
+ }
773074
+ if (shouldForceSingleRunExit()) process.exit(0);
773075
+ }
772120
773076
  function shouldForceJsonExit() {
772121
773077
  if (process.env["OMNIUS_JSON_NO_FORCE_EXIT"] === "1") return false;
772122
773078
  if (process.env["VITEST"] === "true" || process.env["NODE_ENV"] === "test")
@@ -773408,7 +774364,7 @@ Flags:
773408
774364
  --dry-run Validate patches, don't write to disk
773409
774365
  --offline Use FakeBackend, no backend connection needed
773410
774366
  -l, --local Save settings to .omnius/settings.json (project-local)
773411
- -v, --verbose Verbose output
774367
+ -v, --verbose Lightweight console mode: print each tool call, result, and reasoning step as plain text (no TUI)
773412
774368
  --max-retries <n> Max retries per model request
773413
774369
  --timeout-ms <ms> Overall task timeout
773414
774370
  --suite <name> Eval suite: basic (default) or full