zelari-code 2.0.0-alpha.4 → 2.0.0-alpha.5

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.
@@ -1939,40 +1939,47 @@ import os3 from "node:os";
1939
1939
  function getProviderConfigPath() {
1940
1940
  return process.env.ANATHEMA_PROVIDER_CONFIG_FILE ?? path4.join(os3.homedir(), ".tmp", "zelari-code", "provider.json");
1941
1941
  }
1942
- function getProviderConfig() {
1943
- const envActive = process.env.ANATHEMA_ACTIVE_PROVIDER;
1944
- const envModel = process.env.OPENAI_MODEL;
1945
- const file2 = getProviderConfigPath();
1946
- let stored = null;
1947
- if (existsSync3(file2)) {
1948
- try {
1949
- const raw = readFileSync3(file2, "utf-8");
1950
- const parsed = JSON.parse(raw);
1951
- if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
1952
- stored = {
1953
- activeProviderId: parsed.activeProviderId,
1954
- modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
1955
- thinkingByProvider: { ...DEFAULTS.thinkingByProvider, ...parsed.thinkingByProvider },
1956
- customEndpoints: mergeCustomEndpoints(parsed.customEndpoints),
1957
- krakenVerifier: mergeKrakenVerifier(parsed.krakenVerifier)
1958
- };
1959
- }
1960
- } catch {
1961
- }
1942
+ function mergeStoredProviderConfig(parsed) {
1943
+ if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
1944
+ return {
1945
+ activeProviderId: parsed.activeProviderId,
1946
+ modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
1947
+ thinkingByProvider: { ...DEFAULTS.thinkingByProvider, ...parsed.thinkingByProvider },
1948
+ customEndpoints: mergeCustomEndpoints(parsed.customEndpoints),
1949
+ krakenVerifier: mergeKrakenVerifier(parsed.krakenVerifier)
1950
+ };
1962
1951
  }
1963
- const base = stored ?? {
1952
+ return cloneDefaults();
1953
+ }
1954
+ function cloneDefaults() {
1955
+ return {
1964
1956
  ...DEFAULTS,
1965
1957
  modelByProvider: { ...DEFAULTS.modelByProvider },
1966
1958
  thinkingByProvider: { ...DEFAULTS.thinkingByProvider },
1967
1959
  customEndpoints: { ...DEFAULTS.customEndpoints }
1968
1960
  };
1961
+ }
1962
+ function applyEnvOverrides(config2) {
1963
+ const envActive = process.env.ANATHEMA_ACTIVE_PROVIDER;
1964
+ const envModel = process.env.OPENAI_MODEL;
1969
1965
  if (envActive && PROVIDERS.some((p3) => p3.id === envActive)) {
1970
- base.activeProviderId = envActive;
1966
+ config2.activeProviderId = envActive;
1971
1967
  }
1972
1968
  if (envModel && envModel.trim().length > 0) {
1973
- base.modelByProvider[base.activeProviderId] = envModel;
1969
+ config2.modelByProvider[config2.activeProviderId] = envModel;
1970
+ }
1971
+ return config2;
1972
+ }
1973
+ function getProviderConfig() {
1974
+ const file2 = getProviderConfigPath();
1975
+ let parsed = null;
1976
+ if (existsSync3(file2)) {
1977
+ try {
1978
+ parsed = JSON.parse(readFileSync3(file2, "utf-8"));
1979
+ } catch {
1980
+ }
1974
1981
  }
1975
- return base;
1982
+ return applyEnvOverrides(mergeStoredProviderConfig(parsed));
1976
1983
  }
1977
1984
  function writeProviderConfig(config2) {
1978
1985
  const file2 = getProviderConfigPath();
@@ -2105,25 +2112,12 @@ function getActiveModel() {
2105
2112
  }
2106
2113
  async function loadProviderConfig() {
2107
2114
  const file2 = getProviderConfigPath();
2115
+ let parsed = null;
2108
2116
  try {
2109
- const raw = await fs2.readFile(file2, "utf-8");
2110
- const parsed = JSON.parse(raw);
2111
- if (parsed && typeof parsed === "object" && typeof parsed.activeProviderId === "string" && parsed.modelByProvider && typeof parsed.modelByProvider === "object") {
2112
- return {
2113
- activeProviderId: parsed.activeProviderId,
2114
- modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
2115
- thinkingByProvider: { ...DEFAULTS.thinkingByProvider, ...parsed.thinkingByProvider },
2116
- customEndpoints: mergeCustomEndpoints(parsed.customEndpoints)
2117
- };
2118
- }
2117
+ parsed = JSON.parse(await fs2.readFile(file2, "utf-8"));
2119
2118
  } catch {
2120
2119
  }
2121
- return {
2122
- ...DEFAULTS,
2123
- modelByProvider: { ...DEFAULTS.modelByProvider },
2124
- thinkingByProvider: { ...DEFAULTS.thinkingByProvider },
2125
- customEndpoints: { ...DEFAULTS.customEndpoints }
2126
- };
2120
+ return applyEnvOverrides(mergeStoredProviderConfig(parsed));
2127
2121
  }
2128
2122
  var DEFAULTS;
2129
2123
  var init_providerConfig = __esm({
@@ -28387,6 +28381,23 @@ var init_modelSurface = __esm({
28387
28381
  }
28388
28382
  });
28389
28383
 
28384
+ // packages/core/dist/session/agentAdapter.js
28385
+ function derivedToAgentMessages(messages) {
28386
+ const out = [];
28387
+ for (const m of messages) {
28388
+ const agent = { role: m.role, content: m.content };
28389
+ if (m.toolCallId !== void 0)
28390
+ agent.toolCallId = m.toolCallId;
28391
+ out.push(agent);
28392
+ }
28393
+ return out;
28394
+ }
28395
+ var init_agentAdapter = __esm({
28396
+ "packages/core/dist/session/agentAdapter.js"() {
28397
+ "use strict";
28398
+ }
28399
+ });
28400
+
28390
28401
  // packages/core/dist/session/writer.js
28391
28402
  import { promises as fs9 } from "node:fs";
28392
28403
  import path14 from "node:path";
@@ -28841,6 +28852,7 @@ var init_session = __esm({
28841
28852
  "use strict";
28842
28853
  init_types8();
28843
28854
  init_modelSurface();
28855
+ init_agentAdapter();
28844
28856
  init_writer();
28845
28857
  init_replay();
28846
28858
  init_store();
@@ -30170,6 +30182,7 @@ __export(dist_exports, {
30170
30182
  defaultPersonaParse: () => defaultPersonaParse,
30171
30183
  deriveMessages: () => deriveMessages,
30172
30184
  deriveMissionState: () => deriveMissionState,
30185
+ derivedToAgentMessages: () => derivedToAgentMessages,
30173
30186
  detectAssistantTextLoop: () => detectAssistantTextLoop,
30174
30187
  detectAssistantTextLoopWindow: () => detectAssistantTextLoopWindow,
30175
30188
  detectDegradedRun: () => detectDegradedRun,
@@ -30740,6 +30753,34 @@ var init_sessionSpine = __esm({
30740
30753
  userMessage(text) {
30741
30754
  void this.append({ kind: "user.message", actor: ACTOR_USER, data: { text } });
30742
30755
  }
30756
+ /**
30757
+ * Log an assistant message outside the streaming path — legacy
30758
+ * `--history` import (Exit-1/E1.2). Same event shape the message_end
30759
+ * coalescer emits, so deriveMessages() treats both identically.
30760
+ */
30761
+ assistantMessage(text, extra) {
30762
+ void this.append({
30763
+ kind: "assistant.message",
30764
+ actor: ACTOR_AGENT,
30765
+ data: { text, ...extra }
30766
+ });
30767
+ }
30768
+ /** Await all pending appends (import → derive read-back needs this). */
30769
+ async flush() {
30770
+ await this.chain;
30771
+ }
30772
+ /**
30773
+ * Derive prior-turn model context from the on-disk log. Null when the
30774
+ * log is missing/empty — callers decide whether that means "fresh".
30775
+ */
30776
+ async derivedPriorTurns() {
30777
+ if (this.status !== "active" && this.status !== "closed") return null;
30778
+ const report = await readSessionLog(
30779
+ path21.join(this.sessionsDir, this.sessionId, "events.jsonl")
30780
+ ).catch(() => null);
30781
+ if (!report || report.events.length === 0) return null;
30782
+ return deriveMessages(report.events);
30783
+ }
30743
30784
  /** Mirror one BrainEvent (coalescing message deltas until message_end). */
30744
30785
  mirrorBrainEvent(ev) {
30745
30786
  if (this.status !== "active" || !this.writer) return;
@@ -39550,6 +39591,526 @@ var init_toolRegistry = __esm({
39550
39591
  }
39551
39592
  });
39552
39593
 
39594
+ // src/cli/phase.ts
39595
+ var phase_exports = {};
39596
+ __export(phase_exports, {
39597
+ PHASES: () => PHASES,
39598
+ PLAN_ALLOWED_WRITE_TOOLS: () => PLAN_ALLOWED_WRITE_TOOLS,
39599
+ PLAN_BLOCKED_TOOLS: () => PLAN_BLOCKED_TOOLS,
39600
+ describePhase: () => describePhase,
39601
+ nextPhase: () => nextPhase,
39602
+ parsePhase: () => parsePhase
39603
+ });
39604
+ function parsePhase(input) {
39605
+ const v = input.trim().toLowerCase();
39606
+ return PHASES.includes(v) ? v : null;
39607
+ }
39608
+ function nextPhase(current) {
39609
+ return current === "plan" ? "build" : "plan";
39610
+ }
39611
+ function describePhase(phase2) {
39612
+ switch (phase2) {
39613
+ case "plan":
39614
+ return "plan \u2014 explore & design only (no project writes; plan files allowed)";
39615
+ default:
39616
+ return "build \u2014 implement with full tools";
39617
+ }
39618
+ }
39619
+ var PHASES, PLAN_ALLOWED_WRITE_TOOLS, PLAN_BLOCKED_TOOLS;
39620
+ var init_phase = __esm({
39621
+ "src/cli/phase.ts"() {
39622
+ "use strict";
39623
+ PHASES = ["plan", "build"];
39624
+ PLAN_ALLOWED_WRITE_TOOLS = /* @__PURE__ */ new Set([
39625
+ // Workspace plan/docs — intentional plan-mode outputs
39626
+ "createPlan",
39627
+ "createTask",
39628
+ "updateTask",
39629
+ "createMilestone",
39630
+ "createDocument",
39631
+ "createDecision",
39632
+ "linkDocuments"
39633
+ // Soft writes that only touch .zelari / plan paths are still gated in
39634
+ // toolRegistry by path when needed; write_file/edit_file stay DENIED.
39635
+ ]);
39636
+ PLAN_BLOCKED_TOOLS = /* @__PURE__ */ new Set([
39637
+ "write_file",
39638
+ "edit_file",
39639
+ "apply_diff",
39640
+ "bash"
39641
+ ]);
39642
+ }
39643
+ });
39644
+
39645
+ // src/cli/mode.ts
39646
+ function nextMode(current) {
39647
+ const i = MODES.indexOf(current);
39648
+ return MODES[(i + 1) % MODES.length] ?? "kraken";
39649
+ }
39650
+ function parseMode(input) {
39651
+ const v = input.trim().toLowerCase();
39652
+ if (MODES.includes(v)) return v;
39653
+ return MODE_ALIASES[v] ?? null;
39654
+ }
39655
+ function describeMode(mode) {
39656
+ switch (mode) {
39657
+ case "council":
39658
+ return "council \u2014 multi-member plan/design (Caronte\u2026Lucifero; build needs ZELARI_COUNCIL_CAN_BUILD=1)";
39659
+ case "zelari":
39660
+ return "zelari \u2014 mission: plan@council \u2192 build@kraken (legacy: ZELARI_BUILD_VIA_AGENT=0)";
39661
+ default:
39662
+ return "kraken \u2014 super-agent lead (spawns explore/general/verify tentacles; default implementer)";
39663
+ }
39664
+ }
39665
+ var MODES, MODE_ALIASES;
39666
+ var init_mode = __esm({
39667
+ "src/cli/mode.ts"() {
39668
+ "use strict";
39669
+ MODES = ["kraken", "council", "zelari"];
39670
+ MODE_ALIASES = {
39671
+ agent: "kraken",
39672
+ single: "kraken"
39673
+ };
39674
+ }
39675
+ });
39676
+
39677
+ // src/cli/headless.ts
39678
+ import { readFileSync as readFileSync22 } from "node:fs";
39679
+ function defaultProfileForMode(mode) {
39680
+ switch (mode) {
39681
+ case "council":
39682
+ return "council/v1";
39683
+ case "zelari":
39684
+ return "mission/v1";
39685
+ default:
39686
+ return "kraken/v1";
39687
+ }
39688
+ }
39689
+ function parseHeadlessFlags(argv) {
39690
+ if (!argv.includes("--headless")) {
39691
+ return { options: null };
39692
+ }
39693
+ let task;
39694
+ let output = "json";
39695
+ let mode = "kraken";
39696
+ let phase2 = "build";
39697
+ let modeExplicit = false;
39698
+ let councilFlag = false;
39699
+ let provider;
39700
+ let model;
39701
+ let history2;
39702
+ let todos2;
39703
+ let once = false;
39704
+ let profile;
39705
+ let resumeSessionId;
39706
+ let exportSessionPath;
39707
+ let strictDone = false;
39708
+ let krakenGraph;
39709
+ let planOnly = process.env.ZELARI_KRAKEN_PLAN_ONLY === "1" || process.env.ZELARI_KRAKEN_PLAN_ONLY === "true";
39710
+ let runPlan = process.env.ZELARI_KRAKEN_RUN_PLAN;
39711
+ for (let i = 0; i < argv.length; i++) {
39712
+ const arg = argv[i];
39713
+ if (arg === "--headless") continue;
39714
+ if (arg === "--output") {
39715
+ const next = argv[i + 1];
39716
+ if (next === "json" || next === "plain") {
39717
+ output = next;
39718
+ i++;
39719
+ } else {
39720
+ return {
39721
+ options: null,
39722
+ error: `--output requires 'json' or 'plain', got '${next ?? "(missing)"}'`
39723
+ };
39724
+ }
39725
+ } else if (arg === "--task") {
39726
+ task = argv[i + 1];
39727
+ i++;
39728
+ } else if (arg === "--task-file") {
39729
+ const next = argv[i + 1];
39730
+ if (next) {
39731
+ try {
39732
+ const fromFile = readFileSync22(next, "utf-8");
39733
+ if (fromFile.trim()) task = fromFile;
39734
+ } catch {
39735
+ }
39736
+ }
39737
+ i++;
39738
+ } else if (arg === "--council") {
39739
+ councilFlag = true;
39740
+ } else if (arg === "--mode") {
39741
+ const next = argv[i + 1];
39742
+ const parsed = next ? parseMode(next) : null;
39743
+ if (!parsed) {
39744
+ return {
39745
+ options: null,
39746
+ error: `--mode requires 'kraken', 'council', or 'zelari' (agent=alias), got '${next ?? "(missing)"}'`
39747
+ };
39748
+ }
39749
+ mode = parsed;
39750
+ modeExplicit = true;
39751
+ i++;
39752
+ } else if (arg === "--phase") {
39753
+ const next = argv[i + 1];
39754
+ const parsed = next ? parsePhase(next) : null;
39755
+ if (!parsed) {
39756
+ return {
39757
+ options: null,
39758
+ error: `--phase requires 'plan' or 'build', got '${next ?? "(missing)"}'`
39759
+ };
39760
+ }
39761
+ phase2 = parsed;
39762
+ i++;
39763
+ } else if (arg === "--provider") {
39764
+ provider = argv[i + 1];
39765
+ i++;
39766
+ } else if (arg === "--model") {
39767
+ model = argv[i + 1];
39768
+ i++;
39769
+ } else if (arg === "--history" || arg === "--history-file") {
39770
+ const next = argv[i + 1];
39771
+ if (next) {
39772
+ let raw = null;
39773
+ if (arg === "--history-file") {
39774
+ try {
39775
+ raw = readFileSync22(next, "utf-8");
39776
+ } catch {
39777
+ raw = null;
39778
+ }
39779
+ } else {
39780
+ raw = next;
39781
+ }
39782
+ if (raw) {
39783
+ try {
39784
+ const parsedHist = JSON.parse(raw);
39785
+ if (Array.isArray(parsedHist)) {
39786
+ history2 = parsedHist.filter(
39787
+ (m) => !!m && typeof m === "object" && typeof m.role === "string"
39788
+ ).map((m) => {
39789
+ const role = String(m.role);
39790
+ const raw2 = m.content;
39791
+ const content = typeof raw2 === "string" ? raw2 : raw2 == null ? "" : typeof raw2 === "object" ? JSON.stringify(raw2) : String(raw2);
39792
+ const msg = {
39793
+ role,
39794
+ content
39795
+ };
39796
+ if (typeof m.toolCallId === "string") {
39797
+ msg.toolCallId = m.toolCallId;
39798
+ }
39799
+ return msg;
39800
+ }).filter(
39801
+ (m) => m.role === "user" || m.role === "assistant" || m.role === "tool" || m.role === "system"
39802
+ );
39803
+ }
39804
+ } catch {
39805
+ }
39806
+ }
39807
+ i++;
39808
+ }
39809
+ } else if (arg === "--todos") {
39810
+ const next = argv[i + 1];
39811
+ if (next) {
39812
+ try {
39813
+ const parsed = JSON.parse(next);
39814
+ if (Array.isArray(parsed)) {
39815
+ todos2 = parsed.filter(
39816
+ (t) => !!t && typeof t === "object" && typeof t.content === "string"
39817
+ ).map((t) => ({
39818
+ id: typeof t.id === "string" ? t.id : void 0,
39819
+ content: String(t.content).slice(0, 500),
39820
+ status: t.status
39821
+ }));
39822
+ }
39823
+ } catch {
39824
+ }
39825
+ i++;
39826
+ }
39827
+ } else if (arg === "--once") {
39828
+ once = true;
39829
+ } else if (arg === "--profile") {
39830
+ const next = argv[i + 1];
39831
+ if (!next || next.startsWith("--")) {
39832
+ return { options: null, error: `--profile requires a profile id (e.g. kraken/v1), got '${next ?? "(missing)"}'` };
39833
+ }
39834
+ try {
39835
+ resolveProfile(next);
39836
+ } catch (err) {
39837
+ return {
39838
+ options: null,
39839
+ error: err instanceof Error ? err.message : String(err)
39840
+ };
39841
+ }
39842
+ profile = next;
39843
+ i++;
39844
+ } else if (arg === "--resume") {
39845
+ const next = argv[i + 1];
39846
+ if (!next || next.startsWith("--")) {
39847
+ return { options: null, error: `--resume requires a session id, got '${next ?? "(missing)"}'` };
39848
+ }
39849
+ resumeSessionId = next;
39850
+ i++;
39851
+ } else if (arg === "--export-session") {
39852
+ const next = argv[i + 1];
39853
+ if (!next || next.startsWith("--")) {
39854
+ return { options: null, error: `--export-session requires a path (or - for stdout), got '${next ?? "(missing)"}'` };
39855
+ }
39856
+ exportSessionPath = next;
39857
+ i++;
39858
+ } else if (arg === "--strict-done") {
39859
+ strictDone = true;
39860
+ } else if (arg === "--kraken-graph") {
39861
+ krakenGraph = argv[i + 1];
39862
+ i++;
39863
+ } else if (arg === "--kraken-graph-file") {
39864
+ const next = argv[i + 1];
39865
+ if (next) {
39866
+ try {
39867
+ const fromFile = readFileSync22(next, "utf-8");
39868
+ if (fromFile.trim()) krakenGraph = fromFile;
39869
+ } catch {
39870
+ }
39871
+ }
39872
+ i++;
39873
+ } else if (arg === "--plan-only") {
39874
+ planOnly = true;
39875
+ } else if (arg === "--run-plan") {
39876
+ runPlan = argv[i + 1];
39877
+ i++;
39878
+ }
39879
+ }
39880
+ if (councilFlag && !modeExplicit) {
39881
+ mode = "council";
39882
+ } else if (councilFlag && modeExplicit && mode !== "council") {
39883
+ return {
39884
+ options: null,
39885
+ error: `--council conflicts with --mode ${mode}`
39886
+ };
39887
+ }
39888
+ if (task && krakenGraph) {
39889
+ return { options: null, error: "--task and --kraken-graph are mutually exclusive" };
39890
+ }
39891
+ if ((!task || task.trim().length === 0) && (!krakenGraph || krakenGraph.trim().length === 0)) {
39892
+ return { options: null, error: "--headless requires --task <prompt> or --kraken-graph <goal>" };
39893
+ }
39894
+ return {
39895
+ options: {
39896
+ task: task ?? "",
39897
+ output,
39898
+ mode,
39899
+ phase: phase2,
39900
+ useCouncil: mode === "council",
39901
+ provider,
39902
+ model,
39903
+ ...history2 && history2.length > 0 ? { history: history2 } : {},
39904
+ ...todos2 && todos2.length > 0 ? { todos: todos2 } : {},
39905
+ ...once ? { once: true } : {},
39906
+ ...profile ? { profile } : {},
39907
+ ...resumeSessionId ? { resumeSessionId } : {},
39908
+ ...exportSessionPath ? { exportSessionPath } : {},
39909
+ ...strictDone ? { strictDone: true } : {},
39910
+ ...krakenGraph ? { krakenGraph } : {},
39911
+ ...planOnly ? { planOnly: true } : {},
39912
+ ...runPlan ? { runPlan } : {}
39913
+ }
39914
+ };
39915
+ }
39916
+ async function resolveHeadlessKey(providerId) {
39917
+ const spec = PROVIDERS.find((p3) => p3.id === providerId);
39918
+ if (!spec) {
39919
+ return { error: `unknown provider: '${providerId}'` };
39920
+ }
39921
+ const resolved = await resolveApiKeyWithMeta(providerId);
39922
+ if (!resolved || !resolved.apiKey) {
39923
+ return {
39924
+ error: `no API key for provider '${providerId}'.
39925
+ Set the env var ${spec.envVar} or save a key via /login.`
39926
+ };
39927
+ }
39928
+ const { resolveBaseUrl: resolveBaseUrl2 } = await Promise.resolve().then(() => (init_openai_compatible(), openai_compatible_exports));
39929
+ return {
39930
+ apiKey: resolved.apiKey,
39931
+ baseUrl: resolveBaseUrl2(providerId)
39932
+ };
39933
+ }
39934
+ function resolveHeadlessProvider(opts) {
39935
+ const provider = opts.provider ?? getActiveProvider().id;
39936
+ const model = opts.model ?? getModelForProvider(provider);
39937
+ return { provider, model };
39938
+ }
39939
+ function emitEvent(event) {
39940
+ process.stdout.write(JSON.stringify(event) + "\n");
39941
+ }
39942
+ var init_headless = __esm({
39943
+ "src/cli/headless.ts"() {
39944
+ "use strict";
39945
+ init_keyStore();
39946
+ init_providerConfig();
39947
+ init_openai_compatible();
39948
+ init_phase();
39949
+ init_mode();
39950
+ init_runtime2();
39951
+ }
39952
+ });
39953
+
39954
+ // src/cli/headlessSpine.ts
39955
+ var headlessSpine_exports = {};
39956
+ __export(headlessSpine_exports, {
39957
+ derivedModelSeed: () => derivedModelSeed,
39958
+ exportSessionById: () => exportSessionById,
39959
+ missionStateFromSpine: () => missionStateFromSpine,
39960
+ openHeadlessSpine: () => openHeadlessSpine,
39961
+ resolveHeadlessProfileId: () => resolveHeadlessProfileId,
39962
+ seedHeadlessModelHistory: () => seedHeadlessModelHistory
39963
+ });
39964
+ function resolveHeadlessProfileId(mode, explicit) {
39965
+ if (explicit) return resolveProfile(explicit).id;
39966
+ return defaultProfileForMode(mode ?? "kraken");
39967
+ }
39968
+ async function openHeadlessSpine(opts) {
39969
+ const profileId = resolveHeadlessProfileId(opts.mode, opts.profile);
39970
+ let profileTools = [];
39971
+ try {
39972
+ profileTools = resolveProfile(profileId).tools;
39973
+ } catch {
39974
+ profileTools = [];
39975
+ }
39976
+ const extra = {
39977
+ profile: profileId,
39978
+ workspace: opts.workspace ?? process.cwd(),
39979
+ toolManifestHash: profileTools.length > 0 ? toolManifestHash(profileTools) : void 0
39980
+ };
39981
+ const mirrorOpts = {
39982
+ baseDir: opts.baseDir,
39983
+ quiet: opts.quiet,
39984
+ extraStarted: extra
39985
+ };
39986
+ const spine = await SessionSpineMirror.adopt(opts.sessionId, mirrorOpts);
39987
+ if (spine.status === "active") {
39988
+ spine.note("headless.profile", { profile: profileId, mode: opts.mode ?? "kraken" });
39989
+ }
39990
+ return {
39991
+ sessionId: opts.sessionId,
39992
+ profileId,
39993
+ spine,
39994
+ observe(ev) {
39995
+ if (ev && typeof ev === "object" && "type" in ev) {
39996
+ spine.mirrorBrainEvent(ev);
39997
+ }
39998
+ },
39999
+ userMessage(text) {
40000
+ spine.userMessage(text);
40001
+ },
40002
+ verificationRun(payload) {
40003
+ spine.verificationRun(payload);
40004
+ },
40005
+ missionPhase(phase2, note) {
40006
+ spine.missionPhase(phase2, note);
40007
+ },
40008
+ note(text, data) {
40009
+ spine.note(text, data);
40010
+ },
40011
+ async close(reason = "host-exit") {
40012
+ await spine.close(reason);
40013
+ },
40014
+ async interrupt(note) {
40015
+ if (note) spine.note("headless.interrupt", { note });
40016
+ await spine.release();
40017
+ },
40018
+ async exportJson() {
40019
+ try {
40020
+ const store6 = new SessionStore(resolveSessionsDir({ baseDir: opts.baseDir }));
40021
+ if (!await store6.exists(opts.sessionId)) return null;
40022
+ return await exportSessionJson(store6, opts.sessionId);
40023
+ } catch {
40024
+ return null;
40025
+ }
40026
+ }
40027
+ };
40028
+ }
40029
+ async function exportSessionById(sessionId2, baseDir) {
40030
+ try {
40031
+ const store6 = SessionStore.withDefaults(baseDir ? { baseDir } : {});
40032
+ if (!await store6.exists(sessionId2)) {
40033
+ return { ok: false, error: `session not found: ${sessionId2}` };
40034
+ }
40035
+ return { ok: true, json: await exportSessionJson(store6, sessionId2) };
40036
+ } catch (err) {
40037
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
40038
+ }
40039
+ }
40040
+ async function missionStateFromSpine(sessionId2, baseDir) {
40041
+ try {
40042
+ const store6 = SessionStore.withDefaults(baseDir ? { baseDir } : {});
40043
+ if (!await store6.exists(sessionId2)) return null;
40044
+ const projection = await store6.projection(sessionId2);
40045
+ return deriveMissionState(projection);
40046
+ } catch {
40047
+ return null;
40048
+ }
40049
+ }
40050
+ async function seedHeadlessModelHistory(handle, legacy) {
40051
+ const mirror = handle.spine;
40052
+ const legacySeed = filterLegacySeed(legacy);
40053
+ if (mirror.status !== "active") {
40054
+ return { history: legacySeed, importedCount: 0, source: "legacy-fallback" };
40055
+ }
40056
+ const existing = await mirror.derivedPriorTurns();
40057
+ if (existing && existing.length > 0) {
40058
+ return { history: derivedModelSeed(existing), importedCount: 0, source: "spine" };
40059
+ }
40060
+ if (legacySeed.length === 0) {
40061
+ return { history: [], importedCount: 0, source: "spine" };
40062
+ }
40063
+ for (const m of legacySeed) {
40064
+ if (m.role === "user") {
40065
+ mirror.userMessage(m.content);
40066
+ } else {
40067
+ mirror.assistantMessage(m.content, { imported: "legacy-history" });
40068
+ }
40069
+ }
40070
+ await mirror.flush();
40071
+ const derived = await mirror.derivedPriorTurns() ?? [];
40072
+ return {
40073
+ history: derivedModelSeed(derived),
40074
+ importedCount: legacySeed.length,
40075
+ source: "spine-import"
40076
+ };
40077
+ }
40078
+ function filterLegacySeed(legacy) {
40079
+ return (legacy ?? []).filter((m) => m.role === "user" || m.role === "assistant").map(
40080
+ (m) => m.role === "assistant" && m.content ? {
40081
+ role: "assistant",
40082
+ content: cleanAgentContent(m.content, {
40083
+ stripQuestion: false,
40084
+ stripThink: false
40085
+ })
40086
+ } : { role: m.role, content: m.content ?? "" }
40087
+ ).filter((m) => (m.content ?? "").trim().length > 0);
40088
+ }
40089
+ function derivedModelSeed(derived) {
40090
+ return derivedToAgentMessages(derived).map(
40091
+ (m) => m.role === "system" ? { role: "user", content: m.content } : m
40092
+ ).map(
40093
+ (m) => m.role === "assistant" && m.content ? {
40094
+ role: "assistant",
40095
+ content: cleanAgentContent(m.content, {
40096
+ stripQuestion: false,
40097
+ stripThink: false
40098
+ })
40099
+ } : m
40100
+ ).filter((m) => m.role === "user" || m.role === "assistant").filter((m) => (m.content ?? "").trim().length > 0);
40101
+ }
40102
+ var init_headlessSpine = __esm({
40103
+ "src/cli/headlessSpine.ts"() {
40104
+ "use strict";
40105
+ init_dist();
40106
+ init_session();
40107
+ init_mission2();
40108
+ init_runtime2();
40109
+ init_sessionSpine();
40110
+ init_headless();
40111
+ }
40112
+ });
40113
+
39553
40114
  // src/cli/state/fileStateStore.ts
39554
40115
  import { createHash as createHash10, randomUUID as randomUUID2 } from "node:crypto";
39555
40116
  import { promises as fs21 } from "node:fs";
@@ -40502,57 +41063,6 @@ var init_phaseState = __esm({
40502
41063
  }
40503
41064
  });
40504
41065
 
40505
- // src/cli/phase.ts
40506
- var phase_exports = {};
40507
- __export(phase_exports, {
40508
- PHASES: () => PHASES,
40509
- PLAN_ALLOWED_WRITE_TOOLS: () => PLAN_ALLOWED_WRITE_TOOLS,
40510
- PLAN_BLOCKED_TOOLS: () => PLAN_BLOCKED_TOOLS,
40511
- describePhase: () => describePhase,
40512
- nextPhase: () => nextPhase,
40513
- parsePhase: () => parsePhase
40514
- });
40515
- function parsePhase(input) {
40516
- const v = input.trim().toLowerCase();
40517
- return PHASES.includes(v) ? v : null;
40518
- }
40519
- function nextPhase(current) {
40520
- return current === "plan" ? "build" : "plan";
40521
- }
40522
- function describePhase(phase2) {
40523
- switch (phase2) {
40524
- case "plan":
40525
- return "plan \u2014 explore & design only (no project writes; plan files allowed)";
40526
- default:
40527
- return "build \u2014 implement with full tools";
40528
- }
40529
- }
40530
- var PHASES, PLAN_ALLOWED_WRITE_TOOLS, PLAN_BLOCKED_TOOLS;
40531
- var init_phase = __esm({
40532
- "src/cli/phase.ts"() {
40533
- "use strict";
40534
- PHASES = ["plan", "build"];
40535
- PLAN_ALLOWED_WRITE_TOOLS = /* @__PURE__ */ new Set([
40536
- // Workspace plan/docs — intentional plan-mode outputs
40537
- "createPlan",
40538
- "createTask",
40539
- "updateTask",
40540
- "createMilestone",
40541
- "createDocument",
40542
- "createDecision",
40543
- "linkDocuments"
40544
- // Soft writes that only touch .zelari / plan paths are still gated in
40545
- // toolRegistry by path when needed; write_file/edit_file stay DENIED.
40546
- ]);
40547
- PLAN_BLOCKED_TOOLS = /* @__PURE__ */ new Set([
40548
- "write_file",
40549
- "edit_file",
40550
- "apply_diff",
40551
- "bash"
40552
- ]);
40553
- }
40554
- });
40555
-
40556
41066
  // src/cli/provider/localCli/claudeStreamJson.ts
40557
41067
  function textBlock(text) {
40558
41068
  return { type: "text", text };
@@ -40816,14 +41326,14 @@ var init_claudeProvider = __esm({
40816
41326
  });
40817
41327
 
40818
41328
  // src/cli/workspace/projectInstructions.ts
40819
- import { existsSync as existsSync26, readFileSync as readFileSync22 } from "node:fs";
41329
+ import { existsSync as existsSync26, readFileSync as readFileSync23 } from "node:fs";
40820
41330
  import { join as join20 } from "node:path";
40821
41331
  function loadProjectInstructions(projectRoot = process.cwd(), maxChars = MAX_CHARS) {
40822
41332
  for (const name of CANDIDATES) {
40823
41333
  const full = join20(projectRoot, name);
40824
41334
  if (!existsSync26(full)) continue;
40825
41335
  try {
40826
- let raw = readFileSync22(full, "utf8");
41336
+ let raw = readFileSync23(full, "utf8");
40827
41337
  raw = raw.replace(/\r\n/g, "\n").trim();
40828
41338
  if (!raw) continue;
40829
41339
  if (raw.length <= maxChars) {
@@ -40867,7 +41377,7 @@ __export(workspaceSummary_exports, {
40867
41377
  buildWorkspaceSummary: () => buildWorkspaceSummary,
40868
41378
  buildZelariReadHint: () => buildZelariReadHint
40869
41379
  });
40870
- import { existsSync as existsSync27, readFileSync as readFileSync23, readdirSync as readdirSync6, statSync as statSync5 } from "node:fs";
41380
+ import { existsSync as existsSync27, readFileSync as readFileSync24, readdirSync as readdirSync6, statSync as statSync5 } from "node:fs";
40871
41381
  import { join as join21, relative } from "node:path";
40872
41382
  function buildWorkspaceSummary(projectRoot = process.cwd(), options = {}) {
40873
41383
  const { maxEntries = 30, maxChars = 3500, maxDeps = 24, maxScripts = 16 } = options;
@@ -40905,7 +41415,7 @@ function buildPlanSummary(projectRoot = process.cwd(), options) {
40905
41415
  if (!existsSync27(planPath)) return null;
40906
41416
  let plan;
40907
41417
  try {
40908
- plan = JSON.parse(readFileSync23(planPath, "utf8"));
41418
+ plan = JSON.parse(readFileSync24(planPath, "utf8"));
40909
41419
  } catch {
40910
41420
  return null;
40911
41421
  }
@@ -41063,7 +41573,7 @@ function readPackageJson(projectRoot) {
41063
41573
  const p3 = join21(projectRoot, "package.json");
41064
41574
  if (!existsSync27(p3)) return null;
41065
41575
  try {
41066
- return JSON.parse(readFileSync23(p3, "utf8"));
41576
+ return JSON.parse(readFileSync24(p3, "utf8"));
41067
41577
  } catch {
41068
41578
  return null;
41069
41579
  }
@@ -41191,7 +41701,7 @@ var composeContext_exports = {};
41191
41701
  __export(composeContext_exports, {
41192
41702
  composeProjectContext: () => composeProjectContext
41193
41703
  });
41194
- import { existsSync as existsSync29, readdirSync as readdirSync7, readFileSync as readFileSync24 } from "node:fs";
41704
+ import { existsSync as existsSync29, readdirSync as readdirSync7, readFileSync as readFileSync25 } from "node:fs";
41195
41705
  import { join as join23 } from "node:path";
41196
41706
  function cap2(text, max, label) {
41197
41707
  if (!text || text.length <= max) return { text: text || "", truncated: false };
@@ -41332,15 +41842,15 @@ function readDurableHeadSync(projectRoot) {
41332
41842
  try {
41333
41843
  const headPath = join23(projectRoot, ".zelari", "state", "HEAD.json");
41334
41844
  if (!existsSync29(headPath)) return "";
41335
- const head = JSON.parse(readFileSync24(headPath, "utf8"));
41845
+ const head = JSON.parse(readFileSync25(headPath, "utf8"));
41336
41846
  if (!head?.id) return "";
41337
41847
  const metaPath = join23(projectRoot, ".zelari", "state", "commits", `${head.id}.json`);
41338
41848
  if (!existsSync29(metaPath)) return "";
41339
- const meta3 = JSON.parse(readFileSync24(metaPath, "utf8"));
41849
+ const meta3 = JSON.parse(readFileSync25(metaPath, "utf8"));
41340
41850
  const discPath = meta3.artifactDir ? join23(projectRoot, ".zelari", "state", meta3.artifactDir, "discoveries.json") : join23(projectRoot, ".zelari", "state", "artifacts", head.id, "discoveries.json");
41341
41851
  let discoveries = [];
41342
41852
  if (existsSync29(discPath)) {
41343
- discoveries = JSON.parse(readFileSync24(discPath, "utf8"));
41853
+ discoveries = JSON.parse(readFileSync25(discPath, "utf8"));
41344
41854
  }
41345
41855
  const reusable = discoveries.filter((d) => d.reusable !== false);
41346
41856
  const lines = [
@@ -41373,13 +41883,13 @@ var planDetect_exports = {};
41373
41883
  __export(planDetect_exports, {
41374
41884
  hasWorkspacePlan: () => hasWorkspacePlan
41375
41885
  });
41376
- import { existsSync as existsSync30, readFileSync as readFileSync25 } from "node:fs";
41886
+ import { existsSync as existsSync30, readFileSync as readFileSync26 } from "node:fs";
41377
41887
  import { join as join24 } from "node:path";
41378
41888
  function hasWorkspacePlan(projectRoot = process.cwd()) {
41379
41889
  const planPath = join24(resolveWorkspaceRoot(projectRoot), "plan.json");
41380
41890
  if (!existsSync30(planPath)) return false;
41381
41891
  try {
41382
- const parsed = JSON.parse(readFileSync25(planPath, "utf8"));
41892
+ const parsed = JSON.parse(readFileSync26(planPath, "utf8"));
41383
41893
  return Array.isArray(parsed.phases) && parsed.phases.length > 0;
41384
41894
  } catch {
41385
41895
  return false;
@@ -41441,7 +41951,7 @@ import {
41441
41951
  existsSync as existsSync31,
41442
41952
  readdirSync as readdirSync8,
41443
41953
  writeFileSync as writeFileSync17,
41444
- readFileSync as readFileSync26,
41954
+ readFileSync as readFileSync27,
41445
41955
  mkdirSync as mkdirSync15,
41446
41956
  renameSync as renameSync4
41447
41957
  } from "node:fs";
@@ -41462,7 +41972,7 @@ function readPlan(ctx) {
41462
41972
  if (existsSync31(jsonPath)) {
41463
41973
  try {
41464
41974
  const parsed = JSON.parse(
41465
- readFileSync26(jsonPath, "utf8")
41975
+ readFileSync27(jsonPath, "utf8")
41466
41976
  );
41467
41977
  const { phases, tasks, milestones, ...root } = parsed;
41468
41978
  return {
@@ -42026,7 +42536,7 @@ function searchDocumentsStub(ctx) {
42026
42536
  const results = [];
42027
42537
  for (const file2 of files) {
42028
42538
  if (!existsSync31(file2)) continue;
42029
- const raw = readFileSync26(file2, "utf8");
42539
+ const raw = readFileSync27(file2, "utf8");
42030
42540
  const content = raw.toLowerCase();
42031
42541
  let idx = -1;
42032
42542
  let matchLen = 0;
@@ -42535,7 +43045,7 @@ var init_mcpClient = __esm({
42535
43045
  import {
42536
43046
  existsSync as existsSync33,
42537
43047
  mkdirSync as mkdirSync16,
42538
- readFileSync as readFileSync27,
43048
+ readFileSync as readFileSync28,
42539
43049
  writeFileSync as writeFileSync18
42540
43050
  } from "node:fs";
42541
43051
  import { dirname as dirname7, join as join26 } from "node:path";
@@ -42549,7 +43059,7 @@ function getProjectMcpPath(projectRoot) {
42549
43059
  function readFile2(path63) {
42550
43060
  if (!existsSync33(path63)) return {};
42551
43061
  try {
42552
- const parsed = JSON.parse(readFileSync27(path63, "utf8"));
43062
+ const parsed = JSON.parse(readFileSync28(path63, "utf8"));
42553
43063
  const out = {};
42554
43064
  for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
42555
43065
  if (!cfg || typeof cfg.command !== "string" || !cfg.command.trim()) continue;
@@ -42777,7 +43287,7 @@ __export(mcpManager_exports, {
42777
43287
  readMcpConfig: () => readMcpConfig,
42778
43288
  registerMcpTools: () => registerMcpTools
42779
43289
  });
42780
- import { existsSync as existsSync34, readFileSync as readFileSync28 } from "node:fs";
43290
+ import { existsSync as existsSync34, readFileSync as readFileSync29 } from "node:fs";
42781
43291
  import { join as join27 } from "node:path";
42782
43292
  import { homedir as homedir11 } from "node:os";
42783
43293
  function readMcpConfig(projectRoot = process.cwd(), opts) {
@@ -42792,7 +43302,7 @@ function readMcpConfig(projectRoot = process.cwd(), opts) {
42792
43302
  for (const p3 of paths) {
42793
43303
  if (!existsSync34(p3)) continue;
42794
43304
  try {
42795
- const parsed = JSON.parse(readFileSync28(p3, "utf8"));
43305
+ const parsed = JSON.parse(readFileSync29(p3, "utf8"));
42796
43306
  for (const [name, cfg] of Object.entries(parsed.mcpServers ?? {})) {
42797
43307
  if (!cfg || typeof cfg.command !== "string" || cfg.command.length === 0) continue;
42798
43308
  merged[name] = cfg;
@@ -43031,7 +43541,7 @@ __export(agentsMd_exports, {
43031
43541
  serializeAgentsMd: () => serializeAgentsMd,
43032
43542
  updateAgentsMd: () => updateAgentsMd
43033
43543
  });
43034
- import { existsSync as existsSync35, readFileSync as readFileSync29, writeFileSync as writeFileSync19 } from "node:fs";
43544
+ import { existsSync as existsSync35, readFileSync as readFileSync30, writeFileSync as writeFileSync19 } from "node:fs";
43035
43545
  import { createHash as createHash11 } from "node:crypto";
43036
43546
  import { join as join28 } from "node:path";
43037
43547
  import { readFile as readFile3 } from "node:fs/promises";
@@ -43089,7 +43599,7 @@ async function genConventions(ctx) {
43089
43599
  const lines = [];
43090
43600
  const claudeMd = join28(ctx.projectRoot, "CLAUDE.MD");
43091
43601
  if (existsSync35(claudeMd)) {
43092
- const content = readFileSync29(claudeMd, "utf8");
43602
+ const content = readFileSync30(claudeMd, "utf8");
43093
43603
  const match = content.match(/## Architecture rules[\s\S]+?(?=\n## |\n*$)/);
43094
43604
  if (match) {
43095
43605
  lines.push('<!-- Extracted from CLAUDE.MD "Architecture rules" -->');
@@ -43123,7 +43633,7 @@ async function genBuild(ctx) {
43123
43633
  async function genOpenQuestions(ctx) {
43124
43634
  const path63 = join28(ctx.rootDir, "risks.md");
43125
43635
  if (!existsSync35(path63)) return "_No open questions._";
43126
- const content = readFileSync29(path63, "utf8");
43636
+ const content = readFileSync30(path63, "utf8");
43127
43637
  const lines = content.split("\n");
43128
43638
  const questions = [];
43129
43639
  let currentTitle = "";
@@ -43199,7 +43709,7 @@ function titleCase(id) {
43199
43709
  async function updateAgentsMd(ctx, projectRoot) {
43200
43710
  const agentsPath = join28(projectRoot, "AGENTS.MD");
43201
43711
  if (existsSync35(agentsPath)) {
43202
- const content = readFileSync29(agentsPath, "utf8");
43712
+ const content = readFileSync30(agentsPath, "utf8");
43203
43713
  const hasAnyMarker = AUTO_SECTIONS.some((id) => content.includes(MARKER_OPEN(id)));
43204
43714
  if (!hasAnyMarker) {
43205
43715
  return {
@@ -43215,7 +43725,7 @@ async function updateAgentsMd(ctx, projectRoot) {
43215
43725
  }
43216
43726
  let manualContent = "";
43217
43727
  if (existsSync35(agentsPath)) {
43218
- const { manualBlocks } = parseAgentsMd(readFileSync29(agentsPath, "utf8"));
43728
+ const { manualBlocks } = parseAgentsMd(readFileSync30(agentsPath, "utf8"));
43219
43729
  manualContent = manualBlocks.after;
43220
43730
  } else {
43221
43731
  const projectName2 = projectName(projectRoot);
@@ -43231,7 +43741,7 @@ async function updateAgentsMd(ctx, projectRoot) {
43231
43741
  ""
43232
43742
  ].join("\n");
43233
43743
  }
43234
- const oldContent = existsSync35(agentsPath) ? readFileSync29(agentsPath, "utf8") : "";
43744
+ const oldContent = existsSync35(agentsPath) ? readFileSync30(agentsPath, "utf8") : "";
43235
43745
  const { sections: oldSections } = parseAgentsMd(oldContent);
43236
43746
  const changedSections = [];
43237
43747
  for (const id of AUTO_SECTIONS) {
@@ -43368,7 +43878,7 @@ var init_completeDesign = __esm({
43368
43878
  });
43369
43879
 
43370
43880
  // src/cli/workspace/planDriftCheck.ts
43371
- import { existsSync as existsSync36, readFileSync as readFileSync30, readdirSync as readdirSync9, statSync as statSync6, writeFileSync as writeFileSync20 } from "node:fs";
43881
+ import { existsSync as existsSync36, readFileSync as readFileSync31, readdirSync as readdirSync9, statSync as statSync6, writeFileSync as writeFileSync20 } from "node:fs";
43372
43882
  import { join as join29 } from "node:path";
43373
43883
  function findCanonicalDoc(rootDir) {
43374
43884
  const docsDir = join29(rootDir, "docs");
@@ -43399,7 +43909,7 @@ function firstString2(v) {
43399
43909
  }
43400
43910
  function readFileSyncSafe(path63) {
43401
43911
  try {
43402
- return readFileSync30(path63, "utf8");
43912
+ return readFileSync31(path63, "utf8");
43403
43913
  } catch {
43404
43914
  return null;
43405
43915
  }
@@ -43414,7 +43924,7 @@ async function runPlanDriftCheck(rootDir) {
43414
43924
  }
43415
43925
  let plan;
43416
43926
  try {
43417
- plan = JSON.parse(readFileSync30(planPath, "utf8"));
43927
+ plan = JSON.parse(readFileSync31(planPath, "utf8"));
43418
43928
  } catch {
43419
43929
  return { ran: false, reason: ".zelari/plan.json corrupt" };
43420
43930
  }
@@ -43540,7 +44050,7 @@ var init_planDriftCheck = __esm({
43540
44050
 
43541
44051
  // src/cli/workspace/projectSmoke.ts
43542
44052
  import { spawn as spawn14 } from "node:child_process";
43543
- import { existsSync as existsSync37, readFileSync as readFileSync31 } from "node:fs";
44053
+ import { existsSync as existsSync37, readFileSync as readFileSync32 } from "node:fs";
43544
44054
  import { join as join30 } from "node:path";
43545
44055
  function pickSmokeScript(scripts) {
43546
44056
  if (!scripts) return null;
@@ -43559,7 +44069,7 @@ async function runProjectSmoke(projectRoot, timeoutMs = DEFAULT_TIMEOUT_MS3) {
43559
44069
  }
43560
44070
  let scripts = {};
43561
44071
  try {
43562
- const pkg = JSON.parse(readFileSync31(pkgPath, "utf8"));
44072
+ const pkg = JSON.parse(readFileSync32(pkgPath, "utf8"));
43563
44073
  scripts = pkg.scripts ?? {};
43564
44074
  } catch {
43565
44075
  return { ran: false, reason: "package.json unreadable (skipped)" };
@@ -43647,7 +44157,7 @@ __export(postCouncilHook_exports, {
43647
44157
  runPostCouncilHook: () => runPostCouncilHook
43648
44158
  });
43649
44159
  import { spawn as spawn15 } from "node:child_process";
43650
- import { existsSync as existsSync38, readFileSync as readFileSync32 } from "node:fs";
44160
+ import { existsSync as existsSync38, readFileSync as readFileSync33 } from "node:fs";
43651
44161
  import { join as join31 } from "node:path";
43652
44162
  async function runCompleteDesignPostProcessor(ctx, options) {
43653
44163
  if (options?.runMode === "implementation") {
@@ -43669,7 +44179,7 @@ async function runCompleteDesignPostProcessor(ctx, options) {
43669
44179
  }
43670
44180
  let phaseCount = 0;
43671
44181
  try {
43672
- const parsed = JSON.parse(readFileSync32(planJsonPath2, "utf8"));
44182
+ const parsed = JSON.parse(readFileSync33(planJsonPath2, "utf8"));
43673
44183
  phaseCount = Array.isArray(parsed.phases) ? parsed.phases.length : 0;
43674
44184
  } catch {
43675
44185
  return { ran: false, reason: ".zelari/plan.json corrupt" };
@@ -43904,7 +44414,7 @@ __export(councilFeedback_exports, {
43904
44414
  import {
43905
44415
  promises as fs22,
43906
44416
  existsSync as existsSync39,
43907
- readFileSync as readFileSync33,
44417
+ readFileSync as readFileSync34,
43908
44418
  writeFileSync as writeFileSync21,
43909
44419
  mkdirSync as mkdirSync17
43910
44420
  } from "node:fs";
@@ -44014,7 +44524,7 @@ var init_councilFeedback = __esm({
44014
44524
  load() {
44015
44525
  if (!existsSync39(this.file)) return;
44016
44526
  try {
44017
- const raw = readFileSync33(this.file, "utf-8");
44527
+ const raw = readFileSync34(this.file, "utf-8");
44018
44528
  const parsed = JSON.parse(raw);
44019
44529
  if (parsed && Array.isArray(parsed.entries)) {
44020
44530
  this.entries = parsed.entries.filter(
@@ -45388,38 +45898,6 @@ var init_brokerHandlers = __esm({
45388
45898
  }
45389
45899
  });
45390
45900
 
45391
- // src/cli/mode.ts
45392
- function nextMode(current) {
45393
- const i = MODES.indexOf(current);
45394
- return MODES[(i + 1) % MODES.length] ?? "kraken";
45395
- }
45396
- function parseMode(input) {
45397
- const v = input.trim().toLowerCase();
45398
- if (MODES.includes(v)) return v;
45399
- return MODE_ALIASES[v] ?? null;
45400
- }
45401
- function describeMode(mode) {
45402
- switch (mode) {
45403
- case "council":
45404
- return "council \u2014 multi-member plan/design (Caronte\u2026Lucifero; build needs ZELARI_COUNCIL_CAN_BUILD=1)";
45405
- case "zelari":
45406
- return "zelari \u2014 mission: plan@council \u2192 build@kraken (legacy: ZELARI_BUILD_VIA_AGENT=0)";
45407
- default:
45408
- return "kraken \u2014 super-agent lead (spawns explore/general/verify tentacles; default implementer)";
45409
- }
45410
- }
45411
- var MODES, MODE_ALIASES;
45412
- var init_mode = __esm({
45413
- "src/cli/mode.ts"() {
45414
- "use strict";
45415
- MODES = ["kraken", "council", "zelari"];
45416
- MODE_ALIASES = {
45417
- agent: "kraken",
45418
- single: "kraken"
45419
- };
45420
- }
45421
- });
45422
-
45423
45901
  // src/cli/kraken/planner.ts
45424
45902
  var planner_exports = {};
45425
45903
  __export(planner_exports, {
@@ -47891,7 +48369,7 @@ var init_prereqChecks = __esm({
47891
48369
  });
47892
48370
 
47893
48371
  // src/cli/plugins/prefs.ts
47894
- import { existsSync as existsSync42, readFileSync as readFileSync34, writeFileSync as writeFileSync22, mkdirSync as mkdirSync18 } from "node:fs";
48372
+ import { existsSync as existsSync42, readFileSync as readFileSync35, writeFileSync as writeFileSync22, mkdirSync as mkdirSync18 } from "node:fs";
47895
48373
  import path53 from "node:path";
47896
48374
  import os11 from "node:os";
47897
48375
  function getPluginPrefsPath() {
@@ -47901,7 +48379,7 @@ function getPluginPrefs() {
47901
48379
  const file2 = getPluginPrefsPath();
47902
48380
  try {
47903
48381
  if (!existsSync42(file2)) return { ...DEFAULTS2, dontAskAgain: {} };
47904
- const raw = readFileSync34(file2, "utf-8");
48382
+ const raw = readFileSync35(file2, "utf-8");
47905
48383
  const parsed = JSON.parse(raw);
47906
48384
  if (parsed && typeof parsed === "object" && parsed.dontAskAgain && typeof parsed.dontAskAgain === "object") {
47907
48385
  const clean = {};
@@ -48703,7 +49181,7 @@ __export(atMentions_exports, {
48703
49181
  extractAtMentions: () => extractAtMentions,
48704
49182
  hasAtMentions: () => hasAtMentions
48705
49183
  });
48706
- import { existsSync as existsSync46, readFileSync as readFileSync36, statSync as statSync9 } from "node:fs";
49184
+ import { existsSync as existsSync46, readFileSync as readFileSync37, statSync as statSync9 } from "node:fs";
48707
49185
  import { basename as basename3, isAbsolute as isAbsolute2, relative as relative3, resolve, sep } from "node:path";
48708
49186
  function isImagePath(abs) {
48709
49187
  const ext = abs.split(".").pop()?.toLowerCase() ?? "";
@@ -48809,7 +49287,7 @@ function resolveMention(token, cwd) {
48809
49287
  note: `image too large (${Math.round(st.size / 1024)} KB) \u2014 path only`
48810
49288
  };
48811
49289
  }
48812
- const dataBase64 = readFileSync36(abs).toString("base64");
49290
+ const dataBase64 = readFileSync37(abs).toString("base64");
48813
49291
  return {
48814
49292
  raw: token,
48815
49293
  path: rel2,
@@ -48820,7 +49298,7 @@ function resolveMention(token, cwd) {
48820
49298
  };
48821
49299
  }
48822
49300
  try {
48823
- const buf = readFileSync36(abs);
49301
+ const buf = readFileSync37(abs);
48824
49302
  const head = buf.subarray(0, 800).toString("utf8");
48825
49303
  if (!isProbablyText(abs, head)) {
48826
49304
  return {
@@ -48910,388 +49388,6 @@ var init_atMentions = __esm({
48910
49388
  }
48911
49389
  });
48912
49390
 
48913
- // src/cli/headless.ts
48914
- import { readFileSync as readFileSync37 } from "node:fs";
48915
- function defaultProfileForMode(mode) {
48916
- switch (mode) {
48917
- case "council":
48918
- return "council/v1";
48919
- case "zelari":
48920
- return "mission/v1";
48921
- default:
48922
- return "kraken/v1";
48923
- }
48924
- }
48925
- function parseHeadlessFlags(argv) {
48926
- if (!argv.includes("--headless")) {
48927
- return { options: null };
48928
- }
48929
- let task;
48930
- let output = "json";
48931
- let mode = "kraken";
48932
- let phase2 = "build";
48933
- let modeExplicit = false;
48934
- let councilFlag = false;
48935
- let provider;
48936
- let model;
48937
- let history2;
48938
- let todos2;
48939
- let once = false;
48940
- let profile;
48941
- let resumeSessionId;
48942
- let exportSessionPath;
48943
- let strictDone = false;
48944
- let krakenGraph;
48945
- let planOnly = process.env.ZELARI_KRAKEN_PLAN_ONLY === "1" || process.env.ZELARI_KRAKEN_PLAN_ONLY === "true";
48946
- let runPlan = process.env.ZELARI_KRAKEN_RUN_PLAN;
48947
- for (let i = 0; i < argv.length; i++) {
48948
- const arg = argv[i];
48949
- if (arg === "--headless") continue;
48950
- if (arg === "--output") {
48951
- const next = argv[i + 1];
48952
- if (next === "json" || next === "plain") {
48953
- output = next;
48954
- i++;
48955
- } else {
48956
- return {
48957
- options: null,
48958
- error: `--output requires 'json' or 'plain', got '${next ?? "(missing)"}'`
48959
- };
48960
- }
48961
- } else if (arg === "--task") {
48962
- task = argv[i + 1];
48963
- i++;
48964
- } else if (arg === "--task-file") {
48965
- const next = argv[i + 1];
48966
- if (next) {
48967
- try {
48968
- const fromFile = readFileSync37(next, "utf-8");
48969
- if (fromFile.trim()) task = fromFile;
48970
- } catch {
48971
- }
48972
- }
48973
- i++;
48974
- } else if (arg === "--council") {
48975
- councilFlag = true;
48976
- } else if (arg === "--mode") {
48977
- const next = argv[i + 1];
48978
- const parsed = next ? parseMode(next) : null;
48979
- if (!parsed) {
48980
- return {
48981
- options: null,
48982
- error: `--mode requires 'kraken', 'council', or 'zelari' (agent=alias), got '${next ?? "(missing)"}'`
48983
- };
48984
- }
48985
- mode = parsed;
48986
- modeExplicit = true;
48987
- i++;
48988
- } else if (arg === "--phase") {
48989
- const next = argv[i + 1];
48990
- const parsed = next ? parsePhase(next) : null;
48991
- if (!parsed) {
48992
- return {
48993
- options: null,
48994
- error: `--phase requires 'plan' or 'build', got '${next ?? "(missing)"}'`
48995
- };
48996
- }
48997
- phase2 = parsed;
48998
- i++;
48999
- } else if (arg === "--provider") {
49000
- provider = argv[i + 1];
49001
- i++;
49002
- } else if (arg === "--model") {
49003
- model = argv[i + 1];
49004
- i++;
49005
- } else if (arg === "--history" || arg === "--history-file") {
49006
- const next = argv[i + 1];
49007
- if (next) {
49008
- let raw = null;
49009
- if (arg === "--history-file") {
49010
- try {
49011
- raw = readFileSync37(next, "utf-8");
49012
- } catch {
49013
- raw = null;
49014
- }
49015
- } else {
49016
- raw = next;
49017
- }
49018
- if (raw) {
49019
- try {
49020
- const parsedHist = JSON.parse(raw);
49021
- if (Array.isArray(parsedHist)) {
49022
- history2 = parsedHist.filter(
49023
- (m) => !!m && typeof m === "object" && typeof m.role === "string"
49024
- ).map((m) => {
49025
- const role = String(m.role);
49026
- const raw2 = m.content;
49027
- const content = typeof raw2 === "string" ? raw2 : raw2 == null ? "" : typeof raw2 === "object" ? JSON.stringify(raw2) : String(raw2);
49028
- const msg = {
49029
- role,
49030
- content
49031
- };
49032
- if (typeof m.toolCallId === "string") {
49033
- msg.toolCallId = m.toolCallId;
49034
- }
49035
- return msg;
49036
- }).filter(
49037
- (m) => m.role === "user" || m.role === "assistant" || m.role === "tool" || m.role === "system"
49038
- );
49039
- }
49040
- } catch {
49041
- }
49042
- }
49043
- i++;
49044
- }
49045
- } else if (arg === "--todos") {
49046
- const next = argv[i + 1];
49047
- if (next) {
49048
- try {
49049
- const parsed = JSON.parse(next);
49050
- if (Array.isArray(parsed)) {
49051
- todos2 = parsed.filter(
49052
- (t) => !!t && typeof t === "object" && typeof t.content === "string"
49053
- ).map((t) => ({
49054
- id: typeof t.id === "string" ? t.id : void 0,
49055
- content: String(t.content).slice(0, 500),
49056
- status: t.status
49057
- }));
49058
- }
49059
- } catch {
49060
- }
49061
- i++;
49062
- }
49063
- } else if (arg === "--once") {
49064
- once = true;
49065
- } else if (arg === "--profile") {
49066
- const next = argv[i + 1];
49067
- if (!next || next.startsWith("--")) {
49068
- return { options: null, error: `--profile requires a profile id (e.g. kraken/v1), got '${next ?? "(missing)"}'` };
49069
- }
49070
- try {
49071
- resolveProfile(next);
49072
- } catch (err) {
49073
- return {
49074
- options: null,
49075
- error: err instanceof Error ? err.message : String(err)
49076
- };
49077
- }
49078
- profile = next;
49079
- i++;
49080
- } else if (arg === "--resume") {
49081
- const next = argv[i + 1];
49082
- if (!next || next.startsWith("--")) {
49083
- return { options: null, error: `--resume requires a session id, got '${next ?? "(missing)"}'` };
49084
- }
49085
- resumeSessionId = next;
49086
- i++;
49087
- } else if (arg === "--export-session") {
49088
- const next = argv[i + 1];
49089
- if (!next || next.startsWith("--")) {
49090
- return { options: null, error: `--export-session requires a path (or - for stdout), got '${next ?? "(missing)"}'` };
49091
- }
49092
- exportSessionPath = next;
49093
- i++;
49094
- } else if (arg === "--strict-done") {
49095
- strictDone = true;
49096
- } else if (arg === "--kraken-graph") {
49097
- krakenGraph = argv[i + 1];
49098
- i++;
49099
- } else if (arg === "--kraken-graph-file") {
49100
- const next = argv[i + 1];
49101
- if (next) {
49102
- try {
49103
- const fromFile = readFileSync37(next, "utf-8");
49104
- if (fromFile.trim()) krakenGraph = fromFile;
49105
- } catch {
49106
- }
49107
- }
49108
- i++;
49109
- } else if (arg === "--plan-only") {
49110
- planOnly = true;
49111
- } else if (arg === "--run-plan") {
49112
- runPlan = argv[i + 1];
49113
- i++;
49114
- }
49115
- }
49116
- if (councilFlag && !modeExplicit) {
49117
- mode = "council";
49118
- } else if (councilFlag && modeExplicit && mode !== "council") {
49119
- return {
49120
- options: null,
49121
- error: `--council conflicts with --mode ${mode}`
49122
- };
49123
- }
49124
- if (task && krakenGraph) {
49125
- return { options: null, error: "--task and --kraken-graph are mutually exclusive" };
49126
- }
49127
- if ((!task || task.trim().length === 0) && (!krakenGraph || krakenGraph.trim().length === 0)) {
49128
- return { options: null, error: "--headless requires --task <prompt> or --kraken-graph <goal>" };
49129
- }
49130
- return {
49131
- options: {
49132
- task: task ?? "",
49133
- output,
49134
- mode,
49135
- phase: phase2,
49136
- useCouncil: mode === "council",
49137
- provider,
49138
- model,
49139
- ...history2 && history2.length > 0 ? { history: history2 } : {},
49140
- ...todos2 && todos2.length > 0 ? { todos: todos2 } : {},
49141
- ...once ? { once: true } : {},
49142
- ...profile ? { profile } : {},
49143
- ...resumeSessionId ? { resumeSessionId } : {},
49144
- ...exportSessionPath ? { exportSessionPath } : {},
49145
- ...strictDone ? { strictDone: true } : {},
49146
- ...krakenGraph ? { krakenGraph } : {},
49147
- ...planOnly ? { planOnly: true } : {},
49148
- ...runPlan ? { runPlan } : {}
49149
- }
49150
- };
49151
- }
49152
- async function resolveHeadlessKey(providerId) {
49153
- const spec = PROVIDERS.find((p3) => p3.id === providerId);
49154
- if (!spec) {
49155
- return { error: `unknown provider: '${providerId}'` };
49156
- }
49157
- const resolved = await resolveApiKeyWithMeta(providerId);
49158
- if (!resolved || !resolved.apiKey) {
49159
- return {
49160
- error: `no API key for provider '${providerId}'.
49161
- Set the env var ${spec.envVar} or save a key via /login.`
49162
- };
49163
- }
49164
- const { resolveBaseUrl: resolveBaseUrl2 } = await Promise.resolve().then(() => (init_openai_compatible(), openai_compatible_exports));
49165
- return {
49166
- apiKey: resolved.apiKey,
49167
- baseUrl: resolveBaseUrl2(providerId)
49168
- };
49169
- }
49170
- function resolveHeadlessProvider(opts) {
49171
- const provider = opts.provider ?? getActiveProvider().id;
49172
- const model = opts.model ?? getModelForProvider(provider);
49173
- return { provider, model };
49174
- }
49175
- function emitEvent(event) {
49176
- process.stdout.write(JSON.stringify(event) + "\n");
49177
- }
49178
- var init_headless = __esm({
49179
- "src/cli/headless.ts"() {
49180
- "use strict";
49181
- init_keyStore();
49182
- init_providerConfig();
49183
- init_openai_compatible();
49184
- init_phase();
49185
- init_mode();
49186
- init_runtime2();
49187
- }
49188
- });
49189
-
49190
- // src/cli/headlessSpine.ts
49191
- var headlessSpine_exports = {};
49192
- __export(headlessSpine_exports, {
49193
- exportSessionById: () => exportSessionById,
49194
- missionStateFromSpine: () => missionStateFromSpine,
49195
- openHeadlessSpine: () => openHeadlessSpine,
49196
- resolveHeadlessProfileId: () => resolveHeadlessProfileId
49197
- });
49198
- function resolveHeadlessProfileId(mode, explicit) {
49199
- if (explicit) return resolveProfile(explicit).id;
49200
- return defaultProfileForMode(mode ?? "kraken");
49201
- }
49202
- async function openHeadlessSpine(opts) {
49203
- const profileId = resolveHeadlessProfileId(opts.mode, opts.profile);
49204
- let profileTools = [];
49205
- try {
49206
- profileTools = resolveProfile(profileId).tools;
49207
- } catch {
49208
- profileTools = [];
49209
- }
49210
- const extra = {
49211
- profile: profileId,
49212
- workspace: opts.workspace ?? process.cwd(),
49213
- toolManifestHash: profileTools.length > 0 ? toolManifestHash(profileTools) : void 0
49214
- };
49215
- const mirrorOpts = {
49216
- baseDir: opts.baseDir,
49217
- quiet: opts.quiet,
49218
- extraStarted: extra
49219
- };
49220
- const spine = await SessionSpineMirror.adopt(opts.sessionId, mirrorOpts);
49221
- if (spine.status === "active") {
49222
- spine.note("headless.profile", { profile: profileId, mode: opts.mode ?? "kraken" });
49223
- }
49224
- return {
49225
- sessionId: opts.sessionId,
49226
- profileId,
49227
- spine,
49228
- observe(ev) {
49229
- if (ev && typeof ev === "object" && "type" in ev) {
49230
- spine.mirrorBrainEvent(ev);
49231
- }
49232
- },
49233
- userMessage(text) {
49234
- spine.userMessage(text);
49235
- },
49236
- verificationRun(payload) {
49237
- spine.verificationRun(payload);
49238
- },
49239
- missionPhase(phase2, note) {
49240
- spine.missionPhase(phase2, note);
49241
- },
49242
- note(text, data) {
49243
- spine.note(text, data);
49244
- },
49245
- async close(reason = "host-exit") {
49246
- await spine.close(reason);
49247
- },
49248
- async interrupt(note) {
49249
- if (note) spine.note("headless.interrupt", { note });
49250
- await spine.release();
49251
- },
49252
- async exportJson() {
49253
- try {
49254
- const store6 = new SessionStore(resolveSessionsDir({ baseDir: opts.baseDir }));
49255
- if (!await store6.exists(opts.sessionId)) return null;
49256
- return await exportSessionJson(store6, opts.sessionId);
49257
- } catch {
49258
- return null;
49259
- }
49260
- }
49261
- };
49262
- }
49263
- async function exportSessionById(sessionId2, baseDir) {
49264
- try {
49265
- const store6 = SessionStore.withDefaults(baseDir ? { baseDir } : {});
49266
- if (!await store6.exists(sessionId2)) {
49267
- return { ok: false, error: `session not found: ${sessionId2}` };
49268
- }
49269
- return { ok: true, json: await exportSessionJson(store6, sessionId2) };
49270
- } catch (err) {
49271
- return { ok: false, error: err instanceof Error ? err.message : String(err) };
49272
- }
49273
- }
49274
- async function missionStateFromSpine(sessionId2, baseDir) {
49275
- try {
49276
- const store6 = SessionStore.withDefaults(baseDir ? { baseDir } : {});
49277
- if (!await store6.exists(sessionId2)) return null;
49278
- const projection = await store6.projection(sessionId2);
49279
- return deriveMissionState(projection);
49280
- } catch {
49281
- return null;
49282
- }
49283
- }
49284
- var init_headlessSpine = __esm({
49285
- "src/cli/headlessSpine.ts"() {
49286
- "use strict";
49287
- init_session();
49288
- init_mission2();
49289
- init_runtime2();
49290
- init_sessionSpine();
49291
- init_headless();
49292
- }
49293
- });
49294
-
49295
49391
  // src/cli/triggerLock.ts
49296
49392
  var triggerLock_exports = {};
49297
49393
  __export(triggerLock_exports, {
@@ -55028,6 +55124,9 @@ function strictGateEventPayload(evaluation) {
55028
55124
  };
55029
55125
  }
55030
55126
 
55127
+ // src/cli/hooks/useChatTurn.ts
55128
+ init_headlessSpine();
55129
+
55031
55130
  // src/cli/hooks/permissionPicker.ts
55032
55131
  init_toolPermissions();
55033
55132
 
@@ -55391,6 +55490,18 @@ function useChatTurn(params) {
55391
55490
  try {
55392
55491
  const anchored = maybeAnchorShortAnswer(userText);
55393
55492
  const effectiveUserText = anchored ?? userText;
55493
+ let historyForModel;
55494
+ {
55495
+ const mirror = writerRef.current?.spine ?? null;
55496
+ let spineSeed = null;
55497
+ if (mirror && mirror.status === "active") {
55498
+ const derived = await mirror.derivedPriorTurns();
55499
+ if (derived && derived.length > 0) {
55500
+ spineSeed = derivedModelSeed(derived);
55501
+ }
55502
+ }
55503
+ historyForModel = spineSeed ?? getHistory();
55504
+ }
55394
55505
  writerRef.current?.spine?.userMessage(effectiveUserText);
55395
55506
  const localCli = (process.env.ZELARI_LOCAL_CLI ?? "").trim();
55396
55507
  let localCliProvider = null;
@@ -55546,7 +55657,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
55546
55657
  });
55547
55658
  void writerRef.current?.append(compactionEvent);
55548
55659
  }
55549
- historySeedLen = getHistory().length;
55660
+ historySeedLen = historyForModel.length;
55550
55661
  let composedWorkspace = "";
55551
55662
  let composedInstructions = "";
55552
55663
  let hasPlan = false;
@@ -55729,7 +55840,7 @@ _(${req.context})_` : "") + "\n\u2192 scegli dalla lista (il turno continua dopo
55729
55840
  // v1.8.0: shared rolling history (agent/council/zelari) so short
55730
55841
  // answers bind to prior ---QUESTION--- blocks. Possibly empty
55731
55842
  // when ZELARI_HISTORY_TURNS=0.
55732
- ...getHistory(),
55843
+ ...historyForModel,
55733
55844
  { role: "user", content: effectiveUserText }
55734
55845
  ],
55735
55846
  tools: toolRegistry.toOpenAITools().map((t) => ({
@@ -59103,7 +59214,7 @@ async function handlePromoteMember(ctx, memberId) {
59103
59214
  }
59104
59215
 
59105
59216
  // src/cli/branchManager.ts
59106
- import { promises as fs32, existsSync as existsSync44, readFileSync as readFileSync35, writeFileSync as writeFileSync23, mkdirSync as mkdirSync19, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
59217
+ import { promises as fs32, existsSync as existsSync44, readFileSync as readFileSync36, writeFileSync as writeFileSync23, mkdirSync as mkdirSync19, statSync as statSync7, rmSync as rmSync3 } from "node:fs";
59107
59218
  import path56 from "node:path";
59108
59219
  import os13 from "node:os";
59109
59220
  var META_FILENAME = "meta.json";
@@ -59129,7 +59240,7 @@ function readBranchMeta(name, baseDir) {
59129
59240
  throw new BranchNotFoundError(`Branch "${name}" not found`);
59130
59241
  }
59131
59242
  try {
59132
- const raw = readFileSync35(metaPath, "utf-8");
59243
+ const raw = readFileSync36(metaPath, "utf-8");
59133
59244
  const parsed = JSON.parse(raw);
59134
59245
  if (!parsed || typeof parsed !== "object" || typeof parsed.name !== "string" || typeof parsed.createdAt !== "number" || typeof parsed.fromSessionId !== "string") {
59135
59246
  throw new BranchCorruptError(`Branch "${name}" meta.json is malformed`);
@@ -61438,6 +61549,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
61438
61549
  profile: opts.profile,
61439
61550
  workspace: process.cwd()
61440
61551
  });
61552
+ const seededHistory = await seedHeadlessModelHistory(spine, opts.history);
61441
61553
  if (opts.task) spine.userMessage(opts.task);
61442
61554
  resetKrakenCandidates();
61443
61555
  resetKrakenTurnMetrics();
@@ -61587,15 +61699,7 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
61587
61699
  }
61588
61700
  ];
61589
61701
  }
61590
- const historySeed = (opts.history ?? []).filter((m) => m.role === "user" || m.role === "assistant").map(
61591
- (m) => m.role === "assistant" && m.content ? {
61592
- role: "assistant",
61593
- content: cleanAgentContent(m.content, {
61594
- stripQuestion: false,
61595
- stripThink: false
61596
- })
61597
- } : { role: m.role, content: m.content ?? "" }
61598
- ).filter((m) => (m.content ?? "").trim().length > 0);
61702
+ const historySeed = seededHistory.history;
61599
61703
  const effectiveTask = buildAgentUserWithHistory(opts.task, historySeed);
61600
61704
  const maxToolLoop = (() => {
61601
61705
  const n = envNumber(process.env.ZELARI_MAX_TOOL_LOOP_ITERATIONS, {
@@ -61902,6 +62006,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
61902
62006
  profile: opts.profile,
61903
62007
  workspace: process.cwd()
61904
62008
  });
62009
+ const seededHistory = await seedHeadlessModelHistory(spine, opts.history);
61905
62010
  if (opts.task) spine.userMessage(opts.task);
61906
62011
  const { shouldAllowCouncilBuild: shouldAllowCouncilBuild2 } = await Promise.resolve().then(() => (init_buildPolicy(), buildPolicy_exports));
61907
62012
  let councilRunMode = planModeFromOpts(opts) ? "design-phase" : "implementation";
@@ -61919,15 +62024,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
61919
62024
  );
61920
62025
  const { FeedbackStore: FeedbackStore2 } = await Promise.resolve().then(() => (init_councilFeedback(), councilFeedback_exports));
61921
62026
  const feedbackStore = new FeedbackStore2();
61922
- const historySeed = (opts.history ?? []).map(
61923
- (m) => m.role === "assistant" && m.content ? {
61924
- ...m,
61925
- content: cleanAgentContent(m.content, {
61926
- stripQuestion: false,
61927
- stripThink: false
61928
- })
61929
- } : m
61930
- );
62027
+ const historySeed = seededHistory.history;
61931
62028
  const effectiveTask = buildCouncilTaskWithHistory(opts.task, historySeed);
61932
62029
  let exitCode = 0;
61933
62030
  const scrub = createStreamScrubber2();
@@ -62046,6 +62143,7 @@ async function runHeadlessZelari(opts, provider, model, providerStream) {
62046
62143
  profile: opts.profile ?? "mission/v1",
62047
62144
  workspace: projectRoot
62048
62145
  });
62146
+ const seededHistory = await seedHeadlessModelHistory(spine, opts.history);
62049
62147
  if (opts.task) spine.userMessage(opts.task);
62050
62148
  spine.missionPhase("design", "mission-start");
62051
62149
  const { buildMissionBrief: buildMissionBrief2 } = await Promise.resolve().then(() => (init_council(), council_exports));
@@ -62078,15 +62176,7 @@ async function runHeadlessZelari(opts, provider, model, providerStream) {
62078
62176
  process.stderr.write(message + "\n");
62079
62177
  }
62080
62178
  };
62081
- const historySeed = (opts.history ?? []).map(
62082
- (m) => m.role === "assistant" && m.content ? {
62083
- ...m,
62084
- content: cleanAgentContent(m.content, {
62085
- stripQuestion: false,
62086
- stripThink: false
62087
- })
62088
- } : m
62089
- );
62179
+ const historySeed = seededHistory.history;
62090
62180
  const missionTask = buildCouncilTaskWithHistory(opts.task, historySeed);
62091
62181
  emit(`[zelari] mission brief
62092
62182
  ${JSON.stringify({ deliverable: brief.deliverableThisMission, mvp: brief.sliceMvp?.title }, null, 0)}`);