@bendyline/gezel 1.0.7 → 1.1.1

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.
@@ -1061,6 +1061,65 @@ var CraftbookStepInputSchema = z6.object({
1061
1061
  /** Read from the artifacts drawer instead of the project workspace. */
1062
1062
  artifact: z6.boolean().optional().describe("True for the artifacts drawer; false/omitted for the project workspace.")
1063
1063
  });
1064
+ var CraftbookStepWritableOutputMediumSchema = z6.enum([
1065
+ "workspace",
1066
+ "artifact",
1067
+ "task-note"
1068
+ ]);
1069
+ var CraftbookStepOutputMediumSchema = z6.enum([
1070
+ ...CraftbookStepWritableOutputMediumSchema.options,
1071
+ "none"
1072
+ ]);
1073
+ var CraftbookStepToolPolicySchema = z6.object({
1074
+ disallowToolsets: z6.array(z6.string().trim().min(1)).min(1).optional(),
1075
+ disallowBuiltinToolsets: z6.array(z6.string().trim().min(1)).min(1).optional(),
1076
+ outputMedium: CraftbookStepOutputMediumSchema.optional(),
1077
+ /**
1078
+ * Other intentional write surfaces used while producing the primary
1079
+ * result (for example edit workspace source + emit an artifact report).
1080
+ * `none` is never a secondary medium.
1081
+ */
1082
+ additionalOutputMedia: z6.array(CraftbookStepWritableOutputMediumSchema).min(1).optional()
1083
+ }).strict().superRefine((policy, ctx) => {
1084
+ const additional = new Set(policy.additionalOutputMedia ?? []);
1085
+ if (policy.outputMedium === "none" && additional.size > 0) {
1086
+ ctx.addIssue({
1087
+ code: z6.ZodIssueCode.custom,
1088
+ path: ["additionalOutputMedia"],
1089
+ message: "`none` cannot have secondary output media"
1090
+ });
1091
+ }
1092
+ if (policy.outputMedium && policy.outputMedium !== "none" && additional.has(policy.outputMedium)) {
1093
+ ctx.addIssue({
1094
+ code: z6.ZodIssueCode.custom,
1095
+ path: ["additionalOutputMedia"],
1096
+ message: "the primary output medium must not be repeated as a secondary medium"
1097
+ });
1098
+ }
1099
+ const media = /* @__PURE__ */ new Set([policy.outputMedium, ...additional]);
1100
+ const denied = new Set(policy.disallowBuiltinToolsets ?? []);
1101
+ if (media.has("workspace") && denied.has("workspace-fs-write")) {
1102
+ ctx.addIssue({
1103
+ code: z6.ZodIssueCode.custom,
1104
+ path: ["disallowBuiltinToolsets"],
1105
+ message: "workspace output conflicts with disallowing `workspace-fs-write`"
1106
+ });
1107
+ }
1108
+ if (media.has("artifact") && denied.has("artifacts")) {
1109
+ ctx.addIssue({
1110
+ code: z6.ZodIssueCode.custom,
1111
+ path: ["disallowBuiltinToolsets"],
1112
+ message: "artifact output conflicts with disallowing `artifacts`"
1113
+ });
1114
+ }
1115
+ if (media.has("task-note") && denied.has("tasks")) {
1116
+ ctx.addIssue({
1117
+ code: z6.ZodIssueCode.custom,
1118
+ path: ["disallowBuiltinToolsets"],
1119
+ message: "task-note output conflicts with disallowing `tasks`"
1120
+ });
1121
+ }
1122
+ });
1064
1123
  var ModelTierSchema = z6.enum(MODEL_TIER_ORDER);
1065
1124
  var CraftbookStepSchema = z6.object({
1066
1125
  id: z6.string().min(1),
@@ -1094,13 +1153,17 @@ var CraftbookStepSchema = z6.object({
1094
1153
  capabilityFloor: ModelTierSchema.optional(),
1095
1154
  /** Per-phase indexed-context policy; overrides gezel and install defaults. */
1096
1155
  retrieval: RetrievalPolicySchema.optional(),
1156
+ /** Per-step subtractive tool and output-surface policy. */
1157
+ toolPolicy: CraftbookStepToolPolicySchema.optional(),
1097
1158
  assignee: TaskAssigneeSchema.optional(),
1098
1159
  /** Setup scripts, run in order when the step activates. Single ref = legacy shape. */
1099
1160
  onEnter: ScriptRefListSchema.optional(),
1100
1161
  /**
1101
1162
  * Cleanup scripts — the `finally` of the step. Run in order AFTER the
1102
- * gate (if any) approves; never on a gate reject. Branch predicates
1103
- * read the LAST ref's output (legacy routing; prefer gate routing).
1163
+ * gate (if any) approves; never on a gate reject. Every script must
1164
+ * succeed or the step remains incomplete and the task pauses. Branch
1165
+ * predicates read the LAST ref's output (legacy routing; prefer gate
1166
+ * routing).
1104
1167
  */
1105
1168
  onExit: ScriptRefListSchema.optional(),
1106
1169
  /** Required file inputs for this step, in the order they should be opened. */
@@ -1485,6 +1548,8 @@ var NewCraftbookStepSchema = z6.object({
1485
1548
  capabilityFloor: ModelTierSchema.optional(),
1486
1549
  /** See {@link CraftbookStepSchema.shape.retrieval}. */
1487
1550
  retrieval: RetrievalPolicySchema.optional(),
1551
+ /** See {@link CraftbookStepSchema.shape.toolPolicy}. */
1552
+ toolPolicy: CraftbookStepToolPolicySchema.optional(),
1488
1553
  assignee: TaskAssigneeSchema.optional(),
1489
1554
  onEnter: ScriptRefListSchema.optional(),
1490
1555
  onExit: ScriptRefListSchema.optional(),
@@ -1792,6 +1857,8 @@ var STEP_FENCE_KEYS = [
1792
1857
  "suggestedGezelId",
1793
1858
  "suggestedRole",
1794
1859
  "capabilityFloor",
1860
+ "retrieval",
1861
+ "toolPolicy",
1795
1862
  "assignee",
1796
1863
  "deliverable",
1797
1864
  "onEnter",
@@ -1992,7 +2059,7 @@ function defaultStepIdForName(name) {
1992
2059
  }
1993
2060
 
1994
2061
  // src/schemas/gezel.ts
1995
- import { z as z19 } from "zod";
2062
+ import { z as z20 } from "zod";
1996
2063
 
1997
2064
  // src/poppetje/schema.ts
1998
2065
  import { z as z7 } from "zod";
@@ -2074,7 +2141,20 @@ var FIGURE_SCALES = {
2074
2141
  var FIGURE_SCALE_KEYS = Object.keys(FIGURE_SCALES);
2075
2142
  var HAT_OPTIONS = ["cap", "beanie", "kerchief", "straw", "newsboy", "hood"];
2076
2143
  var DRESS_OPTIONS = ["scarf", "apron", "collar", "turtleneck"];
2077
- var HAIR_SHAPES = ["halo", "short", "long", "bun", "braids", "shaved", "bald"];
2144
+ var HAIR_SHAPES = [
2145
+ "halo",
2146
+ "short",
2147
+ "bob",
2148
+ "medium",
2149
+ "long",
2150
+ "extra-long",
2151
+ "bun",
2152
+ "braids",
2153
+ "shaved",
2154
+ "bald"
2155
+ ];
2156
+ var BANGS_OPTIONS = ["straight", "side-swept", "curtain", "short"];
2157
+ var HAIR_PART_OPTIONS = ["none", "center", "left", "right"];
2078
2158
  var ACCESSORY_OPTIONS = [
2079
2159
  "glasses",
2080
2160
  "sunglasses",
@@ -2155,6 +2235,9 @@ var PoppetjeSchema = z7.preprocess(
2155
2235
  skin2: z7.string(),
2156
2236
  hair: z7.string(),
2157
2237
  hairShape: z7.enum(HAIR_SHAPES),
2238
+ /** Optional styling choices; older files retain an open, unparted hairline. */
2239
+ bangs: z7.enum(BANGS_OPTIONS).nullable().optional().default(null),
2240
+ hairPart: z7.enum(HAIR_PART_OPTIONS).optional().default("none"),
2158
2241
  /** Replaces hair when set; 'hood' renders at body level. */
2159
2242
  hat: z7.enum(HAT_OPTIONS).nullable().optional().default(null),
2160
2243
  /** Body overlay; null for an unadorned shirt. */
@@ -2331,73 +2414,119 @@ var GezelGrowthSummarySchema = z12.object({
2331
2414
  });
2332
2415
 
2333
2416
  // src/schemas/model-tuning.ts
2417
+ import { z as z14 } from "zod";
2418
+
2419
+ // src/schemas/llama-cpp-config.ts
2334
2420
  import { z as z13 } from "zod";
2335
- var DrySamplerSchema = z13.object({
2336
- multiplier: z13.number().min(0).max(5).describe("DRY penalty strength. 0 disables. 0.8 is a reasonable default."),
2337
- base: z13.number().min(0).max(5).optional().describe("Base of the exponential penalty for repeated tokens. Default 1.75."),
2338
- allowedLength: z13.number().int().min(0).max(64).optional().describe("Minimum n-gram length before DRY kicks in. Default 2.")
2421
+ var LlamaCppLoadModeSchema = z13.enum([
2422
+ "auto",
2423
+ "none",
2424
+ "mmap",
2425
+ "mlock",
2426
+ "mmap+mlock",
2427
+ "dio"
2428
+ ]);
2429
+ var LlamaCppLazyModeSchema = z13.enum(["on", "auto", "off"]);
2430
+ var LlamaCppV4ConfigSchema = z13.object({
2431
+ /**
2432
+ * Model file loading policy (`--load-mode`). Unset leaves the server on
2433
+ * Auto; the legacy `llamaCppMlock: true` setting maps to `mlock`.
2434
+ */
2435
+ llamaCppLoadMode: LlamaCppLoadModeSchema.optional(),
2436
+ /** On-demand loading for large row-addressable tensors (`--lazy-mode`). */
2437
+ llamaCppLazyMode: LlamaCppLazyModeSchema.optional(),
2438
+ /** Preserve and replay private reasoning across assistant history. */
2439
+ llamaCppReasoningPreserve: z13.boolean().optional(),
2440
+ /**
2441
+ * Keep dense FFN weights from the first N blocks in RAM. Unset delegates
2442
+ * to the hardware planner; zero explicitly disables automatic planning.
2443
+ */
2444
+ llamaCppNCpuFfn: z13.number().int().min(0).optional()
2445
+ });
2446
+ var LlamaCppV4ConfigResetSchema = z13.object({
2447
+ llamaCppMlock: z13.boolean().nullable().optional(),
2448
+ llamaCppLoadMode: LlamaCppLoadModeSchema.nullable().optional(),
2449
+ llamaCppLazyMode: LlamaCppLazyModeSchema.nullable().optional(),
2450
+ llamaCppReasoningPreserve: z13.boolean().nullable().optional(),
2451
+ llamaCppNCpuFfn: z13.number().int().min(0).nullable().optional()
2452
+ });
2453
+
2454
+ // src/schemas/model-tuning.ts
2455
+ var DrySamplerSchema = z14.object({
2456
+ multiplier: z14.number().min(0).max(5).describe("DRY penalty strength. 0 disables. 0.8 is a reasonable default."),
2457
+ base: z14.number().min(0).max(5).optional().describe("Base of the exponential penalty for repeated tokens. Default 1.75."),
2458
+ allowedLength: z14.number().int().min(0).max(64).optional().describe("Minimum n-gram length before DRY kicks in. Default 2.")
2339
2459
  }).describe("DRY anti-repetition sampler (llama.cpp only).");
2340
- var XtcSamplerSchema = z13.object({
2341
- probability: z13.number().min(0).max(1).describe("Probability of triggering XTC on any given step."),
2342
- threshold: z13.number().min(0).max(1).describe("Minimum top-token probability for XTC to fire.")
2460
+ var XtcSamplerSchema = z14.object({
2461
+ probability: z14.number().min(0).max(1).describe("Probability of triggering XTC on any given step."),
2462
+ threshold: z14.number().min(0).max(1).describe("Minimum top-token probability for XTC to fire.")
2343
2463
  }).describe("XTC sampler (llama.cpp only).");
2344
- var SamplingBlockSchema = z13.object({
2345
- temperature: z13.number().min(0).max(2).optional().describe("Sampling temperature. 0 = greedy. Most reasoning models want 0.6\u20131.0."),
2346
- topP: z13.number().min(0).max(1).optional().describe("Nucleus sampling. 0.95 is the common default for Qwen, Gemma, Nemotron."),
2347
- topK: z13.number().int().min(0).max(1e3).optional().describe("Top-k cutoff. 20 for Qwen think, 64 for Gemma, 1 for greedy-on-instruct."),
2348
- minP: z13.number().min(0).max(1).optional().describe("Min-p cutoff (llama.cpp / MLX / Ollama). Qwen recommends 0."),
2349
- maxTokens: z13.number().int().positive().optional().describe("Per-turn output token cap. Maps to num_predict / max_tokens / n_predict."),
2350
- seed: z13.number().int().optional().describe("RNG seed. Unset / negative = random. Best-effort determinism on cloud."),
2351
- repetitionPenalty: z13.number().min(0).max(3).optional().describe("Local engines (Ollama / llama.cpp / MLX): repeat_penalty. 1.0 = off, 1.1 = mild."),
2352
- repetitionContext: z13.number().int().positive().optional().describe("Local engines: window size for repetition penalty (`repeat_last_n`)."),
2353
- frequencyPenalty: z13.number().min(-2).max(2).optional().describe("Cloud (OpenAI) and Ollama / llama.cpp: penalize repeated tokens by frequency."),
2354
- presencePenalty: z13.number().min(-2).max(2).optional().describe("Cloud (OpenAI) and Ollama / llama.cpp: penalize any reused token."),
2464
+ var SamplingBlockSchema = z14.object({
2465
+ temperature: z14.number().min(0).max(2).optional().describe("Sampling temperature. 0 = greedy. Most reasoning models want 0.6\u20131.0."),
2466
+ topP: z14.number().min(0).max(1).optional().describe("Nucleus sampling. 0.95 is the common default for Qwen, Gemma, Nemotron."),
2467
+ topK: z14.number().int().min(0).max(1e3).optional().describe("Top-k cutoff. 20 for Qwen think, 64 for Gemma, 1 for greedy-on-instruct."),
2468
+ minP: z14.number().min(0).max(1).optional().describe("Min-p cutoff (llama.cpp / MLX / Ollama). Qwen recommends 0."),
2469
+ maxTokens: z14.number().int().positive().optional().describe("Per-turn output token cap. Maps to num_predict / max_tokens / n_predict."),
2470
+ seed: z14.number().int().optional().describe("RNG seed. Unset / negative = random. Best-effort determinism on cloud."),
2471
+ repetitionPenalty: z14.number().min(0).max(3).optional().describe("Local engines (Ollama / llama.cpp / MLX): repeat_penalty. 1.0 = off, 1.1 = mild."),
2472
+ repetitionContext: z14.number().int().positive().optional().describe("Local engines: window size for repetition penalty (`repeat_last_n`)."),
2473
+ frequencyPenalty: z14.number().min(-2).max(2).optional().describe("Cloud (OpenAI) and Ollama / llama.cpp: penalize repeated tokens by frequency."),
2474
+ presencePenalty: z14.number().min(-2).max(2).optional().describe("Cloud (OpenAI) and Ollama / llama.cpp: penalize any reused token."),
2355
2475
  dry: DrySamplerSchema.optional(),
2356
2476
  xtc: XtcSamplerSchema.optional()
2357
2477
  }).describe("Sampling parameters applied per-request.");
2358
- var ReasoningBlockSchema = z13.object({
2359
- effort: z13.enum(["low", "medium", "high"]).optional().describe(
2478
+ var ReasoningBlockSchema = z14.object({
2479
+ effort: z14.enum(["low", "medium", "high"]).optional().describe(
2360
2480
  "Cloud reasoning effort. Maps to OpenAI `reasoning.effort` and Anthropic `thinking.budget_tokens` tiers."
2361
2481
  ),
2362
- thinkingBudget: z13.number().int().positive().optional().describe(
2482
+ thinkingBudget: z14.number().int().positive().optional().describe(
2363
2483
  "Explicit thinking-token budget (Anthropic `thinking.budget_tokens`, Nemotron `reasoning_budget`). Wins over `effort` when both set."
2364
2484
  ),
2365
- enableThinking: z13.boolean().optional().describe(
2485
+ enableThinking: z14.boolean().optional().describe(
2366
2486
  "Chat-template toggle for dual-mode models (Qwen3+, Nemotron Nano/Super). Implicit on cloud thinking models."
2367
2487
  ),
2368
- templateKwargs: z13.record(z13.string(), z13.union([z13.string(), z13.number(), z13.boolean()])).optional().describe(
2488
+ templateKwargs: z14.record(z14.string(), z14.union([z14.string(), z14.number(), z14.boolean()])).optional().describe(
2369
2489
  "Chat-template variables that drive this model's reasoning depth, forwarded verbatim as `chat_template_kwargs` on local engines. The names are the model's own \u2014 GPT-OSS reads `reasoning_effort`, Muse Glimmer reads `reasoning_strength` (low|medium|high|xhigh) \u2014 so the manifest declares them rather than the runtime guessing. Lives under `reasoning` (not `engine`) because depth is a per-request choice a tuning profile overrides: `thinking-coding` can ask for xhigh while `instruct` asks for low. Cloud providers ignore it; use `reasoning.effort` there."
2370
2490
  )
2371
2491
  }).describe("Reasoning controls.");
2372
- var StructuredOutputSchema = z13.object({
2373
- responseFormat: z13.enum(["text", "json_object"]).optional().describe("Output mode. `text` = freeform (default). `json_object` = enforce JSON."),
2374
- jsonSchema: z13.unknown().optional().describe("Pin output to a JSON Schema (OpenAI strict mode, llama.cpp --json-schema)."),
2375
- grammar: z13.string().optional().describe("llama.cpp GBNF grammar. Last-resort structured-output knob.")
2492
+ var StructuredOutputSchema = z14.object({
2493
+ responseFormat: z14.enum(["text", "json_object"]).optional().describe("Output mode. `text` = freeform (default). `json_object` = enforce JSON."),
2494
+ jsonSchema: z14.unknown().optional().describe("Pin output to a JSON Schema (OpenAI strict mode, llama.cpp --json-schema)."),
2495
+ grammar: z14.string().optional().describe("llama.cpp GBNF grammar. Last-resort structured-output knob.")
2376
2496
  }).describe("Structured-output controls.");
2377
- var PromptTagsSchema = z13.object({
2378
- enableThinkingTag: z13.string().optional().describe("User-prompt tag that enables thinking for this turn (e.g. `/think`)."),
2379
- disableThinkingTag: z13.string().optional().describe("User-prompt tag that disables thinking for this turn (e.g. `/no_think`).")
2497
+ var PromptTagsSchema = z14.object({
2498
+ enableThinkingTag: z14.string().optional().describe("User-prompt tag that enables thinking for this turn (e.g. `/think`)."),
2499
+ disableThinkingTag: z14.string().optional().describe("User-prompt tag that disables thinking for this turn (e.g. `/no_think`).")
2380
2500
  }).describe("Per-turn reasoning toggle tags.");
2381
- var LlamaCppEngineConfigSchema = z13.object({
2382
- nGpuLayers: z13.number().int().min(-1).optional().describe("`--n-gpu-layers` override. -1 = all. Unset = b9843 `auto`/`--fit`."),
2383
- cpuMoe: z13.boolean().optional().describe("`--cpu-moe`: keep ALL MoE experts in system RAM (attention/dense on GPU)."),
2384
- nCpuMoe: z13.number().int().min(0).optional().describe("`--n-cpu-moe N`: keep the first N layers\u2019 MoE experts in RAM. Partial split."),
2385
- cacheReuse: z13.number().int().min(0).optional().describe(
2501
+ var LlamaCppEngineConfigSchema = z14.object({
2502
+ nGpuLayers: z14.number().int().min(-1).optional().describe("`--n-gpu-layers` override. -1 = all. Unset = b9843 `auto`/`--fit`."),
2503
+ cpuMoe: z14.boolean().optional().describe("`--cpu-moe`: keep ALL MoE experts in system RAM (attention/dense on GPU)."),
2504
+ nCpuMoe: z14.number().int().min(0).optional().describe("`--n-cpu-moe N`: keep the first N layers\u2019 MoE experts in RAM. Partial split."),
2505
+ nCpuFfn: z14.number().int().min(0).optional().describe(
2506
+ "`--n-cpu-ffn N`: keep the first N layers\u2019 dense FFN weights in RAM. 0 disables the hardware planner."
2507
+ ),
2508
+ loadMode: LlamaCppLoadModeSchema.optional().describe(
2509
+ "llama.cpp v0.4.0 `--load-mode` override for this model."
2510
+ ),
2511
+ lazyMode: LlamaCppLazyModeSchema.optional().describe(
2512
+ "llama.cpp v0.4.0 on-demand tensor loading mode."
2513
+ ),
2514
+ cacheReuse: z14.number().int().min(0).optional().describe(
2386
2515
  "`--cache-reuse N` prefix-KV reuse chunk. 0 = disable. Unset inherits the global default."
2387
2516
  ),
2388
- swaFull: z13.boolean().optional().describe("`--swa-full`: full-size SWA cache (Gemma family)."),
2389
- flashAttn: z13.enum(["on", "off", "auto"]).optional().describe("`--flash-attn` mode override for this model."),
2390
- ubatchSize: z13.number().int().positive().optional().describe("`--ubatch-size` (inner microbatch) override for this model."),
2391
- contextSize: z13.number().int().positive().optional().describe(
2517
+ swaFull: z14.boolean().optional().describe("`--swa-full`: full-size SWA cache (Gemma family)."),
2518
+ flashAttn: z14.enum(["on", "off", "auto"]).optional().describe("`--flash-attn` mode override for this model."),
2519
+ ubatchSize: z14.number().int().positive().optional().describe("`--ubatch-size` (inner microbatch) override for this model."),
2520
+ contextSize: z14.number().int().positive().optional().describe(
2392
2521
  "Per-turn context ceiling (tokens) this model launches with. Capped by GGUF train ctx."
2393
2522
  ),
2394
- chatTemplate: z13.string().min(1).optional().describe(
2523
+ chatTemplate: z14.string().min(1).optional().describe(
2395
2524
  "`--chat-template` override for GGUFs whose embedded Jinja template is incompatible with llama.cpp tool parsing."
2396
2525
  ),
2397
- threads: z13.number().int().positive().optional().describe("`--threads` override."),
2398
- batchSize: z13.number().int().positive().optional().describe("`--batch-size` override."),
2399
- spec: z13.object({
2400
- type: z13.enum([
2526
+ threads: z14.number().int().positive().optional().describe("`--threads` override."),
2527
+ batchSize: z14.number().int().positive().optional().describe("`--batch-size` override."),
2528
+ spec: z14.object({
2529
+ type: z14.enum([
2401
2530
  "none",
2402
2531
  "draft-mtp",
2403
2532
  "draft-eagle3",
@@ -2409,24 +2538,24 @@ var LlamaCppEngineConfigSchema = z13.object({
2409
2538
  "ngram-map-k4v",
2410
2539
  "ngram-cache"
2411
2540
  ]).optional().describe("`--spec-type` speculative-decoding mode for this model."),
2412
- mtp: z13.boolean().optional().describe(
2541
+ mtp: z14.boolean().optional().describe(
2413
2542
  "VERIFIED capability metadata: this model\u2019s target or companion GGUF carries MTP tensors. Does not enable `draft-mtp` by itself."
2414
2543
  ),
2415
- draftModelId: z13.string().optional().describe("Catalog id / path of the draft model for `draft-simple`."),
2416
- nMax: z13.number().int().positive().optional().describe("`--spec-draft-n-max`: tokens drafted per step.")
2544
+ draftModelId: z14.string().optional().describe("Catalog id / path of the draft model for `draft-simple`."),
2545
+ nMax: z14.number().int().positive().optional().describe("`--spec-draft-n-max`: tokens drafted per step.")
2417
2546
  }).optional().describe("Speculative-decoding config for this model.")
2418
2547
  }).describe("Per-model llama.cpp launch-flag defaults (engine-level, applied at model load).");
2419
- var EngineConfigSchema = z13.object({
2548
+ var EngineConfigSchema = z14.object({
2420
2549
  llamaCpp: LlamaCppEngineConfigSchema.optional()
2421
2550
  }).describe("Per-model engine launch-flag defaults, keyed by engine.");
2422
- var ChatModelTuningBaseSchema = z13.object({
2551
+ var ChatModelTuningBaseSchema = z14.object({
2423
2552
  sampling: SamplingBlockSchema.optional(),
2424
2553
  samplingWhenThinking: SamplingBlockSchema.optional().describe(
2425
2554
  "Sparse override of `sampling` applied when the runtime determines reasoning is engaged. Used by Qwen3+ (different sampling for /think mode) and Nemotron Nano (different sampling for thinking vs instruct)."
2426
2555
  ),
2427
2556
  reasoning: ReasoningBlockSchema.optional(),
2428
2557
  output: StructuredOutputSchema.optional(),
2429
- toolChoice: z13.enum(["auto", "required", "none"]).optional().describe(
2558
+ toolChoice: z14.enum(["auto", "required", "none"]).optional().describe(
2430
2559
  "Tool selection mode (cloud + llama.cpp + MLX). `auto` lets the model decide; `required` forces a tool call this turn; `none` disables tools."
2431
2560
  ),
2432
2561
  promptTags: PromptTagsSchema.optional()
@@ -2435,16 +2564,16 @@ var ChatModelTuningSchema = ChatModelTuningBaseSchema.extend({
2435
2564
  engine: EngineConfigSchema.optional().describe(
2436
2565
  "Per-model ENGINE launch-flag defaults (llama.cpp `--n-gpu-layers`, `--cpu-moe`, `--spec-type`, \u2026). Applied once at model load, not per request \u2014 so it lives on the top-level tuning object, not inside per-request `profiles`."
2437
2566
  ),
2438
- profiles: z13.record(TuningProfileIdSchema, ChatModelTuningBaseSchema.partial()).optional().describe(
2567
+ profiles: z14.record(TuningProfileIdSchema, ChatModelTuningBaseSchema.partial()).optional().describe(
2439
2568
  "Named tuning presets this model implements. Gezel frontmatter `tuningProfile` selects one; the resolver applies the profile as a layer between installDefault and catalog base. Missing requested profiles walk the canonical fallback chain."
2440
2569
  )
2441
2570
  }).describe("Per-model sampling, reasoning, and output defaults.");
2442
2571
 
2443
2572
  // src/schemas/question.ts
2444
- import { z as z15 } from "zod";
2573
+ import { z as z16 } from "zod";
2445
2574
 
2446
2575
  // src/schemas/npm-package.ts
2447
- import { z as z14 } from "zod";
2576
+ import { z as z15 } from "zod";
2448
2577
  var NPM_NAME_SEGMENT = /^[a-z0-9](?:[a-z0-9._~-]*[a-z0-9])?$/;
2449
2578
  var SEMVER_NUMBER = String.raw`(?:0|[1-9]\d*)`;
2450
2579
  var SEMVER_PART = String.raw`(?:${SEMVER_NUMBER}|[xX*])`;
@@ -2476,28 +2605,28 @@ function isValidNpmRegistryVersion(value) {
2476
2605
  return atoms.length > 0 && atoms.every((atom) => SEMVER_ATOM.test(atom));
2477
2606
  });
2478
2607
  }
2479
- var NpmPackageNameSchema = z14.string().refine(isValidNpmPackageName, {
2608
+ var NpmPackageNameSchema = z15.string().refine(isValidNpmPackageName, {
2480
2609
  message: "must be a lowercase npm registry package name (for example zod or @types/node)"
2481
2610
  });
2482
- var NpmRegistryVersionSchema = z14.string().refine(isValidNpmRegistryVersion, {
2611
+ var NpmRegistryVersionSchema = z15.string().refine(isValidNpmRegistryVersion, {
2483
2612
  message: "must be a registry dist-tag or semver range"
2484
2613
  });
2485
- var NpmRegistryPackageRequestSchema = z14.object({
2614
+ var NpmRegistryPackageRequestSchema = z15.object({
2486
2615
  package: NpmPackageNameSchema,
2487
2616
  version: NpmRegistryVersionSchema.optional()
2488
2617
  }).strict();
2489
2618
 
2490
2619
  // src/schemas/question.ts
2491
- var NpmInstallApprovalDecisionSchema = z15.object({
2620
+ var NpmInstallApprovalDecisionSchema = z16.object({
2492
2621
  package: NpmPackageNameSchema,
2493
2622
  version: NpmRegistryVersionSchema,
2494
- decision: z15.enum(["install", "always", "decline"])
2623
+ decision: z16.enum(["install", "always", "decline"])
2495
2624
  });
2496
- var QuestionAnswerSchema = z15.object({
2625
+ var QuestionAnswerSchema = z16.object({
2497
2626
  /** Indices into `choices` the user picked. Empty when only write-in. */
2498
- selectedChoices: z15.array(z15.number().int().min(0)).optional(),
2627
+ selectedChoices: z16.array(z16.number().int().min(0)).optional(),
2499
2628
  /** Free-text the user typed. Empty when they only clicked choices. */
2500
- writeIn: z15.string().optional(),
2629
+ writeIn: z16.string().optional(),
2501
2630
  /**
2502
2631
  * Set when the user explicitly dismissed BUT wants the gezel to
2503
2632
  * proceed anyway with sensible defaults. Triggers a synthetic
@@ -2510,7 +2639,7 @@ var QuestionAnswerSchema = z15.object({
2510
2639
  * mean it literally (declining an image generation, an npm install,
2511
2640
  * a schedule) and on the permission broker's dismissal path.
2512
2641
  */
2513
- declined: z15.boolean().optional(),
2642
+ declined: z16.boolean().optional(),
2514
2643
  /**
2515
2644
  * Set when the user just wants the question to go away — no
2516
2645
  * follow-up turn, no work done, nothing for the gezel to act on.
@@ -2519,135 +2648,136 @@ var QuestionAnswerSchema = z15.object({
2519
2648
  * from `declined` so the model never sees a "user wants defaults"
2520
2649
  * signal that the user didn't intend. UI label: "Skip".
2521
2650
  */
2522
- silentSkip: z15.boolean().optional(),
2651
+ silentSkip: z16.boolean().optional(),
2523
2652
  /**
2524
2653
  * Per-package decisions for `npm-install-approval` questions. When
2525
2654
  * set, the answer handler installs / always-allows / declines each
2526
2655
  * package and emits a single follow-up summary into the session.
2527
2656
  */
2528
- npmInstallDecisions: z15.array(NpmInstallApprovalDecisionSchema).optional(),
2529
- at: z15.string()
2657
+ npmInstallDecisions: z16.array(NpmInstallApprovalDecisionSchema).optional(),
2658
+ at: z16.string()
2530
2659
  });
2531
- var NpmInstallApprovalPackageSchema = z15.object({
2660
+ var NpmInstallApprovalPackageSchema = z16.object({
2532
2661
  package: NpmPackageNameSchema,
2533
2662
  version: NpmRegistryVersionSchema
2534
2663
  });
2535
- var CommandApprovalScopeSchema = z15.enum(["script", "npx"]);
2536
- var CommandApprovalInputFileSchema = z15.object({
2664
+ var CommandApprovalScopeSchema = z16.enum(["script", "npx"]);
2665
+ var CommandApprovalInputFileSchema = z16.object({
2537
2666
  /** Workspace-relative, slash-normalized path shown in the approval prompt. */
2538
- path: z15.string().min(1),
2539
- sha256: z15.string().regex(/^[a-f0-9]{64}$/)
2667
+ path: z16.string().min(1),
2668
+ sha256: z16.string().regex(/^[a-f0-9]{64}$/)
2540
2669
  });
2541
- var CommandApprovalIntentSchema = z15.object({
2542
- kind: z15.literal("command-approval"),
2670
+ var CommandApprovalIntentSchema = z16.object({
2671
+ kind: z16.literal("command-approval"),
2543
2672
  scope: CommandApprovalScopeSchema,
2544
- name: z15.string().min(1),
2545
- body: z15.string().optional(),
2546
- args: z15.array(z15.string()).optional(),
2547
- inputFiles: z15.array(CommandApprovalInputFileSchema).max(128).optional()
2548
- });
2549
- var ToolPermissionIntentSchema = z15.object({
2550
- kind: z15.literal("tool-permission"),
2551
- toolName: z15.string(),
2552
- toolInput: z15.record(z15.string(), z15.unknown())
2553
- });
2554
- var ClaudeUserQuestionOptionSchema = z15.object({
2555
- label: z15.string().min(1),
2556
- description: z15.string().optional()
2557
- });
2558
- var ClaudeUserQuestionIntentSchema = z15.object({
2559
- kind: z15.literal("claude-user-question"),
2673
+ name: z16.string().min(1),
2674
+ body: z16.string().optional(),
2675
+ args: z16.array(z16.string()).optional(),
2676
+ inputFiles: z16.array(CommandApprovalInputFileSchema).max(128).optional()
2677
+ });
2678
+ var ToolPermissionIntentSchema = z16.object({
2679
+ kind: z16.literal("tool-permission"),
2680
+ toolName: z16.string(),
2681
+ toolInput: z16.record(z16.string(), z16.unknown())
2682
+ });
2683
+ var ClaudeUserQuestionOptionSchema = z16.object({
2684
+ label: z16.string().min(1),
2685
+ description: z16.string().optional()
2686
+ });
2687
+ var ClaudeUserQuestionIntentSchema = z16.object({
2688
+ kind: z16.literal("claude-user-question"),
2560
2689
  /** The CLI's short topic chip for the question (e.g. "Gate block"). */
2561
- header: z15.string().optional(),
2690
+ header: z16.string().optional(),
2562
2691
  /** Options with descriptions; labels mirror the Question's `choices`. */
2563
- options: z15.array(ClaudeUserQuestionOptionSchema),
2692
+ options: z16.array(ClaudeUserQuestionOptionSchema),
2564
2693
  /** 0-based position within the originating multi-question call. */
2565
- questionIndex: z15.number().int().min(0),
2694
+ questionIndex: z16.number().int().min(0),
2566
2695
  /** Total questions in the originating call (cards appear sequentially). */
2567
- questionCount: z15.number().int().min(1)
2568
- });
2569
- var ToolsetInstallApprovalIntentSchema = z15.object({
2570
- kind: z15.literal("toolset-install-approval"),
2571
- toolsetId: z15.string(),
2572
- sourceId: z15.string(),
2573
- version: z15.string(),
2574
- targetProjectId: z15.string(),
2575
- craftbookId: z15.string()
2576
- });
2577
- var ImageGenerationApprovalIntentSchema = z15.object({
2578
- kind: z15.literal("image-generation-approval"),
2579
- provider: z15.string(),
2580
- model: z15.string(),
2696
+ questionCount: z16.number().int().min(1)
2697
+ });
2698
+ var ToolsetInstallApprovalIntentSchema = z16.object({
2699
+ kind: z16.literal("toolset-install-approval"),
2700
+ toolsetId: z16.string(),
2701
+ sourceId: z16.string(),
2702
+ version: z16.string(),
2703
+ targetProjectId: z16.string(),
2704
+ craftbookId: z16.string()
2705
+ });
2706
+ var ImageGenerationApprovalIntentSchema = z16.object({
2707
+ kind: z16.literal("image-generation-approval"),
2708
+ provider: z16.string(),
2709
+ model: z16.string(),
2581
2710
  /** Truncated prompt the model is about to send. Surfaced verbatim. */
2582
- promptPreview: z15.string(),
2711
+ promptPreview: z16.string(),
2583
2712
  /** Resolved generation size, e.g. '2K 16:9' or '1024x1024'. Optional. */
2584
- estimatedSize: z15.string().optional()
2713
+ estimatedSize: z16.string().optional()
2585
2714
  });
2586
- var VideoGenerationApprovalIntentSchema = z15.object({
2587
- kind: z15.literal("video-generation-approval"),
2588
- provider: z15.string(),
2589
- model: z15.string(),
2590
- promptPreview: z15.string(),
2715
+ var VideoGenerationApprovalIntentSchema = z16.object({
2716
+ kind: z16.literal("video-generation-approval"),
2717
+ provider: z16.string(),
2718
+ model: z16.string(),
2719
+ promptPreview: z16.string(),
2591
2720
  /** Resolved clip shape, e.g. '704×480 · 97f · 24fps'. Optional. */
2592
- estimatedSize: z15.string().optional()
2721
+ estimatedSize: z16.string().optional()
2593
2722
  });
2594
- var ScheduleApprovalIntentSchema = z15.object({
2595
- kind: z15.literal("schedule-approval"),
2596
- typeId: z15.string(),
2597
- craftbookId: z15.string(),
2723
+ var ScheduleApprovalIntentSchema = z16.object({
2724
+ kind: z16.literal("schedule-approval"),
2725
+ typeId: z16.string(),
2726
+ craftbookId: z16.string(),
2598
2727
  /**
2599
2728
  * Recurrence flavor. Absent → 'scheduled' (every question written
2600
2729
  * before this field existed is a cron schedule). 'night-shift' hosts
2601
2730
  * run inside the Night Shift window instead of on a user-visible cron;
2602
2731
  * the card copy switches accordingly.
2603
2732
  */
2604
- runMode: z15.enum(["scheduled", "night-shift"]).optional(),
2733
+ runMode: z16.enum(["scheduled", "night-shift"]).optional(),
2605
2734
  /**
2606
2735
  * 5-field cron expression (UTC). Surfaced verbatim on the card for
2607
2736
  * 'scheduled' hosts; for 'night-shift' hosts it is the internal
2608
2737
  * heartbeat and the card shows the window instead.
2609
2738
  */
2610
- cron: z15.string(),
2611
- overlap: z15.enum(["skip", "queue", "concurrent"]).optional()
2739
+ cron: z16.string(),
2740
+ overlap: z16.enum(["skip", "queue", "concurrent"]).optional()
2612
2741
  });
2613
- var NightShiftReviewIntentSchema = z15.object({
2614
- kind: z15.literal("night-shift-review"),
2742
+ var NightShiftReviewIntentSchema = z16.object({
2743
+ kind: z16.literal("night-shift-review"),
2615
2744
  /** The window's day key (see `nightShiftWindowKey`). */
2616
- windowKey: z15.string(),
2617
- tasksCompleted: z15.number(),
2618
- reports: z15.array(
2619
- z15.object({
2620
- projectId: z15.string(),
2621
- path: z15.string(),
2622
- title: z15.string().optional(),
2623
- actionCount: z15.number()
2745
+ windowKey: z16.string(),
2746
+ tasksCompleted: z16.number(),
2747
+ reports: z16.array(
2748
+ z16.object({
2749
+ projectId: z16.string(),
2750
+ path: z16.string(),
2751
+ title: z16.string().optional(),
2752
+ actionCount: z16.number()
2624
2753
  })
2625
2754
  )
2626
2755
  });
2627
- var TaskPausedReasonSchema = z15.enum([
2756
+ var TaskPausedReasonSchema = z16.enum([
2628
2757
  "gate_exhausted",
2629
2758
  "gate_plateau",
2630
2759
  "gate_unsatisfiable",
2631
2760
  "gate_infrastructure",
2761
+ "step_exit_infrastructure",
2632
2762
  "step_stalled",
2633
2763
  "budget_exhausted"
2634
2764
  ]);
2635
- var TaskPausedIntentSchema = z15.object({
2636
- kind: z15.literal("task-paused"),
2765
+ var TaskPausedIntentSchema = z16.object({
2766
+ kind: z16.literal("task-paused"),
2637
2767
  /** `projectId/num` of the paused task — the dedup key. */
2638
- taskRef: z15.string(),
2639
- stepId: z15.string().optional(),
2768
+ taskRef: z16.string(),
2769
+ stepId: z16.string().optional(),
2640
2770
  reason: TaskPausedReasonSchema
2641
2771
  });
2642
- var QuestionIntentSchema = z15.discriminatedUnion("kind", [
2643
- z15.object({
2644
- kind: z15.literal("npm-install-approval"),
2772
+ var QuestionIntentSchema = z16.discriminatedUnion("kind", [
2773
+ z16.object({
2774
+ kind: z16.literal("npm-install-approval"),
2645
2775
  /**
2646
2776
  * Packages that need approval. Always at least one; multiple when
2647
2777
  * the gezel batched an install call (encouraged) or when we merged
2648
2778
  * a later request into the same pending question for dedup.
2649
2779
  */
2650
- packages: z15.array(NpmInstallApprovalPackageSchema).min(1)
2780
+ packages: z16.array(NpmInstallApprovalPackageSchema).min(1)
2651
2781
  }),
2652
2782
  CommandApprovalIntentSchema,
2653
2783
  ToolPermissionIntentSchema,
@@ -2659,61 +2789,61 @@ var QuestionIntentSchema = z15.discriminatedUnion("kind", [
2659
2789
  NightShiftReviewIntentSchema,
2660
2790
  TaskPausedIntentSchema
2661
2791
  ]);
2662
- var QuestionSchema = z15.object({
2663
- id: z15.string(),
2664
- projectId: z15.string(),
2665
- gezelId: z15.string(),
2666
- sessionId: z15.string(),
2792
+ var QuestionSchema = z16.object({
2793
+ id: z16.string(),
2794
+ projectId: z16.string(),
2795
+ gezelId: z16.string(),
2796
+ sessionId: z16.string(),
2667
2797
  /** Body of the question — supports markdown. */
2668
- prompt: z15.string().min(1),
2798
+ prompt: z16.string().min(1),
2669
2799
  /** Optional preset choices. Empty / omitted => write-in only. */
2670
- choices: z15.array(z15.string()).max(20).optional(),
2800
+ choices: z16.array(z16.string()).max(20).optional(),
2671
2801
  /** Whether the user can also type a write-in alongside choices. Default true. */
2672
- allowWriteIn: z15.boolean().optional(),
2802
+ allowWriteIn: z16.boolean().optional(),
2673
2803
  /** Whether multiple choices may be selected. Default false. */
2674
- multiSelect: z15.boolean().optional(),
2804
+ multiSelect: z16.boolean().optional(),
2675
2805
  /**
2676
2806
  * Approval-flow attachment: a task this question is *about*. Stored in
2677
2807
  * `projectId/num` form so existing parsing helpers work. The UI shows
2678
2808
  * the task title + status above the prompt and offers an "Open task"
2679
2809
  * link.
2680
2810
  */
2681
- taskRef: z15.string().optional(),
2811
+ taskRef: z16.string().optional(),
2682
2812
  /**
2683
2813
  * Approval-flow attachment: a document this question is *about*.
2684
2814
  * Project-relative path when `projectId` is set, otherwise into the
2685
2815
  * global `~/.gezel/documents/` library. The UI renders a collapsed
2686
2816
  * preview + "Open document" link.
2687
2817
  */
2688
- documentPath: z15.string().optional(),
2818
+ documentPath: z16.string().optional(),
2689
2819
  /**
2690
2820
  * Service-created specialized-question marker (see `QuestionIntent`
2691
2821
  * for context). Absent for plain user-facing questions asked via
2692
2822
  * the `ask_user_question` MCP tool.
2693
2823
  */
2694
2824
  intent: QuestionIntentSchema.optional(),
2695
- createdAt: z15.string(),
2825
+ createdAt: z16.string(),
2696
2826
  /** Set once the user has answered (or declined). */
2697
2827
  answer: QuestionAnswerSchema.optional()
2698
2828
  });
2699
2829
 
2700
2830
  // src/schemas/recognition.ts
2701
- import { z as z16 } from "zod";
2702
- var ImageExifSchema = z16.object({
2703
- make: z16.string().optional(),
2704
- model: z16.string().optional(),
2705
- lensModel: z16.string().optional(),
2706
- dateTimeOriginal: z16.string().optional(),
2707
- orientation: z16.number().int().min(1).max(8).optional(),
2708
- software: z16.string().optional(),
2709
- imageDescription: z16.string().optional()
2710
- });
2711
- var ImageStaticMetaSchema = z16.object({
2712
- format: z16.enum(["png", "jpeg", "gif", "webp", "svg", "unknown"]),
2713
- width: z16.number().int().positive().optional(),
2714
- height: z16.number().int().positive().optional(),
2715
- byteLength: z16.number().int().nonnegative(),
2716
- sha256: z16.string().regex(/^[a-f0-9]{64}$/),
2831
+ import { z as z17 } from "zod";
2832
+ var ImageExifSchema = z17.object({
2833
+ make: z17.string().optional(),
2834
+ model: z17.string().optional(),
2835
+ lensModel: z17.string().optional(),
2836
+ dateTimeOriginal: z17.string().optional(),
2837
+ orientation: z17.number().int().min(1).max(8).optional(),
2838
+ software: z17.string().optional(),
2839
+ imageDescription: z17.string().optional()
2840
+ });
2841
+ var ImageStaticMetaSchema = z17.object({
2842
+ format: z17.enum(["png", "jpeg", "gif", "webp", "svg", "unknown"]),
2843
+ width: z17.number().int().positive().optional(),
2844
+ height: z17.number().int().positive().optional(),
2845
+ byteLength: z17.number().int().nonnegative(),
2846
+ sha256: z17.string().regex(/^[a-f0-9]{64}$/),
2717
2847
  /**
2718
2848
  * PNG `tEXt`/`iTXt`/`zTXt` keyword→value pairs. Generation provenance lives
2719
2849
  * here (A1111 writes `parameters`, ComfyUI writes `prompt`/`workflow`) and
@@ -2722,171 +2852,171 @@ var ImageStaticMetaSchema = z16.object({
2722
2852
  * Attacker-controlled: anyone can author a PNG whose `Description` chunk
2723
2853
  * reads "Ignore previous instructions". Renderers MUST fence and cap this.
2724
2854
  */
2725
- pngText: z16.record(z16.string(), z16.string()).optional(),
2855
+ pngText: z17.record(z17.string(), z17.string()).optional(),
2726
2856
  exif: ImageExifSchema.optional(),
2727
2857
  /** Withheld from every prompt. See the schema doc above. */
2728
- gps: z16.object({ lat: z16.number(), lon: z16.number() }).optional(),
2858
+ gps: z17.object({ lat: z17.number(), lon: z17.number() }).optional(),
2729
2859
  /** True when the file carried location data we deliberately dropped. */
2730
- gpsRedacted: z16.boolean().optional(),
2860
+ gpsRedacted: z17.boolean().optional(),
2731
2861
  /**
2732
2862
  * Heuristic from dimensions, format, and metadata — drives `auto` mode
2733
2863
  * selection without paying a classifier call.
2734
2864
  */
2735
- likelyScreenshot: z16.boolean().optional()
2865
+ likelyScreenshot: z17.boolean().optional()
2736
2866
  });
2737
- var RecognitionModeSchema = z16.enum(["describe", "ocr", "ui", "extract"]);
2738
- var RecognitionModeRequestSchema = z16.enum(["auto", "describe", "ocr", "ui", "extract"]);
2739
- var ImageRecognitionSchema = z16.object({
2740
- schemaVersion: z16.literal(1),
2741
- sha256: z16.string().regex(/^[a-f0-9]{64}$/),
2867
+ var RecognitionModeSchema = z17.enum(["describe", "ocr", "ui", "extract"]);
2868
+ var RecognitionModeRequestSchema = z17.enum(["auto", "describe", "ocr", "ui", "extract"]);
2869
+ var ImageRecognitionSchema = z17.object({
2870
+ schemaVersion: z17.literal(1),
2871
+ sha256: z17.string().regex(/^[a-f0-9]{64}$/),
2742
2872
  meta: ImageStaticMetaSchema,
2743
- modes: z16.array(RecognitionModeSchema).min(1),
2744
- description: z16.string().optional(),
2745
- ocrText: z16.string().optional(),
2746
- structured: z16.object({
2747
- templateId: z16.string().optional(),
2748
- data: z16.unknown()
2873
+ modes: z17.array(RecognitionModeSchema).min(1),
2874
+ description: z17.string().optional(),
2875
+ ocrText: z17.string().optional(),
2876
+ structured: z17.object({
2877
+ templateId: z17.string().optional(),
2878
+ data: z17.unknown()
2749
2879
  }).optional(),
2750
- engine: z16.enum(["llama-cpp", "mlx", "mock", "none"]),
2751
- modelId: z16.string(),
2752
- status: z16.enum(["ok", "partial", "failed", "static-only"]),
2753
- failureReason: z16.string().optional(),
2754
- durationMs: z16.number().int().nonnegative(),
2755
- at: z16.string()
2756
- });
2757
- var MessageImageDigestSchema = z16.object({
2880
+ engine: z17.enum(["llama-cpp", "mlx", "mock", "none"]),
2881
+ modelId: z17.string(),
2882
+ status: z17.enum(["ok", "partial", "failed", "static-only"]),
2883
+ failureReason: z17.string().optional(),
2884
+ durationMs: z17.number().int().nonnegative(),
2885
+ at: z17.string()
2886
+ });
2887
+ var MessageImageDigestSchema = z17.object({
2758
2888
  /** The markdown ref exactly as it appears in the message body. */
2759
- ref: z16.string(),
2760
- sha256: z16.string().regex(/^[a-f0-9]{64}$/),
2889
+ ref: z17.string(),
2890
+ sha256: z17.string().regex(/^[a-f0-9]{64}$/),
2761
2891
  /** Pre-rendered, already capped and fenced-safe. */
2762
- digest: z16.string(),
2763
- modelId: z16.string(),
2764
- modes: z16.array(RecognitionModeSchema),
2765
- status: z16.enum(["ok", "partial", "failed", "static-only"]),
2766
- at: z16.string()
2892
+ digest: z17.string(),
2893
+ modelId: z17.string(),
2894
+ modes: z17.array(RecognitionModeSchema),
2895
+ status: z17.enum(["ok", "partial", "failed", "static-only"]),
2896
+ at: z17.string()
2767
2897
  });
2768
- var RecognitionRequestSchema = z16.object({
2898
+ var RecognitionRequestSchema = z17.object({
2769
2899
  /** Project-relative artifact path, e.g. `attachments/<uuid>.png`. */
2770
- artifactPath: z16.string().min(1).optional(),
2771
- data: z16.string().min(1).optional(),
2772
- mimeType: z16.string().optional(),
2900
+ artifactPath: z17.string().min(1).optional(),
2901
+ data: z17.string().min(1).optional(),
2902
+ mimeType: z17.string().optional(),
2773
2903
  mode: RecognitionModeRequestSchema.default("auto"),
2774
2904
  /** JSON Schema for `extract` mode — fed to llama-server `response_format`. */
2775
- schema: z16.unknown().optional(),
2905
+ schema: z17.unknown().optional(),
2776
2906
  /** Overrides the configured recognition model for this call. */
2777
- model: z16.string().optional()
2778
- });
2779
- var RecognitionHealthSchema = z16.object({
2780
- state: z16.enum(["ok", "no-model", "not-configured", "error"]),
2781
- modelId: z16.string().optional(),
2782
- detail: z16.string().optional()
2783
- });
2784
- var RecognitionPullEventSchema = z16.union([
2785
- z16.object({
2786
- type: z16.literal("progress"),
2787
- bytesWritten: z16.number().int().nonnegative(),
2788
- totalBytes: z16.number().int().nonnegative().optional()
2907
+ model: z17.string().optional()
2908
+ });
2909
+ var RecognitionHealthSchema = z17.object({
2910
+ state: z17.enum(["ok", "no-model", "not-configured", "error"]),
2911
+ modelId: z17.string().optional(),
2912
+ detail: z17.string().optional()
2913
+ });
2914
+ var RecognitionPullEventSchema = z17.union([
2915
+ z17.object({
2916
+ type: z17.literal("progress"),
2917
+ bytesWritten: z17.number().int().nonnegative(),
2918
+ totalBytes: z17.number().int().nonnegative().optional()
2789
2919
  }),
2790
- z16.object({ type: z16.literal("error"), error: z16.string() }),
2791
- z16.object({ type: z16.literal("done"), id: z16.string() })
2920
+ z17.object({ type: z17.literal("error"), error: z17.string() }),
2921
+ z17.object({ type: z17.literal("done"), id: z17.string() })
2792
2922
  ]);
2793
- var RecognitionCatalogEntrySchema = z16.object({
2794
- id: z16.string(),
2795
- name: z16.string(),
2796
- description: z16.string(),
2797
- license: z16.string(),
2798
- approxSizeBytes: z16.number().int().nonnegative(),
2799
- recoScore: z16.number()
2800
- });
2801
- var ListRecognitionCatalogResponseSchema = z16.object({
2802
- models: z16.array(RecognitionCatalogEntrySchema)
2803
- });
2804
- var InstalledRecognitionModelSchema = z16.object({
2805
- id: z16.string(),
2806
- name: z16.string(),
2807
- approxSizeBytes: z16.number().int().nonnegative(),
2808
- installedAt: z16.string(),
2809
- weightsPath: z16.string().optional(),
2810
- mmprojPath: z16.string().optional()
2811
- });
2812
- var ListInstalledRecognitionModelsResponseSchema = z16.object({
2813
- models: z16.array(InstalledRecognitionModelSchema)
2923
+ var RecognitionCatalogEntrySchema = z17.object({
2924
+ id: z17.string(),
2925
+ name: z17.string(),
2926
+ description: z17.string(),
2927
+ license: z17.string(),
2928
+ approxSizeBytes: z17.number().int().nonnegative(),
2929
+ recoScore: z17.number()
2930
+ });
2931
+ var ListRecognitionCatalogResponseSchema = z17.object({
2932
+ models: z17.array(RecognitionCatalogEntrySchema)
2933
+ });
2934
+ var InstalledRecognitionModelSchema = z17.object({
2935
+ id: z17.string(),
2936
+ name: z17.string(),
2937
+ approxSizeBytes: z17.number().int().nonnegative(),
2938
+ installedAt: z17.string(),
2939
+ weightsPath: z17.string().optional(),
2940
+ mmprojPath: z17.string().optional()
2941
+ });
2942
+ var ListInstalledRecognitionModelsResponseSchema = z17.object({
2943
+ models: z17.array(InstalledRecognitionModelSchema)
2814
2944
  });
2815
2945
 
2816
2946
  // src/schemas/session-lineage.ts
2817
- import { z as z17 } from "zod";
2818
- var SessionLinkSchema = z17.object({
2819
- sessionId: z17.string(),
2820
- gezelId: z17.string()
2947
+ import { z as z18 } from "zod";
2948
+ var SessionLinkSchema = z18.object({
2949
+ sessionId: z18.string(),
2950
+ gezelId: z18.string()
2821
2951
  });
2822
2952
  var SessionParentSchema = SessionLinkSchema.extend({
2823
- kind: z17.enum(["delegation", "consultation", "task-entry", "task-handoff"])
2953
+ kind: z18.enum(["delegation", "consultation", "task-entry", "task-handoff"])
2824
2954
  });
2825
2955
 
2826
2956
  // src/schemas/session-telemetry.ts
2827
- import { z as z18 } from "zod";
2828
- var SessionGpuTaskSchema = z18.enum([
2957
+ import { z as z19 } from "zod";
2958
+ var SessionGpuTaskSchema = z19.enum([
2829
2959
  "image_generation",
2830
2960
  "video_generation",
2831
2961
  "image_recognition"
2832
2962
  ]);
2833
- var SessionTurnPhaseSchema = z18.enum(["preparing", "recall", "provider"]);
2834
- var SessionTurnTelemetrySchema = z18.object({
2963
+ var SessionTurnPhaseSchema = z19.enum(["preparing", "recall", "provider"]);
2964
+ var SessionTurnTelemetrySchema = z19.object({
2835
2965
  /** Epoch ms when the in-flight turn started. */
2836
- startedAt: z18.number(),
2966
+ startedAt: z19.number(),
2837
2967
  phase: SessionTurnPhaseSchema,
2838
2968
  /** Epoch ms when `phase` last changed. */
2839
- phaseStartedAt: z18.number(),
2969
+ phaseStartedAt: z19.number(),
2840
2970
  /** Provider requests issued by this user-visible turn, including retries. */
2841
- providerRequestsStarted: z18.number().int().nonnegative(),
2842
- streamedContentChars: z18.number().int().nonnegative(),
2843
- toolCalls: z18.number().int().nonnegative(),
2844
- fileMutations: z18.number().int().nonnegative()
2971
+ providerRequestsStarted: z19.number().int().nonnegative(),
2972
+ streamedContentChars: z19.number().int().nonnegative(),
2973
+ toolCalls: z19.number().int().nonnegative(),
2974
+ fileMutations: z19.number().int().nonnegative()
2845
2975
  });
2846
- var SessionTelemetrySchema = z18.object({
2847
- sessionId: z18.string(),
2848
- gezelId: z18.string(),
2849
- projectId: z18.string(),
2976
+ var SessionTelemetrySchema = z19.object({
2977
+ sessionId: z19.string(),
2978
+ gezelId: z19.string(),
2979
+ projectId: z19.string(),
2850
2980
  /** True while a send is currently running for this session. */
2851
- inflight: z18.boolean(),
2852
- turnsStarted: z18.number().int().nonnegative(),
2981
+ inflight: z19.boolean(),
2982
+ turnsStarted: z19.number().int().nonnegative(),
2853
2983
  /** Provider requests issued across all turns in this daemon process. */
2854
- providerRequestsStarted: z18.number().int().nonnegative(),
2855
- deltaChunks: z18.number().int().nonnegative(),
2856
- streamedContentChars: z18.number().int().nonnegative(),
2857
- wirePulses: z18.number().int().nonnegative(),
2858
- heartbeats: z18.number().int().nonnegative(),
2859
- enginePhaseEvents: z18.number().int().nonnegative(),
2984
+ providerRequestsStarted: z19.number().int().nonnegative(),
2985
+ deltaChunks: z19.number().int().nonnegative(),
2986
+ streamedContentChars: z19.number().int().nonnegative(),
2987
+ wirePulses: z19.number().int().nonnegative(),
2988
+ heartbeats: z19.number().int().nonnegative(),
2989
+ enginePhaseEvents: z19.number().int().nonnegative(),
2860
2990
  /**
2861
2991
  * `engine_phase === 'generating'` transitions — roughly one per completion
2862
2992
  * request the engine served (the slot-launch granularity stall logic and
2863
2993
  * the eval chatter threshold were calibrated against).
2864
2994
  */
2865
- generationSpurts: z18.number().int().nonnegative(),
2866
- toolCalls: z18.number().int().nonnegative(),
2867
- toolArgChars: z18.number().int().nonnegative(),
2868
- fileMutations: z18.number().int().nonnegative(),
2869
- gpuEvents: z18.number().int().nonnegative(),
2995
+ generationSpurts: z19.number().int().nonnegative(),
2996
+ toolCalls: z19.number().int().nonnegative(),
2997
+ toolArgChars: z19.number().int().nonnegative(),
2998
+ fileMutations: z19.number().int().nonnegative(),
2999
+ gpuEvents: z19.number().int().nonnegative(),
2870
3000
  gpuTaskActive: SessionGpuTaskSchema.nullable(),
2871
3001
  /** Epoch ms of the last streamed signal (delta / pulse / heartbeat / phase). */
2872
- lastStreamActivityAt: z18.number().nullable(),
2873
- lastToolActivityAt: z18.number().nullable(),
2874
- lastMutationAt: z18.number().nullable(),
2875
- lastGpuActivityAt: z18.number().nullable(),
3002
+ lastStreamActivityAt: z19.number().nullable(),
3003
+ lastToolActivityAt: z19.number().nullable(),
3004
+ lastMutationAt: z19.number().nullable(),
3005
+ lastGpuActivityAt: z19.number().nullable(),
2876
3006
  /** Max of all activity timestamps — "when did ANY progress signal last fire". */
2877
- lastProgressAt: z18.number().nullable(),
3007
+ lastProgressAt: z19.number().nullable(),
2878
3008
  /** Counters scoped to the currently-running turn; null between turns. */
2879
3009
  currentTurn: SessionTurnTelemetrySchema.nullable()
2880
3010
  });
2881
- var SessionTelemetryListResponseSchema = z18.object({
3011
+ var SessionTelemetryListResponseSchema = z19.object({
2882
3012
  /** Bumped when counter semantics change; consumers gate on it. */
2883
- version: z18.literal(1),
2884
- capturedAt: z18.number(),
2885
- sessions: z18.array(SessionTelemetrySchema)
3013
+ version: z19.literal(1),
3014
+ capturedAt: z19.number(),
3015
+ sessions: z19.array(SessionTelemetrySchema)
2886
3016
  });
2887
3017
 
2888
3018
  // src/schemas/gezel.ts
2889
- var ProviderNameSchema = z19.enum([
3019
+ var ProviderNameSchema = z20.enum([
2890
3020
  "copilot",
2891
3021
  "openai",
2892
3022
  "anthropic",
@@ -2895,11 +3025,11 @@ var ProviderNameSchema = z19.enum([
2895
3025
  "ollama",
2896
3026
  "llama-cpp",
2897
3027
  "mlx",
2898
- // DwarfStar/ds4 — antirez's DeepSeek-V4-specific engine. Like llama-cpp/mlx
2899
- // it serves an OpenAI-compatible HTTP API from a supervised native binary,
2900
- // but it only loads antirez's DeepSeek-V4 GGUFs and streams MoE experts from
2901
- // SSD so a 284B model fits a 64GB Mac. GPU-only (Metal/CUDA); see the ds4
2902
- // provider for the availability gating.
3028
+ // DwarfStar/ds4 — antirez's specialized DeepSeek/GLM MoE engine. Like
3029
+ // llama-cpp/mlx it serves an OpenAI-compatible HTTP API from a supervised
3030
+ // native binary, but it only loads GGUF layouts the engine explicitly
3031
+ // supports. GPU-only (Metal/CUDA/ROCm upstream); see the ds4 provider for
3032
+ // Gezel's platform availability gating.
2903
3033
  "ds4",
2904
3034
  // Inference hosted on another paired gezel daemon ("remote models"). A
2905
3035
  // single enum arm fronts a family of paired servers; the specific server is
@@ -2908,27 +3038,27 @@ var ProviderNameSchema = z19.enum([
2908
3038
  // forward-pass is remoted — so `remote` is NOT a local provider.
2909
3039
  "remote"
2910
3040
  ]);
2911
- var GezelGenderSchema = z19.enum(["male", "female", "non-binary"]);
2912
- var FixedFunctionConfigSchema = z19.object({
3041
+ var GezelGenderSchema = z20.enum(["male", "female", "non-binary"]);
3042
+ var FixedFunctionConfigSchema = z20.object({
2913
3043
  /** MCP tool name to forward to (e.g. `'generate_image'`). */
2914
- tool: z19.string().min(1),
3044
+ tool: z20.string().min(1),
2915
3045
  /** Argument key on the tool that receives the user's message text. */
2916
- promptKey: z19.string().min(1).default("prompt"),
3046
+ promptKey: z20.string().min(1).default("prompt"),
2917
3047
  /** Defaults merged into every call; user text on `promptKey` always wins. */
2918
- defaults: z19.record(z19.string(), z19.unknown()).optional()
3048
+ defaults: z20.record(z20.string(), z20.unknown()).optional()
2919
3049
  });
2920
- var GezelTraitSchema = z19.object({
2921
- id: z19.string(),
3050
+ var GezelTraitSchema = z20.object({
3051
+ id: z20.string(),
2922
3052
  /** One imperative second-person sentence, rendered as a prompt bullet. */
2923
- text: z19.string().min(1).max(200),
2924
- adoptedAt: z19.string(),
2925
- source: z19.enum(["levelup", "manual"]).optional()
3053
+ text: z20.string().min(1).max(200),
3054
+ adoptedAt: z20.string(),
3055
+ source: z20.enum(["levelup", "manual"]).optional()
2926
3056
  });
2927
- var GezelFrontmatterSchema = z19.object({
3057
+ var GezelFrontmatterSchema = z20.object({
2928
3058
  id: EntityIdSchema.optional(),
2929
- name: z19.string(),
2930
- description: z19.string().optional(),
2931
- role: z19.string().optional(),
3059
+ name: z20.string(),
3060
+ description: z20.string().optional(),
3061
+ role: z20.string().optional(),
2932
3062
  /**
2933
3063
  * Kebab-case slug derived from `role` (or `gezel-N` when role is absent),
2934
3064
  * globally unique across the install. Collisions get `-2`, `-3`, …
@@ -2936,7 +3066,7 @@ var GezelFrontmatterSchema = z19.object({
2936
3066
  * identifier for @-mentions and as the sole rendered identifier when
2937
3067
  * `config.roleBasedNameOnlyMode` is enabled.
2938
3068
  */
2939
- roleBasedName: z19.string().optional(),
3069
+ roleBasedName: z20.string().optional(),
2940
3070
  /**
2941
3071
  * One of `male` / `female` / `non-binary`. Assigned at creation time
2942
3072
  * from the matching gendered first-name pool (with a small chance of
@@ -2945,9 +3075,9 @@ var GezelFrontmatterSchema = z19.object({
2945
3075
  * own prompt. Absent on legacy gezels, where references omit pronouns.
2946
3076
  */
2947
3077
  gender: GezelGenderSchema.optional(),
2948
- model: z19.string().optional(),
3078
+ model: z20.string().optional(),
2949
3079
  provider: ProviderNameSchema.optional(),
2950
- reasoningEffort: z19.string().optional(),
3080
+ reasoningEffort: z20.string().optional(),
2951
3081
  /**
2952
3082
  * Per-gezel sampling / reasoning / structured-output / tool-call overrides.
2953
3083
  * Sparse — only set fields override the catalog's recommended defaults.
@@ -2980,8 +3110,8 @@ var GezelFrontmatterSchema = z19.object({
2980
3110
  * low-temperature `thinking-precise` without locking the user out.
2981
3111
  */
2982
3112
  suggestedTuningProfile: TuningProfileIdSchema.optional(),
2983
- tools: z19.array(z19.string()).optional(),
2984
- tags: z19.array(z19.string()).optional(),
3113
+ tools: z20.array(z20.string()).optional(),
3114
+ tags: z20.array(z20.string()).optional(),
2985
3115
  /**
2986
3116
  * When set, switches this gezel into "fixed-function" mode: chat
2987
3117
  * messages bypass the LLM and forward to the named MCP tool. See
@@ -2991,9 +3121,9 @@ var GezelFrontmatterSchema = z19.object({
2991
3121
  */
2992
3122
  fixedFunction: FixedFunctionConfigSchema.optional(),
2993
3123
  /** Ollama-only: override the context window (tokens) for this gezel. */
2994
- numCtx: z19.number().int().positive().optional(),
3124
+ numCtx: z20.number().int().positive().optional(),
2995
3125
  /** When false, suppresses auto-recall on session start for this gezel. */
2996
- autoRecall: z19.boolean().optional(),
3126
+ autoRecall: z20.boolean().optional(),
2997
3127
  /**
2998
3128
  * Per-gezel proactive indexed-context policy. Supersedes `autoRecall` when
2999
3129
  * present; absent inherits the install default. The generic `search` tool is
@@ -3004,7 +3134,7 @@ var GezelFrontmatterSchema = z19.object({
3004
3134
  * Chat bubble font id (one of `GEZEL_CHAT_FONTS[*].id`). When unset or
3005
3135
  * unrecognized, chat bubbles inherit the app default (Hanken Grotesk).
3006
3136
  */
3007
- font: z19.string().optional(),
3137
+ font: z20.string().optional(),
3008
3138
  /**
3009
3139
  * Kokoro TTS voice id (one of `KOKORO_VOICES[*].id`, e.g. `af_heart`,
3010
3140
  * `bm_george`). Drives spoken audio rendering — `synthesize_speech`
@@ -3013,7 +3143,7 @@ var GezelFrontmatterSchema = z19.object({
3013
3143
  * dialog. Absent on legacy gezels — synthesize falls back to the
3014
3144
  * default voice (`af_heart`) when missing.
3015
3145
  */
3016
- voice: z19.string().optional(),
3146
+ voice: z20.string().optional(),
3017
3147
  /**
3018
3148
  * Provenance: the id of the gilde catalog template this gezel was
3019
3149
  * created from, if any. Written by exact-template or about-omitted
@@ -3021,7 +3151,7 @@ var GezelFrontmatterSchema = z19.object({
3021
3151
  * Absent on bespoke-generated or hand-authored gezels. The UI uses
3022
3152
  * this to offer "reset to original template" on the about editor.
3023
3153
  */
3024
- templateId: z19.string().optional(),
3154
+ templateId: z20.string().optional(),
3025
3155
  /**
3026
3156
  * Provenance: the semver of the template version installed at create
3027
3157
  * time. Paired with `templateId`. Absent on gezels created before this
@@ -3029,7 +3159,7 @@ var GezelFrontmatterSchema = z19.object({
3029
3159
  * source version" and offers a refresh to current latest without
3030
3160
  * comparing.
3031
3161
  */
3032
- templateVersion: z19.string().optional(),
3162
+ templateVersion: z20.string().optional(),
3033
3163
  /**
3034
3164
  * Copilot-only: when true, deny the Copilot CLI's built-in tools
3035
3165
  * (bash, web_fetch, view, str_replace_editor, read_file, write_file,
@@ -3038,7 +3168,7 @@ var GezelFrontmatterSchema = z19.object({
3038
3168
  * itself defaults to the sandboxed MCP surface.
3039
3169
  * Provider other than copilot: ignored.
3040
3170
  */
3041
- sandboxCopilot: z19.boolean().optional(),
3171
+ sandboxCopilot: z20.boolean().optional(),
3042
3172
  /**
3043
3173
  * `anthropic-cli`-only: per-gezel override for the Claude CLI permission
3044
3174
  * mode. Forwarded as `--permission-mode <value>` to each `claude` invocation.
@@ -3064,7 +3194,7 @@ var GezelFrontmatterSchema = z19.object({
3064
3194
  * abstract sigil instead of the parametric poppetje. Default (absent /
3065
3195
  * false) renders the poppetje everywhere. Toggled from Gezel Detail.
3066
3196
  */
3067
- iconOverride: z19.boolean().optional(),
3197
+ iconOverride: z20.boolean().optional(),
3068
3198
  /**
3069
3199
  * Standing behavior traits, adopted through the growth system (or
3070
3200
  * hand-authored). Rendered as their own `### Traits` block in the
@@ -3073,7 +3203,7 @@ var GezelFrontmatterSchema = z19.object({
3073
3203
  * The frontmatter list is AUTHORITATIVE for what's active — growth.json
3074
3204
  * keeps the evidence-bearing adoption log.
3075
3205
  */
3076
- traits: z19.array(GezelTraitSchema).max(8).optional(),
3206
+ traits: z20.array(GezelTraitSchema).max(8).optional(),
3077
3207
  /**
3078
3208
  * Overrides `config.recognition.mode` for this gezel. A gezel whose job is
3079
3209
  * reading screenshots sets `always`; everyone else inherits.
@@ -3083,48 +3213,48 @@ var GezelFrontmatterSchema = z19.object({
3083
3213
  * support burden. Native vision is a property of the model *install*, not of
3084
3214
  * the gezel, so it has no frontmatter counterpart.
3085
3215
  */
3086
- recognition: z19.enum(["auto", "always", "off"]).optional()
3216
+ recognition: z20.enum(["auto", "always", "off"]).optional()
3087
3217
  });
3088
- var GezelSectionSchema = z19.object({
3089
- heading: z19.string(),
3090
- template: z19.string().optional(),
3091
- params: z19.record(z19.string(), z19.string()).optional(),
3092
- body: z19.string()
3218
+ var GezelSectionSchema = z20.object({
3219
+ heading: z20.string(),
3220
+ template: z20.string().optional(),
3221
+ params: z20.record(z20.string(), z20.string()).optional(),
3222
+ body: z20.string()
3093
3223
  });
3094
- var ParsedGezelSchema = z19.object({
3224
+ var ParsedGezelSchema = z20.object({
3095
3225
  frontmatter: GezelFrontmatterSchema,
3096
- sections: z19.array(GezelSectionSchema),
3097
- source: z19.string()
3226
+ sections: z20.array(GezelSectionSchema),
3227
+ source: z20.string()
3098
3228
  });
3099
- var GezelSummarySchema = z19.object({
3229
+ var GezelSummarySchema = z20.object({
3100
3230
  id: EntityIdSchema,
3101
- name: z19.string(),
3102
- description: z19.string().optional(),
3103
- role: z19.string().optional(),
3231
+ name: z20.string(),
3232
+ description: z20.string().optional(),
3233
+ role: z20.string().optional(),
3104
3234
  /** Mirrors `GezelFrontmatter.roleBasedName`. */
3105
- roleBasedName: z19.string().optional(),
3235
+ roleBasedName: z20.string().optional(),
3106
3236
  /** Mirrors `GezelFrontmatter.gender`. */
3107
3237
  gender: GezelGenderSchema.optional(),
3108
- model: z19.string().optional(),
3238
+ model: z20.string().optional(),
3109
3239
  provider: ProviderNameSchema.optional(),
3110
- reasoningEffort: z19.string().optional(),
3240
+ reasoningEffort: z20.string().optional(),
3111
3241
  /** Mirrors `GezelFrontmatter.tuningProfile`. */
3112
3242
  tuningProfile: TuningProfileIdSchema.optional(),
3113
3243
  /** Mirrors `GezelFrontmatter.suggestedTuningProfile`. */
3114
3244
  suggestedTuningProfile: TuningProfileIdSchema.optional(),
3115
- numCtx: z19.number().int().positive().optional(),
3116
- autoRecall: z19.boolean().optional(),
3245
+ numCtx: z20.number().int().positive().optional(),
3246
+ autoRecall: z20.boolean().optional(),
3117
3247
  /** Mirrors `GezelFrontmatter.retrieval`. */
3118
3248
  retrieval: RetrievalPolicySchema.optional(),
3119
- font: z19.string().optional(),
3249
+ font: z20.string().optional(),
3120
3250
  /** Mirrors `GezelFrontmatter.voice` — Kokoro TTS voice id. */
3121
- voice: z19.string().optional(),
3251
+ voice: z20.string().optional(),
3122
3252
  /** Mirrors `GezelFrontmatter.templateId` when the gezel came from a gilde template. */
3123
- templateId: z19.string().optional(),
3253
+ templateId: z20.string().optional(),
3124
3254
  /** Mirrors `GezelFrontmatter.templateVersion`. */
3125
- templateVersion: z19.string().optional(),
3255
+ templateVersion: z20.string().optional(),
3126
3256
  /** Mirrors `GezelFrontmatter.sandboxCopilot`. */
3127
- sandboxCopilot: z19.boolean().optional(),
3257
+ sandboxCopilot: z20.boolean().optional(),
3128
3258
  /** Mirrors `GezelFrontmatter.claudePermissionMode`. */
3129
3259
  claudePermissionMode: ClaudePermissionModeSchema.optional(),
3130
3260
  /** Mirrors `GezelFrontmatter.codexPermissionMode`. */
@@ -3137,7 +3267,7 @@ var GezelSummarySchema = z19.object({
3137
3267
  * affordance.
3138
3268
  */
3139
3269
  fixedFunction: FixedFunctionConfigSchema.optional(),
3140
- icon: z19.string().optional(),
3270
+ icon: z20.string().optional(),
3141
3271
  /**
3142
3272
  * The resolved poppetje character data for this gezel. Inlined on
3143
3273
  * every list/detail response so the UI can render the parametric SVG
@@ -3147,9 +3277,9 @@ var GezelSummarySchema = z19.object({
3147
3277
  */
3148
3278
  poppetje: PoppetjeSchema.optional(),
3149
3279
  /** Mirrors `GezelFrontmatter.iconOverride`. */
3150
- iconOverride: z19.boolean().optional(),
3280
+ iconOverride: z20.boolean().optional(),
3151
3281
  /** Mirrors `GezelFrontmatter.recognition`. */
3152
- recognition: z19.enum(["auto", "always", "off"]).optional(),
3282
+ recognition: z20.enum(["auto", "always", "off"]).optional(),
3153
3283
  /**
3154
3284
  * Where this gezel lives. `global` (the default when absent — back-compat
3155
3285
  * with every gezel on disk before this field existed) is the install-wide
@@ -3159,15 +3289,15 @@ var GezelSummarySchema = z19.object({
3159
3289
  * badges project-scoped gezels and the roster only surfaces them inside
3160
3290
  * their own project.
3161
3291
  */
3162
- scope: z19.enum(["global", "project"]).optional(),
3292
+ scope: z20.enum(["global", "project"]).optional(),
3163
3293
  /**
3164
3294
  * Filesystem ownership boundary, distinct from `scope` above. Shared gezel
3165
3295
  * identity lives in the installer-managed machine root; chats, memories,
3166
3296
  * growth, credentials, and installed toolsets remain in the user home.
3167
3297
  */
3168
- storageScope: z19.enum(["user", "machine-shared"]).optional(),
3298
+ storageScope: z20.enum(["user", "machine-shared"]).optional(),
3169
3299
  /** Mirrors `GezelFrontmatter.traits`. */
3170
- traits: z19.array(GezelTraitSchema).optional(),
3300
+ traits: z20.array(GezelTraitSchema).optional(),
3171
3301
  /**
3172
3302
  * Lightweight growth summary (level + pending level-up flag),
3173
3303
  * hydrated from growth.json and inlined on list/detail responses —
@@ -3175,11 +3305,11 @@ var GezelSummarySchema = z19.object({
3175
3305
  * without N+1 follow-up requests.
3176
3306
  */
3177
3307
  growth: GezelGrowthSummarySchema.optional(),
3178
- updatedAt: z19.string()
3308
+ updatedAt: z20.string()
3179
3309
  });
3180
3310
  var GezelDetailSchema = GezelSummarySchema.extend({
3181
3311
  parsed: ParsedGezelSchema,
3182
- about: z19.string(),
3312
+ about: z20.string(),
3183
3313
  /**
3184
3314
  * Optional contents of the per-gezel `tools.md` file. When present
3185
3315
  * (non-null), fully replaces the auto-injected `## Tools available
@@ -3189,87 +3319,95 @@ var GezelDetailSchema = GezelSummarySchema.extend({
3189
3319
  * default) means no override file exists and the runtime renders
3190
3320
  * the auto-block from the live MCP bridge.
3191
3321
  */
3192
- toolsMd: z19.string().nullable().default(null)
3322
+ toolsMd: z20.string().nullable().default(null)
3193
3323
  });
3194
- var ToolCallImageSchema = z19.object({
3324
+ var ToolCallImageSchema = z20.object({
3195
3325
  /** Path relative to the project's artifacts/ root (e.g. `sessions/2026-04-19_143015_snake-test/tool-3-img-0.png`). */
3196
- path: z19.string(),
3326
+ path: z20.string(),
3197
3327
  /** MIME type of the image, used by the UI to set the right `<img>` src URL. */
3198
- mimeType: z19.string()
3328
+ mimeType: z20.string()
3199
3329
  });
3200
- var ToolCallAudioSchema = z19.object({
3330
+ var ToolCallAudioSchema = z20.object({
3201
3331
  /** Path relative to the project's artifacts/ root. */
3202
- path: z19.string(),
3332
+ path: z20.string(),
3203
3333
  /** MIME type, e.g. `audio/wav`. */
3204
- mimeType: z19.string(),
3334
+ mimeType: z20.string(),
3205
3335
  /** Duration in seconds when known — used by the UI to show length without preloading the blob. */
3206
- durationSeconds: z19.number().optional(),
3336
+ durationSeconds: z20.number().optional(),
3207
3337
  /** Voice id used to produce this audio (TTS only). */
3208
- voice: z19.string().optional()
3338
+ voice: z20.string().optional()
3209
3339
  });
3210
- var ToolCallVideoSchema = z19.object({
3340
+ var ToolCallVideoSchema = z20.object({
3211
3341
  /** Path relative to the project's artifacts/ root (e.g. `generated/video-123.mp4`). */
3212
- path: z19.string(),
3342
+ path: z20.string(),
3213
3343
  /** MIME type, e.g. `video/mp4`. */
3214
- mimeType: z19.string(),
3344
+ mimeType: z20.string(),
3215
3345
  /** Optional poster-frame artifact path for the `<video poster>` attribute. */
3216
- posterPath: z19.string().optional()
3346
+ posterPath: z20.string().optional()
3217
3347
  });
3218
- var ToolCardStepSchema = z19.object({
3219
- id: z19.string(),
3220
- name: z19.string(),
3221
- status: z19.enum(["done", "active", "pending"])
3348
+ var ToolCardStepSchema = z20.object({
3349
+ id: z20.string(),
3350
+ name: z20.string(),
3351
+ status: z20.enum(["done", "active", "pending"])
3222
3352
  });
3223
- var CraftbookStartCardSchema = z19.object({
3224
- kind: z19.literal("craftbook-start"),
3225
- craftbookId: z19.string(),
3226
- craftbookName: z19.string(),
3353
+ var CraftbookStartCardSchema = z20.object({
3354
+ kind: z20.literal("craftbook-start"),
3355
+ craftbookId: z20.string(),
3356
+ craftbookName: z20.string(),
3227
3357
  /** Task ref `projectId/num`. */
3228
- taskRef: z19.string(),
3358
+ taskRef: z20.string(),
3229
3359
  /** The TASK's project — may differ from the session's when invoked cross-project. */
3230
- projectId: z19.string(),
3360
+ projectId: z20.string(),
3231
3361
  /** Task status at event time. */
3232
- status: z19.string(),
3233
- activeStepId: z19.string().optional(),
3234
- steps: z19.array(ToolCardStepSchema),
3362
+ status: z20.string(),
3363
+ activeStepId: z20.string().optional(),
3364
+ steps: z20.array(ToolCardStepSchema),
3235
3365
  /** True when the call idempotently returned an already-running task. */
3236
- reused: z19.boolean().optional(),
3366
+ reused: z20.boolean().optional(),
3237
3367
  /**
3238
3368
  * The craftbook declares it works better with the External services
3239
3369
  * capability. The UI nudges (with the optional author rationale) only
3240
3370
  * while the resolved security policy has it disabled.
3241
3371
  */
3242
- recommendsExternalServices: z19.object({ reason: z19.string().optional() }).optional()
3243
- });
3244
- var TaskStepAdvanceCardSchema = z19.object({
3245
- kind: z19.literal("task-step-advance"),
3246
- craftbookId: z19.string(),
3247
- craftbookName: z19.string(),
3248
- taskRef: z19.string(),
3249
- projectId: z19.string(),
3250
- status: z19.string(),
3251
- completedStepId: z19.string(),
3252
- completedStepName: z19.string().optional(),
3372
+ recommendsExternalServices: z20.object({ reason: z20.string().optional() }).optional()
3373
+ });
3374
+ var TaskStepAdvanceCardSchema = z20.object({
3375
+ kind: z20.literal("task-step-advance"),
3376
+ craftbookId: z20.string(),
3377
+ craftbookName: z20.string(),
3378
+ taskRef: z20.string(),
3379
+ projectId: z20.string(),
3380
+ status: z20.string(),
3381
+ completedStepId: z20.string(),
3382
+ completedStepName: z20.string().optional(),
3253
3383
  /** Absent when the advance took the task terminal (complete/canceled). */
3254
- activeStepId: z19.string().optional(),
3255
- activeStepName: z19.string().optional(),
3256
- steps: z19.array(ToolCardStepSchema)
3384
+ activeStepId: z20.string().optional(),
3385
+ activeStepName: z20.string().optional(),
3386
+ steps: z20.array(ToolCardStepSchema)
3257
3387
  });
3258
- var ToolCallCardSchema = z19.discriminatedUnion("kind", [
3388
+ var ToolCallCardSchema = z20.discriminatedUnion("kind", [
3259
3389
  CraftbookStartCardSchema,
3260
3390
  TaskStepAdvanceCardSchema
3261
3391
  ]);
3262
- var ChatMessageToolCallSchema = z19.object({
3263
- name: z19.string(),
3264
- durationMs: z19.number(),
3265
- success: z19.boolean(),
3266
- errorMessage: z19.string().optional(),
3392
+ var ChatMessageToolCallSchema = z20.object({
3393
+ name: z20.string(),
3394
+ /**
3395
+ * ISO timestamp of the call's START. Optional: absent on every message
3396
+ * persisted before this field existed, so readers must not assume it.
3397
+ * End time derives as `at + durationMs`. This is what gives replay
3398
+ * (run recordings, the eval movie pipeline) intra-turn ordering with
3399
+ * absolute time — array order alone cannot place calls on a timeline.
3400
+ */
3401
+ at: z20.string().optional(),
3402
+ durationMs: z20.number(),
3403
+ success: z20.boolean(),
3404
+ errorMessage: z20.string().optional(),
3267
3405
  /** File path the tool touched, for the References pane. */
3268
- path: z19.string().optional(),
3406
+ path: z20.string().optional(),
3269
3407
  /** Ordered file paths touched by a batched filesystem tool. */
3270
- paths: z19.array(z19.string()).optional(),
3408
+ paths: z20.array(z20.string()).optional(),
3271
3409
  /** Compact, human-readable one-liner ("→ Freja: update the game loop · file: workspace/index.html"). */
3272
- argsSummary: z19.string().optional(),
3410
+ argsSummary: z20.string().optional(),
3273
3411
  /**
3274
3412
  * The tool call's FULL arguments, rendered as readable text (field by
3275
3413
  * field, bulky values shown in full — not truncated like
@@ -3280,26 +3418,26 @@ var ChatMessageToolCallSchema = z19.object({
3280
3418
  * arguments are not a secret vector in this codebase (secrets live in
3281
3419
  * the toolset-config path), so this is not separately redacted.
3282
3420
  */
3283
- argsFull: z19.string().optional(),
3421
+ argsFull: z20.string().optional(),
3284
3422
  /** Short full response, or a bounded beginning/end summary for a long response. */
3285
- resultText: z19.string().optional(),
3423
+ resultText: z20.string().optional(),
3286
3424
  /** True when `resultText` is a bounded summary rather than the complete response. */
3287
- resultTruncated: z19.boolean().optional(),
3425
+ resultTruncated: z20.boolean().optional(),
3288
3426
  /** Image artifacts the tool returned (e.g. browser_snapshot screenshots). */
3289
- images: z19.array(ToolCallImageSchema).optional(),
3427
+ images: z20.array(ToolCallImageSchema).optional(),
3290
3428
  /** Audio artifacts the tool returned (e.g. synthesize_speech WAV). */
3291
- audios: z19.array(ToolCallAudioSchema).optional(),
3429
+ audios: z20.array(ToolCallAudioSchema).optional(),
3292
3430
  /** Video artifacts the tool returned (e.g. generate_video mp4). */
3293
- videos: z19.array(ToolCallVideoSchema).optional(),
3431
+ videos: z20.array(ToolCallVideoSchema).optional(),
3294
3432
  /**
3295
3433
  * Unified diff describing the change a surgical-edit tool made
3296
3434
  * (`replace_in_file`, `apply_patch`, `insert_at_marker`). Used by the UI
3297
3435
  * to render an inline diff under the tool-call row. Capped at ~100KB
3298
3436
  * server-side; larger diffs are truncated with a marker line.
3299
3437
  */
3300
- diff: z19.string().optional(),
3301
- addedLines: z19.number().int().nonnegative().optional(),
3302
- removedLines: z19.number().int().nonnegative().optional(),
3438
+ diff: z20.string().optional(),
3439
+ addedLines: z20.number().int().nonnegative().optional(),
3440
+ removedLines: z20.number().int().nonnegative().optional(),
3303
3441
  /** Rich inline card payload for tools with special renderings — see ToolCallCardSchema. */
3304
3442
  card: ToolCallCardSchema.optional(),
3305
3443
  /**
@@ -3322,35 +3460,53 @@ var ChatMessageToolCallSchema = z19.object({
3322
3460
  * message written before this field existed — the expander then
3323
3461
  * renders the plain trace it always did.
3324
3462
  */
3325
- afterReasoningChars: z19.number().int().min(0).optional()
3463
+ afterReasoningChars: z20.number().int().min(0).optional()
3326
3464
  });
3327
- var ChatSessionSourceSchema = z19.object({
3328
- kind: z19.literal("external"),
3465
+ var ChatSessionSourceSchema = z20.object({
3466
+ kind: z20.literal("external"),
3329
3467
  /** Stable integration id, e.g. `pi`. */
3330
- appId: z19.string().min(1),
3468
+ appId: z20.string().min(1),
3331
3469
  /** Human-facing application name, e.g. `Pi`. */
3332
- appName: z19.string().min(1),
3470
+ appName: z20.string().min(1),
3333
3471
  /** The external application's stable conversation/session identifier. */
3334
- externalConversationId: z19.string().min(1),
3472
+ externalConversationId: z20.string().min(1),
3335
3473
  /** External threads are ledger views; the owning app controls replies. */
3336
- readOnly: z19.literal(true),
3474
+ readOnly: z20.literal(true),
3337
3475
  /** Working-directory hint supplied by the external app, when available. */
3338
- workingDirectory: z19.string().optional(),
3476
+ workingDirectory: z20.string().optional(),
3339
3477
  /** Project id/name hint supplied by the external app, when available. */
3340
- projectHint: z19.string().optional()
3478
+ projectHint: z20.string().optional()
3341
3479
  });
3342
- var ReferencedFileKindSchema = z19.enum(["artifact", "workspace"]);
3343
- var ReferencedFileSchema = z19.object({
3480
+ var ReferencedFileKindSchema = z20.enum(["artifact", "workspace"]);
3481
+ var ReferencedFileSchema = z20.object({
3344
3482
  kind: ReferencedFileKindSchema,
3345
- path: z19.string()
3346
- });
3347
- var ChatMessageSchema = z19.object({
3348
- role: z19.enum(["user", "assistant"]),
3349
- content: z19.string(),
3350
- at: z19.string(),
3351
- from: z19.object({
3352
- gezelId: z19.string(),
3353
- gezelName: z19.string()
3483
+ path: z20.string()
3484
+ });
3485
+ var ContextCompactionSchema = z20.object({
3486
+ removedCount: z20.number().int().nonnegative(),
3487
+ contextWindow: z20.number().int().positive(),
3488
+ estimatedTokensBefore: z20.number().int().nonnegative(),
3489
+ compactionCount: z20.number().int().positive(),
3490
+ autoCompactRatio: z20.number().positive().max(1)
3491
+ });
3492
+ var ChatMessageSchema = z20.object({
3493
+ role: z20.enum(["user", "assistant"]),
3494
+ content: z20.string(),
3495
+ at: z20.string(),
3496
+ from: z20.object({
3497
+ gezelId: z20.string(),
3498
+ gezelName: z20.string(),
3499
+ /**
3500
+ * The SENDER's session id — the durable per-edge record of which
3501
+ * thread this message came from. `session.parentSession` only says
3502
+ * which session first opened the thread (stable containment);
3503
+ * this field is the ground truth for every individual delegation
3504
+ * edge, including later senders into an existing session. Optional:
3505
+ * absent on messages persisted before the field existed.
3506
+ */
3507
+ sessionId: z20.string().optional(),
3508
+ /** How the sender reached this session; mirrors SessionParent.kind. */
3509
+ kind: z20.enum(["delegation", "consultation", "task-entry", "task-handoff"]).optional()
3354
3510
  }).optional(),
3355
3511
  /**
3356
3512
  * Real files the assistant reply named in its body text — artifacts
@@ -3360,7 +3516,7 @@ var ChatMessageSchema = z19.object({
3360
3516
  * match a real file. Back-stops Copilot's tool-call blindspot and any
3361
3517
  * "AI wrote a file outside the MCP tools" path.
3362
3518
  */
3363
- referencedFiles: z19.array(ReferencedFileSchema).optional(),
3519
+ referencedFiles: z20.array(ReferencedFileSchema).optional(),
3364
3520
  /**
3365
3521
  * The artifact-only projection of {@link referencedFiles}, still
3366
3522
  * written so an older `@bendyline/gezel-cli` (or any out-of-tree
@@ -3370,7 +3526,7 @@ var ChatMessageSchema = z19.object({
3370
3526
  *
3371
3527
  * @deprecated superseded by `referencedFiles`
3372
3528
  */
3373
- referencedArtifacts: z19.array(z19.string()).optional(),
3529
+ referencedArtifacts: z20.array(z20.string()).optional(),
3374
3530
  /**
3375
3531
  * Task refs (`<projectId>/<num>`) the assistant reply mentioned. Same
3376
3532
  * shape as `referencedFiles` — populated on save, gated on the
@@ -3379,7 +3535,7 @@ var ChatMessageSchema = z19.object({
3379
3535
  * gezel-ux-roadmap/2" mention so the user can jump to it without
3380
3536
  * scrolling the body for the ref.
3381
3537
  */
3382
- referencedTasks: z19.array(z19.string()).optional(),
3538
+ referencedTasks: z20.array(z20.string()).optional(),
3383
3539
  /**
3384
3540
  * Indexed-context sources consulted for THIS user turn (proactive
3385
3541
  * retrieval). Citations only — source/path/line/score, never the retrieved
@@ -3387,15 +3543,15 @@ var ChatMessageSchema = z19.object({
3387
3543
  * "consulted N sources" row so proactive RAG is visible diligence instead
3388
3544
  * of invisible machinery.
3389
3545
  */
3390
- retrieval: z19.object({
3391
- hits: z19.array(
3392
- z19.object({
3546
+ retrieval: z20.object({
3547
+ hits: z20.array(
3548
+ z20.object({
3393
3549
  source: RetrievalSourceSchema,
3394
- projectId: z19.string().optional(),
3395
- path: z19.string().optional(),
3396
- line: z19.number().int().positive().optional(),
3397
- lineEnd: z19.number().int().positive().optional(),
3398
- score: z19.number()
3550
+ projectId: z20.string().optional(),
3551
+ path: z20.string().optional(),
3552
+ line: z20.number().int().positive().optional(),
3553
+ lineEnd: z20.number().int().positive().optional(),
3554
+ score: z20.number()
3399
3555
  })
3400
3556
  )
3401
3557
  }).optional(),
@@ -3405,7 +3561,7 @@ var ChatMessageSchema = z19.object({
3405
3561
  * "thinking" expando above the reply body so the user can still see
3406
3562
  * what ran even after the live stream has closed.
3407
3563
  */
3408
- toolCalls: z19.array(ChatMessageToolCallSchema).optional(),
3564
+ toolCalls: z20.array(ChatMessageToolCallSchema).optional(),
3409
3565
  /**
3410
3566
  * Phase announcements the model emitted via Copilot's `report_intent`
3411
3567
  * tool during this turn. Each entry carries the intent label and an
@@ -3416,10 +3572,10 @@ var ChatMessageSchema = z19.object({
3416
3572
  * replay and history export are unaffected. Copilot-only; other
3417
3573
  * providers don't emit these.
3418
3574
  */
3419
- intents: z19.array(
3420
- z19.object({
3421
- label: z19.string(),
3422
- afterChars: z19.number().int().min(0)
3575
+ intents: z20.array(
3576
+ z20.object({
3577
+ label: z20.string(),
3578
+ afterChars: z20.number().int().min(0)
3423
3579
  })
3424
3580
  ).optional(),
3425
3581
  /**
@@ -3429,7 +3585,7 @@ var ChatMessageSchema = z19.object({
3429
3585
  * itself lives in the per-project questions file; this id is just
3430
3586
  * the foreign key.
3431
3587
  */
3432
- pendingQuestionId: z19.string().optional(),
3588
+ pendingQuestionId: z20.string().optional(),
3433
3589
  /**
3434
3590
  * Marks the message as a system-generated synthesis rather than a real
3435
3591
  * model turn.
@@ -3458,13 +3614,20 @@ var ChatMessageSchema = z19.object({
3458
3614
  * UI renders these as muted bubbles; the model sees them as normal
3459
3615
  * assistant turns (the role label is what matters to the API).
3460
3616
  */
3461
- synthetic: z19.enum([
3617
+ synthetic: z20.enum([
3462
3618
  "compaction-summary",
3463
3619
  "context-loop-halt",
3464
3620
  "turn-aborted",
3465
3621
  "growth-announcement",
3466
3622
  "keurmeester-notice"
3467
3623
  ]).optional(),
3624
+ /**
3625
+ * Present on a synthetic `compaction-summary` message. The UI renders this
3626
+ * as an explicit context-maintenance marker (including the effective token
3627
+ * window and number of messages summarized) rather than pretending it was
3628
+ * an ordinary assistant reply.
3629
+ */
3630
+ contextCompaction: ContextCompactionSchema.optional(),
3468
3631
  /**
3469
3632
  * Display flag: the model sees this message as normal history, but the
3470
3633
  * chat transcript UI never renders a bubble for it. Set on
@@ -3476,7 +3639,7 @@ var ChatMessageSchema = z19.object({
3476
3639
  * from loaded transcripts and the live-timeline handler skips its bubble
3477
3640
  * while still opening the assistant's streaming slot.
3478
3641
  */
3479
- hidden: z19.boolean().optional(),
3642
+ hidden: z20.boolean().optional(),
3480
3643
  /**
3481
3644
  * This user message was delivered from the session's mid-turn queue
3482
3645
  * as a nudge — typed while the previous turn was still streaming and
@@ -3484,7 +3647,14 @@ var ChatMessageSchema = z19.object({
3484
3647
  * Display-only marker: the model sees a normal user turn; the UI
3485
3648
  * renders a small "nudged" chip on the bubble.
3486
3649
  */
3487
- nudge: z19.boolean().optional(),
3650
+ nudge: z20.boolean().optional(),
3651
+ /**
3652
+ * The prompt draft (`artifacts/prompts/<draftId>/`) this user message was
3653
+ * sent from. Display-only: the model never sees it, and the draft may since
3654
+ * have been swept, so the UI must treat a dangling id as "no prompt to
3655
+ * open" rather than an error.
3656
+ */
3657
+ draftId: z20.string().optional(),
3488
3658
  /**
3489
3659
  * The machinery — not the human — authored this `role: 'user'` message.
3490
3660
  * Task dispatch seeds, step handoffs, and project-page reaction seeds
@@ -3503,7 +3673,7 @@ var ChatMessageSchema = z19.object({
3503
3673
  * widen it without a second field. Messages written before this field
3504
3674
  * existed are inferred at read time — see `Store.listTimeline`.
3505
3675
  */
3506
- origin: z19.enum(["system"]).optional(),
3676
+ origin: z20.enum(["system"]).optional(),
3507
3677
  /**
3508
3678
  * Persistent warnings attached to this assistant turn — fabricated
3509
3679
  * tool-use detection, degraded provider state, etc. The streaming
@@ -3513,7 +3683,7 @@ var ChatMessageSchema = z19.object({
3513
3683
  * reload. Populated by the chat manager just before `events.publish`
3514
3684
  * fires the `complete` event.
3515
3685
  */
3516
- warnings: z19.array(z19.string()).optional(),
3686
+ warnings: z20.array(z20.string()).optional(),
3517
3687
  /**
3518
3688
  * Chain-of-thought captured during this turn. Local providers
3519
3689
  * (ollama, llama-cpp, mlx, ds4) extract `<think>…</think>` /
@@ -3526,14 +3696,14 @@ var ChatMessageSchema = z19.object({
3526
3696
  * Responses hides reasoning server-side and leaves this unset.
3527
3697
  * Empty / whitespace-only captures are dropped.
3528
3698
  */
3529
- reasoning: z19.string().optional(),
3699
+ reasoning: z20.string().optional(),
3530
3700
  /**
3531
3701
  * Observed wall-clock span of the streamed private-reasoning trace,
3532
3702
  * measured from the first `reasoning_delta` to the last. Optional
3533
3703
  * because older messages and providers that only expose reasoning at
3534
3704
  * commit time have no trustworthy phase timing.
3535
3705
  */
3536
- reasoningDurationMs: z19.number().int().nonnegative().optional(),
3706
+ reasoningDurationMs: z20.number().int().nonnegative().optional(),
3537
3707
  /**
3538
3708
  * Tool-call bodies the model emitted that the salvage layer
3539
3709
  * couldn't parse — the literal text from `<|tool_call|>` markers
@@ -3548,10 +3718,10 @@ var ChatMessageSchema = z19.object({
3548
3718
  * hundred chars per body in the populator so a long fabricated body
3549
3719
  * doesn't blow up the session file.
3550
3720
  */
3551
- attemptedToolCalls: z19.array(
3552
- z19.object({
3553
- body: z19.string(),
3554
- reason: z19.string().optional()
3721
+ attemptedToolCalls: z20.array(
3722
+ z20.object({
3723
+ body: z20.string(),
3724
+ reason: z20.string().optional()
3555
3725
  })
3556
3726
  ).optional(),
3557
3727
  /**
@@ -3567,28 +3737,28 @@ var ChatMessageSchema = z19.object({
3567
3737
  * daemon restart, a provider reset, or a context-pressure rebuild — leaving
3568
3738
  * the model replaying a bare `![](attachments/9f3.png)`.
3569
3739
  */
3570
- recognizedImages: z19.array(MessageImageDigestSchema).optional()
3740
+ recognizedImages: z20.array(MessageImageDigestSchema).optional()
3571
3741
  });
3572
- var ChatTurnErrorDetailSchema = z19.object({
3573
- code: z19.string().max(64).optional(),
3742
+ var ChatTurnErrorDetailSchema = z20.object({
3743
+ code: z20.string().max(64).optional(),
3574
3744
  /** Component that failed — a provider name (`llama-cpp`) or a subsystem. */
3575
- engine: z19.string().max(64).optional(),
3745
+ engine: z20.string().max(64).optional(),
3576
3746
  /** Correlation key, also written into the engine's own incident log. */
3577
- incidentId: z19.string().max(64).optional(),
3747
+ incidentId: z20.string().max(64).optional(),
3578
3748
  /** Native crash class from the exit snapshot, e.g. `cuda-out-of-memory`. */
3579
- panicKind: z19.string().max(64).optional(),
3580
- exitCode: z19.number().int().nullable().optional(),
3581
- signal: z19.string().max(32).nullable().optional(),
3749
+ panicKind: z20.string().max(64).optional(),
3750
+ exitCode: z20.number().int().nullable().optional(),
3751
+ signal: z20.string().max(32).nullable().optional(),
3582
3752
  /**
3583
3753
  * Request-independent launch facts copied from the crash snapshot, which
3584
3754
  * is contractually free of prompts, tool arguments, and secrets. Bounded
3585
3755
  * by the extractor. A machine profile cannot reconstruct which model at
3586
3756
  * which context size with which KV type crashed; this can.
3587
3757
  */
3588
- diagnostics: z19.record(z19.string(), z19.union([z19.string(), z19.number(), z19.boolean()])).optional()
3758
+ diagnostics: z20.record(z20.string(), z20.union([z20.string(), z20.number(), z20.boolean()])).optional()
3589
3759
  });
3590
- var ChatEventSchema = z19.discriminatedUnion("type", [
3591
- z19.object({ type: z19.literal("delta"), content: z19.string() }),
3760
+ var ChatEventSchema = z20.discriminatedUnion("type", [
3761
+ z20.object({ type: z20.literal("delta"), content: z20.string() }),
3592
3762
  /**
3593
3763
  * Live private-reasoning tokens (ds4's think phase), streamed on their
3594
3764
  * own channel so they never mix into the visible `delta` stream, the
@@ -3596,14 +3766,14 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3596
3766
  * renders them as a distinct "thinking" block that collapses into the
3597
3767
  * committed message's reasoning expander once `complete` lands.
3598
3768
  */
3599
- z19.object({ type: z19.literal("reasoning_delta"), content: z19.string() }),
3600
- z19.object({ type: z19.literal("complete"), message: ChatMessageSchema }),
3769
+ z20.object({ type: z20.literal("reasoning_delta"), content: z20.string() }),
3770
+ z20.object({ type: z20.literal("complete"), message: ChatMessageSchema }),
3601
3771
  /**
3602
3772
  * The user submitted a message, but a cold provider session is still being
3603
3773
  * created. Project timelines render this as a temporary pending row until
3604
3774
  * the durable `user_message` or a terminal `error` arrives.
3605
3775
  */
3606
- z19.object({ type: z19.literal("user_message_pending"), preview: z19.string() }),
3776
+ z20.object({ type: z20.literal("user_message_pending"), preview: z20.string() }),
3607
3777
  /**
3608
3778
  * Emitted right after the user's message is appended to the session
3609
3779
  * record. The legacy session-scoped UI inserted user messages locally
@@ -3611,27 +3781,29 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3611
3781
  * envelope streams need it so the interleaved timeline can render the
3612
3782
  * user's bubble immediately, before any assistant deltas.
3613
3783
  */
3614
- z19.object({ type: z19.literal("user_message"), message: ChatMessageSchema }),
3784
+ z20.object({ type: z20.literal("user_message"), message: ChatMessageSchema }),
3615
3785
  /**
3616
3786
  * Emitted when the assistant invokes an MCP tool (OpenAI + Mock paths
3617
3787
  * only — Copilot runs tools inside its subprocess, invisible to us).
3618
3788
  * The UI surfaces these as "thinking" breadcrumbs.
3619
3789
  */
3620
- z19.object({
3621
- type: z19.literal("tool"),
3622
- name: z19.string(),
3623
- durationMs: z19.number(),
3624
- success: z19.boolean(),
3625
- errorMessage: z19.string().optional(),
3790
+ z20.object({
3791
+ type: z20.literal("tool"),
3792
+ name: z20.string(),
3793
+ /** ISO start-of-call timestamp; see ChatMessageToolCallSchema.at. */
3794
+ at: z20.string().optional(),
3795
+ durationMs: z20.number(),
3796
+ success: z20.boolean(),
3797
+ errorMessage: z20.string().optional(),
3626
3798
  /**
3627
3799
  * File path the tool touched (if any). Set for tools that take a `path`
3628
3800
  * argument: readFile, writeFile, read_artifact, write_artifact,
3629
3801
  * read_document, write_document. Lets the UI build a References panel
3630
3802
  * without guessing.
3631
3803
  */
3632
- path: z19.string().optional(),
3804
+ path: z20.string().optional(),
3633
3805
  /** Ordered file paths touched by a batched filesystem tool. */
3634
- paths: z19.array(z19.string()).optional(),
3806
+ paths: z20.array(z20.string()).optional(),
3635
3807
  /**
3636
3808
  * Compact human-readable preview of the non-bulky arguments. Example:
3637
3809
  * `gezel: "Maya", message: "what's the status of..."`. Values are
@@ -3639,46 +3811,46 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3639
3811
  * UI to render a useful in-progress tool line instead of just the
3640
3812
  * tool name.
3641
3813
  */
3642
- argsSummary: z19.string().optional(),
3814
+ argsSummary: z20.string().optional(),
3643
3815
  /** Full, readable args for the expand + copy affordance. See the persisted `ChatMessageToolCall.argsFull`. */
3644
- argsFull: z19.string().optional(),
3816
+ argsFull: z20.string().optional(),
3645
3817
  /** Short full response, or a bounded beginning/end summary. */
3646
- resultText: z19.string().optional(),
3818
+ resultText: z20.string().optional(),
3647
3819
  /** True when `resultText` is a bounded summary rather than the complete response. */
3648
- resultTruncated: z19.boolean().optional(),
3820
+ resultTruncated: z20.boolean().optional(),
3649
3821
  /**
3650
3822
  * Image artifacts the tool returned (most commonly browser screenshots).
3651
3823
  * Paths are relative to the project's artifacts/ root and resolved
3652
3824
  * to URLs by the UI via the artifact-read endpoint.
3653
3825
  */
3654
- images: z19.array(ToolCallImageSchema).optional(),
3826
+ images: z20.array(ToolCallImageSchema).optional(),
3655
3827
  /**
3656
3828
  * Audio artifacts the tool returned (synthesize_speech narrations,
3657
3829
  * voice memos transcribed via transcribe_audio). Same artifact-path
3658
3830
  * resolution as `images`.
3659
3831
  */
3660
- audios: z19.array(ToolCallAudioSchema).optional(),
3832
+ audios: z20.array(ToolCallAudioSchema).optional(),
3661
3833
  /**
3662
3834
  * Video artifacts the tool returned (`generate_video`). Same
3663
3835
  * artifact-path resolution as `images`; rendered as a `<video>`
3664
3836
  * player in the chat row.
3665
3837
  */
3666
- videos: z19.array(ToolCallVideoSchema).optional(),
3838
+ videos: z20.array(ToolCallVideoSchema).optional(),
3667
3839
  /**
3668
3840
  * Unified diff describing the change a surgical-edit tool made
3669
3841
  * (`replace_in_file`, `apply_patch`, `insert_at_marker`). Streams to the
3670
3842
  * UI mid-turn so the chat bubble can render an inline diff under
3671
3843
  * the tool-call row even before the assistant message is finalized.
3672
3844
  */
3673
- diff: z19.string().optional(),
3674
- addedLines: z19.number().int().nonnegative().optional(),
3675
- removedLines: z19.number().int().nonnegative().optional(),
3845
+ diff: z20.string().optional(),
3846
+ addedLines: z20.number().int().nonnegative().optional(),
3847
+ removedLines: z20.number().int().nonnegative().optional(),
3676
3848
  /** Rich inline card payload for tools with special renderings — see ToolCallCardSchema. */
3677
3849
  card: ToolCallCardSchema.optional()
3678
3850
  }),
3679
- z19.object({
3680
- type: z19.literal("error"),
3681
- error: z19.string(),
3851
+ z20.object({
3852
+ type: z20.literal("error"),
3853
+ error: z20.string(),
3682
3854
  // Not `detail` — three sibling variants in this union already use that
3683
3855
  // name for free-form progress prose, and one union with two meanings for
3684
3856
  // one key is a trap.
@@ -3689,8 +3861,8 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3689
3861
  * surface. This is terminal for the live UI, but is deliberately not an
3690
3862
  * error: it must not poison the session or render failure recovery UI.
3691
3863
  */
3692
- z19.object({ type: z19.literal("cancelled") }),
3693
- z19.object({ type: z19.literal("done") }),
3864
+ z20.object({ type: z20.literal("cancelled") }),
3865
+ z20.object({ type: z20.literal("done") }),
3694
3866
  /**
3695
3867
  * Emitted when a turn ends up waiting in the provider queue for more
3696
3868
  * than a brief grace period (~200ms). `aheadOf` is an approximate
@@ -3700,7 +3872,7 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3700
3872
  * emit this event — avoids flashing the indicator on the happy path
3701
3873
  * where the queue is empty.
3702
3874
  */
3703
- z19.object({ type: z19.literal("queued"), aheadOf: z19.number().int().min(0) }),
3875
+ z20.object({ type: z20.literal("queued"), aheadOf: z20.number().int().min(0) }),
3704
3876
  /**
3705
3877
  * Ollama-only: emitted for each bare framing chunk that arrives
3706
3878
  * on the wire without visible content / tool_calls — the
@@ -3710,7 +3882,7 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3710
3882
  * when the model isn't producing visible output. Reset on the
3711
3883
  * next real `delta`, `tool`, or `complete`.
3712
3884
  */
3713
- z19.object({ type: z19.literal("wire_pulse") }),
3885
+ z20.object({ type: z20.literal("wire_pulse") }),
3714
3886
  /**
3715
3887
  * Live tool-argument stream. Fired while the model is generating a
3716
3888
  * structured tool call — most visibly a multi-minute `write_file`
@@ -3722,7 +3894,7 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3722
3894
  * "working" block (same pattern as `reasoning_delta`) and drops the
3723
3895
  * block when the corresponding `tool` event lands.
3724
3896
  */
3725
- z19.object({ type: z19.literal("tool_args_delta"), name: z19.string(), content: z19.string() }),
3897
+ z20.object({ type: z20.literal("tool_args_delta"), name: z20.string(), content: z20.string() }),
3726
3898
  /**
3727
3899
  * Emitted when a provider tells us it's still doing work — even though
3728
3900
  * no visible text/tool event has arrived. Today this is wired from
@@ -3733,24 +3905,24 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3733
3905
  * Optional `label` carries a short phase hint ('thinking', 'tool',
3734
3906
  * etc.) that the streaming bubble can surface as a status line.
3735
3907
  */
3736
- z19.object({ type: z19.literal("heartbeat"), label: z19.string().optional() }),
3908
+ z20.object({ type: z20.literal("heartbeat"), label: z20.string().optional() }),
3737
3909
  /**
3738
3910
  * Provider-side warning surfaced mid-turn (e.g. Copilot rate-limit,
3739
3911
  * context pressure, degraded mode). The UI renders these inline on
3740
3912
  * the streaming bubble so the user sees them immediately instead of
3741
3913
  * only finding out when the turn completes or times out.
3742
3914
  */
3743
- z19.object({
3744
- type: z19.literal("warning"),
3745
- message: z19.string(),
3915
+ z20.object({
3916
+ type: z20.literal("warning"),
3917
+ message: z20.string(),
3746
3918
  /**
3747
3919
  * Optional in-app destination for a warning's inline action. Kept
3748
3920
  * deliberately narrow: warnings are still readable prose when an older
3749
3921
  * client ignores this additive field.
3750
3922
  */
3751
- action: z19.object({
3752
- kind: z19.literal("settings"),
3753
- section: z19.enum(["llamaCpp", "mlx", "ds4"])
3923
+ action: z20.object({
3924
+ kind: z20.literal("settings"),
3925
+ section: z20.enum(["llamaCpp", "mlx", "ds4"])
3754
3926
  }).optional()
3755
3927
  }),
3756
3928
  /**
@@ -3761,18 +3933,18 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3761
3933
  * offset on the final assistant message so completed bubbles render
3762
3934
  * the same segmentation on reload.
3763
3935
  */
3764
- z19.object({ type: z19.literal("intent"), label: z19.string() }),
3936
+ z20.object({ type: z20.literal("intent"), label: z20.string() }),
3765
3937
  /**
3766
3938
  * Emitted when a new message is enqueued on the per-session queue
3767
3939
  * because the session already has a turn in flight. The timeline
3768
3940
  * renders a "ghost bubble" under the session's streaming bubble
3769
3941
  * showing the queued text preview. Cleared via `queue_removed`.
3770
3942
  */
3771
- z19.object({
3772
- type: z19.literal("queue_enqueued"),
3773
- queueId: z19.string(),
3774
- preview: z19.string(),
3775
- enqueuedAt: z19.string(),
3943
+ z20.object({
3944
+ type: z20.literal("queue_enqueued"),
3945
+ queueId: z20.string(),
3946
+ preview: z20.string(),
3947
+ enqueuedAt: z20.string(),
3776
3948
  /**
3777
3949
  * The entry was queued as a mid-turn nudge — the ghost bubble labels
3778
3950
  * it "nudge" and contiguous nudges merge into one turn on drain.
@@ -3780,7 +3952,7 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3780
3952
  * every coalesce/edit); the edit affordance fetches it lazily via
3781
3953
  * `GET /api/sessions/:id/queue`.
3782
3954
  */
3783
- nudge: z19.boolean().optional()
3955
+ nudge: z20.boolean().optional()
3784
3956
  }),
3785
3957
  /**
3786
3958
  * Emitted when a queued entry leaves the queue — either because
@@ -3789,22 +3961,39 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3789
3961
  * dropped without running (`reason: 'canceled'` via user action,
3790
3962
  * `reason: 'rejected'` via session archive / delete / shutdown).
3791
3963
  */
3792
- z19.object({
3793
- type: z19.literal("queue_removed"),
3794
- queueId: z19.string(),
3795
- reason: z19.enum(["started", "canceled", "rejected"])
3964
+ z20.object({
3965
+ type: z20.literal("queue_removed"),
3966
+ queueId: z20.string(),
3967
+ reason: z20.enum(["started", "canceled", "rejected"])
3968
+ }),
3969
+ /**
3970
+ * Effective context policy for a local or remote-local session. Emitted on
3971
+ * each turn so the live UI can show the model's token window immediately;
3972
+ * the same values are persisted on the session for reloads.
3973
+ */
3974
+ z20.object({
3975
+ type: z20.literal("context_window"),
3976
+ numCtx: z20.number().int().positive(),
3977
+ model: z20.string(),
3978
+ autoCompactRatio: z20.number().positive().max(1),
3979
+ /**
3980
+ * Estimated prompt size for the turn about to run, in the same
3981
+ * chars/4 units the compaction check itself uses. Absent on older
3982
+ * daemons, which published the window without the fill.
3983
+ */
3984
+ estimatedTokens: z20.number().int().nonnegative().optional()
3796
3985
  }),
3797
3986
  /**
3798
- * Local-provider context policy: emitted when accumulated conversation
3799
- * exceeds a safety fraction of the session's effective model context.
3800
- * The UI may suggest starting fresh because this event is never emitted
3801
- * for a first-turn standing system/tool prefix.
3987
+ * Local-provider context policy: emitted only when accumulated conversation
3988
+ * could not be compacted automatically. Normal pressure is handled without
3989
+ * a warning; this is the exceptional maintenance-failure path.
3802
3990
  */
3803
- z19.object({
3804
- type: z19.literal("context_warning"),
3805
- estimatedTokens: z19.number(),
3806
- numCtx: z19.number(),
3807
- model: z19.string()
3991
+ z20.object({
3992
+ type: z20.literal("context_warning"),
3993
+ estimatedTokens: z20.number(),
3994
+ numCtx: z20.number(),
3995
+ model: z20.string(),
3996
+ reason: z20.literal("compaction_failed").optional()
3808
3997
  }),
3809
3998
  /**
3810
3999
  * Local-provider context policy: emitted right after in-flight compaction collapses
@@ -3813,10 +4002,16 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3813
4002
  * for a "compacted" variant and refreshes the visible timeline (older
3814
4003
  * bubbles are now gone from disk).
3815
4004
  */
3816
- z19.object({
3817
- type: z19.literal("context_compacted"),
3818
- removedCount: z19.number().int().nonnegative(),
3819
- model: z19.string()
4005
+ z20.object({
4006
+ type: z20.literal("context_compacted"),
4007
+ removedCount: z20.number().int().nonnegative(),
4008
+ model: z20.string(),
4009
+ /** Optional for wire compatibility with pre-context-visibility daemons. */
4010
+ numCtx: z20.number().int().positive().optional(),
4011
+ estimatedTokensBefore: z20.number().int().nonnegative().optional(),
4012
+ autoCompactRatio: z20.number().positive().max(1).optional(),
4013
+ compactionCount: z20.number().int().positive().optional(),
4014
+ mode: z20.enum(["between-turn", "mid-turn"]).optional()
3820
4015
  }),
3821
4016
  /**
3822
4017
  * Emitted when the chat manager detects a self-chat / compaction loop —
@@ -3825,10 +4020,10 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3825
4020
  * compaction cycle without making progress. The pipeline halts the turn
3826
4021
  * so the user can intervene; the UI surfaces a "looks stuck" banner.
3827
4022
  */
3828
- z19.object({
3829
- type: z19.literal("context_loop"),
3830
- compactionsThisSend: z19.number().int().positive(),
3831
- reason: z19.string()
4023
+ z20.object({
4024
+ type: z20.literal("context_loop"),
4025
+ compactionsThisSend: z20.number().int().positive(),
4026
+ reason: z20.string()
3832
4027
  }),
3833
4028
  /**
3834
4029
  * Emitted when the Keurmeester (frontier quality inspector) steps in
@@ -3836,23 +4031,23 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3836
4031
  * UI renders a "stepped in" notice on the thread; the full case
3837
4032
  * record lives under `~/.gezel/keurmeester/cases/` keyed by caseId.
3838
4033
  */
3839
- z19.object({
3840
- type: z19.literal("keurmeester_intervention"),
3841
- caseId: z19.string(),
3842
- gezelId: z19.string(),
3843
- gezelName: z19.string(),
3844
- action: z19.string(),
3845
- summary: z19.string()
4034
+ z20.object({
4035
+ type: z20.literal("keurmeester_intervention"),
4036
+ caseId: z20.string(),
4037
+ gezelId: z20.string(),
4038
+ gezelName: z20.string(),
4039
+ action: z20.string(),
4040
+ summary: z20.string()
3846
4041
  }),
3847
4042
  /**
3848
4043
  * Emitted once per session the first time auto-recall runs, so the UI
3849
4044
  * can render a "pulled N memories from prior work" chip above the first
3850
4045
  * assistant reply.
3851
4046
  */
3852
- z19.object({
3853
- type: z19.literal("recall_applied"),
3854
- hitCount: z19.number(),
3855
- query: z19.string()
4047
+ z20.object({
4048
+ type: z20.literal("recall_applied"),
4049
+ hitCount: z20.number(),
4050
+ query: z20.string()
3856
4051
  }),
3857
4052
  /**
3858
4053
  * Emitted when a gezel posts a structured question via the
@@ -3860,14 +4055,14 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3860
4055
  * questions on this event so the in-chat card, Home pane, and Home
3861
4056
  * tab badge all light up together.
3862
4057
  */
3863
- z19.object({ type: z19.literal("question_asked"), question: QuestionSchema }),
4058
+ z20.object({ type: z20.literal("question_asked"), question: QuestionSchema }),
3864
4059
  /**
3865
4060
  * Emitted when the user submits (or declines) an answer. The UI
3866
4061
  * uses the same fan-out as `question_asked` to refresh every
3867
4062
  * surface; the chat bubble's pending card collapses to its
3868
4063
  * answered state.
3869
4064
  */
3870
- z19.object({ type: z19.literal("question_answered"), question: QuestionSchema }),
4065
+ z20.object({ type: z20.literal("question_answered"), question: QuestionSchema }),
3871
4066
  /**
3872
4067
  * A durable task audit event, fanned onto the project's live stream after
3873
4068
  * it has been appended to History. This keeps lightweight clients (most
@@ -3875,13 +4070,13 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3875
4070
  * second task lifecycle bus. `task.tick` heartbeats are intentionally not
3876
4071
  * published; this channel is for user-meaningful changes.
3877
4072
  */
3878
- z19.object({
3879
- type: z19.literal("task_event"),
3880
- eventId: z19.string(),
3881
- kind: z19.string(),
3882
- summary: z19.string(),
3883
- at: z19.string(),
3884
- taskRef: z19.string().optional(),
4073
+ z20.object({
4074
+ type: z20.literal("task_event"),
4075
+ eventId: z20.string(),
4076
+ kind: z20.string(),
4077
+ summary: z20.string(),
4078
+ at: z20.string(),
4079
+ taskRef: z20.string().optional(),
3885
4080
  /**
3886
4081
  * Gezel responsible for the event, when History recorded one. Kept
3887
4082
  * separate from the human-readable summary so fixed-presentation
@@ -3889,18 +4084,18 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3889
4084
  * their own naming mode instead of leaking the friendly name embedded
3890
4085
  * in the audit prose.
3891
4086
  */
3892
- gezelId: z19.string().optional()
4087
+ gezelId: z20.string().optional()
3893
4088
  }),
3894
4089
  /**
3895
4090
  * Emitted when a gezel crosses a growth level threshold and a pending
3896
4091
  * level-up is created. The UI refreshes growth badges/dots and raises
3897
4092
  * a single calm OS notification when the window is hidden.
3898
4093
  */
3899
- z19.object({
3900
- type: z19.literal("growth_level_up"),
3901
- gezelId: z19.string(),
3902
- gezelName: z19.string(),
3903
- toLevel: z19.number().int()
4094
+ z20.object({
4095
+ type: z20.literal("growth_level_up"),
4096
+ gezelId: z20.string(),
4097
+ gezelName: z20.string(),
4098
+ toLevel: z20.number().int()
3904
4099
  }),
3905
4100
  /**
3906
4101
  * llama-cpp-only: lifecycle phase of the supervised on-device engine
@@ -3923,19 +4118,19 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3923
4118
  * the phase label so users who want to know what's happening can
3924
4119
  * see, without cluttering the happy-path status line.
3925
4120
  */
3926
- z19.object({
3927
- type: z19.literal("engine_phase"),
3928
- provider: z19.enum(["llama-cpp", "mlx", "ds4"]),
3929
- phase: z19.enum(["starting", "loading_model", "prefill", "generating", "ready"]),
4121
+ z20.object({
4122
+ type: z20.literal("engine_phase"),
4123
+ provider: z20.enum(["llama-cpp", "mlx", "ds4"]),
4124
+ phase: z20.enum(["starting", "loading_model", "prefill", "generating", "ready"]),
3930
4125
  /**
3931
4126
  * Human-readable subject for an ephemeral background completion. Unlike
3932
4127
  * `detail` (engine diagnostics), this names the user's work — for example
3933
4128
  * "Indexing src/app.ts". Ordinary chat turns leave it absent.
3934
4129
  */
3935
- activity: z19.string().optional(),
3936
- detail: z19.string().optional(),
3937
- progress: z19.number().min(0).max(1).optional(),
3938
- ttftMs: z19.number().int().nonnegative().optional(),
4130
+ activity: z20.string().optional(),
4131
+ detail: z20.string().optional(),
4132
+ progress: z20.number().min(0).max(1).optional(),
4133
+ ttftMs: z20.number().int().nonnegative().optional(),
3939
4134
  /**
3940
4135
  * Exact cumulative completion tokens decoded so far this turn, as the
3941
4136
  * engine counts them (llama-server `timings.predicted_n`, MLX's
@@ -3944,14 +4139,14 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3944
4139
  * to an explicitly-approximate character estimate when it is absent,
3945
4140
  * so this field is what lets a readout drop its "≈".
3946
4141
  */
3947
- outputTokens: z19.number().int().nonnegative().optional(),
4142
+ outputTokens: z20.number().int().nonnegative().optional(),
3948
4143
  /**
3949
4144
  * Exact decode rate right now, engine-measured over the generation
3950
4145
  * phase alone (llama-server `timings.predicted_per_second`, MLX's
3951
4146
  * `generation_tps`). Same contract as `outputTokens`: absent means the
3952
4147
  * UI must derive and mark its own estimate.
3953
4148
  */
3954
- tokensPerSec: z19.number().nonnegative().optional()
4149
+ tokensPerSec: z20.number().nonnegative().optional()
3955
4150
  }),
3956
4151
  /**
3957
4152
  * Per-turn telemetry for locally-hosted providers (llama-cpp, Ollama,
@@ -3966,21 +4161,21 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3966
4161
  * local speed metric isn't meaningful when the latency is
3967
4162
  * dominated by network round-trips.
3968
4163
  */
3969
- z19.object({
3970
- type: z19.literal("turn_stats"),
3971
- provider: z19.enum(["llama-cpp", "ollama", "mlx", "ds4"]),
4164
+ z20.object({
4165
+ type: z20.literal("turn_stats"),
4166
+ provider: z20.enum(["llama-cpp", "ollama", "mlx", "ds4"]),
3972
4167
  /**
3973
4168
  * Model that generated the turn, as the session recorded it. Lets the
3974
4169
  * UI bucket speed by model instead of averaging a 27B and a 4B into
3975
4170
  * one meaningless number. Optional because older daemons (and remote
3976
4171
  * peers on an older wire) don't send it.
3977
4172
  */
3978
- model: z19.string().optional(),
3979
- promptTokens: z19.number().int().nonnegative(),
3980
- completionTokens: z19.number().int().nonnegative(),
3981
- durationMs: z19.number().int().nonnegative(),
4173
+ model: z20.string().optional(),
4174
+ promptTokens: z20.number().int().nonnegative(),
4175
+ completionTokens: z20.number().int().nonnegative(),
4176
+ durationMs: z20.number().int().nonnegative(),
3982
4177
  /** Generation speed in tokens/sec — completionTokens / generationSeconds. */
3983
- tokensPerSec: z19.number().nonnegative().optional()
4178
+ tokensPerSec: z20.number().nonnegative().optional()
3984
4179
  }),
3985
4180
  /**
3986
4181
  * Static engine-level metrics that don't change during a session —
@@ -3992,11 +4187,11 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
3992
4187
  * `engine_phase` (every session waiting on the same supervisor
3993
4188
  * startup gets a copy).
3994
4189
  */
3995
- z19.object({
3996
- type: z19.literal("engine_stats"),
3997
- provider: z19.enum(["llama-cpp", "mlx", "ds4"]),
4190
+ z20.object({
4191
+ type: z20.literal("engine_stats"),
4192
+ provider: z20.enum(["llama-cpp", "mlx", "ds4"]),
3998
4193
  /** Total bytes allocated across all GGUF buffers + KV cache. */
3999
- ramAllocBytes: z19.number().nonnegative()
4194
+ ramAllocBytes: z20.number().nonnegative()
4000
4195
  }),
4001
4196
  /**
4002
4197
  * VRAM tenancy change — a non-LLM workload has taken (or released)
@@ -4026,9 +4221,9 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4026
4221
  * `step`/`totalSteps` drive a real progress bar; `secondsPerStep`
4027
4222
  * lets the UI show an ETA.
4028
4223
  */
4029
- z19.object({
4030
- type: z19.literal("gpu_swap"),
4031
- state: z19.enum(["started", "progress", "ended"]),
4224
+ z20.object({
4225
+ type: z20.literal("gpu_swap"),
4226
+ state: z20.enum(["started", "progress", "ended"]),
4032
4227
  /**
4033
4228
  * Shared with session telemetry so a new workload can't light up the
4034
4229
  * bubble while staying invisible to stall detection.
@@ -4041,12 +4236,12 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4041
4236
  * seconds", which reads as a bug.
4042
4237
  */
4043
4238
  task: SessionGpuTaskSchema,
4044
- detail: z19.string().optional(),
4045
- prompt: z19.string().optional(),
4046
- progress: z19.number().min(0).max(1).optional(),
4047
- step: z19.number().int().nonnegative().optional(),
4048
- totalSteps: z19.number().int().positive().optional(),
4049
- secondsPerStep: z19.number().nonnegative().optional()
4239
+ detail: z20.string().optional(),
4240
+ prompt: z20.string().optional(),
4241
+ progress: z20.number().min(0).max(1).optional(),
4242
+ step: z20.number().int().nonnegative().optional(),
4243
+ totalSteps: z20.number().int().positive().optional(),
4244
+ secondsPerStep: z20.number().nonnegative().optional()
4050
4245
  }),
4051
4246
  /**
4052
4247
  * The turn is parked inside a synchronous `ask_gezel` /
@@ -4069,10 +4264,10 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4069
4264
  * side, same as the `ask_gezel` tool result), so the UI can render
4070
4265
  * it verbatim.
4071
4266
  */
4072
- z19.object({
4073
- type: z19.literal("awaiting_gezel"),
4074
- state: z19.enum(["started", "ended"]),
4075
- targetGezelName: z19.string()
4267
+ z20.object({
4268
+ type: z20.literal("awaiting_gezel"),
4269
+ state: z20.enum(["started", "ended"]),
4270
+ targetGezelName: z20.string()
4076
4271
  }),
4077
4272
  /**
4078
4273
  * A new project was created (via the New Project dialog, the
@@ -4083,10 +4278,10 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4083
4278
  * for the next manual refresh / tab-focus poll. Not a renderable
4084
4279
  * timeline event (like `growth_level_up`); the chat surfaces ignore it.
4085
4280
  */
4086
- z19.object({
4087
- type: z19.literal("project_created"),
4088
- projectId: z19.string(),
4089
- name: z19.string()
4281
+ z20.object({
4282
+ type: z20.literal("project_created"),
4283
+ projectId: z20.string(),
4284
+ name: z20.string()
4090
4285
  }),
4091
4286
  /**
4092
4287
  * A project was deleted (via the Project Actions menu, or an equivalent
@@ -4096,10 +4291,10 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4096
4291
  * waiting for the next manual refresh / tab-focus poll. Not a renderable
4097
4292
  * timeline event; the chat surfaces ignore it.
4098
4293
  */
4099
- z19.object({
4100
- type: z19.literal("project_deleted"),
4101
- projectId: z19.string(),
4102
- name: z19.string()
4294
+ z20.object({
4295
+ type: z20.literal("project_deleted"),
4296
+ projectId: z20.string(),
4297
+ name: z20.string()
4103
4298
  }),
4104
4299
  /**
4105
4300
  * A new shared gezel joined the global roster. Emitted on the global
@@ -4108,10 +4303,30 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4108
4303
  * gezels deliberately do not emit this event because they do not belong in
4109
4304
  * the global Gezellen list.
4110
4305
  */
4111
- z19.object({
4112
- type: z19.literal("gezel_created"),
4113
- gezelId: z19.string(),
4114
- name: z19.string()
4306
+ z20.object({
4307
+ type: z20.literal("gezel_created"),
4308
+ gezelId: z20.string(),
4309
+ name: z20.string()
4310
+ }),
4311
+ /**
4312
+ * A prompt draft was created, edited, re-filed, sent, or removed. Emitted
4313
+ * on the project stream so a thread picker open in another window folds the
4314
+ * change in. Content-only churn rides this event too (autosave fires it
4315
+ * about once a second per typing user), so consumers must debounce and
4316
+ * should ignore an event for the draft they are themselves editing.
4317
+ *
4318
+ * `gezelId` is the draft's, not the envelope's: a draft that will start a
4319
+ * new thread has no session for the envelope to be scoped by.
4320
+ */
4321
+ z20.object({
4322
+ type: z20.literal("prompt_draft_changed"),
4323
+ projectId: z20.string(),
4324
+ gezelId: z20.string(),
4325
+ draftId: z20.string(),
4326
+ sessionId: z20.string().nullable(),
4327
+ status: z20.enum(["draft", "sent"]),
4328
+ deleted: z20.boolean().optional(),
4329
+ updatedAt: z20.string()
4115
4330
  }),
4116
4331
  /**
4117
4332
  * Global (project-less) signal that Night Shift mode flipped ON/OFF.
@@ -4119,10 +4334,10 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4119
4334
  * menu pill reflects the live state. `source` is the active driver
4120
4335
  * (scheduled window vs. a manual shift), null when inactive.
4121
4336
  */
4122
- z19.object({
4123
- type: z19.literal("night_shift"),
4124
- active: z19.boolean(),
4125
- source: z19.enum(["scheduled", "manual"]).nullable()
4337
+ z20.object({
4338
+ type: z20.literal("night_shift"),
4339
+ active: z20.boolean(),
4340
+ source: z20.enum(["scheduled", "manual"]).nullable()
4126
4341
  }),
4127
4342
  /**
4128
4343
  * Global signal from the meester status generator. `started` fires
@@ -4131,10 +4346,10 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4131
4346
  * produced nothing usable — the Home greeting refetches on the
4132
4347
  * terminal states instead of polling.
4133
4348
  */
4134
- z19.object({
4135
- type: z19.literal("meester_status"),
4136
- state: z19.enum(["started", "ended", "failed"]),
4137
- generatedAt: z19.string().optional()
4349
+ z20.object({
4350
+ type: z20.literal("meester_status"),
4351
+ state: z20.enum(["started", "ended", "failed"]),
4352
+ generatedAt: z20.string().optional()
4138
4353
  }),
4139
4354
  /**
4140
4355
  * Global signal from the ambient dashboard generator. `ended` means a
@@ -4143,11 +4358,11 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4143
4358
  * the wallpaper when the user opted in, and the Settings card
4144
4359
  * refreshes its preview.
4145
4360
  */
4146
- z19.object({
4147
- type: z19.literal("ambient_dashboard"),
4148
- state: z19.enum(["started", "ended", "failed"]),
4149
- generatedAt: z19.string().optional(),
4150
- filename: z19.string().optional()
4361
+ z20.object({
4362
+ type: z20.literal("ambient_dashboard"),
4363
+ state: z20.enum(["started", "ended", "failed"]),
4364
+ generatedAt: z20.string().optional(),
4365
+ filename: z20.string().optional()
4151
4366
  }),
4152
4367
  /**
4153
4368
  * Global (history-free) heartbeat from the boekwachter indexing loops —
@@ -4155,23 +4370,23 @@ var ChatEventSchema = z19.discriminatedUnion("type", [
4155
4370
  * indicator pill; complements (doesn't replace) the polled per-project
4156
4371
  * index status. `pending` = files still awaiting AI enrichment when known.
4157
4372
  */
4158
- z19.object({
4159
- type: z19.literal("index_progress"),
4160
- phase: z19.enum(["scan", "shadow", "enrich", "review", "digest"]),
4161
- state: z19.enum(["started", "progress", "ended"]),
4162
- projectId: z19.string().optional(),
4163
- detail: z19.string().optional(),
4164
- pending: z19.number().int().nonnegative().optional(),
4373
+ z20.object({
4374
+ type: z20.literal("index_progress"),
4375
+ phase: z20.enum(["scan", "shadow", "enrich", "review", "digest"]),
4376
+ state: z20.enum(["started", "progress", "ended"]),
4377
+ projectId: z20.string().optional(),
4378
+ detail: z20.string().optional(),
4379
+ pending: z20.number().int().nonnegative().optional(),
4165
4380
  /** The concrete autonomous gezel doing this work, when the project has one. */
4166
- gezelId: z19.string().optional(),
4381
+ gezelId: z20.string().optional(),
4167
4382
  /** Snapshot of their display name so transient progress remains human-readable. */
4168
- gezelName: z19.string().optional()
4383
+ gezelName: z20.string().optional()
4169
4384
  })
4170
4385
  ]);
4171
- var ChatEventEnvelopeSchema = z19.object({
4172
- sessionId: z19.string(),
4173
- gezelId: z19.string(),
4174
- projectId: z19.string(),
4386
+ var ChatEventEnvelopeSchema = z20.object({
4387
+ sessionId: z20.string(),
4388
+ gezelId: z20.string(),
4389
+ projectId: z20.string(),
4175
4390
  /** Present when this live session was opened by another session. */
4176
4391
  parentSession: SessionParentSchema.optional(),
4177
4392
  /** Immediate task-step session that handed work to this live session. */
@@ -4308,8 +4523,8 @@ function promoteBareChannelNames(text) {
4308
4523
  }
4309
4524
 
4310
4525
  // src/schemas/report-action.ts
4311
- import { z as z20 } from "zod";
4312
- var ReportActionKindSchema = z20.enum(["fire-craftbook", "create-task", "apply-edits"]);
4526
+ import { z as z21 } from "zod";
4527
+ var ReportActionKindSchema = z21.enum(["fire-craftbook", "create-task", "apply-edits"]);
4313
4528
  var commonFields = {
4314
4529
  /**
4315
4530
  * Author-supplied stable slug — keeps lifecycle state attached across
@@ -4317,121 +4532,121 @@ var commonFields = {
4317
4532
  * content hash (`a-<hash>`), which is stable only while the block's
4318
4533
  * body is byte-identical.
4319
4534
  */
4320
- id: z20.string().regex(/^[a-z0-9][a-z0-9_-]*$/i).optional(),
4535
+ id: z21.string().regex(/^[a-z0-9][a-z0-9_-]*$/i).optional(),
4321
4536
  /** Short human label for the card ("Fix the unchecked null in parser.ts"). */
4322
- title: z20.string().min(1),
4537
+ title: z21.string().min(1),
4323
4538
  /** One-or-two-sentence rationale shown under the title. */
4324
- reason: z20.string().optional(),
4539
+ reason: z21.string().optional(),
4325
4540
  /**
4326
4541
  * Target project. Defaults to the report's own project. Cross-project
4327
4542
  * targets are a primary case — the bundled oversight report lives in
4328
4543
  * `default` but recommends work in specific projects.
4329
4544
  */
4330
- projectId: z20.string().optional()
4545
+ projectId: z21.string().optional()
4331
4546
  };
4332
- var FireCraftbookActionSchema = z20.object({
4333
- kind: z20.literal("fire-craftbook"),
4547
+ var FireCraftbookActionSchema = z21.object({
4548
+ kind: z21.literal("fire-craftbook"),
4334
4549
  ...commonFields,
4335
- craftbookId: z20.string().min(1),
4550
+ craftbookId: z21.string().min(1),
4336
4551
  /** Invocation params for the craftbook's paramSchema (stringified values). */
4337
- params: z20.record(z20.string(), z20.string()).optional()
4552
+ params: z21.record(z21.string(), z21.string()).optional()
4338
4553
  });
4339
- var CreateTaskActionSchema = z20.object({
4340
- kind: z20.literal("create-task"),
4554
+ var CreateTaskActionSchema = z21.object({
4555
+ kind: z21.literal("create-task"),
4341
4556
  ...commonFields,
4342
4557
  /** Full work instruction for the bespoke task's single step. */
4343
- prompt: z20.string().min(1),
4558
+ prompt: z21.string().min(1),
4344
4559
  /** Role to recruit for the work (ensure_gezel jobTitle). Default: software developer. */
4345
- role: z20.string().optional()
4560
+ role: z21.string().optional()
4346
4561
  });
4347
- var ApplyEditsActionSchema = z20.object({
4348
- kind: z20.literal("apply-edits"),
4562
+ var ApplyEditsActionSchema = z21.object({
4563
+ kind: z21.literal("apply-edits"),
4349
4564
  ...commonFields,
4350
- edits: z20.array(
4351
- z20.object({
4565
+ edits: z21.array(
4566
+ z21.object({
4352
4567
  /** Workspace-relative target file in the TARGET project. */
4353
- path: z20.string().min(1),
4568
+ path: z21.string().min(1),
4354
4569
  /** Artifacts-relative sidecar `.diff` path in the REPORT's project. */
4355
- diffArtifact: z20.string().min(1)
4570
+ diffArtifact: z21.string().min(1)
4356
4571
  })
4357
4572
  ).min(1)
4358
4573
  });
4359
- var ReportActionSchema = z20.discriminatedUnion("kind", [
4574
+ var ReportActionSchema = z21.discriminatedUnion("kind", [
4360
4575
  FireCraftbookActionSchema,
4361
4576
  CreateTaskActionSchema,
4362
4577
  ApplyEditsActionSchema
4363
4578
  ]);
4364
- var ReportActionStateSchema = z20.enum([
4579
+ var ReportActionStateSchema = z21.enum([
4365
4580
  "suggested",
4366
4581
  "fired",
4367
4582
  "applied",
4368
4583
  "failed",
4369
4584
  "dismissed"
4370
4585
  ]);
4371
- var ReportActionRecordSchema = z20.object({
4372
- actionId: z20.string(),
4586
+ var ReportActionRecordSchema = z21.object({
4587
+ actionId: z21.string(),
4373
4588
  /** Artifacts-relative path of the report the action came from. */
4374
- reportPath: z20.string(),
4589
+ reportPath: z21.string(),
4375
4590
  kind: ReportActionKindSchema,
4376
- contentHash: z20.string(),
4377
- firstSeenAt: z20.string(),
4591
+ contentHash: z21.string(),
4592
+ firstSeenAt: z21.string(),
4378
4593
  state: ReportActionStateSchema,
4379
4594
  /** Task materialized by fire-craftbook / create-task. */
4380
- taskRef: z20.string().optional(),
4381
- firedAt: z20.string().optional(),
4595
+ taskRef: z21.string().optional(),
4596
+ firedAt: z21.string().optional(),
4382
4597
  /** Stamped when the fired task settles. */
4383
- settledAt: z20.string().optional(),
4384
- outcome: z20.enum(["complete", "canceled"]).optional(),
4598
+ settledAt: z21.string().optional(),
4599
+ outcome: z21.enum(["complete", "canceled"]).optional(),
4385
4600
  /** apply-edits per-file results. */
4386
- results: z20.array(
4387
- z20.object({
4388
- path: z20.string(),
4389
- ok: z20.boolean(),
4390
- error: z20.string().optional()
4601
+ results: z21.array(
4602
+ z21.object({
4603
+ path: z21.string(),
4604
+ ok: z21.boolean(),
4605
+ error: z21.string().optional()
4391
4606
  })
4392
4607
  ).optional()
4393
4608
  });
4394
- var ReportActionParseIssueSchema = z20.object({
4609
+ var ReportActionParseIssueSchema = z21.object({
4395
4610
  /** Zero-based index among the report's gezel-action fences. */
4396
- index: z20.number().int(),
4397
- message: z20.string(),
4611
+ index: z21.number().int(),
4612
+ message: z21.string(),
4398
4613
  /** Raw fence body, for the "unreadable action block" card. */
4399
- raw: z20.string()
4614
+ raw: z21.string()
4400
4615
  });
4401
- var ReportActionViewSchema = z20.object({
4616
+ var ReportActionViewSchema = z21.object({
4402
4617
  action: ReportActionSchema,
4403
- id: z20.string(),
4404
- contentHash: z20.string(),
4618
+ id: z21.string(),
4619
+ contentHash: z21.string(),
4405
4620
  state: ReportActionStateSchema,
4406
- taskRef: z20.string().optional(),
4407
- firedAt: z20.string().optional(),
4408
- settledAt: z20.string().optional(),
4409
- outcome: z20.enum(["complete", "canceled"]).optional(),
4410
- results: z20.array(z20.object({ path: z20.string(), ok: z20.boolean(), error: z20.string().optional() })).optional(),
4621
+ taskRef: z21.string().optional(),
4622
+ firedAt: z21.string().optional(),
4623
+ settledAt: z21.string().optional(),
4624
+ outcome: z21.enum(["complete", "canceled"]).optional(),
4625
+ results: z21.array(z21.object({ path: z21.string(), ok: z21.boolean(), error: z21.string().optional() })).optional(),
4411
4626
  /** The stored record predates a changed block body (report regenerated). */
4412
- contentChanged: z20.boolean().optional()
4627
+ contentChanged: z21.boolean().optional()
4413
4628
  });
4414
- var ReportActionsResponseSchema = z20.object({
4415
- actions: z20.array(ReportActionViewSchema),
4416
- issues: z20.array(ReportActionParseIssueSchema),
4629
+ var ReportActionsResponseSchema = z21.object({
4630
+ actions: z21.array(ReportActionViewSchema),
4631
+ issues: z21.array(ReportActionParseIssueSchema),
4417
4632
  /** Records whose action vanished from the regenerated report. */
4418
- stale: z20.array(ReportActionRecordSchema)
4633
+ stale: z21.array(ReportActionRecordSchema)
4419
4634
  });
4420
- var FireReportActionRequestSchema = z20.object({
4635
+ var FireReportActionRequestSchema = z21.object({
4421
4636
  /** Artifacts-relative report path. */
4422
- path: z20.string().min(1),
4423
- actionId: z20.string().min(1),
4637
+ path: z21.string().min(1),
4638
+ actionId: z21.string().min(1),
4424
4639
  /** apply-edits: none. fire-craftbook: overrides the block's params. */
4425
- params: z20.record(z20.string(), z20.string()).optional()
4640
+ params: z21.record(z21.string(), z21.string()).optional()
4426
4641
  });
4427
- var FireReportActionResponseSchema = z20.object({
4642
+ var FireReportActionResponseSchema = z21.object({
4428
4643
  record: ReportActionRecordSchema,
4429
4644
  /** Set for fire-craftbook / create-task. */
4430
- taskRef: z20.string().optional()
4645
+ taskRef: z21.string().optional()
4431
4646
  });
4432
- var DismissReportActionRequestSchema = z20.object({
4433
- path: z20.string().min(1),
4434
- actionId: z20.string().min(1)
4647
+ var DismissReportActionRequestSchema = z21.object({
4648
+ path: z21.string().min(1),
4649
+ actionId: z21.string().min(1)
4435
4650
  });
4436
4651
 
4437
4652
  // src/markdown/report-actions.ts