zelari-code 1.9.4 → 1.11.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.
@@ -19,6 +19,7 @@ import { getActiveProvider, getModelForProvider } from './providerConfig.js';
19
19
  import { openaiCompatibleProvider } from './provider/openai-compatible.js';
20
20
  import { parsePhase } from './phase.js';
21
21
  import { parseMode } from './mode.js';
22
+ import { readFileSync } from 'node:fs';
22
23
  const HELP_TEXT = `zelari-code --headless --task <prompt> [options]
23
24
 
24
25
  Non-interactive mode. Streams BrainEvents as NDJSON to stdout (one JSON
@@ -32,6 +33,8 @@ Options:
32
33
  --phase plan|build Work phase (default: build)
33
34
  --provider <id> Provider override (default: active)
34
35
  --model <name> Model override (default: provider default)
36
+ --history <json> Prior turns (JSON AgentMessage[]) for multi-turn context
37
+ --history-file <path> Same as --history but read from a file (avoids Windows argv cap)
35
38
 
36
39
  Exit codes:
37
40
  0 completed
@@ -55,6 +58,7 @@ export function parseHeadlessFlags(argv) {
55
58
  let councilFlag = false;
56
59
  let provider;
57
60
  let model;
61
+ let history;
58
62
  for (let i = 0; i < argv.length; i++) {
59
63
  const arg = argv[i];
60
64
  if (arg === '--headless')
@@ -112,6 +116,42 @@ export function parseHeadlessFlags(argv) {
112
116
  model = argv[i + 1];
113
117
  i++;
114
118
  }
119
+ else if (arg === '--history' || arg === '--history-file') {
120
+ // Multi-turn context from the desktop. `--history` takes the JSON inline
121
+ // (kept for backward compat / scripting); `--history-file` reads it from
122
+ // a tempfile. The file path is PREFERRED on Windows because CreateProcess
123
+ // caps the command line at ~32KB (os error 206) and a long chat history
124
+ // overflows it. Invalid/missing JSON is ignored: the run degrades to
125
+ // stateless (pre-v1.10.0 behavior) rather than erroring out.
126
+ const next = argv[i + 1];
127
+ if (next) {
128
+ let raw = null;
129
+ if (arg === '--history-file') {
130
+ try {
131
+ raw = readFileSync(next, 'utf-8');
132
+ }
133
+ catch {
134
+ raw = null; // File gone/unreadable — run stateless.
135
+ }
136
+ }
137
+ else {
138
+ raw = next;
139
+ }
140
+ if (raw) {
141
+ try {
142
+ const parsedHist = JSON.parse(raw);
143
+ if (Array.isArray(parsedHist)) {
144
+ history = parsedHist.filter((m) => m && typeof m === 'object' && typeof m.role === 'string' &&
145
+ typeof m.content === 'string');
146
+ }
147
+ }
148
+ catch {
149
+ // Swallow: stale/incompatible history.
150
+ }
151
+ }
152
+ i++;
153
+ }
154
+ }
115
155
  }
116
156
  // --council is an alias for --mode council when --mode was not set.
117
157
  if (councilFlag && !modeExplicit) {
@@ -135,6 +175,7 @@ export function parseHeadlessFlags(argv) {
135
175
  useCouncil: mode === 'council',
136
176
  provider,
137
177
  model,
178
+ ...(history && history.length > 0 ? { history } : {}),
138
179
  },
139
180
  };
140
181
  }
@@ -1 +1 @@
1
- {"version":3,"file":"headless.js","sourceRoot":"","sources":["../../src/cli/headless.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"headless.js","sourceRoot":"","sources":["../../src/cli/headless.ts"],"names":[],"mappings":"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"}
@@ -19774,6 +19774,16 @@ ${cached2}`
19774
19774
  finishRef.value = "tool_calls";
19775
19775
  }
19776
19776
  }
19777
+ if (finishRef.value === "tool_calls" && turnToolCalls.length === 0 && turnToolResults.length === 0) {
19778
+ const truncErr = createBrainEvent("error", this.sessionId, {
19779
+ severity: "recoverable",
19780
+ message: "Tool call was truncated (finish_reason=tool_calls but no complete tool_call received). The provider cut the response mid-arguments. Retry with a shorter payload or split the work.",
19781
+ code: "tool_call_truncated"
19782
+ });
19783
+ this.emit(truncErr);
19784
+ yield truncErr;
19785
+ finishRef.value = "stop";
19786
+ }
19777
19787
  if (turnToolCalls.length > 0 || turnText.length > 0) {
19778
19788
  this.config.messages.push({
19779
19789
  role: "assistant",
@@ -20170,6 +20180,8 @@ function openaiCompatibleProvider(config2) {
20170
20180
  return;
20171
20181
  }
20172
20182
  try {
20183
+ const timeoutSignal = AbortSignal.timeout(PROVIDER_TIMEOUT_MS);
20184
+ const fetchSignal = params.signal ? AbortSignal.any([params.signal, timeoutSignal]) : timeoutSignal;
20173
20185
  response = await fetch(`${config2.baseUrl}/chat/completions`, {
20174
20186
  method: "POST",
20175
20187
  headers: {
@@ -20181,11 +20193,17 @@ function openaiCompatibleProvider(config2) {
20181
20193
  // controller) so `.cancel()` actually aborts the HTTP request.
20182
20194
  // `config.signal` is the factory-level signal, typically undefined.
20183
20195
  // v0.6.0 audit HIGH-2.
20184
- signal: params.signal
20196
+ // v1.10.0: also apply PROVIDER_TIMEOUT_MS so a stalled connection
20197
+ // can't hang the harness forever.
20198
+ signal: fetchSignal
20185
20199
  });
20186
20200
  } catch (err) {
20187
20201
  lastStatus = 0;
20188
20202
  lastErrText = err instanceof Error ? err.message : String(err);
20203
+ if (params.signal?.aborted) {
20204
+ yield { kind: "error", message: "aborted" };
20205
+ return;
20206
+ }
20189
20207
  if (attempt < MAX_RETRIES) {
20190
20208
  await abortableSleep(backoffDelay(attempt, null), params.signal);
20191
20209
  continue;
@@ -20246,6 +20264,10 @@ function openaiCompatibleProvider(config2) {
20246
20264
  if (typeof delta?.content === "string" && delta.content.length > 0) {
20247
20265
  yield { kind: "text", delta: delta.content };
20248
20266
  }
20267
+ const reasoning = delta?.reasoning_content ?? delta?.reasoning;
20268
+ if (typeof reasoning === "string" && reasoning.length > 0) {
20269
+ yield { kind: "thinking", delta: reasoning };
20270
+ }
20249
20271
  if (Array.isArray(delta?.tool_calls)) {
20250
20272
  for (const tc of delta.tool_calls) {
20251
20273
  const idx = tc.index ?? 0;
@@ -20306,7 +20328,7 @@ async function providerConfigFor(providerId) {
20306
20328
  providerId
20307
20329
  };
20308
20330
  }
20309
- var RETRYABLE_STATUSES, MAX_RETRIES, BACKOFF_BASE_MS, BACKOFF_CAP_MS, PROVIDER_ENDPOINTS;
20331
+ var RETRYABLE_STATUSES, MAX_RETRIES, BACKOFF_BASE_MS, BACKOFF_CAP_MS, PROVIDER_TIMEOUT_MS, PROVIDER_ENDPOINTS;
20310
20332
  var init_openai_compatible = __esm({
20311
20333
  "src/cli/provider/openai-compatible.ts"() {
20312
20334
  "use strict";
@@ -20320,6 +20342,11 @@ var init_openai_compatible = __esm({
20320
20342
  })();
20321
20343
  BACKOFF_BASE_MS = 500;
20322
20344
  BACKOFF_CAP_MS = 8e3;
20345
+ PROVIDER_TIMEOUT_MS = (() => {
20346
+ const raw = process.env.ZELARI_PROVIDER_TIMEOUT_MS;
20347
+ const n = raw ? Number.parseInt(raw, 10) : 3e5;
20348
+ return Number.isFinite(n) && n >= 1e4 ? n : 3e5;
20349
+ })();
20323
20350
  PROVIDER_ENDPOINTS = {
20324
20351
  "openai-compatible": "https://api.x.ai/v1",
20325
20352
  "minimax": "https://api.minimax.io/v1",
@@ -30392,7 +30419,7 @@ __export(doctor_exports, {
30392
30419
  runDoctor: () => runDoctor
30393
30420
  });
30394
30421
  import { execSync as execSync2 } from "node:child_process";
30395
- import { existsSync as existsSync32, readFileSync as readFileSync26, readlinkSync, statSync as statSync6 } from "node:fs";
30422
+ import { existsSync as existsSync32, readFileSync as readFileSync27, readlinkSync, statSync as statSync6 } from "node:fs";
30396
30423
  import { createRequire as createRequire3 } from "node:module";
30397
30424
  import { fileURLToPath as fileURLToPath2 } from "node:url";
30398
30425
  import path35 from "node:path";
@@ -30402,7 +30429,7 @@ function findPackageRoot(start) {
30402
30429
  const candidate = path35.join(dir, "package.json");
30403
30430
  if (existsSync32(candidate)) {
30404
30431
  try {
30405
- const pkg = JSON.parse(readFileSync26(candidate, "utf8"));
30432
+ const pkg = JSON.parse(readFileSync27(candidate, "utf8"));
30406
30433
  if (pkg.name === "zelari-code") return dir;
30407
30434
  } catch {
30408
30435
  }
@@ -30426,7 +30453,7 @@ function tryExec(cmd) {
30426
30453
  function readPackageJson3() {
30427
30454
  try {
30428
30455
  const pkgPath = path35.join(packageRoot, "package.json");
30429
- return JSON.parse(readFileSync26(pkgPath, "utf8"));
30456
+ return JSON.parse(readFileSync27(pkgPath, "utf8"));
30430
30457
  } catch {
30431
30458
  return null;
30432
30459
  }
@@ -30451,7 +30478,7 @@ function checkShim(pkgName) {
30451
30478
  try {
30452
30479
  const st = statSync6(shimPath);
30453
30480
  if (isWin) {
30454
- const content = readFileSync26(shimPath, "utf8");
30481
+ const content = readFileSync27(shimPath, "utf8");
30455
30482
  if (content.includes(`${pkgName}\\bin\\`) || content.includes(`${pkgName}/bin/`)) {
30456
30483
  return OK(`shim OK at ${shimPath} (${st.size} bytes)`);
30457
30484
  }
@@ -38696,6 +38723,7 @@ init_keyStore();
38696
38723
  init_providerConfig();
38697
38724
  init_openai_compatible();
38698
38725
  init_phase();
38726
+ import { readFileSync as readFileSync25 } from "node:fs";
38699
38727
  function parseHeadlessFlags(argv) {
38700
38728
  if (!argv.includes("--headless")) {
38701
38729
  return { options: null };
@@ -38708,6 +38736,7 @@ function parseHeadlessFlags(argv) {
38708
38736
  let councilFlag = false;
38709
38737
  let provider;
38710
38738
  let model;
38739
+ let history2;
38711
38740
  for (let i = 0; i < argv.length; i++) {
38712
38741
  const arg = argv[i];
38713
38742
  if (arg === "--headless") continue;
@@ -38756,6 +38785,32 @@ function parseHeadlessFlags(argv) {
38756
38785
  } else if (arg === "--model") {
38757
38786
  model = argv[i + 1];
38758
38787
  i++;
38788
+ } else if (arg === "--history" || arg === "--history-file") {
38789
+ const next = argv[i + 1];
38790
+ if (next) {
38791
+ let raw = null;
38792
+ if (arg === "--history-file") {
38793
+ try {
38794
+ raw = readFileSync25(next, "utf-8");
38795
+ } catch {
38796
+ raw = null;
38797
+ }
38798
+ } else {
38799
+ raw = next;
38800
+ }
38801
+ if (raw) {
38802
+ try {
38803
+ const parsedHist = JSON.parse(raw);
38804
+ if (Array.isArray(parsedHist)) {
38805
+ history2 = parsedHist.filter(
38806
+ (m) => m && typeof m === "object" && typeof m.role === "string" && typeof m.content === "string"
38807
+ );
38808
+ }
38809
+ } catch {
38810
+ }
38811
+ }
38812
+ i++;
38813
+ }
38759
38814
  }
38760
38815
  }
38761
38816
  if (councilFlag && !modeExplicit) {
@@ -38777,7 +38832,8 @@ function parseHeadlessFlags(argv) {
38777
38832
  phase: phase2,
38778
38833
  useCouncil: mode === "council",
38779
38834
  provider,
38780
- model
38835
+ model,
38836
+ ...history2 && history2.length > 0 ? { history: history2 } : {}
38781
38837
  }
38782
38838
  };
38783
38839
  }
@@ -38810,12 +38866,66 @@ function emitEvent(event) {
38810
38866
 
38811
38867
  // src/cli/runHeadless.ts
38812
38868
  init_harness();
38869
+ init_conversationContext();
38813
38870
  init_toolRegistry();
38814
38871
  init_skills2();
38815
38872
  init_envNumber();
38816
38873
  init_phaseState();
38817
38874
  init_phase();
38875
+
38876
+ // src/cli/utils/streamScrub.ts
38877
+ function createStreamScrubber() {
38878
+ let rawBuf = "";
38879
+ let emittedLen = 0;
38880
+ const snapshot = () => {
38881
+ const cleaned = cleanAgentContent(rawBuf);
38882
+ if (cleaned.length <= emittedLen) return "";
38883
+ const delta = cleaned.slice(emittedLen);
38884
+ emittedLen = cleaned.length;
38885
+ return delta;
38886
+ };
38887
+ return {
38888
+ push(rawDelta) {
38889
+ rawBuf += rawDelta;
38890
+ return snapshot();
38891
+ },
38892
+ flush() {
38893
+ return snapshot();
38894
+ },
38895
+ reset() {
38896
+ rawBuf = "";
38897
+ emittedLen = 0;
38898
+ }
38899
+ };
38900
+ }
38901
+
38902
+ // src/cli/runHeadless.ts
38818
38903
  async function runHeadless(opts) {
38904
+ let crashed = false;
38905
+ const handleFatal = (label, err) => {
38906
+ if (crashed) return;
38907
+ crashed = true;
38908
+ const msg = err instanceof Error ? err.message : String(err);
38909
+ const stack = err instanceof Error && err.stack ? `
38910
+ ${err.stack}` : "";
38911
+ const line = `[zelari-code --headless] FATAL ${label}: ${msg}${stack}`;
38912
+ try {
38913
+ emitEvent({
38914
+ type: "error",
38915
+ severity: "fatal",
38916
+ message: `${label}: ${msg}`,
38917
+ code: "uncaught"
38918
+ });
38919
+ } catch {
38920
+ }
38921
+ try {
38922
+ process.stderr.write(line + "\n");
38923
+ } catch {
38924
+ }
38925
+ process.exit(2);
38926
+ };
38927
+ process.on("uncaughtException", (err) => handleFatal("uncaughtException", err));
38928
+ process.on("unhandledRejection", (err) => handleFatal("unhandledRejection", err));
38819
38929
  setPhase(opts.phase ?? "build");
38820
38930
  const { provider, model } = resolveHeadlessProvider(opts);
38821
38931
  const key = await resolveHeadlessKey(provider);
@@ -38917,13 +39027,19 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
38917
39027
  languageDirectiveContent
38918
39028
  ].join("\n");
38919
39029
  }
39030
+ const historySeed = (opts.history ?? []).map(
39031
+ (m) => m.role === "assistant" && m.content ? { ...m, content: cleanAgentContent(m.content, { stripQuestion: false }) } : m
39032
+ );
39033
+ const effectiveTask = maybeAnchorShortAnswer(opts.task) ?? opts.task;
39034
+ const historySeedLen = historySeed.length;
38920
39035
  const harness = new AgentHarness({
38921
39036
  model,
38922
39037
  provider,
38923
39038
  sessionId,
38924
39039
  messages: [
38925
39040
  { role: "system", content: systemPrompt },
38926
- { role: "user", content: opts.task }
39041
+ ...historySeed,
39042
+ { role: "user", content: effectiveTask }
38927
39043
  ],
38928
39044
  tools,
38929
39045
  toolRegistry,
@@ -38936,23 +39052,39 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
38936
39052
  let finalReason = "completed";
38937
39053
  let exitCode = 0;
38938
39054
  const textBuffer = [];
39055
+ const scrub = createStreamScrubber();
38939
39056
  try {
38940
39057
  for await (const event of harness.run()) {
38941
- if (opts.output === "json") {
38942
- emitEvent(event);
39058
+ if (event.type === "message_start") {
39059
+ scrub.reset();
38943
39060
  }
38944
- if (event.type === "message_delta") {
38945
- if (opts.output === "plain") {
38946
- process.stdout.write(event.delta);
39061
+ if (event.type === "message_delta" && typeof event.delta === "string") {
39062
+ const cleanDelta = scrub.push(event.delta);
39063
+ if (opts.output === "json") {
39064
+ if (cleanDelta.length > 0) {
39065
+ emitEvent({ ...event, delta: cleanDelta });
39066
+ }
39067
+ } else if (opts.output === "plain") {
39068
+ if (cleanDelta.length > 0) process.stdout.write(cleanDelta);
38947
39069
  } else {
38948
- textBuffer.push(event.delta);
39070
+ if (cleanDelta.length > 0) textBuffer.push(cleanDelta);
38949
39071
  }
38950
- } else if (event.type === "agent_end") {
38951
- finalReason = event.reason;
38952
- if (event.reason === "error") exitCode = 3;
38953
- } else if (event.type === "error") {
38954
- if (event.severity === "fatal") {
38955
- exitCode = 2;
39072
+ } else {
39073
+ if (opts.output === "json") {
39074
+ emitEvent(event);
39075
+ }
39076
+ if (event.type === "agent_end") {
39077
+ const tail = scrub.flush();
39078
+ if (tail.length > 0) {
39079
+ if (opts.output === "plain") process.stdout.write(tail);
39080
+ else textBuffer.push(tail);
39081
+ }
39082
+ finalReason = event.reason;
39083
+ if (event.reason === "error") exitCode = 3;
39084
+ } else if (event.type === "error") {
39085
+ if (event.severity === "fatal") {
39086
+ exitCode = 2;
39087
+ }
38956
39088
  }
38957
39089
  }
38958
39090
  }
@@ -38967,6 +39099,21 @@ async function runHeadlessSingle(opts, provider, model, providerStream) {
38967
39099
  process.stdout.write(textBuffer.join(""));
38968
39100
  }
38969
39101
  process.stdout.write("");
39102
+ if (finalReason !== "error" && opts.output === "json") {
39103
+ try {
39104
+ const all = harness.getMessages();
39105
+ const seedLen = 1 + historySeedLen + 1;
39106
+ if (all.length > seedLen) {
39107
+ const tail = all.slice(seedLen).map(
39108
+ (m) => m.role === "assistant" && m.content ? { ...m, content: cleanAgentContent(m.content, { stripQuestion: false }) } : m
39109
+ );
39110
+ if (tail.length > 0) {
39111
+ emitEvent({ type: "history_snapshot", messages: tail });
39112
+ }
39113
+ }
39114
+ } catch {
39115
+ }
39116
+ }
38970
39117
  if (finalReason === "error") return 3;
38971
39118
  return exitCode;
38972
39119
  }
@@ -38991,6 +39138,7 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
38991
39138
  const { FeedbackStore: FeedbackStore2 } = await Promise.resolve().then(() => (init_councilFeedback(), councilFeedback_exports));
38992
39139
  const feedbackStore = new FeedbackStore2();
38993
39140
  let exitCode = 0;
39141
+ const scrub = createStreamScrubber();
38994
39142
  try {
38995
39143
  for await (const event of dispatchCouncil2(opts.task, {
38996
39144
  apiKey: "REDACTED",
@@ -39002,14 +39150,25 @@ async function runHeadlessCouncil(opts, provider, model, providerStream) {
39002
39150
  feedbackStore,
39003
39151
  runMode: planModeFromOpts(opts) ? "design-phase" : "implementation"
39004
39152
  })) {
39005
- if (opts.output === "json") {
39006
- emitEvent(event);
39007
- } else if (event.type === "message_delta") {
39008
- process.stdout.write(event.delta);
39009
- } else if (event.type === "agent_end" && event.reason === "error") {
39010
- exitCode = 3;
39011
- } else if (event.type === "error" && event.severity === "fatal") {
39012
- exitCode = 2;
39153
+ if (event.type === "message_start") {
39154
+ scrub.reset();
39155
+ }
39156
+ if (event.type === "message_delta" && typeof event.delta === "string") {
39157
+ const cleanDelta = scrub.push(event.delta);
39158
+ if (opts.output === "json") {
39159
+ if (cleanDelta.length > 0) emitEvent({ ...event, delta: cleanDelta });
39160
+ } else if (opts.output === "plain" && cleanDelta.length > 0) {
39161
+ process.stdout.write(cleanDelta);
39162
+ }
39163
+ } else {
39164
+ if (opts.output === "json") emitEvent(event);
39165
+ if (event.type === "agent_end") {
39166
+ const tail = scrub.flush();
39167
+ if (opts.output === "plain" && tail.length > 0) process.stdout.write(tail);
39168
+ if (event.reason === "error") exitCode = 3;
39169
+ } else if (event.type === "error" && event.severity === "fatal") {
39170
+ exitCode = 2;
39171
+ }
39013
39172
  }
39014
39173
  }
39015
39174
  } catch (err) {
@@ -39066,6 +39225,7 @@ ${ragContext}` : slicePrompt;
39066
39225
  let writeCount = 0;
39067
39226
  let chairmanErrored = false;
39068
39227
  let membersCompleted = 0;
39228
+ const scrub = createStreamScrubber();
39069
39229
  for await (const event of dispatchCouncil2(fullPrompt, {
39070
39230
  apiKey: "REDACTED",
39071
39231
  model,
@@ -39077,13 +39237,21 @@ ${ragContext}` : slicePrompt;
39077
39237
  runMode: planModeFromOpts(opts) ? "design-phase" : runMode,
39078
39238
  maxToolCallsChairman: chairmanBudget
39079
39239
  })) {
39080
- if (opts.output === "json") {
39081
- emitEvent(event);
39082
- } else if (event.type === "message_delta") {
39083
- process.stdout.write(event.delta);
39240
+ if (event.type === "message_start") {
39241
+ scrub.reset();
39084
39242
  }
39085
39243
  if (event.type === "message_delta" && typeof event.delta === "string") {
39086
39244
  synthesisText += event.delta;
39245
+ const cleanDelta = scrub.push(event.delta);
39246
+ if (opts.output === "json") {
39247
+ if (cleanDelta.length > 0) emitEvent({ ...event, delta: cleanDelta });
39248
+ } else if (opts.output === "plain" && cleanDelta.length > 0) {
39249
+ process.stdout.write(cleanDelta);
39250
+ }
39251
+ } else {
39252
+ if (opts.output === "json") {
39253
+ emitEvent(event);
39254
+ }
39087
39255
  }
39088
39256
  if (event.type === "tool_execution_end") {
39089
39257
  const name = event.toolName ?? event.name ?? "";
@@ -39396,7 +39564,7 @@ async function runDiscoverModels(providerArg) {
39396
39564
 
39397
39565
  // src/cli/skillsMd.ts
39398
39566
  init_skills2();
39399
- import { existsSync as existsSync31, readdirSync as readdirSync4, readFileSync as readFileSync25 } from "node:fs";
39567
+ import { existsSync as existsSync31, readdirSync as readdirSync4, readFileSync as readFileSync26 } from "node:fs";
39400
39568
  import { join as join23 } from "node:path";
39401
39569
  import { homedir as homedir6 } from "node:os";
39402
39570
  var CODING_CATEGORIES = /* @__PURE__ */ new Set([
@@ -39485,7 +39653,7 @@ function loadSkillMdSkills(projectRoot = process.cwd(), options = {}) {
39485
39653
  const skillPath = join23(dir, entry, "SKILL.md");
39486
39654
  if (!existsSync31(skillPath)) continue;
39487
39655
  try {
39488
- const parsed = parseSkillMd(readFileSync25(skillPath, "utf8"), skillPath);
39656
+ const parsed = parseSkillMd(readFileSync26(skillPath, "utf8"), skillPath);
39489
39657
  if (!parsed) {
39490
39658
  summary.skipped.push({ path: skillPath, reason: "missing/invalid frontmatter (name, description) or empty body" });
39491
39659
  continue;