zelari-code 2.0.1 → 2.1.0

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.
@@ -33708,6 +33708,7 @@ function resetKrakenCandidates() {
33708
33708
  g.__zelariKrakenCandidates = [];
33709
33709
  g.__zelariKrakenSelection = null;
33710
33710
  g.__zelariKrakenCheckResults = null;
33711
+ g.__zelariVerifyToolTrace = null;
33711
33712
  }
33712
33713
  function setKrakenSelection(verdict) {
33713
33714
  const g = globalThis;
@@ -33722,15 +33723,21 @@ function krakenRequiredChecks() {
33722
33723
  if (!verdict || verdict.status !== "selected") return [];
33723
33724
  return verdict.requiredChecks;
33724
33725
  }
33725
- function setKrakenCheckResults(results) {
33726
+ function setKrakenCheckResults(results, toolTrace) {
33726
33727
  const g = globalThis;
33727
33728
  g.__zelariKrakenCheckResults = results;
33729
+ g.__zelariVerifyToolTrace = toolTrace ? [...toolTrace] : null;
33728
33730
  }
33729
33731
  function getKrakenCheckResults() {
33730
33732
  const g = globalThis;
33731
33733
  const results = g.__zelariKrakenCheckResults;
33732
33734
  return results ? [...results] : null;
33733
33735
  }
33736
+ function getLastVerifyToolTrace() {
33737
+ const g = globalThis;
33738
+ const trace = g.__zelariVerifyToolTrace;
33739
+ return trace ? [...trace] : null;
33740
+ }
33734
33741
  function krakenChecksPassed() {
33735
33742
  const results = getKrakenCheckResults();
33736
33743
  if (!results) return void 0;
@@ -34114,20 +34121,49 @@ function maxToolCallsForThoroughness(thoroughness, agent) {
34114
34121
  if (thoroughness === "deep") return 12;
34115
34122
  return 6;
34116
34123
  }
34124
+ function toolCommandHint(args) {
34125
+ if (!args) return void 0;
34126
+ for (const key of ["command", "cmd", "script", "pattern", "path", "query", "url"]) {
34127
+ const v = args[key];
34128
+ if (typeof v === "string" && v.trim()) return v.trim().slice(0, 160);
34129
+ }
34130
+ return void 0;
34131
+ }
34117
34132
  async function runSubAgent(harness, opts = {}) {
34118
34133
  const { signal } = opts;
34119
34134
  let current = "";
34120
34135
  let lastCompleted = "";
34121
34136
  let error51;
34122
34137
  let usage;
34138
+ const pendingTools = /* @__PURE__ */ new Map();
34139
+ const toolTrace = [];
34123
34140
  if (signal?.aborted) return { result: "", aborted: true };
34124
34141
  for await (const ev of harness.run()) {
34125
34142
  if (signal?.aborted) {
34126
34143
  return {
34127
34144
  result: (lastCompleted || current).trim(),
34128
34145
  ...error51 ? { error: error51 } : {},
34129
- aborted: true
34130
- };
34146
+ aborted: true,
34147
+ ...toolTrace.length > 0 ? { toolTrace } : {}
34148
+ };
34149
+ }
34150
+ if (ev.type === "tool_execution_start") {
34151
+ pendingTools.set(ev.toolCallId, { tool: ev.toolName, command: toolCommandHint(ev.args) });
34152
+ } else if (ev.type === "tool_execution_end") {
34153
+ const started = pendingTools.get(ev.toolCallId);
34154
+ pendingTools.delete(ev.toolCallId);
34155
+ toolTrace.push({
34156
+ tool: started?.tool ?? "unknown",
34157
+ callId: ev.toolCallId,
34158
+ ok: !ev.isError,
34159
+ ...started?.command ? { command: started.command } : {},
34160
+ output: String(ev.result ?? "").slice(0, TOOL_TRACE_OUTPUT_MAX),
34161
+ durationMs: ev.durationMs,
34162
+ endedAt: Date.now()
34163
+ });
34164
+ if (toolTrace.length > TOOL_TRACE_RING) {
34165
+ toolTrace.splice(0, toolTrace.length - TOOL_TRACE_RING);
34166
+ }
34131
34167
  }
34132
34168
  switch (ev.type) {
34133
34169
  case "message_start":
@@ -34158,7 +34194,12 @@ async function runSubAgent(harness, opts = {}) {
34158
34194
  }
34159
34195
  }
34160
34196
  const result = (lastCompleted || current).trim();
34161
- return { result, ...error51 ? { error: error51 } : {}, ...usage ? { usage } : {} };
34197
+ return {
34198
+ result,
34199
+ ...error51 ? { error: error51 } : {},
34200
+ ...usage ? { usage } : {},
34201
+ ...toolTrace.length > 0 ? { toolTrace } : {}
34202
+ };
34162
34203
  }
34163
34204
  async function runTentacle(opts) {
34164
34205
  const { deps, args, agent, thoroughness, parentCwd, sessionId: sessionId2 } = opts;
@@ -34268,7 +34309,7 @@ async function runTentacle(opts) {
34268
34309
  error: `task: failed to start sub-agent \u2014 ${err instanceof Error ? err.message : String(err)}`
34269
34310
  };
34270
34311
  }
34271
- const { result, error: error51, aborted: aborted2, usage } = await runSubAgent(harness, {
34312
+ const { result, error: error51, aborted: aborted2, usage, toolTrace } = await runSubAgent(harness, {
34272
34313
  ...opts.signal ? { signal: opts.signal } : {}
34273
34314
  });
34274
34315
  const durationMs = Date.now() - started;
@@ -34370,6 +34411,7 @@ ${verifyHintForGeneral(args.acceptance)}`;
34370
34411
  result,
34371
34412
  footer,
34372
34413
  ...usage ? { usage } : {},
34414
+ ...toolTrace && toolTrace.length > 0 ? { toolTrace } : {},
34373
34415
  worktreePath: worktree?.path ?? null,
34374
34416
  worktreeHandle: worktree
34375
34417
  };
@@ -34476,7 +34518,8 @@ RESTRICTED in this mode: only agent=${allowedAgents.join("|")} is allowed.` : ""
34476
34518
  const required2 = krakenRequiredChecks();
34477
34519
  if (required2.length > 0) {
34478
34520
  setKrakenCheckResults(
34479
- res.ok ? parseVerifyReport(res.result, required2) : allUnknownCheckResults(required2, `verify tentacle failed: ${res.error}`)
34521
+ res.ok ? parseVerifyReport(res.result, required2) : allUnknownCheckResults(required2, `verify tentacle failed: ${res.error}`),
34522
+ res.ok ? res.toolTrace : void 0
34480
34523
  );
34481
34524
  }
34482
34525
  }
@@ -34489,7 +34532,7 @@ ${res.result}${res.footer}`,
34489
34532
  }
34490
34533
  };
34491
34534
  }
34492
- var EXPLORE_PROMPT, GENERAL_PROMPT, VERIFY_PROMPT, TaskArgsSchema, TaskPurposeSchema, TaskArgsWithPurposeSchema;
34535
+ var EXPLORE_PROMPT, GENERAL_PROMPT, VERIFY_PROMPT, TaskArgsSchema, TaskPurposeSchema, TaskArgsWithPurposeSchema, TOOL_TRACE_RING, TOOL_TRACE_OUTPUT_MAX;
34493
34536
  var init_taskTool = __esm({
34494
34537
  "src/cli/tools/taskTool.ts"() {
34495
34538
  "use strict";
@@ -34559,6 +34602,8 @@ var init_taskTool = __esm({
34559
34602
  TaskArgsWithPurposeSchema = TaskArgsSchema.extend({
34560
34603
  purpose: TaskPurposeSchema
34561
34604
  });
34605
+ TOOL_TRACE_RING = 24;
34606
+ TOOL_TRACE_OUTPUT_MAX = 600;
34562
34607
  }
34563
34608
  });
34564
34609
 
@@ -40496,7 +40541,7 @@ var init_headlessSpine = __esm({
40496
40541
  });
40497
40542
 
40498
40543
  // src/cli/state/fileStateStore.ts
40499
- import { createHash as createHash10, randomUUID as randomUUID2 } from "node:crypto";
40544
+ import { createHash as createHash11, randomUUID as randomUUID2 } from "node:crypto";
40500
40545
  import { promises as fs21 } from "node:fs";
40501
40546
  import * as path41 from "node:path";
40502
40547
  function shortId() {
@@ -40548,7 +40593,7 @@ async function getStateStore(projectRoot, env = process.env) {
40548
40593
  }
40549
40594
  }
40550
40595
  function hashStablePrompt(stable) {
40551
- return createHash10("sha256").update(stable, "utf8").digest("hex").slice(0, 16);
40596
+ return createHash11("sha256").update(stable, "utf8").digest("hex").slice(0, 16);
40552
40597
  }
40553
40598
  var DEFAULT_MATERIALIZE_CHARS, FileDurableStateStore, NoopDurableStateStore;
40554
40599
  var init_fileStateStore = __esm({
@@ -43926,7 +43971,7 @@ __export(agentsMd_exports, {
43926
43971
  updateAgentsMd: () => updateAgentsMd
43927
43972
  });
43928
43973
  import { existsSync as existsSync35, readFileSync as readFileSync30, writeFileSync as writeFileSync19 } from "node:fs";
43929
- import { createHash as createHash11 } from "node:crypto";
43974
+ import { createHash as createHash12 } from "node:crypto";
43930
43975
  import { join as join28 } from "node:path";
43931
43976
  import { readFile as readFile4 } from "node:fs/promises";
43932
43977
  async function readPackageJson2(projectRoot) {
@@ -44141,7 +44186,7 @@ async function updateAgentsMd(ctx, projectRoot) {
44141
44186
  return { changed: true, sections: changedSections };
44142
44187
  }
44143
44188
  function hash2(s) {
44144
- return createHash11("sha256").update(s).digest("hex").slice(0, 16);
44189
+ return createHash12("sha256").update(s).digest("hex").slice(0, 16);
44145
44190
  }
44146
44191
  var AUTO_SECTIONS, MARKER_OPEN, MARKER_CLOSE, GENERATORS;
44147
44192
  var init_agentsMd = __esm({
@@ -50747,7 +50792,7 @@ import {
50747
50792
  } from "node:fs";
50748
50793
  import { join as join38 } from "node:path";
50749
50794
  import { homedir as homedir13 } from "node:os";
50750
- import { createHash as createHash12, randomBytes as randomBytes5, timingSafeEqual } from "node:crypto";
50795
+ import { createHash as createHash13, randomBytes as randomBytes5, timingSafeEqual } from "node:crypto";
50751
50796
  function getZelariHome() {
50752
50797
  return join38(homedir13(), ".zelari-code");
50753
50798
  }
@@ -50823,8 +50868,8 @@ function loadOrCreateToken(explicit) {
50823
50868
  }
50824
50869
  function tokenMatches(expected, provided) {
50825
50870
  if (!provided) return false;
50826
- const a = createHash12("sha256").update(expected).digest();
50827
- const b = createHash12("sha256").update(provided).digest();
50871
+ const a = createHash13("sha256").update(expected).digest();
50872
+ const b = createHash13("sha256").update(provided).digest();
50828
50873
  try {
50829
50874
  return timingSafeEqual(a, b);
50830
50875
  } catch {
@@ -55420,6 +55465,7 @@ init_completionGate();
55420
55465
  // src/cli/kraken/verificationBridge.ts
55421
55466
  init_candidateRegistry();
55422
55467
  init_completionGate();
55468
+ import { createHash as createHash10 } from "node:crypto";
55423
55469
 
55424
55470
  // src/cli/kraken/nativeVerification.ts
55425
55471
  init_runtime2();
@@ -55545,33 +55591,94 @@ function krakenResultsToContract(requiredChecks, results, now = Date.now()) {
55545
55591
  });
55546
55592
  return { criteria, results: verifications };
55547
55593
  }
55548
- async function anchorSelectionEvidence(results, emit) {
55549
- if (!emit) return;
55594
+ function sha256Hex2(input) {
55595
+ return createHash10("sha256").update(input).digest("hex");
55596
+ }
55597
+ function matchNoteToToolTrace(note, trace) {
55598
+ const n = normalize4(note);
55599
+ if (!n) return null;
55600
+ for (let i = trace.length - 1; i >= 0; i--) {
55601
+ const t = trace[i];
55602
+ const cmd = t.command ? normalize4(t.command) : "";
55603
+ if (cmd.length >= 4 && (n.includes(cmd) || cmd.includes(n))) return t;
55604
+ }
55605
+ for (let i = trace.length - 1; i >= 0; i--) {
55606
+ const t = trace[i];
55607
+ const out = normalize4(t.output);
55608
+ if (!out) continue;
55609
+ if (n.length >= 8 && out.includes(n)) return t;
55610
+ const fragments = n.match(/\S*\d[\d.,/%]*\S*/g) ?? [];
55611
+ for (const raw of fragments) {
55612
+ const frag = raw.replace(/[.,;:]+$/, "");
55613
+ if (frag.length >= 3 && out.includes(frag)) return t;
55614
+ }
55615
+ }
55616
+ return null;
55617
+ }
55618
+ async function anchorSelectionEvidence(results, emit, toolTrace) {
55619
+ const counts = { toolResultAnchored: 0, noteFallback: 0 };
55620
+ if (!emit) return counts;
55550
55621
  for (const r of results) {
55551
55622
  for (const ev of r.evidence) {
55552
55623
  if (ev.seq !== void 0) continue;
55553
55624
  if (ev.tier === "verifier-llm" || ev.tier === "human") continue;
55554
55625
  try {
55626
+ const match = toolTrace && toolTrace.length > 0 ? matchNoteToToolTrace(ev.ref, toolTrace) : null;
55627
+ if (match) {
55628
+ const digest = sha256Hex2(match.output);
55629
+ const appended2 = await emit({
55630
+ kind: "verification.evidence",
55631
+ actor: { type: "system", role: "verification" },
55632
+ data: {
55633
+ observation: "tool-result",
55634
+ provenance: "tentacle-tool-capture",
55635
+ criterionId: r.criterionId,
55636
+ tool: match.tool,
55637
+ callId: match.callId,
55638
+ ok: match.ok,
55639
+ digest,
55640
+ outputTail: match.output.slice(0, 240),
55641
+ note: ev.ref,
55642
+ ...match.command ? { command: match.command } : {}
55643
+ }
55644
+ });
55645
+ const toolSeq = appended2 && typeof appended2 === "object" && "seq" in appended2 ? Number(appended2.seq) : NaN;
55646
+ if (Number.isFinite(toolSeq) && toolSeq > 0) {
55647
+ ev.seq = toolSeq;
55648
+ ev.digest = digest;
55649
+ ev.ref = `${match.tool}${match.command ? ` ${match.command}` : ""} \u2192 ${match.ok ? "ok" : "error"} @seq`;
55650
+ counts.toolResultAnchored += 1;
55651
+ }
55652
+ continue;
55653
+ }
55555
55654
  const appended = await emit({
55556
55655
  kind: "verification.evidence",
55557
55656
  actor: { type: "system", role: "verification" },
55558
55657
  data: {
55559
55658
  observation: "verify-report-note",
55659
+ provenance: "note-fallback",
55560
55660
  criterionId: r.criterionId,
55561
55661
  ref: ev.ref,
55562
55662
  tier: ev.tier
55563
55663
  }
55564
55664
  });
55565
55665
  const seq = appended && typeof appended === "object" && "seq" in appended ? Number(appended.seq) : NaN;
55566
- if (Number.isFinite(seq) && seq > 0) ev.seq = seq;
55666
+ if (Number.isFinite(seq) && seq > 0) {
55667
+ ev.seq = seq;
55668
+ counts.noteFallback += 1;
55669
+ }
55567
55670
  } catch {
55568
55671
  }
55569
55672
  }
55570
55673
  }
55674
+ return counts;
55571
55675
  }
55572
55676
  async function evaluateStrictBuildGate(mode, options = {}) {
55573
55677
  const gate = evaluateKrakenCompletionGate(mode);
55574
- if (!gate.selectionUsed || gate.total === 0 || !strictDoneEnabled(options.surface ?? "kraken")) {
55678
+ const strictOn = strictDoneEnabled(options.surface ?? "kraken");
55679
+ const nativeOn = nativePackEnabled(options.env ?? process.env);
55680
+ const selectionAvailable = gate.selectionUsed && gate.total > 0;
55681
+ if (!selectionAvailable && !nativeOn || !strictOn && !nativeOn) {
55575
55682
  return {
55576
55683
  gate,
55577
55684
  strict: false,
@@ -55581,9 +55688,13 @@ async function evaluateStrictBuildGate(mode, options = {}) {
55581
55688
  summary: gate.blocked ? `blocked: ${gate.failedChecks.length} failed, ${gate.unknownChecks.length} unknown` : "open"
55582
55689
  };
55583
55690
  }
55584
- const checks = krakenRequiredChecks();
55585
- const contract = krakenResultsToContract(checks, getKrakenCheckResults());
55586
- await anchorSelectionEvidence(contract.results, options.emit);
55691
+ const checks = selectionAvailable ? krakenRequiredChecks() : [];
55692
+ const contract = selectionAvailable ? krakenResultsToContract(checks, getKrakenCheckResults()) : { criteria: [], results: [] };
55693
+ const anchoring = await anchorSelectionEvidence(
55694
+ contract.results,
55695
+ options.emit,
55696
+ getLastVerifyToolTrace() ?? void 0
55697
+ );
55587
55698
  const native = await evaluateNativePack({
55588
55699
  cwd: options.cwd,
55589
55700
  env: options.env,
@@ -55592,15 +55703,29 @@ async function evaluateStrictBuildGate(mode, options = {}) {
55592
55703
  }).catch(() => null);
55593
55704
  const allCriteria = [...contract.criteria, ...native?.criteria ?? []];
55594
55705
  const allResults = [...contract.results, ...native?.results ?? []];
55706
+ if (allCriteria.length === 0) {
55707
+ return {
55708
+ gate,
55709
+ strict: false,
55710
+ evaluation: null,
55711
+ native,
55712
+ results: allResults,
55713
+ blocked: gate.blocked,
55714
+ summary: gate.blocked ? `blocked: ${gate.failedChecks.length} failed, ${gate.unknownChecks.length} unknown` : "open (native pack bound no command)"
55715
+ };
55716
+ }
55595
55717
  const evaluation = evaluateCompletion(allCriteria, allResults, STRICT_BUILD_POLICY);
55596
55718
  const blocked = gate.blocked || evaluation.verdict !== "PASS";
55719
+ const legacyPart = selectionAvailable ? `${gate.passed}/${gate.total} legacy-pass, ` : "no selection contract, ";
55597
55720
  return {
55598
55721
  gate,
55599
55722
  strict: true,
55723
+ results: allResults,
55724
+ anchoring,
55600
55725
  evaluation,
55601
55726
  native,
55602
55727
  blocked,
55603
- summary: blocked ? `blocked (strict ${evaluation?.verdict ?? "n/a"}): ${gate.passed}/${gate.total} legacy-pass, evidence ${evaluation?.evidenceComplete ? "complete" : "incomplete"}` : `open (strict PASS): ${evaluation?.satisfied.length ?? 0}/${allCriteria.length} criteria pass with evidence`
55728
+ summary: blocked ? `blocked (strict ${evaluation?.verdict ?? "n/a"}): ${legacyPart}evidence ${evaluation?.evidenceComplete ? "complete" : "incomplete"}` : `open (strict PASS): ${evaluation?.satisfied.length ?? 0}/${allCriteria.length} criteria pass with evidence`
55604
55729
  };
55605
55730
  }
55606
55731
  var STRICT_DONE_EXIT_CODE = 4;
@@ -55621,7 +55746,8 @@ function strictGateEventPayload(evaluation) {
55621
55746
  evidence: evaluation.evaluation ? {
55622
55747
  satisfied: evaluation.evaluation.satisfied,
55623
55748
  unsatisfied: evaluation.evaluation.unsatisfied,
55624
- complete: evaluation.evaluation.evidenceComplete
55749
+ complete: evaluation.evaluation.evidenceComplete,
55750
+ provenance: evaluation.anchoring ?? null
55625
55751
  } : null,
55626
55752
  // F2: deterministic pack results — real command evidence, replayable.
55627
55753
  native: evaluation.native ? {
@@ -55634,6 +55760,16 @@ function strictGateEventPayload(evaluation) {
55634
55760
  detail: r.detail
55635
55761
  }))
55636
55762
  } : null,
55763
+ // 2.1 T4: advisory verifier review (opt-in) — informational, never
55764
+ // authoritative: verdict/blocked above come from the deterministic policy.
55765
+ verifier: evaluation.review ? {
55766
+ verdict: evaluation.review.verdict,
55767
+ score: evaluation.review.score ?? null,
55768
+ rationale: evaluation.review.rationale ?? null,
55769
+ fallback: evaluation.review.fallback ?? null,
55770
+ effectiveModel: evaluation.review.effectiveModel,
55771
+ advisory: true
55772
+ } : null,
55637
55773
  summary: evaluation.summary
55638
55774
  };
55639
55775
  }
@@ -56389,7 +56525,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
56389
56525
  if (event.type === "agent_end") {
56390
56526
  let krakenSuppressFinish = false;
56391
56527
  const krakenSpineEmit = (input) => writerRef.current?.spine?.appendEvent(input) ?? Promise.resolve(null);
56392
- if (event.reason === "completed" && !krakenRepairEnqueued && isKrakenSelectionEnabled() && workPhase === "build") {
56528
+ if (event.reason === "completed" && !krakenRepairEnqueued && (isKrakenSelectionEnabled() || nativePackEnabled()) && workPhase === "build") {
56393
56529
  const strictGate = await evaluateStrictBuildGate("build", { emit: krakenSpineEmit });
56394
56530
  const krakenGate = strictGate.gate;
56395
56531
  writerRef.current?.spine?.verificationRun(strictGateEventPayload(strictGate));
@@ -61763,6 +61899,93 @@ init_sessionTodos();
61763
61899
  import { promises as fs36 } from "node:fs";
61764
61900
  import path61 from "node:path";
61765
61901
  import { randomUUID as randomUUID6 } from "node:crypto";
61902
+
61903
+ // src/cli/kraken/verifierLifecycle.ts
61904
+ init_verification2();
61905
+ init_krakenSelectTool();
61906
+
61907
+ // src/cli/kraken/verifierResolution.ts
61908
+ init_providerConfig();
61909
+ function verifierOverrideToModelSelection(override) {
61910
+ if (override && typeof override.provider === "string" && typeof override.model === "string" && override.provider.trim().length > 0 && override.model.trim().length > 0) {
61911
+ return {
61912
+ mode: "fixed",
61913
+ provider: override.provider.trim(),
61914
+ model: override.model.trim()
61915
+ };
61916
+ }
61917
+ return { mode: "inherit" };
61918
+ }
61919
+ function loadVerifierModelSelection() {
61920
+ return verifierOverrideToModelSelection(getKrakenVerifierOverride());
61921
+ }
61922
+
61923
+ // src/cli/kraken/verifierLifecycle.ts
61924
+ function verifierReviewEnabled(selection = loadVerifierModelSelection(), env = process.env) {
61925
+ const v = env.ZELARI_VERIFIER_REVIEW?.toLowerCase();
61926
+ if (v === "0" || v === "false" || v === "off") return false;
61927
+ if (v === "1" || v === "true" || v === "on") return true;
61928
+ return selection.mode === "fixed";
61929
+ }
61930
+ function makeVerifierCallModel(loadStream, identity, timeoutMs = 12e4) {
61931
+ return async ({ system, user }) => {
61932
+ const stream = await loadStream(identity.provider, identity.model);
61933
+ if (!stream) {
61934
+ throw new Error(`no provider config for verifier "${identity.provider}"`);
61935
+ }
61936
+ const { text } = await collectProviderText(stream, {
61937
+ messages: [
61938
+ { role: "system", content: system },
61939
+ { role: "user", content: user }
61940
+ ],
61941
+ model: identity.model,
61942
+ provider: identity.provider,
61943
+ tools: [],
61944
+ signal: AbortSignal.timeout(timeoutMs)
61945
+ });
61946
+ return { text, provider: identity.provider, model: identity.model };
61947
+ };
61948
+ }
61949
+ function resolveIdentity(selection, session) {
61950
+ if (selection.mode === "fixed") {
61951
+ return { provider: selection.provider, model: selection.model };
61952
+ }
61953
+ return session && session.provider && session.model ? session : null;
61954
+ }
61955
+ async function runAdvisoryVerifierReview(evaluation, deps = {}) {
61956
+ if (!evaluation.evaluation || !evaluation.results) return null;
61957
+ const env = deps.env ?? process.env;
61958
+ const selection = deps.selection ?? loadVerifierModelSelection();
61959
+ if (!verifierReviewEnabled(selection, env)) return null;
61960
+ const identity = resolveIdentity(selection, deps.session);
61961
+ let callModel = deps.callModel;
61962
+ if (!callModel) {
61963
+ if (!identity || !deps.loadStream) return null;
61964
+ callModel = makeVerifierCallModel(deps.loadStream, identity, deps.timeoutMs);
61965
+ }
61966
+ const service = new VerifierService({
61967
+ callModel,
61968
+ config: {
61969
+ enabled: true,
61970
+ model: selection,
61971
+ progressScoring: false,
61972
+ bon: { enabled: false, n: 3 }
61973
+ },
61974
+ emit: deps.emit,
61975
+ env
61976
+ });
61977
+ const passed = evaluation.results.filter((r) => r.status === "pass").length;
61978
+ const summary = `Kraken BUILD turn \u2014 deterministic evidence: ${passed}/${evaluation.results.length} criteria pass, completion verdict ${evaluation.evaluation.verdict}.`;
61979
+ const review = await service.reviewCompletion({
61980
+ summary,
61981
+ results: evaluation.results,
61982
+ session: deps.session
61983
+ });
61984
+ evaluation.review = review;
61985
+ return review;
61986
+ }
61987
+
61988
+ // src/cli/runHeadless.ts
61766
61989
  init_headlessSpine();
61767
61990
  async function runHeadless(opts) {
61768
61991
  resetTaskSpawnCount();
@@ -62017,13 +62240,6 @@ ${formatKrakenGraphDigest2(
62017
62240
  emitEvent({ type: "message_delta", delta: finalAscii });
62018
62241
  emitEvent({ type: "message_end" });
62019
62242
  emitEvent({ type: "agent_end", reason: summary.converged ? "completed" : "error" });
62020
- emitEvent({
62021
- type: "history_snapshot",
62022
- messages: [
62023
- { role: "user", content: prompt },
62024
- { role: "assistant", content: finalAscii }
62025
- ]
62026
- });
62027
62243
  } else {
62028
62244
  process.stdout.write(`${finalAscii}
62029
62245
  `);
@@ -62406,8 +62622,29 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
62406
62622
  };
62407
62623
  }
62408
62624
  let strictExit = 0;
62409
- if (pass.finalReason === "completed" && pass.exitCode === 0 && opts.mode === "kraken" && isKrakenSelectionEnabled() && !planModeFromOpts(opts)) {
62625
+ const verifierReviewDeps = {
62626
+ session: { provider, model },
62627
+ loadStream: async (providerId, modelId) => {
62628
+ if (providerId === provider) return providerStream;
62629
+ try {
62630
+ const key = await resolveHeadlessKey(providerId);
62631
+ if ("error" in key) return null;
62632
+ const { buildProviderStream: buildProviderStream2 } = await Promise.resolve().then(() => (init_resolveStream(), resolveStream_exports));
62633
+ return buildProviderStream2({
62634
+ providerId,
62635
+ apiKey: key.apiKey,
62636
+ baseUrl: key.baseUrl,
62637
+ model: modelId
62638
+ });
62639
+ } catch {
62640
+ return null;
62641
+ }
62642
+ },
62643
+ emit: (input) => spine.appendEvent(input)
62644
+ };
62645
+ if (pass.finalReason === "completed" && pass.exitCode === 0 && opts.mode === "kraken" && (isKrakenSelectionEnabled() || nativePackEnabled()) && !planModeFromOpts(opts)) {
62410
62646
  const strictGate = await evaluateStrictBuildGate("build", { emit: (input) => spine.appendEvent(input) });
62647
+ await runAdvisoryVerifierReview(strictGate, verifierReviewDeps).catch(() => void 0);
62411
62648
  const gate = strictGate.gate;
62412
62649
  const verificationPayload = strictGateEventPayload(strictGate);
62413
62650
  spine.verificationRun(verificationPayload);
@@ -62441,6 +62678,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
62441
62678
  emittedWrites: pass.emittedWrites + repair.emittedWrites
62442
62679
  };
62443
62680
  const after = await evaluateStrictBuildGate("build", { emit: (input) => spine.appendEvent(input) });
62681
+ await runAdvisoryVerifierReview(after, verifierReviewDeps).catch(() => void 0);
62444
62682
  const afterPayload = strictGateEventPayload(after);
62445
62683
  spine.verificationRun(afterPayload);
62446
62684
  if (opts.output === "json") {
@@ -62465,41 +62703,8 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
62465
62703
  process.stdout.write(pass.textBuffer.join(""));
62466
62704
  }
62467
62705
  process.stdout.write("");
62468
- if (pass.finalReason !== "error" && opts.output === "json") {
62469
- try {
62470
- const all = pass.messages;
62471
- let lastAsst = "";
62472
- for (let i = all.length - 1; i >= 0; i--) {
62473
- const m = all[i];
62474
- if (m?.role === "assistant" && (m.content ?? "").trim()) {
62475
- lastAsst = cleanAgentContent(m.content, {
62476
- stripQuestion: false,
62477
- stripThink: false
62478
- });
62479
- break;
62480
- }
62481
- }
62482
- if (!lastAsst.trim() && pass.textBuffer.length > 0) {
62483
- lastAsst = pass.textBuffer.join("").trim();
62484
- }
62485
- if (wantWrites && pass.successfulWrites === 0) {
62486
- lastAsst = (lastAsst ? `${lastAsst}
62487
-
62488
- ` : "") + "[zelari] WARNING: BUILD turn ended with zero successful file writes. The planned changes may still need to be applied on disk.";
62489
- emitEvent({
62490
- type: "log",
62491
- message: "[headless] BUILD warning: still zero successful writes after retry"
62492
- });
62493
- }
62494
- const snapshot = [
62495
- { role: "user", content: opts.task },
62496
- ...lastAsst ? [{ role: "assistant", content: lastAsst }] : []
62497
- ];
62498
- if (snapshot.length > 0) {
62499
- emitEvent({ type: "history_snapshot", messages: snapshot });
62500
- }
62501
- } catch {
62502
- }
62706
+ if (pass.finalReason !== "error" && opts.output === "json" && wantWrites && pass.successfulWrites === 0) {
62707
+ emitEvent({ type: "log", message: "[headless] BUILD warning: still zero successful writes after retry" });
62503
62708
  }
62504
62709
  try {
62505
62710
  const closeStatus = pass.finalReason === "error" ? "error" : strictExit !== 0 ? "stopped" : "completed";
@@ -62659,16 +62864,6 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
62659
62864
  );
62660
62865
  return 2;
62661
62866
  }
62662
- if (opts.output === "json") {
62663
- try {
62664
- const snapshot = [
62665
- { role: "user", content: opts.task },
62666
- ...lastAssistantText ? [{ role: "assistant", content: lastAssistantText }] : []
62667
- ];
62668
- emitEvent({ type: "history_snapshot", messages: snapshot });
62669
- } catch {
62670
- }
62671
- }
62672
62867
  try {
62673
62868
  await spine.close(exitCode === 0 ? "completed" : "error");
62674
62869
  } catch {
@@ -63027,18 +63222,6 @@ ${ragContext}` : slicePrompt;
63027
63222
  }
63028
63223
  }
63029
63224
  }
63030
- if (opts.output === "json") {
63031
- try {
63032
- emitEvent({
63033
- type: "history_snapshot",
63034
- messages: [
63035
- { role: "user", content: opts.task },
63036
- ...lastMissionAssistant ? [{ role: "assistant", content: lastMissionAssistant }] : []
63037
- ]
63038
- });
63039
- } catch {
63040
- }
63041
- }
63042
63225
  return exitCode;
63043
63226
  }
63044
63227