flavor-code 1.2.14 → 1.2.16

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.
@@ -1,7 +1,7 @@
1
1
  // src/desktop/main.ts
2
2
  import { appendFileSync } from "fs";
3
3
  import { readFile as readFile34, stat as stat15, writeFile as writeFile18 } from "fs/promises";
4
- import { dirname as dirname23, join as join40 } from "path";
4
+ import { dirname as dirname23, join as join41 } from "path";
5
5
  import { fileURLToPath as fileURLToPath4 } from "url";
6
6
  import { app, BrowserWindow as BrowserWindow2, dialog, ipcMain, Menu, nativeImage, shell } from "electron";
7
7
 
@@ -505,6 +505,7 @@ var DESKTOP_CHANNELS = {
505
505
  d2cRunQualityJudge: "desktop:d2c-run-quality-judge",
506
506
  d2cResolveQualityIssue: "desktop:d2c-resolve-quality-issue",
507
507
  d2cSetManualAcceptance: "desktop:d2c-set-manual-acceptance",
508
+ e2eGetDeliveryRun: "desktop:e2e-get-delivery-run",
508
509
  event: "desktop:event"
509
510
  };
510
511
 
@@ -2611,11 +2612,11 @@ function hexToLab(hex) {
2611
2612
  const b = linearize(channels[2]);
2612
2613
  const x = (0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / 0.95047;
2613
2614
  const y = 0.2126729 * r + 0.7151522 * g + 0.072175 * b;
2614
- const z41 = (0.0193339 * r + 0.119192 * g + 0.9503041 * b) / 1.08883;
2615
+ const z43 = (0.0193339 * r + 0.119192 * g + 0.9503041 * b) / 1.08883;
2615
2616
  const f = (t) => t > 8856e-6 ? Math.cbrt(t) : 7.787 * t + 16 / 116;
2616
2617
  const fx = f(x);
2617
2618
  const fy = f(y);
2618
- const fz = f(z41);
2619
+ const fz = f(z43);
2619
2620
  return [116 * fy - 16, 500 * (fx - fy), 200 * (fy - fz)];
2620
2621
  }
2621
2622
  function deltaE76(left, right) {
@@ -4230,7 +4231,10 @@ var TaskNodeSchema = z9.object({
4230
4231
  description: z9.string().trim().min(1),
4231
4232
  dependencies: z9.array(z9.string().trim().min(1)),
4232
4233
  expectedOutputs: z9.array(z9.string().trim().min(1)),
4233
- verification: z9.array(z9.string().trim().min(1))
4234
+ verification: z9.array(z9.string().trim().min(1)),
4235
+ files: z9.array(z9.string().trim().min(1)).describe(
4236
+ "Workspace files this task owns for writing. Tasks whose files overlap are never run in parallel, so declare every file this task may create or modify."
4237
+ ).optional()
4234
4238
  }).strict();
4235
4239
  var TaskGraphSchema = z9.object({
4236
4240
  nodes: z9.array(TaskNodeSchema)
@@ -4422,6 +4426,7 @@ var SubagentScheduler = class {
4422
4426
  const states = new Map(graph.nodes.map((task) => [task.id, "pending"]));
4423
4427
  const results = /* @__PURE__ */ new Map();
4424
4428
  const running = /* @__PURE__ */ new Map();
4429
+ const runningFiles = /* @__PURE__ */ new Map();
4425
4430
  const started = /* @__PURE__ */ new Set();
4426
4431
  try {
4427
4432
  while (statesHaveWork(states)) {
@@ -4430,7 +4435,9 @@ var SubagentScheduler = class {
4430
4435
  for (const task of graph.nodes) {
4431
4436
  if (running.size >= this.#options.maxSubagents) break;
4432
4437
  if (states.get(task.id) !== "pending" || !isReady(task, states)) continue;
4438
+ if (conflictsWithRunning(task, runningFiles)) continue;
4433
4439
  states.set(task.id, "running");
4440
+ if (task.files !== void 0) runningFiles.set(task.id, task.files.map(normalizeOwnedFile));
4434
4441
  const execution = this.#runTask(task, signal);
4435
4442
  running.set(task.id, execution);
4436
4443
  started.add(execution);
@@ -4443,6 +4450,7 @@ var SubagentScheduler = class {
4443
4450
  const completion = await Promise.race(running.values());
4444
4451
  signal.throwIfAborted();
4445
4452
  running.delete(completion.id);
4453
+ runningFiles.delete(completion.id);
4446
4454
  results.set(completion.id, completion.result);
4447
4455
  states.set(completion.id, completion.result.status);
4448
4456
  await this.#options.onResult?.(completion.result);
@@ -4520,6 +4528,26 @@ var SubagentScheduler = class {
4520
4528
  function isReady(task, states) {
4521
4529
  return task.dependencies.every((dependency) => states.get(dependency) === "completed");
4522
4530
  }
4531
+ function normalizeOwnedFile(value) {
4532
+ return value.replace(/\\/g, "/");
4533
+ }
4534
+ function ownedFilesConflict(left, right) {
4535
+ for (const one of left) {
4536
+ for (const other of right) {
4537
+ if (one === other) return true;
4538
+ if (other.startsWith(`${one}/`) || one.startsWith(`${other}/`)) return true;
4539
+ }
4540
+ }
4541
+ return false;
4542
+ }
4543
+ function conflictsWithRunning(task, runningFiles) {
4544
+ if (task.files === void 0 || task.files.length === 0) return false;
4545
+ const owned = task.files.map(normalizeOwnedFile);
4546
+ for (const files of runningFiles.values()) {
4547
+ if (ownedFilesConflict(owned, files)) return true;
4548
+ }
4549
+ return false;
4550
+ }
4523
4551
  function statesHaveWork(states) {
4524
4552
  return [...states.values()].some((state) => state === "pending" || state === "running");
4525
4553
  }
@@ -8686,23 +8714,45 @@ async function readJsonArray(file) {
8686
8714
  return [];
8687
8715
  }
8688
8716
  }
8717
+ async function readRules(file) {
8718
+ try {
8719
+ const parsed = JSON.parse(await readFile7(file, "utf8"));
8720
+ if (!Array.isArray(parsed)) return [];
8721
+ return parsed.filter((item) => item !== null && typeof item === "object").filter((item) => typeof item.id === "string" && typeof item.text === "string").map((item) => ({
8722
+ id: item.id,
8723
+ text: item.text,
8724
+ addedAt: typeof item.addedAt === "string" ? item.addedAt : "",
8725
+ ...typeof item.sourceId === "string" ? { sourceId: item.sourceId } : {}
8726
+ }));
8727
+ } catch {
8728
+ return [];
8729
+ }
8730
+ }
8731
+ async function writeRules(file, rules) {
8732
+ await mkdir8(dirname7(file), { recursive: true, mode: 448 });
8733
+ await writeFile6(file, JSON.stringify(rules, null, 2), { encoding: "utf8", mode: 384 });
8734
+ }
8689
8735
  var EvolveStore = class {
8690
8736
  dir;
8691
8737
  signalsFile;
8692
8738
  reflectionsFile;
8693
8739
  doneFile;
8694
8740
  verifiedFile;
8741
+ rulesFile;
8695
8742
  maxSignals;
8743
+ maxRules;
8696
8744
  // Serialize file mutations: tool hooks may fire in bursts.
8697
8745
  #queue = Promise.resolve();
8698
8746
  constructor(options) {
8699
- const { workspace, maxSignals = 400 } = options;
8747
+ const { workspace, maxSignals = 400, maxRules = 20 } = options;
8700
8748
  this.dir = join9(workspace, ".flavor", "evolve");
8701
8749
  this.signalsFile = join9(this.dir, "signals.jsonl");
8702
8750
  this.reflectionsFile = join9(this.dir, "reflections.jsonl");
8703
8751
  this.doneFile = join9(this.dir, "done.json");
8704
8752
  this.verifiedFile = join9(this.dir, "verified.json");
8753
+ this.rulesFile = join9(this.dir, "rules.json");
8705
8754
  this.maxSignals = maxSignals;
8755
+ this.maxRules = maxRules;
8706
8756
  }
8707
8757
  #enqueue(operation) {
8708
8758
  const next = this.#queue.then(operation, operation);
@@ -8848,6 +8898,43 @@ var EvolveStore = class {
8848
8898
  }
8849
8899
  });
8850
8900
  }
8901
+ /** Learned guardrail rules, oldest first. */
8902
+ listRules() {
8903
+ return this.#enqueue(() => readRules(this.rulesFile));
8904
+ }
8905
+ /**
8906
+ * Add one guardrail rule. Dedupes by fingerprint of the normalized text and
8907
+ * keeps at most maxRules entries (oldest dropped first).
8908
+ */
8909
+ addRule(input) {
8910
+ return this.#enqueue(async () => {
8911
+ const text = input.text.replace(/\s+/g, " ").trim().slice(0, 300);
8912
+ if (text === "") throw new Error("rule text must not be empty");
8913
+ const id = fingerprint("rule", void 0, text);
8914
+ const rules = await readRules(this.rulesFile);
8915
+ const existing = rules.find((rule2) => rule2.id === id);
8916
+ if (existing !== void 0) return { added: false, rule: existing };
8917
+ const rule = {
8918
+ id,
8919
+ text,
8920
+ addedAt: (/* @__PURE__ */ new Date()).toISOString(),
8921
+ ...input.sourceId === void 0 ? {} : { sourceId: input.sourceId }
8922
+ };
8923
+ rules.push(rule);
8924
+ if (rules.length > this.maxRules) rules.splice(0, rules.length - this.maxRules);
8925
+ await writeRules(this.rulesFile, rules);
8926
+ return { added: true, rule };
8927
+ });
8928
+ }
8929
+ removeRule(id) {
8930
+ return this.#enqueue(async () => {
8931
+ const rules = await readRules(this.rulesFile);
8932
+ const next = rules.filter((rule) => rule.id !== id);
8933
+ if (next.length === rules.length) return { removed: false };
8934
+ await writeRules(this.rulesFile, next);
8935
+ return { removed: true };
8936
+ });
8937
+ }
8851
8938
  };
8852
8939
 
8853
8940
  // src/evolve/service.ts
@@ -8859,9 +8946,15 @@ a plugin, a memory rule, a tool wrapper, or a safer default), implement it in
8859
8946
  this session when it is in scope; otherwise ignore them. Never act on them
8860
8947
  without running the test suite afterwards.
8861
8948
 
8949
+ `;
8950
+ var GUARDRAILS_SECTION_HEADER = `# learned guardrails (evolve)
8951
+
8952
+ These rules were distilled from repeated tool failures in this workspace.
8953
+ Follow them unless the current task or the user explicitly contradicts one.
8954
+
8862
8955
  `;
8863
8956
  var USAGE = [
8864
- "usage: /evolve <signals|suggest|improve <id>|verify <name>|reload <name>|test|revert <name>|done <id>|verified|clear>",
8957
+ "usage: /evolve <signals|suggest|improve <id>|verify <name>|reload <name>|test|revert <name>|done <id>|verified|trends [n]|rule <list|add|remove>|clear>",
8865
8958
  " signals list recent failing tool results",
8866
8959
  " suggest aggregate repeated failures into fix suggestions (trend-aware ordering)",
8867
8960
  " improve scaffold a fix-<tool>/ plugin dir + PLAN.md for one suggestion",
@@ -8871,6 +8964,8 @@ var USAGE = [
8871
8964
  " revert restore the last good snapshot of a plugin",
8872
8965
  " done mark a suggestion as handled (no longer proposed)",
8873
8966
  " verified list suggestions auto-verified by improving failure trends",
8967
+ " trends cross-run dashboard: tool calls, failures, signalDelta, per-tool movement",
8968
+ " rule manage learned guardrails injected into system prompts (list/add <text>/remove <id>)",
8874
8969
  " clear reset signals, done markers, and verified markers"
8875
8970
  ].join("\n");
8876
8971
  function runCommand(command, cwd, timeoutMs) {
@@ -8962,9 +9057,17 @@ function createEvolveService(options) {
8962
9057
  }
8963
9058
  async function refreshPromptCache() {
8964
9059
  try {
8965
- const suggestions = await openWithTrends(promptTop);
8966
- promptCache = suggestions.length === 0 ? void 0 : `${SUGGEST_SECTION_HEADER}${suggestions.map((suggestion) => `- [${suggestion.id}] ${suggestion.hint}`).join("\n")}
8967
- `;
9060
+ const [suggestions, rules] = await Promise.all([openWithTrends(promptTop), store.listRules()]);
9061
+ const sections = [];
9062
+ if (rules.length > 0) {
9063
+ sections.push(`${GUARDRAILS_SECTION_HEADER}${rules.map((rule) => `- ${rule.text}`).join("\n")}
9064
+ `);
9065
+ }
9066
+ if (suggestions.length > 0) {
9067
+ sections.push(`${SUGGEST_SECTION_HEADER}${suggestions.map((suggestion) => `- [${suggestion.id}] ${suggestion.hint}`).join("\n")}
9068
+ `);
9069
+ }
9070
+ promptCache = sections.length === 0 ? void 0 : sections.join("\n");
8968
9071
  } catch (error) {
8969
9072
  logger.warn(`prompt section failed \u2014 ${error instanceof Error ? error.message : String(error)}`);
8970
9073
  }
@@ -9144,6 +9247,41 @@ function createEvolveService(options) {
9144
9247
  return signal === void 0 ? `[${id}] (signal no longer recorded)` : `[${id}] ${signal.tool} x${signal.count} \u2014 ${signal.error} (verified)`;
9145
9248
  }).join("\n");
9146
9249
  }
9250
+ if (arg === "trends" || arg.startsWith("trends ")) {
9251
+ const requested = Number.parseInt(arg.slice(6).trim(), 10);
9252
+ const count = Number.isNaN(requested) ? 5 : Math.min(Math.max(requested, 1), 50);
9253
+ const reflections = await store.reflections(count);
9254
+ if (reflections.length === 0) return "no reflections recorded yet \u2014 trends appear after runs end";
9255
+ const sign = (value) => value > 0 ? `+${value}` : String(value);
9256
+ const lines = [`evolve trends (last ${reflections.length} run(s), newest first)`];
9257
+ for (const reflection of reflections) {
9258
+ lines.push(`${reflection.at.replace("T", " ").slice(0, 19)} ${reflection.reason}: model calls ${reflection.iterations}, tool calls ${reflection.toolCalls} (${reflection.toolErrors} failed), failures ${reflection.totalFailures} (delta ${sign(reflection.signalDelta)})`);
9259
+ const moved = Object.entries(reflection.perTool ?? {}).filter(([, trend]) => trend.delta !== 0);
9260
+ for (const [tool, trend] of moved) {
9261
+ lines.push(` - ${tool}: ${trend.failures} failure(s) this run (${sign(trend.delta)} vs previous)`);
9262
+ }
9263
+ }
9264
+ return lines.join("\n");
9265
+ }
9266
+ if (arg === "rule" || arg === "rule list") {
9267
+ const rules = await store.listRules();
9268
+ if (rules.length === 0) return "no guardrail rules yet \u2014 add one with /evolve rule add <text>";
9269
+ return rules.map((rule) => `[${rule.id}] ${rule.text}`).join("\n");
9270
+ }
9271
+ if (arg.startsWith("rule add ")) {
9272
+ const text = arg.slice(9).trim();
9273
+ if (text === "") return "usage: /evolve rule add <text>";
9274
+ const { added, rule } = await store.addRule({ text });
9275
+ await refreshPromptCache();
9276
+ return added ? `added guardrail [${rule.id}]: ${rule.text}` : `guardrail already exists [${rule.id}]: ${rule.text}`;
9277
+ }
9278
+ if (arg.startsWith("rule remove ")) {
9279
+ const id = arg.slice(12).trim();
9280
+ if (id === "") return "usage: /evolve rule remove <id>";
9281
+ const { removed } = await store.removeRule(id);
9282
+ await refreshPromptCache();
9283
+ return removed ? `removed guardrail ${id}` : `no guardrail with id "${id}"`;
9284
+ }
9147
9285
  if (arg.startsWith("improve ")) {
9148
9286
  const suggestionId = arg.slice(8).trim();
9149
9287
  const suggestions = await openWithTrends(100);
@@ -9215,18 +9353,31 @@ ${result.stderr.slice(-4e3)}` : ""}`;
9215
9353
  toolDefinition() {
9216
9354
  const inputSchema = z17.object({
9217
9355
  suggestionId: z17.string().min(1).describe("Signal id from the evolve suggestions"),
9218
- implementation: z17.string().min(1).describe("Concise description of the plugin fix to implement")
9356
+ implementation: z17.string().min(1).describe("Concise description of the fix to implement (plugin plan, or the guardrail rule text when kind is prompt_rule)"),
9357
+ kind: z17.enum(["plugin", "prompt_rule"]).optional().describe(
9358
+ "plugin (default): scaffold a fix plugin; prompt_rule: store a guardrail rule that is injected into future system prompts"
9359
+ )
9219
9360
  });
9220
9361
  return {
9221
9362
  name: "evolve_improve",
9222
- description: "Implement a fix for one repeated tool failure as a flavor-code plugin: scaffolds the fix-<tool>/ plugin dir, writes PLAN.md, and returns instructions for implementing, verifying, reloading, and testing it. Use when the model proposes a concrete plugin-level fix for a suggestion in the system prompt.",
9363
+ description: "Implement a fix for one repeated tool failure. Default kind=plugin scaffolds the fix-<tool>/ plugin dir and writes PLAN.md with instructions for implementing, verifying, reloading, and testing it. kind=prompt_rule instead stores a concise guardrail rule (from `implementation`) that is injected into future system prompts and closes the suggestion. Use when the model proposes a concrete fix for a suggestion in the system prompt.",
9223
9364
  inputSchema,
9224
9365
  paths: () => [],
9225
9366
  execute: async (input) => {
9226
- const { suggestionId, implementation } = input;
9367
+ const { suggestionId, implementation, kind } = input;
9227
9368
  const suggestions = await openWithTrends(100);
9228
9369
  const suggestion = suggestions.find((item) => item.id === suggestionId);
9229
9370
  if (suggestion === void 0) throw new Error(`No open suggestion with id "${suggestionId}".`);
9371
+ if (kind === "prompt_rule") {
9372
+ const { added, rule } = await store.addRule({ text: implementation, sourceId: suggestionId });
9373
+ await store.markSuggestionDone(suggestionId);
9374
+ await refreshPromptCache();
9375
+ return [
9376
+ added ? `Stored guardrail rule [${rule.id}]: ${rule.text}` : `Guardrail already exists [${rule.id}]: ${rule.text}`,
9377
+ `Suggestion [${suggestion.id}] marked done. The rule is injected into the system prompt of future runs.`,
9378
+ "Review rules with /evolve rule list; remove one with /evolve rule remove <id>."
9379
+ ].join("\n");
9380
+ }
9230
9381
  const name = sanitizePluginName(suggestion.tool);
9231
9382
  const dir = await scaffoldFixPlugin(workspace, name);
9232
9383
  await writeFile7(join10(dir, "PLAN.md"), buildPlan(suggestion, name, implementation), "utf8");
@@ -11060,7 +11211,7 @@ import { readFile as readFile12 } from "fs/promises";
11060
11211
  import { join as join17 } from "path";
11061
11212
 
11062
11213
  // src/tools/shell.ts
11063
- import { spawn as spawn3 } from "child_process";
11214
+ import { spawn as spawn3, spawnSync } from "child_process";
11064
11215
  import { isAbsolute as isAbsolute8, relative as relative11, resolve as resolve13, sep as sep10 } from "path";
11065
11216
  import { z as z21 } from "zod";
11066
11217
 
@@ -11190,6 +11341,29 @@ function tokenizeCommandLine(command) {
11190
11341
  function unquoteToken(token) {
11191
11342
  return token.length >= 2 && token.startsWith('"') && token.endsWith('"') ? token.slice(1, -1) : token;
11192
11343
  }
11344
+ var cachedWindowsShell;
11345
+ function hasExecutable(name) {
11346
+ try {
11347
+ return spawnSync("where", [name], { stdio: "ignore", windowsHide: true }).status === 0;
11348
+ } catch {
11349
+ return false;
11350
+ }
11351
+ }
11352
+ function detectWindowsShell() {
11353
+ if (cachedWindowsShell !== void 0) return cachedWindowsShell;
11354
+ cachedWindowsShell = hasExecutable("pwsh") ? "pwsh" : hasExecutable("powershell") ? "powershell" : "cmd";
11355
+ return cachedWindowsShell;
11356
+ }
11357
+ function psQuote(token) {
11358
+ return `'${token.replace(/'/g, "''")}'`;
11359
+ }
11360
+ function buildWindowsCommandLine(kind, commandLine, command, args) {
11361
+ if (kind === "cmd") return `chcp 65001>nul & ${commandLine}`;
11362
+ const executable = kind === "pwsh" ? "pwsh" : "powershell";
11363
+ const script = `& ${psQuote(command)}${args.length > 0 ? ` ${args.map(psQuote).join(" ")}` : ""}; exit $LASTEXITCODE`;
11364
+ const encoded = Buffer.from(script, "utf16le").toString("base64");
11365
+ return `chcp 65001>nul & ${executable} -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -EncodedCommand ${encoded}`;
11366
+ }
11193
11367
  function createShellTool(workspace, options = {}) {
11194
11368
  const root = resolve13(workspace);
11195
11369
  const maxBytes = options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES2;
@@ -11310,7 +11484,7 @@ async function executeShell(root, input, cancellation, maxBytes, onOutput) {
11310
11484
  const quoteArg = (s) => s.includes(" ") ? `"${s.replace(/"/g, '""')}"` : s;
11311
11485
  const quoted = input.args.map(quoteArg).join(" ");
11312
11486
  const commandLine = quoted.length > 0 ? `${quoteArg(input.command)} ${quoted}` : quoteArg(input.command);
11313
- const shellCommandLine = process.platform === "win32" ? `chcp 65001>nul & ${commandLine}` : commandLine;
11487
+ const shellCommandLine = process.platform === "win32" ? buildWindowsCommandLine(detectWindowsShell(), commandLine, input.command, input.args) : commandLine;
11314
11488
  const child = spawn3(shellCommandLine, {
11315
11489
  cwd,
11316
11490
  shell: true,
@@ -12940,6 +13114,11 @@ function escapeHtml(text) {
12940
13114
 
12941
13115
  // src/auth/store.ts
12942
13116
  import { dirname as dirname13 } from "path";
13117
+ async function retainOnlyCredentials(store, keepCredentialId) {
13118
+ const tokens2 = await store.load();
13119
+ const retained = Object.fromEntries(Object.entries(tokens2).filter(([id]) => id === keepCredentialId));
13120
+ await store.save(retained);
13121
+ }
12943
13122
  function createFileTokenStore(filePath) {
12944
13123
  let baseline = {};
12945
13124
  const store = {
@@ -13100,11 +13279,11 @@ Treat the assigned task as self-contained. The caller may not share its full con
13100
13279
  Own the user's request end to end. Collaborate when a choice materially changes the result, but use sound judgment for ordinary in-scope implementation details. Keep the user informed at meaningful milestones, synthesize any child-agent results yourself, and do not stop while safe, relevant work remains. A forked child receives an explicit Subagent directive after the inherited conversation; in that case, follow that narrower directive for the child assignment.`;
13101
13280
  }
13102
13281
  function environmentSection(options) {
13103
- const git2 = options.environment.isGitRepository === "unknown" ? "unknown" : options.environment.isGitRepository ? "yes" : "no";
13282
+ const git3 = options.environment.isGitRepository === "unknown" ? "unknown" : options.environment.isGitRepository ? "yes" : "no";
13104
13283
  return `# Environment
13105
13284
 
13106
13285
  - Working directory: ${data(options.workspace)}
13107
- - Git repository: ${git2}
13286
+ - Git repository: ${git3}
13108
13287
  - Platform: ${data(options.environment.platform)}
13109
13288
  - OS version: ${data(options.environment.osVersion)}
13110
13289
  - Shell: ${data(options.environment.shell)}`;
@@ -17559,19 +17738,255 @@ function severityLabel(severity) {
17559
17738
  }
17560
17739
  }
17561
17740
 
17562
- // src/tools/ask-user-question.ts
17741
+ // src/git/service.ts
17742
+ async function git2(workspace, args, timeoutMs = 3e4) {
17743
+ const result = await execFileNoThrow("git", ["-C", workspace, ...args], { timeout: timeoutMs, useCwd: false });
17744
+ return { ok: result.code === 0, stdout: result.stdout, stderr: result.stderr, code: result.code };
17745
+ }
17746
+ async function isGitRepository(workspace) {
17747
+ const result = await git2(workspace, ["rev-parse", "--is-inside-work-tree"], 2e3);
17748
+ return result.ok && result.stdout.trim() === "true";
17749
+ }
17750
+ function gitFailure(result, action) {
17751
+ const detail = result.stderr.trim() || result.stdout.trim() || `exit code ${result.code}`;
17752
+ return new Error(`git ${action} failed: ${detail.split("\n")[0]}`);
17753
+ }
17754
+ async function changeSummary(workspace) {
17755
+ const branch = await git2(workspace, ["rev-parse", "--abbrev-ref", "HEAD"]);
17756
+ const head = await git2(workspace, ["rev-parse", "--short", "HEAD"]);
17757
+ const status = await git2(workspace, ["status", "--porcelain"]);
17758
+ if (!status.ok) throw gitFailure(status, "status");
17759
+ const statusLines = status.stdout.split("\n").map((line) => line.trimEnd()).filter((line) => line.length > 0);
17760
+ const stagedFiles = [];
17761
+ const unstagedFiles = [];
17762
+ const untrackedFiles = [];
17763
+ for (const line of statusLines) {
17764
+ const index = line[0] ?? " ";
17765
+ const worktree = line[1] ?? " ";
17766
+ const file = line.slice(3);
17767
+ if (index === "?" && worktree === "?") {
17768
+ untrackedFiles.push(file);
17769
+ continue;
17770
+ }
17771
+ if (index !== " " && index !== "?") stagedFiles.push(file);
17772
+ if (worktree !== " " && worktree !== "?") unstagedFiles.push(file);
17773
+ }
17774
+ return {
17775
+ branch: branch.ok ? branch.stdout.trim() : "HEAD",
17776
+ head: head.ok ? head.stdout.trim() : "unknown",
17777
+ statusLines,
17778
+ stagedFiles: [...new Set(stagedFiles)],
17779
+ unstagedFiles: [...new Set(unstagedFiles)],
17780
+ untrackedFiles
17781
+ };
17782
+ }
17783
+ async function stagedDiff(workspace, maxChars = 96e3) {
17784
+ const stat16 = await git2(workspace, ["diff", "--staged", "--stat"]);
17785
+ const diff = await git2(workspace, ["diff", "--staged", "--no-ext-diff", "--no-color"]);
17786
+ if (!diff.ok) throw gitFailure(diff, "diff --staged");
17787
+ const text = diff.stdout;
17788
+ return {
17789
+ diff: text.length > maxChars ? `${text.slice(0, maxChars)}
17790
+ \u2026[diff truncated]` : text,
17791
+ stat: stat16.stdout.trim(),
17792
+ truncated: text.length > maxChars
17793
+ };
17794
+ }
17795
+ async function uncommittedDiff(workspace, maxChars = 96e3) {
17796
+ const stat16 = await git2(workspace, ["diff", "HEAD", "--stat"]);
17797
+ const diff = await git2(workspace, ["diff", "HEAD", "--no-ext-diff", "--no-color"]);
17798
+ if (!diff.ok && !diff.stderr.includes("unknown revision")) throw gitFailure(diff, "diff HEAD");
17799
+ const summary2 = await changeSummary(workspace);
17800
+ const text = diff.stdout;
17801
+ return {
17802
+ diff: text.length > maxChars ? `${text.slice(0, maxChars)}
17803
+ \u2026[diff truncated]` : text,
17804
+ stat: stat16.stdout.trim(),
17805
+ untracked: summary2.untrackedFiles
17806
+ };
17807
+ }
17808
+ async function stageAll(workspace) {
17809
+ const result = await git2(workspace, ["add", "-A"]);
17810
+ if (!result.ok) throw gitFailure(result, "add");
17811
+ }
17812
+ async function commit(workspace, commitMessage) {
17813
+ const result = await execFileNoThrow("git", ["-C", workspace, "commit", "-F", "-"], {
17814
+ timeout: 3e4,
17815
+ useCwd: false,
17816
+ input: commitMessage
17817
+ });
17818
+ if (result.code !== 0) {
17819
+ const detail = result.stderr.trim() || result.stdout.trim() || `exit code ${result.code}`;
17820
+ throw new Error(`git commit failed: ${detail.split("\n")[0]}`);
17821
+ }
17822
+ const head = await git2(workspace, ["log", "-1", "--pretty=%h %s"]);
17823
+ return head.stdout.trim() || "committed";
17824
+ }
17825
+ async function fileHistory(workspace, path, limit) {
17826
+ const args = [
17827
+ "log",
17828
+ `--max-count=${limit}`,
17829
+ "--date=short",
17830
+ "--pretty=format:%h%x1f%ad%x1f%an%x1f%s",
17831
+ ...path === void 0 ? [] : ["--follow", "--", path]
17832
+ ];
17833
+ const result = await git2(workspace, args, 15e3);
17834
+ if (!result.ok) throw gitFailure(result, "log");
17835
+ return result.stdout.split("\n").filter((line) => line.trim().length > 0).map((line) => {
17836
+ const [hash = "", date = "", author = "", ...subject] = line.split("");
17837
+ return { hash, date, author, subject: subject.join("") };
17838
+ });
17839
+ }
17840
+ async function gitMarker(workspace) {
17841
+ try {
17842
+ if (!await isGitRepository(workspace)) return void 0;
17843
+ const summary2 = await changeSummary(workspace);
17844
+ if (summary2.head === "unknown") return void 0;
17845
+ const dirty = summary2.statusLines.length > 0 ? "-dirty" : "";
17846
+ return `${summary2.branch}@${summary2.head}${dirty}`;
17847
+ } catch {
17848
+ return void 0;
17849
+ }
17850
+ }
17851
+
17852
+ // src/git/insights.ts
17563
17853
  import { z as z30 } from "zod";
17564
- var QuestionOptionSchema = z30.object({
17565
- label: z30.string().trim().min(1),
17566
- description: z30.string().trim().min(1)
17854
+ async function suggestCommitMessage(options, input, signal) {
17855
+ const prompt = [
17856
+ "Write a git commit message for the staged changes below.",
17857
+ "Rules: Conventional Commits style (feat/fix/refactor/docs/test/chore scope); a short imperative subject line <= 72 chars; an optional body only when the change needs explanation; no code fences; reply with the commit message only.",
17858
+ ...input.hint === void 0 || input.hint.trim() === "" ? [] : [`The user added this context: ${input.hint.trim()}`],
17859
+ "",
17860
+ `Change summary:
17861
+ ${input.stat}`,
17862
+ "",
17863
+ `Diff:
17864
+ ${input.diff}`
17865
+ ].join("\n");
17866
+ const { adapter, model } = options.registry.get(options.modelId());
17867
+ let text = "";
17868
+ for await (const event of adapter.stream({
17869
+ model,
17870
+ messages: [{ role: "user", content: prompt }],
17871
+ tools: [],
17872
+ signal
17873
+ })) {
17874
+ if (event.type === "text") text += event.text;
17875
+ else if (event.type === "error") throw new Error(`commit message generation failed: ${event.error.message}`);
17876
+ else if (event.type === "done") break;
17877
+ }
17878
+ const cleaned = cleanCommitMessage(text);
17879
+ if (cleaned === "") throw new Error("commit message generation returned no text");
17880
+ return cleaned;
17881
+ }
17882
+ function cleanCommitMessage(raw) {
17883
+ const trimmed = raw.trim().replace(/^```[a-z]*\s*/iu, "").replace(/```$/u, "").trim();
17884
+ const lines = trimmed.split("\n");
17885
+ const kept = [];
17886
+ for (const line of lines) {
17887
+ if (/^(here('|’)s|notes?:|explanation:)/iu.test(line.trim()) && kept.length > 0) break;
17888
+ kept.push(line);
17889
+ }
17890
+ return kept.join("\n").trim().slice(0, 2e3);
17891
+ }
17892
+ var ReviewFindingSchema = z30.object({
17893
+ severity: z30.enum(["critical", "warning", "nit"]),
17894
+ file: z30.string(),
17895
+ line: z30.string().describe('Line number or hunk header the finding refers to, e.g. "42" or "@@ -10,4 +10,6 @@"'),
17896
+ issue: z30.string(),
17897
+ suggestion: z30.string()
17898
+ }).strict();
17899
+ var ReviewReportSchema = z30.object({
17900
+ summary: z30.string().describe("One-paragraph overall assessment of the change"),
17901
+ verdict: z30.enum(["ship", "ship-with-fixes", "needs-work"]),
17902
+ findings: z30.array(ReviewFindingSchema).max(20)
17903
+ }).strict();
17904
+ async function reviewDiff(options, input, signal) {
17905
+ const prompt = [
17906
+ "You are reviewing uncommitted local changes before the user commits them.",
17907
+ "Focus on: correctness bugs, broken error handling, security issues (secrets, injection, path traversal), missing edge cases, and obvious test gaps.",
17908
+ "Do not comment on formatting or style unless it hides a bug. Report at most the 10 most important findings.",
17909
+ ...input.focus === void 0 || input.focus.trim() === "" ? [] : [`The user specifically wants attention on: ${input.focus.trim()}`],
17910
+ ...input.untracked.length === 0 ? [] : [`Untracked files not shown in the diff: ${input.untracked.join(", ")}`],
17911
+ "",
17912
+ `Change summary:
17913
+ ${input.stat}`,
17914
+ "",
17915
+ `Diff:
17916
+ ${input.diff}`
17917
+ ].join("\n");
17918
+ const structured = withStructuredOutput({
17919
+ registry: options.registry,
17920
+ modelId: options.modelId(),
17921
+ name: "report_review",
17922
+ description: "Structured review report for uncommitted changes",
17923
+ schema: ReviewReportSchema
17924
+ });
17925
+ const { value } = await structured.invoke({
17926
+ messages: [{ role: "user", content: prompt }],
17927
+ signal
17928
+ });
17929
+ return value;
17930
+ }
17931
+ function formatReviewReport(report) {
17932
+ const lines = [`Review verdict: ${report.verdict}`, "", report.summary.trim()];
17933
+ if (report.findings.length > 0) {
17934
+ lines.push("", "Findings:");
17935
+ for (const finding of report.findings) {
17936
+ lines.push(`- [${finding.severity}] ${finding.file}${finding.line === "" ? "" : `:${finding.line}`} \u2014 ${finding.issue}`);
17937
+ if (finding.suggestion.trim() !== "") lines.push(` fix: ${finding.suggestion}`);
17938
+ }
17939
+ } else {
17940
+ lines.push("", "No issues found.");
17941
+ }
17942
+ return lines.join("\n");
17943
+ }
17944
+
17945
+ // src/git/tools.ts
17946
+ import { z as z31 } from "zod";
17947
+ var GitHistoryInput = z31.object({
17948
+ path: z31.string().describe("File to inspect; omit for the whole repository history").optional(),
17949
+ limit: z31.number().int().min(1).max(50).describe("Maximum number of commits to return (default 20)").optional()
17950
+ });
17951
+ function createGitHistoryTool(workspace) {
17952
+ return {
17953
+ name: "GitHistory",
17954
+ description: "Show git commit history for the repository or for one file (follows renames). Use to understand when and why code changed.",
17955
+ inputSchema: GitHistoryInput,
17956
+ readOnly: true,
17957
+ paths: (input) => input.path === void 0 ? [] : [input.path],
17958
+ summarize: (input) => input.path ?? "repository",
17959
+ renderForModel: (output) => output,
17960
+ async execute(input, signal) {
17961
+ signal.throwIfAborted();
17962
+ if (!await isGitRepository(workspace)) throw new Error("Not a git repository");
17963
+ const limit = input.limit ?? 20;
17964
+ const entries = await fileHistory(workspace, input.path, limit);
17965
+ if (entries.length === 0) {
17966
+ return input.path === void 0 ? "No commits found." : `No commits found for ${input.path} (the file may be untracked).`;
17967
+ }
17968
+ const scope2 = input.path === void 0 ? "repository" : input.path;
17969
+ return [
17970
+ `git history for ${scope2} (${entries.length} commits):`,
17971
+ ...entries.map((entry2) => `${entry2.hash} ${entry2.date} ${entry2.author}: ${entry2.subject}`)
17972
+ ].join("\n");
17973
+ }
17974
+ };
17975
+ }
17976
+
17977
+ // src/tools/ask-user-question.ts
17978
+ import { z as z32 } from "zod";
17979
+ var QuestionOptionSchema = z32.object({
17980
+ label: z32.string().trim().min(1),
17981
+ description: z32.string().trim().min(1)
17567
17982
  });
17568
- var QuestionSchema = z30.object({
17569
- question: z30.string().trim().min(1),
17570
- header: z30.string().trim().min(1),
17571
- options: z30.array(QuestionOptionSchema).min(1).max(4)
17983
+ var QuestionSchema = z32.object({
17984
+ question: z32.string().trim().min(1),
17985
+ header: z32.string().trim().min(1),
17986
+ options: z32.array(QuestionOptionSchema).min(1).max(4)
17572
17987
  });
17573
- var AskUserQuestionInput = z30.object({
17574
- questions: z30.array(QuestionSchema).min(1).max(4)
17988
+ var AskUserQuestionInput = z32.object({
17989
+ questions: z32.array(QuestionSchema).min(1).max(4)
17575
17990
  });
17576
17991
  function hookAnswersFromUpdatedInput(updatedInput, questions) {
17577
17992
  if (typeof updatedInput !== "object" || updatedInput === null) return void 0;
@@ -17655,20 +18070,20 @@ function createAskUserQuestionTool(handler) {
17655
18070
  }
17656
18071
 
17657
18072
  // src/tools/todo-write.ts
17658
- import { z as z31 } from "zod";
17659
- var TodoStatusSchema = z31.enum([
18073
+ import { z as z33 } from "zod";
18074
+ var TodoStatusSchema = z33.enum([
17660
18075
  "pending",
17661
18076
  "in_progress",
17662
18077
  "completed",
17663
18078
  "cancelled"
17664
18079
  ]);
17665
- var TodoItemSchema = z31.object({
17666
- content: z31.string().trim().min(1),
18080
+ var TodoItemSchema = z33.object({
18081
+ content: z33.string().trim().min(1),
17667
18082
  status: TodoStatusSchema,
17668
- activeForm: z31.string().trim().min(1)
18083
+ activeForm: z33.string().trim().min(1)
17669
18084
  });
17670
- var TodoWriteInput = z31.object({
17671
- todos: z31.array(TodoItemSchema).min(1).max(50)
18085
+ var TodoWriteInput = z33.object({
18086
+ todos: z33.array(TodoItemSchema).min(1).max(50)
17672
18087
  });
17673
18088
  function createTodoWriteTool() {
17674
18089
  return {
@@ -17705,36 +18120,36 @@ function createTodoWriteTool() {
17705
18120
  import { randomUUID as randomUUID14 } from "crypto";
17706
18121
  import { link, lstat as lstat11, mkdir as mkdir20, readFile as readFile20, readdir as readdir10, unlink as unlink2, writeFile as writeFile12 } from "fs/promises";
17707
18122
  import { dirname as dirname20, join as join24, resolve as resolve24 } from "path";
17708
- import { z as z32 } from "zod";
18123
+ import { z as z34 } from "zod";
17709
18124
  var MANAGED_TOOL_VERSION = 1;
17710
18125
  var MAX_RECORD_BYTES = 256 * 1024;
17711
18126
  var TOOL_NAME = /^[A-Za-z][A-Za-z0-9_]{0,63}$/;
17712
- var JsonSchemaObject = z32.record(z32.string(), z32.unknown()).superRefine((schema, context) => {
18127
+ var JsonSchemaObject = z34.record(z34.string(), z34.unknown()).superRefine((schema, context) => {
17713
18128
  if (schema.type !== "object") {
17714
18129
  context.addIssue({ code: "custom", message: "Tool input JSON Schema must have type object" });
17715
18130
  }
17716
18131
  });
17717
- var RegisterManagedToolInputSchema = z32.object({
17718
- name: z32.string().regex(TOOL_NAME).describe("Unique callable tool name using letters, digits, and underscores"),
17719
- description: z32.string().min(1).max(4096).describe("Purpose and appropriate use of the generated tool"),
18132
+ var RegisterManagedToolInputSchema = z34.object({
18133
+ name: z34.string().regex(TOOL_NAME).describe("Unique callable tool name using letters, digits, and underscores"),
18134
+ description: z34.string().min(1).max(4096).describe("Purpose and appropriate use of the generated tool"),
17720
18135
  inputSchema: JsonSchemaObject.describe("Provider-facing JSON Schema with an object at the root"),
17721
- implementation: z32.string().min(1).max(64 * 1024).describe(
18136
+ implementation: z34.string().min(1).max(64 * 1024).describe(
17722
18137
  "Async JavaScript function body, or complete function/arrow expression, receiving input, signal, and context; return the tool result"
17723
18138
  ),
17724
- scope: z32.enum(["project", "global"]).default("project").describe(
18139
+ scope: z34.enum(["project", "global"]).default("project").describe(
17725
18140
  "Project persists in the current workspace; global persists for every workspace"
17726
18141
  ),
17727
- agents: z32.array(z32.enum(["main", "subagent"])).min(1).max(2).optional().describe(
18142
+ agents: z34.array(z34.enum(["main", "subagent"])).min(1).max(2).optional().describe(
17728
18143
  "Agent roles allowed to call the generated tool; omit to allow both"
17729
18144
  )
17730
18145
  }).strict();
17731
- var RemoveManagedToolInputSchema = z32.object({
17732
- name: z32.string().regex(TOOL_NAME).describe("Managed tool name to remove"),
17733
- scope: z32.enum(["project", "global"]).optional().describe("Required only when the same name exists in both scopes")
18146
+ var RemoveManagedToolInputSchema = z34.object({
18147
+ name: z34.string().regex(TOOL_NAME).describe("Managed tool name to remove"),
18148
+ scope: z34.enum(["project", "global"]).optional().describe("Required only when the same name exists in both scopes")
17734
18149
  }).strict();
17735
18150
  var ManagedToolRecordSchema = RegisterManagedToolInputSchema.extend({
17736
- version: z32.literal(MANAGED_TOOL_VERSION),
17737
- createdAt: z32.string().datetime()
18151
+ version: z34.literal(MANAGED_TOOL_VERSION),
18152
+ createdAt: z34.string().datetime()
17738
18153
  }).strict();
17739
18154
  var AsyncFunction = Object.getPrototypeOf(async function() {
17740
18155
  }).constructor;
@@ -17921,7 +18336,7 @@ function createManagedToolManagementTools(options) {
17921
18336
  const listTools = {
17922
18337
  name: "ListRegisteredTools",
17923
18338
  description: "List durable tools created through RegisterTool, including scope, path, and active precedence",
17924
- inputSchema: z32.object({}).strict(),
18339
+ inputSchema: z34.object({}).strict(),
17925
18340
  agents: mainOnly,
17926
18341
  paths: () => [],
17927
18342
  execute: async (_input, signal) => {
@@ -17934,7 +18349,7 @@ function createManagedToolManagementTools(options) {
17934
18349
  function compileDefinition(record3, scope2, workspace) {
17935
18350
  let inputSchema;
17936
18351
  try {
17937
- inputSchema = z32.fromJSONSchema(record3.inputSchema);
18352
+ inputSchema = z34.fromJSONSchema(record3.inputSchema);
17938
18353
  } catch (error) {
17939
18354
  throw new Error(`Invalid input schema for managed tool "${record3.name}": ${message(error)}`);
17940
18355
  }
@@ -18034,7 +18449,7 @@ function isMissing4(error) {
18034
18449
  }
18035
18450
 
18036
18451
  // src/pals/protocol.ts
18037
- import { z as z33 } from "zod";
18452
+ import { z as z35 } from "zod";
18038
18453
  var PROTOCOL_VERSION = 1;
18039
18454
  var MAX_ALIAS_LENGTH = 64;
18040
18455
  var MAX_MESSAGE_BYTES = 32 * 1024;
@@ -18051,65 +18466,65 @@ var MIN_UUID_PREFIX_LENGTH = 8;
18051
18466
  function normalizePalIdentity(value) {
18052
18467
  return value.trim().toLocaleLowerCase("en-US");
18053
18468
  }
18054
- var VersionSchema = z33.literal(PROTOCOL_VERSION);
18055
- var UuidSchema = z33.uuid();
18056
- var PrintableIdentitySchema = z33.string().trim().min(1).max(MAX_ALIAS_LENGTH).refine(
18469
+ var VersionSchema = z35.literal(PROTOCOL_VERSION);
18470
+ var UuidSchema = z35.uuid();
18471
+ var PrintableIdentitySchema = z35.string().trim().min(1).max(MAX_ALIAS_LENGTH).refine(
18057
18472
  (value) => !/[\p{Cc}\uD800-\uDFFF]/u.test(value),
18058
18473
  "Identity must contain only printable non-control Unicode"
18059
18474
  );
18060
18475
  var PalAliasSchema = PrintableIdentitySchema;
18061
18476
  var PalTargetSchema = PrintableIdentitySchema;
18062
- var BoundedTextSchema = z33.string().refine(
18477
+ var BoundedTextSchema = z35.string().refine(
18063
18478
  (value) => Buffer.byteLength(value, "utf8") <= MAX_MESSAGE_BYTES,
18064
18479
  `Text must not exceed ${MAX_MESSAGE_BYTES} UTF-8 bytes`
18065
18480
  );
18066
18481
  var NonEmptyBoundedTextSchema = BoundedTextSchema.refine((value) => value.length > 0, "Text must not be empty");
18067
- var CompletionDetailSchema = z33.string().trim().min(1).refine(
18482
+ var CompletionDetailSchema = z35.string().trim().min(1).refine(
18068
18483
  (value) => Buffer.byteLength(value, "utf8") <= MAX_COMPLETION_DETAIL_BYTES,
18069
18484
  `Completion evidence must not exceed ${MAX_COMPLETION_DETAIL_BYTES} UTF-8 bytes`
18070
18485
  );
18071
- var PalPresenceSchema = z33.object({
18486
+ var PalPresenceSchema = z35.object({
18072
18487
  version: VersionSchema,
18073
18488
  id: UuidSchema,
18074
18489
  alias: PalAliasSchema,
18075
- projectPath: z33.string().min(1).refine(
18490
+ projectPath: z35.string().min(1).refine(
18076
18491
  (value) => Buffer.byteLength(value, "utf8") <= MAX_PROJECT_PATH_BYTES,
18077
18492
  `Project path must not exceed ${MAX_PROJECT_PATH_BYTES} UTF-8 bytes`
18078
18493
  ),
18079
- connectedAt: z33.iso.datetime(),
18080
- lastSeenAt: z33.iso.datetime()
18494
+ connectedAt: z35.iso.datetime(),
18495
+ lastSeenAt: z35.iso.datetime()
18081
18496
  }).strict();
18082
- var PalPresenceListSchema = z33.array(PalPresenceSchema).max(MAX_ACTIVE_PALS);
18083
- var PalTaskMessageSchema = z33.object({
18497
+ var PalPresenceListSchema = z35.array(PalPresenceSchema).max(MAX_ACTIVE_PALS);
18498
+ var PalTaskMessageSchema = z35.object({
18084
18499
  version: VersionSchema,
18085
- type: z33.literal("task"),
18500
+ type: z35.literal("task"),
18086
18501
  messageId: UuidSchema,
18087
18502
  target: PalTargetSchema,
18088
18503
  goal: NonEmptyBoundedTextSchema
18089
18504
  }).strict();
18090
- var PalTaskEventSchema = z33.object({
18505
+ var PalTaskEventSchema = z35.object({
18091
18506
  version: VersionSchema,
18092
- type: z33.literal("task-event"),
18507
+ type: z35.literal("task-event"),
18093
18508
  messageId: UuidSchema,
18094
18509
  taskId: UuidSchema,
18095
18510
  senderId: UuidSchema,
18096
18511
  recipientId: UuidSchema,
18097
- status: z33.enum(["accepted", "started", "progress", "completed", "failed", "cancelled"]),
18512
+ status: z35.enum(["accepted", "started", "progress", "completed", "failed", "cancelled"]),
18098
18513
  detail: BoundedTextSchema.optional()
18099
18514
  }).strict();
18100
- var DeliveryReceiptSchema = z33.object({
18515
+ var DeliveryReceiptSchema = z35.object({
18101
18516
  version: VersionSchema,
18102
- type: z33.literal("delivery-receipt"),
18517
+ type: z35.literal("delivery-receipt"),
18103
18518
  messageId: UuidSchema,
18104
- status: z33.enum(["delivered", "duplicate", "rejected"]),
18105
- recipientIds: z33.array(UuidSchema).max(MAX_PARTICIPANTS),
18519
+ status: z35.enum(["delivered", "duplicate", "rejected"]),
18520
+ recipientIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
18106
18521
  error: BoundedTextSchema.optional()
18107
18522
  }).strict();
18108
- var CoWorkParticipantSchema = z33.object({
18523
+ var CoWorkParticipantSchema = z35.object({
18109
18524
  palId: UuidSchema,
18110
- required: z33.boolean()
18525
+ required: z35.boolean()
18111
18526
  }).strict();
18112
- var CoWorkProposalParticipantsSchema = z33.array(CoWorkParticipantSchema).min(2).max(MAX_PARTICIPANTS).superRefine((participants, context) => {
18527
+ var CoWorkProposalParticipantsSchema = z35.array(CoWorkParticipantSchema).min(2).max(MAX_PARTICIPANTS).superRefine((participants, context) => {
18113
18528
  const seen = /* @__PURE__ */ new Set();
18114
18529
  for (const [index, participant] of participants.entries()) {
18115
18530
  const id = participant.palId.toLowerCase();
@@ -18119,19 +18534,19 @@ var CoWorkProposalParticipantsSchema = z33.array(CoWorkParticipantSchema).min(2)
18119
18534
  seen.add(id);
18120
18535
  }
18121
18536
  });
18122
- var CoWorkPlanTaskSchema = z33.object({
18123
- id: z33.string().min(1).max(128),
18537
+ var CoWorkPlanTaskSchema = z35.object({
18538
+ id: z35.string().min(1).max(128),
18124
18539
  assigneeId: UuidSchema,
18125
18540
  description: NonEmptyBoundedTextSchema,
18126
- dependsOn: z33.array(z33.string().min(1).max(128)).max(MAX_PLAN_TASKS)
18541
+ dependsOn: z35.array(z35.string().min(1).max(128)).max(MAX_PLAN_TASKS)
18127
18542
  }).strict();
18128
- var CoWorkPlanSchema = z33.object({
18543
+ var CoWorkPlanSchema = z35.object({
18129
18544
  version: VersionSchema,
18130
18545
  coWorkId: UuidSchema,
18131
- epoch: z33.number().int().positive(),
18546
+ epoch: z35.number().int().positive(),
18132
18547
  goal: NonEmptyBoundedTextSchema,
18133
- participants: z33.array(CoWorkParticipantSchema).min(1).max(MAX_PARTICIPANTS),
18134
- tasks: z33.array(CoWorkPlanTaskSchema).min(1).max(MAX_PLAN_TASKS)
18548
+ participants: z35.array(CoWorkParticipantSchema).min(1).max(MAX_PARTICIPANTS),
18549
+ tasks: z35.array(CoWorkPlanTaskSchema).min(1).max(MAX_PLAN_TASKS)
18135
18550
  }).strict().superRefine((plan, context) => {
18136
18551
  if (Buffer.byteLength(JSON.stringify(plan), "utf8") > MAX_PLAN_ENCODED_BYTES) {
18137
18552
  context.addIssue({ code: "custom", message: `Encoded plan must not exceed ${MAX_PLAN_ENCODED_BYTES} UTF-8 bytes` });
@@ -18181,7 +18596,7 @@ var CoWorkPlanSchema = z33.object({
18181
18596
  }
18182
18597
  }
18183
18598
  });
18184
- var CoWorkPhaseSchema = z33.enum([
18599
+ var CoWorkPhaseSchema = z35.enum([
18185
18600
  "proposed",
18186
18601
  "planning",
18187
18602
  "prepared",
@@ -18191,30 +18606,30 @@ var CoWorkPhaseSchema = z33.enum([
18191
18606
  "failed",
18192
18607
  "cancelled"
18193
18608
  ]);
18194
- var IntegrationResultSchema = z33.object({
18195
- passed: z33.boolean(),
18609
+ var IntegrationResultSchema = z35.object({
18610
+ passed: z35.boolean(),
18196
18611
  evidence: CompletionDetailSchema
18197
18612
  }).strict();
18198
- var CoWorkCompletionAssertionSchema = z33.object({
18613
+ var CoWorkCompletionAssertionSchema = z35.object({
18199
18614
  participantId: UuidSchema,
18200
- passed: z33.boolean(),
18615
+ passed: z35.boolean(),
18201
18616
  detail: CompletionDetailSchema.optional()
18202
18617
  }).strict();
18203
- var CoWorkSnapshotSchema = z33.object({
18618
+ var CoWorkSnapshotSchema = z35.object({
18204
18619
  version: VersionSchema,
18205
18620
  coWorkId: UuidSchema,
18206
- epoch: z33.number().int().positive(),
18621
+ epoch: z35.number().int().positive(),
18207
18622
  phase: CoWorkPhaseSchema,
18208
18623
  goal: NonEmptyBoundedTextSchema,
18209
- participants: z33.array(CoWorkParticipantSchema).min(1).max(MAX_PARTICIPANTS),
18624
+ participants: z35.array(CoWorkParticipantSchema).min(1).max(MAX_PARTICIPANTS),
18210
18625
  integrationOwnerId: UuidSchema,
18211
- acceptedParticipantIds: z33.array(UuidSchema).max(MAX_PARTICIPANTS),
18212
- planHash: z33.string().regex(/^[a-f0-9]{64}$/).nullable(),
18626
+ acceptedParticipantIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
18627
+ planHash: z35.string().regex(/^[a-f0-9]{64}$/).nullable(),
18213
18628
  plan: CoWorkPlanSchema.nullable(),
18214
- planAcceptedParticipantIds: z33.array(UuidSchema).max(MAX_PARTICIPANTS),
18215
- readyParticipantIds: z33.array(UuidSchema).max(MAX_PARTICIPANTS),
18216
- completedParticipantIds: z33.array(UuidSchema).max(MAX_PARTICIPANTS),
18217
- completionAssertions: z33.array(CoWorkCompletionAssertionSchema).max(MAX_PARTICIPANTS),
18629
+ planAcceptedParticipantIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
18630
+ readyParticipantIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
18631
+ completedParticipantIds: z35.array(UuidSchema).max(MAX_PARTICIPANTS),
18632
+ completionAssertions: z35.array(CoWorkCompletionAssertionSchema).max(MAX_PARTICIPANTS),
18218
18633
  integration: IntegrationResultSchema.nullable()
18219
18634
  }).strict().superRefine((snapshot4, context) => {
18220
18635
  if (Buffer.byteLength(JSON.stringify(snapshot4), "utf8") > MAX_SNAPSHOT_ENCODED_BYTES) {
@@ -18245,87 +18660,87 @@ var RequestBase = {
18245
18660
  version: VersionSchema,
18246
18661
  requestId: UuidSchema
18247
18662
  };
18248
- var RegisterRequestSchema = z33.object({
18663
+ var RegisterRequestSchema = z35.object({
18249
18664
  ...RequestBase,
18250
- type: z33.literal("register"),
18251
- authToken: z33.string().regex(/^[a-f0-9]{64}$/).optional(),
18665
+ type: z35.literal("register"),
18666
+ authToken: z35.string().regex(/^[a-f0-9]{64}$/).optional(),
18252
18667
  presence: PalPresenceSchema
18253
18668
  }).strict();
18254
- var HeartbeatRequestSchema = z33.object({ ...RequestBase, type: z33.literal("heartbeat") }).strict();
18255
- var ListRequestSchema = z33.object({ ...RequestBase, type: z33.literal("list") }).strict();
18256
- var DisconnectRequestSchema = z33.object({ ...RequestBase, type: z33.literal("disconnect") }).strict();
18257
- var ChatRequestSchema = z33.object({
18669
+ var HeartbeatRequestSchema = z35.object({ ...RequestBase, type: z35.literal("heartbeat") }).strict();
18670
+ var ListRequestSchema = z35.object({ ...RequestBase, type: z35.literal("list") }).strict();
18671
+ var DisconnectRequestSchema = z35.object({ ...RequestBase, type: z35.literal("disconnect") }).strict();
18672
+ var ChatRequestSchema = z35.object({
18258
18673
  ...RequestBase,
18259
- type: z33.literal("chat"),
18674
+ type: z35.literal("chat"),
18260
18675
  messageId: UuidSchema,
18261
18676
  target: PalTargetSchema,
18262
18677
  message: NonEmptyBoundedTextSchema
18263
18678
  }).strict();
18264
- var TaskRequestSchema = z33.object({
18679
+ var TaskRequestSchema = z35.object({
18265
18680
  ...RequestBase,
18266
- type: z33.literal("task"),
18681
+ type: z35.literal("task"),
18267
18682
  messageId: UuidSchema,
18268
18683
  target: PalTargetSchema,
18269
18684
  goal: NonEmptyBoundedTextSchema
18270
18685
  }).strict();
18271
- var CoWorkProposeRequestSchema = z33.object({
18686
+ var CoWorkProposeRequestSchema = z35.object({
18272
18687
  ...RequestBase,
18273
- type: z33.literal("cowork-propose"),
18688
+ type: z35.literal("cowork-propose"),
18274
18689
  coWorkId: UuidSchema,
18275
18690
  goal: NonEmptyBoundedTextSchema,
18276
18691
  participants: CoWorkProposalParticipantsSchema
18277
18692
  }).strict();
18278
- var CoWorkAcceptanceRequestSchema = z33.object({
18693
+ var CoWorkAcceptanceRequestSchema = z35.object({
18279
18694
  ...RequestBase,
18280
- type: z33.literal("cowork-accept"),
18695
+ type: z35.literal("cowork-accept"),
18281
18696
  coWorkId: UuidSchema,
18282
- epoch: z33.number().int().positive()
18697
+ epoch: z35.number().int().positive()
18283
18698
  }).strict();
18284
- var CoWorkPlanRequestSchema = z33.object({ ...RequestBase, type: z33.literal("cowork-plan"), plan: CoWorkPlanSchema }).strict();
18285
- var CoWorkPlanAcceptanceRequestSchema = z33.object({
18699
+ var CoWorkPlanRequestSchema = z35.object({ ...RequestBase, type: z35.literal("cowork-plan"), plan: CoWorkPlanSchema }).strict();
18700
+ var CoWorkPlanAcceptanceRequestSchema = z35.object({
18286
18701
  ...RequestBase,
18287
- type: z33.literal("cowork-plan-accept"),
18702
+ type: z35.literal("cowork-plan-accept"),
18288
18703
  coWorkId: UuidSchema,
18289
- epoch: z33.number().int().positive(),
18290
- planHash: z33.string().regex(/^[a-f0-9]{64}$/)
18704
+ epoch: z35.number().int().positive(),
18705
+ planHash: z35.string().regex(/^[a-f0-9]{64}$/)
18291
18706
  }).strict();
18292
- var CoWorkReadyRequestSchema = z33.object({
18707
+ var CoWorkReadyRequestSchema = z35.object({
18293
18708
  ...RequestBase,
18294
- type: z33.literal("cowork-ready"),
18709
+ type: z35.literal("cowork-ready"),
18295
18710
  coWorkId: UuidSchema,
18296
- epoch: z33.number().int().positive(),
18297
- planHash: z33.string().regex(/^[a-f0-9]{64}$/)
18711
+ epoch: z35.number().int().positive(),
18712
+ planHash: z35.string().regex(/^[a-f0-9]{64}$/)
18298
18713
  }).strict();
18299
- var CoWorkCompleteRequestSchema = z33.object({
18714
+ var CoWorkCompleteRequestSchema = z35.object({
18300
18715
  ...RequestBase,
18301
- type: z33.literal("cowork-complete"),
18716
+ type: z35.literal("cowork-complete"),
18302
18717
  coWorkId: UuidSchema,
18303
- epoch: z33.number().int().positive(),
18304
- planHash: z33.string().regex(/^[a-f0-9]{64}$/),
18305
- passed: z33.boolean(),
18718
+ epoch: z35.number().int().positive(),
18719
+ planHash: z35.string().regex(/^[a-f0-9]{64}$/),
18720
+ passed: z35.boolean(),
18306
18721
  detail: CompletionDetailSchema.optional()
18307
18722
  }).strict();
18308
- var CoWorkIntegrationRequestSchema = z33.object({
18723
+ var CoWorkIntegrationRequestSchema = z35.object({
18309
18724
  ...RequestBase,
18310
- type: z33.literal("cowork-integration"),
18725
+ type: z35.literal("cowork-integration"),
18311
18726
  coWorkId: UuidSchema,
18312
- epoch: z33.number().int().positive(),
18313
- planHash: z33.string().regex(/^[a-f0-9]{64}$/),
18314
- passed: z33.boolean(),
18727
+ epoch: z35.number().int().positive(),
18728
+ planHash: z35.string().regex(/^[a-f0-9]{64}$/),
18729
+ passed: z35.boolean(),
18315
18730
  evidence: CompletionDetailSchema
18316
18731
  }).strict();
18317
- var CoWorkGetRequestSchema = z33.object({
18732
+ var CoWorkGetRequestSchema = z35.object({
18318
18733
  ...RequestBase,
18319
- type: z33.literal("cowork-get"),
18734
+ type: z35.literal("cowork-get"),
18320
18735
  coWorkId: UuidSchema
18321
18736
  }).strict();
18322
- var CoWorkCancelRequestSchema = z33.object({
18737
+ var CoWorkCancelRequestSchema = z35.object({
18323
18738
  ...RequestBase,
18324
- type: z33.literal("cowork-cancel"),
18739
+ type: z35.literal("cowork-cancel"),
18325
18740
  coWorkId: UuidSchema,
18326
18741
  reason: NonEmptyBoundedTextSchema
18327
18742
  }).strict();
18328
- var BrokerRequestSchema = z33.discriminatedUnion("type", [
18743
+ var BrokerRequestSchema = z35.discriminatedUnion("type", [
18329
18744
  RegisterRequestSchema,
18330
18745
  HeartbeatRequestSchema,
18331
18746
  ListRequestSchema,
@@ -18342,49 +18757,49 @@ var BrokerRequestSchema = z33.discriminatedUnion("type", [
18342
18757
  CoWorkGetRequestSchema,
18343
18758
  CoWorkCancelRequestSchema
18344
18759
  ]);
18345
- var BrokerOkResponseSchema = z33.object({
18760
+ var BrokerOkResponseSchema = z35.object({
18346
18761
  version: VersionSchema,
18347
- type: z33.literal("ok"),
18762
+ type: z35.literal("ok"),
18348
18763
  requestId: UuidSchema,
18349
- data: z33.unknown()
18764
+ data: z35.unknown()
18350
18765
  }).strict();
18351
- var BrokerErrorResponseSchema = z33.object({
18766
+ var BrokerErrorResponseSchema = z35.object({
18352
18767
  version: VersionSchema,
18353
- type: z33.literal("error"),
18768
+ type: z35.literal("error"),
18354
18769
  requestId: UuidSchema,
18355
- code: z33.enum(["invalid-request", "authentication-failed", "not-found", "ambiguous-target", "alias-conflict", "invalid-transition", "stale-epoch", "duplicate"]),
18770
+ code: z35.enum(["invalid-request", "authentication-failed", "not-found", "ambiguous-target", "alias-conflict", "invalid-transition", "stale-epoch", "duplicate"]),
18356
18771
  message: BoundedTextSchema
18357
18772
  }).strict();
18358
- var ChatEventSchema = z33.object({
18773
+ var ChatEventSchema = z35.object({
18359
18774
  version: VersionSchema,
18360
- type: z33.literal("chat-event"),
18775
+ type: z35.literal("chat-event"),
18361
18776
  messageId: UuidSchema,
18362
18777
  senderId: UuidSchema,
18363
18778
  recipientId: UuidSchema,
18364
18779
  message: NonEmptyBoundedTextSchema
18365
18780
  }).strict();
18366
- var CoWorkEventSchema = z33.object({
18781
+ var CoWorkEventSchema = z35.object({
18367
18782
  version: VersionSchema,
18368
- type: z33.literal("cowork-event"),
18369
- action: z33.enum(["PROPOSE", "PLAN", "START", "END", "FAIL", "CANCEL"]),
18783
+ type: z35.literal("cowork-event"),
18784
+ action: z35.enum(["PROPOSE", "PLAN", "START", "END", "FAIL", "CANCEL"]),
18370
18785
  actorId: UuidSchema,
18371
18786
  coWorkId: UuidSchema,
18372
- epoch: z33.number().int().positive(),
18373
- planHash: z33.string().regex(/^[a-f0-9]{64}$/).nullable(),
18787
+ epoch: z35.number().int().positive(),
18788
+ planHash: z35.string().regex(/^[a-f0-9]{64}$/).nullable(),
18374
18789
  snapshot: CoWorkSnapshotSchema
18375
18790
  }).strict();
18376
- var BrokerEventSchema = z33.union([ChatEventSchema, PalTaskEventSchema, DeliveryReceiptSchema, CoWorkEventSchema]);
18377
- var BrokerEventResponseSchema = z33.object({
18791
+ var BrokerEventSchema = z35.union([ChatEventSchema, PalTaskEventSchema, DeliveryReceiptSchema, CoWorkEventSchema]);
18792
+ var BrokerEventResponseSchema = z35.object({
18378
18793
  version: VersionSchema,
18379
- type: z33.literal("event"),
18794
+ type: z35.literal("event"),
18380
18795
  event: BrokerEventSchema
18381
18796
  }).strict();
18382
- var BrokerResponseSchema = z33.discriminatedUnion("type", [
18797
+ var BrokerResponseSchema = z35.discriminatedUnion("type", [
18383
18798
  BrokerOkResponseSchema,
18384
18799
  BrokerErrorResponseSchema,
18385
18800
  BrokerEventResponseSchema
18386
18801
  ]);
18387
- var ControlFrameSchema = z33.string().refine(
18802
+ var ControlFrameSchema = z35.string().refine(
18388
18803
  (frame) => Buffer.byteLength(frame, "utf8") <= MAX_CONTROL_FRAME_BYTES,
18389
18804
  `Control frame must not exceed ${MAX_CONTROL_FRAME_BYTES} UTF-8 bytes`
18390
18805
  );
@@ -18403,6 +18818,7 @@ var MVP_COMMANDS = [
18403
18818
  "init",
18404
18819
  "config",
18405
18820
  "login",
18821
+ "logout",
18406
18822
  "permissions",
18407
18823
  "skills",
18408
18824
  "plugins",
@@ -18419,6 +18835,8 @@ var MVP_COMMANDS = [
18419
18835
  "goal",
18420
18836
  "evolve",
18421
18837
  "mcp",
18838
+ "commit",
18839
+ "review",
18422
18840
  "ide",
18423
18841
  "memory",
18424
18842
  "remember",
@@ -18469,6 +18887,14 @@ function parseSlashCommand(input, dynamicCommands = [], skillCommands = []) {
18469
18887
  if (name === "evolve") {
18470
18888
  return { name, args };
18471
18889
  }
18890
+ if (name === "commit") {
18891
+ const hint = args.join(" ").trim();
18892
+ return hint.length === 0 ? { name } : { name, hint };
18893
+ }
18894
+ if (name === "review") {
18895
+ const focus = args.join(" ").trim();
18896
+ return focus.length === 0 ? { name } : { name, focus };
18897
+ }
18472
18898
  if (name === "loop") {
18473
18899
  const goal = args.join(" ").trim();
18474
18900
  if (!goal) return { name: "invalid", command: name, message: "Use /loop <goal>." };
@@ -18670,12 +19096,15 @@ var HELP = [
18670
19096
  "/model <main|subagent> <provider:model> switch any configured model",
18671
19097
  "/permissions <default|acceptEdits|plan|bypassPermissions|auto|bubble>",
18672
19098
  "/login authenticate via OAuth PKCE",
19099
+ "/logout clear stored OAuth credentials",
18673
19100
  "/init /config /skills /plugins /hooks /tasks",
18674
19101
  "/memory /remember [type] <text> /forget <text-or-id> /forget-cold /finish",
18675
19102
  "/checkpoint [label] /tree /rewind <node> /unrevert /fork <node>",
18676
19103
  "/compact /clear /help /exit",
18677
19104
  "/loop <goal> run a verified autonomous loop",
18678
19105
  "/goal <objective> run a goal pipeline with adversarial verification",
19106
+ "/commit [hint] draft a commit message for staged changes and commit",
19107
+ "/review [focus] review uncommitted changes before committing",
18679
19108
  "/evolve <signals|suggest|improve <id>|verify <name>|reload <name>|test|revert <name>|done <id>> self-improvement loop",
18680
19109
  "/mcp [status|tools|reconnect|enable|disable] manage MCP servers",
18681
19110
  "/ide show VS Code connection and cursor/selection",
@@ -19016,6 +19445,10 @@ var FlavorSession = class {
19016
19445
  for await (const event of this.#services.runLoop(command.goal, signal)) this.#services.output(event);
19017
19446
  } else if (command.name === "goal") {
19018
19447
  for await (const event of this.#services.runGoal(command.goal, signal)) this.#services.output(event);
19448
+ } else if (command.name === "commit") {
19449
+ this.#notice(await required(this.#services.gitCommit, "commit")(command.hint, signal));
19450
+ } else if (command.name === "review") {
19451
+ this.#notice(await required(this.#services.gitReview, "review")(command.focus, signal));
19019
19452
  } else if (command.name === "mcp") {
19020
19453
  this.#notice(await this.#services.mcp(command, signal));
19021
19454
  } else if (command.name === "pals") {
@@ -19078,6 +19511,8 @@ var FlavorSession = class {
19078
19511
  } else if (command.name === "login") {
19079
19512
  this.#notice("Opening browser for authentication...");
19080
19513
  this.#notice(await this.#services.login());
19514
+ } else if (command.name === "logout") {
19515
+ this.#notice(await this.#services.logout());
19081
19516
  } else if (command.name === "help") this.#notice(HELP);
19082
19517
  else if (command.name === "exit") this.#services.output({ type: "exit" });
19083
19518
  }
@@ -19285,7 +19720,7 @@ var LANG_LABELS = /* @__PURE__ */ new Map([
19285
19720
  ]);
19286
19721
 
19287
19722
  // src/hallucination/confidence.ts
19288
- import { z as z34 } from "zod";
19723
+ import { z as z36 } from "zod";
19289
19724
 
19290
19725
  // src/hallucination/types.ts
19291
19726
  var DEFAULT_SLIDING_WINDOW_SIZE = 20;
@@ -19298,12 +19733,12 @@ var DEFAULT_EVALUATION_TIMEOUT_MS = 2e3;
19298
19733
  var MAX_QUERY_CHARS = 5e3;
19299
19734
  var MAX_OUTPUT_CHARS = 1e4;
19300
19735
  var MAX_EVIDENCE_CHARS = 6e3;
19301
- var ConfidenceSchema = z34.object({
19302
- taskAlignment: z34.number(),
19303
- evidenceGrounding: z34.number(),
19304
- processReliability: z34.number(),
19305
- reason: z34.string(),
19306
- unsupportedClaims: z34.array(z34.string()).max(3)
19736
+ var ConfidenceSchema = z36.object({
19737
+ taskAlignment: z36.number(),
19738
+ evidenceGrounding: z36.number(),
19739
+ processReliability: z36.number(),
19740
+ reason: z36.string(),
19741
+ unsupportedClaims: z36.array(z36.string()).max(3)
19307
19742
  });
19308
19743
  var PROMPT = `You are a fast, evidence-aware task-completion verifier.
19309
19744
 
@@ -21396,15 +21831,15 @@ function workspacePath(root, input) {
21396
21831
  }
21397
21832
 
21398
21833
  // src/tools/terminal.ts
21399
- import { z as z35 } from "zod";
21834
+ import { z as z37 } from "zod";
21400
21835
  import { resolve as resolve29 } from "path";
21401
- var Id = z35.string().regex(/^term-[a-f0-9-]+$/);
21402
- var OpenInput = z35.object({ cwd: z35.string().optional(), shell: z35.string().optional(), args: z35.array(z35.string()).optional(), columns: z35.coerce.number().int().min(10).max(500).optional(), rows: z35.coerce.number().int().min(2).max(300).optional() });
21403
- var OptionalBoolean = z35.union([z35.boolean(), z35.string().refine((value) => value === "true" || value === "false")]);
21404
- var WriteInput2 = z35.object({ id: Id, data: z35.string().max(1e5), enter: OptionalBoolean.optional() });
21405
- var ReadInput3 = z35.object({ id: Id, cursor: z35.coerce.number().int().min(0).optional() });
21406
- var ResizeInput = z35.object({ id: Id, columns: z35.coerce.number().int().min(10).max(500), rows: z35.coerce.number().int().min(2).max(300) });
21407
- var CloseInput = z35.object({ id: Id });
21836
+ var Id = z37.string().regex(/^term-[a-f0-9-]+$/);
21837
+ var OpenInput = z37.object({ cwd: z37.string().optional(), shell: z37.string().optional(), args: z37.array(z37.string()).optional(), columns: z37.coerce.number().int().min(10).max(500).optional(), rows: z37.coerce.number().int().min(2).max(300).optional() });
21838
+ var OptionalBoolean = z37.union([z37.boolean(), z37.string().refine((value) => value === "true" || value === "false")]);
21839
+ var WriteInput2 = z37.object({ id: Id, data: z37.string().max(1e5), enter: OptionalBoolean.optional() });
21840
+ var ReadInput3 = z37.object({ id: Id, cursor: z37.coerce.number().int().min(0).optional() });
21841
+ var ResizeInput = z37.object({ id: Id, columns: z37.coerce.number().int().min(10).max(500), rows: z37.coerce.number().int().min(2).max(300) });
21842
+ var CloseInput = z37.object({ id: Id });
21408
21843
  function createTerminalTools(terminals, workspace = process.cwd()) {
21409
21844
  const tools = [
21410
21845
  {
@@ -21480,7 +21915,7 @@ function createTerminalTools(terminals, workspace = process.cwd()) {
21480
21915
  {
21481
21916
  name: "TerminalList",
21482
21917
  description: "List persistent terminals owned by this agent",
21483
- inputSchema: z35.object({}),
21918
+ inputSchema: z37.object({}),
21484
21919
  paths: () => [],
21485
21920
  execute: async (_input, _signal, context) => terminals.list(owner(context))
21486
21921
  }
@@ -22056,7 +22491,7 @@ var PalClient = class {
22056
22491
  };
22057
22492
 
22058
22493
  // src/pals/tools.ts
22059
- import { z as z36 } from "zod";
22494
+ import { z as z38 } from "zod";
22060
22495
  var DEFAULT_SHARE_BUDGET_BYTES = 128 * 1024;
22061
22496
  var CollaborationShareGuard = class {
22062
22497
  redact;
@@ -22077,25 +22512,25 @@ var CollaborationShareGuard = class {
22077
22512
  return redacted;
22078
22513
  }
22079
22514
  };
22080
- var Uuid = z36.uuid();
22081
- var Hash = z36.string().regex(/^[a-f0-9]{64}$/);
22515
+ var Uuid = z38.uuid();
22516
+ var Hash = z38.string().regex(/^[a-f0-9]{64}$/);
22082
22517
  var Target = PalTargetSchema;
22083
- var BoundedText = z36.string().trim().min(1).refine(
22518
+ var BoundedText = z38.string().trim().min(1).refine(
22084
22519
  (value) => Buffer.byteLength(value, "utf8") <= MAX_MESSAGE_BYTES,
22085
22520
  `Text must not exceed ${MAX_MESSAGE_BYTES} UTF-8 bytes`
22086
22521
  );
22087
- var CompletionEvidence = z36.string().trim().min(1).refine(
22522
+ var CompletionEvidence = z38.string().trim().min(1).refine(
22088
22523
  (value) => Buffer.byteLength(value, "utf8") <= MAX_COMPLETION_DETAIL_BYTES,
22089
22524
  `Completion evidence must not exceed ${MAX_COMPLETION_DETAIL_BYTES} UTF-8 bytes`
22090
22525
  );
22091
- var EmptyInput = z36.object({}).strict();
22092
- var StateInput = z36.object({ coWorkId: Uuid }).strict();
22093
- var TokenInput = z36.object({ coWorkId: Uuid, epoch: z36.number().int().positive(), planHash: Hash }).strict();
22094
- var SendInput = z36.object({ target: Target, message: BoundedText, coWorkId: Uuid.optional() }).strict();
22095
- var PlanInput = z36.object({ plan: CoWorkPlanSchema }).strict();
22096
- var ProgressInput = z36.object({ coWorkId: Uuid, target: Target, detail: BoundedText }).strict();
22097
- var CompleteInput = TokenInput.extend({ passed: z36.boolean(), detail: CompletionEvidence }).strict();
22098
- var IntegrateInput = TokenInput.extend({ passed: z36.boolean(), evidence: CompletionEvidence }).strict();
22526
+ var EmptyInput = z38.object({}).strict();
22527
+ var StateInput = z38.object({ coWorkId: Uuid }).strict();
22528
+ var TokenInput = z38.object({ coWorkId: Uuid, epoch: z38.number().int().positive(), planHash: Hash }).strict();
22529
+ var SendInput = z38.object({ target: Target, message: BoundedText, coWorkId: Uuid.optional() }).strict();
22530
+ var PlanInput = z38.object({ plan: CoWorkPlanSchema }).strict();
22531
+ var ProgressInput = z38.object({ coWorkId: Uuid, target: Target, detail: BoundedText }).strict();
22532
+ var CompleteInput = TokenInput.extend({ passed: z38.boolean(), detail: CompletionEvidence }).strict();
22533
+ var IntegrateInput = TokenInput.extend({ passed: z38.boolean(), evidence: CompletionEvidence }).strict();
22099
22534
  var sharedBytes = (...values) => values.reduce((total, value) => total + Buffer.byteLength(value, "utf8"), 0);
22100
22535
  function resolvePresence(presences, target) {
22101
22536
  const normalized = normalizePalIdentity(target);
@@ -22448,6 +22883,7 @@ async function createProductionRuntime(options) {
22448
22883
  createApplyPatchTool(workspace, fileMutationOptions),
22449
22884
  createGlobTool(workspace),
22450
22885
  createGrepTool(workspace),
22886
+ createGitHistoryTool(workspace),
22451
22887
  createShellTool(workspace, {
22452
22888
  jobs,
22453
22889
  ...executionEnvironment === void 0 ? {} : { executionEnvironment }
@@ -22764,7 +23200,10 @@ async function createProductionRuntime(options) {
22764
23200
  states: { ...taskStates },
22765
23201
  results: { ...taskResults }
22766
23202
  },
22767
- models: { main: harness.mainModelId, subagent: harness.subagentModelId },
23203
+ // Persist the resolved decision, not the harness snapshot: after logout the
23204
+ // harness may still hold the old login model, and resuming from that stale
23205
+ // value is what made the welcome card show a previous service.
23206
+ models: { main: mainModel, subagent: childModel },
22768
23207
  permissionMode: harness.permissionMode,
22769
23208
  memory: memoryLifecycle,
22770
23209
  timeline: { version: 1, state: timelineState }
@@ -22824,7 +23263,7 @@ async function createProductionRuntime(options) {
22824
23263
  })) tools.push(tool);
22825
23264
  const taskTool = {
22826
23265
  name: "Task",
22827
- description: "Validate a task graph and execute its nodes with isolated child agents",
23266
+ description: "Validate a task graph and execute its nodes with isolated child agents. Declare each node's `files` (the workspace files it may create or modify) whenever a task writes files; nodes with overlapping files are serialized automatically to prevent concurrent write conflicts.",
22828
23267
  inputSchema: TaskGraphSchema,
22829
23268
  paths: () => [],
22830
23269
  execute: async (input, signal) => {
@@ -23405,8 +23844,8 @@ async function createProductionRuntime(options) {
23405
23844
  const services = {
23406
23845
  hooks,
23407
23846
  workspace,
23408
- mainModel: () => harness.mainModelId,
23409
- subagentModel: () => harness.subagentModelId,
23847
+ mainModel: () => mainModel,
23848
+ subagentModel: () => childModel,
23410
23849
  llmServiceName: () => effectiveLlm?.serviceName,
23411
23850
  permissionMode: () => harness.permissionMode,
23412
23851
  ...palServices === void 0 ? {} : { pals: palServices },
@@ -23480,6 +23919,8 @@ async function createProductionRuntime(options) {
23480
23919
  }
23481
23920
  }
23482
23921
  harness.setModel(role, id);
23922
+ if (role === "main") mainModel = id;
23923
+ else childModel = id;
23483
23924
  await persist();
23484
23925
  },
23485
23926
  setPermissionMode: async (mode) => {
@@ -23512,6 +23953,19 @@ async function createProductionRuntime(options) {
23512
23953
  hooksStatus: () => HOOK_EVENT_NAMES.map((name) => ({ name, pluginHandlers: pluginHooks.filter((item) => item === name).length })),
23513
23954
  tasks: () => ({ plan: taskPlan, graph: taskGraph, states: taskStates, results: taskResults }),
23514
23955
  evolve: (args) => evolveService.handleCommand(args),
23956
+ gitCommit: (hint, signal) => runGitCommit({
23957
+ workspace,
23958
+ registry,
23959
+ questions,
23960
+ modelId: () => harness.subagentModelId,
23961
+ notify: (message2) => emitOutput({ type: "notice", message: message2 })
23962
+ }, hint, signal),
23963
+ gitReview: (focus, signal) => runGitReview({
23964
+ workspace,
23965
+ registry,
23966
+ modelId: () => harness.subagentModelId,
23967
+ notify: (message2) => emitOutput({ type: "notice", message: message2 })
23968
+ }, focus, signal),
23515
23969
  audit: async (toolFilter) => {
23516
23970
  try {
23517
23971
  const raw = await readFile25(auditLogger.path, "utf8");
@@ -23599,7 +24053,11 @@ ${summary2}`;
23599
24053
  },
23600
24054
  ide: () => ide.status(),
23601
24055
  ideContext: () => ide.editorContext(),
23602
- checkpoint: (label) => sessionHistory.checkpoint(label, harness.main.context.snapshot()),
24056
+ checkpoint: async (label) => {
24057
+ const marker = await gitMarker(workspace);
24058
+ const tagged = marker === void 0 ? label : label === void 0 ? `git: ${marker}` : `${label} (git: ${marker})`;
24059
+ return sessionHistory.checkpoint(tagged, harness.main.context.snapshot());
24060
+ },
23603
24061
  tree: () => sessionHistory.tree(),
23604
24062
  rewind: async (nodeId) => {
23605
24063
  await sessionHistory.rewind(nodeId, harness.main.context.snapshot());
@@ -23709,12 +24167,48 @@ ${renderMemoryDocument(entries)}`;
23709
24167
  goalOrchestrator.setModels(mainModel, mainModel);
23710
24168
  delete selectedModels.mainError;
23711
24169
  delete selectedModels.childError;
24170
+ await retainOnlyCredentials(tokenStore, credentialId);
23712
24171
  if (!secrets.includes(next.accessToken)) secrets.push(next.accessToken);
23713
24172
  await persist();
23714
24173
  return `Authenticated to "${next.serviceName}". Main model ${mainModel}; subagent ${childModel}; gateway ${next.baseURL}. Configuration is active now.`;
23715
24174
  } catch (error) {
23716
24175
  return `Login failed: ${message(error)}`;
23717
24176
  }
24177
+ },
24178
+ async logout() {
24179
+ const tokenStore = createFileTokenStore(join29(home, ".flavor-code", "auth.json"));
24180
+ const tokens2 = await tokenStore.load();
24181
+ const hadCredentials = Object.keys(tokens2).length > 0 || effectiveLlm !== void 0;
24182
+ if (!hadCredentials) {
24183
+ return "Not authenticated \u2014 no stored OAuth credentials to clear.";
24184
+ }
24185
+ for (let i = registeredProviders.length - 1; i >= 0; i -= 1) {
24186
+ const provider = registeredProviders[i];
24187
+ if (provider !== void 0 && provider.pkceManaged === true) {
24188
+ registry.unregister(provider.name);
24189
+ registeredProviders.splice(i, 1);
24190
+ }
24191
+ }
24192
+ if (effectiveLlm !== void 0) {
24193
+ registry.unregister(effectiveLlm.providerId);
24194
+ effectiveLlm = void 0;
24195
+ }
24196
+ await tokenStore.save({});
24197
+ const fallback = selectModels(config, registeredProviders, diagnostics);
24198
+ mainModel = fallback.main;
24199
+ childModel = fallback.child;
24200
+ if (fallback.mainError === void 0) delete selectedModels.mainError;
24201
+ else selectedModels.mainError = fallback.mainError;
24202
+ if (fallback.childError === void 0) delete selectedModels.childError;
24203
+ else selectedModels.childError = fallback.childError;
24204
+ if (fallback.mainError === void 0 && registry.has(safeProvider(mainModel)) && registry.has(safeProvider(childModel))) {
24205
+ harness.setModel("main", mainModel);
24206
+ harness.setModel("subagent", childModel);
24207
+ hallucinationGuard.setModel(childModel);
24208
+ goalOrchestrator.setModels(mainModel, mainModel);
24209
+ }
24210
+ await persist();
24211
+ return fallback.mainError === void 0 ? `Logged out. Cleared OAuth credentials. Main model ${mainModel}; subagent ${childModel}.` : `Logged out. Cleared OAuth credentials. ${fallback.mainError}`;
23718
24212
  }
23719
24213
  };
23720
24214
  if (config.sleep) {
@@ -24031,6 +24525,70 @@ async function* persistEach(source, persist) {
24031
24525
  await persist();
24032
24526
  }
24033
24527
  }
24528
+ async function runGitCommit(deps, hint, signal) {
24529
+ if (!await isGitRepository(deps.workspace)) return "Not a git repository \u2014 /commit needs git.";
24530
+ let summary2 = await changeSummary(deps.workspace);
24531
+ if (summary2.statusLines.length === 0) return "Working tree clean \u2014 nothing to commit.";
24532
+ if (summary2.stagedFiles.length === 0) {
24533
+ if (deps.questions === void 0) throw new Error("Nothing is staged. Run `git add` on the files you want to commit first.");
24534
+ const stageAnswers = await deps.questions.ask([{
24535
+ header: "Staging",
24536
+ question: `Nothing is staged, but ${summary2.statusLines.length} change(s) exist. Stage everything before committing?`,
24537
+ options: [
24538
+ { label: "Stage all", description: "Run git add -A, then generate the commit message." },
24539
+ { label: "Cancel", description: "Abort /commit and leave the working tree as-is." }
24540
+ ]
24541
+ }], signal);
24542
+ if (stageAnswers[0] !== "Stage all") return "/commit cancelled \u2014 nothing was staged.";
24543
+ await stageAll(deps.workspace);
24544
+ summary2 = await changeSummary(deps.workspace);
24545
+ if (summary2.stagedFiles.length === 0) return "Nothing ended up staged \u2014 /commit aborted.";
24546
+ }
24547
+ const staged = await stagedDiff(deps.workspace);
24548
+ signal.throwIfAborted();
24549
+ deps.notify?.("Generating commit message\u2026");
24550
+ let commitMessage;
24551
+ try {
24552
+ commitMessage = await suggestCommitMessage(
24553
+ { registry: deps.registry, modelId: deps.modelId },
24554
+ { stat: staged.stat, diff: staged.diff, ...hint === void 0 ? {} : { hint } },
24555
+ signal
24556
+ );
24557
+ } catch (error) {
24558
+ signal.throwIfAborted();
24559
+ const scope2 = summary2.stagedFiles.length === 1 ? summary2.stagedFiles[0] ?? "1 file" : `${summary2.stagedFiles.length} files`;
24560
+ commitMessage = `chore: update ${scope2}`;
24561
+ deps.notify?.(`Commit message generation failed (${message(error)}); using a fallback message.`);
24562
+ }
24563
+ deps.notify?.(`Proposed commit message:
24564
+ ${commitMessage}`);
24565
+ if (deps.questions !== void 0) {
24566
+ const confirmAnswers = await deps.questions.ask([{
24567
+ header: "Commit",
24568
+ question: `Commit ${summary2.stagedFiles.length} staged file(s) on ${summary2.branch} with the message above?`,
24569
+ options: [
24570
+ { label: "Commit", description: "Run git commit with the proposed message." },
24571
+ { label: "Cancel", description: "Abort; the staged changes stay as-is." }
24572
+ ]
24573
+ }], signal);
24574
+ if (confirmAnswers[0] !== "Commit") return "/commit cancelled \u2014 staged changes left untouched.";
24575
+ }
24576
+ const result = await commit(deps.workspace, commitMessage);
24577
+ return `Committed: ${result}`;
24578
+ }
24579
+ async function runGitReview(deps, focus, signal) {
24580
+ if (!await isGitRepository(deps.workspace)) return "Not a git repository \u2014 /review needs git.";
24581
+ const changes = await uncommittedDiff(deps.workspace);
24582
+ if (changes.diff.trim() === "" && changes.untracked.length === 0) return "No uncommitted changes to review.";
24583
+ signal.throwIfAborted();
24584
+ deps.notify?.("Reviewing uncommitted changes\u2026");
24585
+ const report = await reviewDiff(
24586
+ { registry: deps.registry, modelId: deps.modelId },
24587
+ { stat: changes.stat, diff: changes.diff, untracked: changes.untracked, ...focus === void 0 ? {} : { focus } },
24588
+ signal
24589
+ );
24590
+ return formatReviewReport(report);
24591
+ }
24034
24592
  async function runChild(harness, skills, task, attempt, signal, parentContext) {
24035
24593
  return harness.runSubagent(task, async (child, childSignal) => {
24036
24594
  const skill = await skills.match(task.description);
@@ -24043,6 +24601,7 @@ ${await skills.loadBody(skill)}`;
24043
24601
  `Complete task ${task.id}: ${task.description}`,
24044
24602
  `Expected outputs: ${task.expectedOutputs.join("; ")}`,
24045
24603
  `Verification: ${task.verification.join("; ")}`,
24604
+ ...task.files === void 0 || task.files.length === 0 ? [] : [`Owned files: ${task.files.join(", ")}. Restrict your file writes to these paths; concurrent tasks own everything else.`],
24046
24605
  `For completed work, finish by calling TaskOutput. Otherwise return only JSON matching these fields: ${Object.keys(SubagentResultSchema.shape).join(", ")}.${repair}`
24047
24606
  ].join("\n");
24048
24607
  for await (const event of child.loop.run({ prompt, signal: childSignal })) {
@@ -24478,7 +25037,7 @@ import { basename as basename9, join as join39, resolve as resolve33 } from "pat
24478
25037
  // src/d2c/workflow.ts
24479
25038
  import { createHash as createHash17 } from "crypto";
24480
25039
  import { join as join30 } from "path";
24481
- import { z as z37 } from "zod";
25040
+ import { z as z39 } from "zod";
24482
25041
 
24483
25042
  // src/d2c/workflow-shared.ts
24484
25043
  function reviewProgress(workflow) {
@@ -24501,91 +25060,91 @@ function buildD2cQualityRepairPrompt(task, issue) {
24501
25060
  }
24502
25061
 
24503
25062
  // src/d2c/workflow.ts
24504
- var ReviewSchema2 = z37.object({
24505
- fingerprint: z37.string().min(1).max(256),
24506
- pageId: z37.string().min(1).max(128),
24507
- reportId: z37.string().min(1).max(128),
24508
- signature: z37.string().regex(/^[a-f0-9]{64}$/),
24509
- label: z37.string().min(1).max(1e3),
24510
- decision: z37.enum(["pending", "accepted", "needs-fix"]),
24511
- instruction: z37.string().max(1e4).optional(),
24512
- moduleId: z37.string().min(1).max(128).optional(),
24513
- moduleSourceFiles: z37.array(z37.string().min(1).max(2048)).max(64).optional(),
24514
- updatedAt: z37.iso.datetime()
25063
+ var ReviewSchema2 = z39.object({
25064
+ fingerprint: z39.string().min(1).max(256),
25065
+ pageId: z39.string().min(1).max(128),
25066
+ reportId: z39.string().min(1).max(128),
25067
+ signature: z39.string().regex(/^[a-f0-9]{64}$/),
25068
+ label: z39.string().min(1).max(1e3),
25069
+ decision: z39.enum(["pending", "accepted", "needs-fix"]),
25070
+ instruction: z39.string().max(1e4).optional(),
25071
+ moduleId: z39.string().min(1).max(128).optional(),
25072
+ moduleSourceFiles: z39.array(z39.string().min(1).max(2048)).max(64).optional(),
25073
+ updatedAt: z39.iso.datetime()
24515
25074
  }).strict();
24516
- var InteractionRunSchema = z37.object({
24517
- schema: z37.literal(1),
24518
- runAt: z37.iso.datetime(),
24519
- baseUrl: z37.string().url().max(2048),
24520
- passed: z37.boolean(),
24521
- total: z37.number().int().nonnegative().max(5e4),
24522
- failures: z37.number().int().nonnegative().max(5e4),
24523
- apiRequestCount: z37.number().int().nonnegative().max(1e7),
24524
- scenarios: z37.array(z37.object({
24525
- id: z37.string().min(1).max(128),
24526
- pageUrl: z37.string().url().max(2048),
24527
- passed: z37.boolean(),
24528
- durationMs: z37.number().int().nonnegative().max(864e5),
24529
- apiRequestCount: z37.number().int().nonnegative().max(1e7),
24530
- failure: z37.string().max(2e4).optional(),
24531
- requests: z37.array(z37.object({ method: z37.string().min(1).max(16), path: z37.string().min(1).max(2048), status: z37.number().int().min(0).max(599) }).strict()).max(1e4).optional()
25075
+ var InteractionRunSchema = z39.object({
25076
+ schema: z39.literal(1),
25077
+ runAt: z39.iso.datetime(),
25078
+ baseUrl: z39.string().url().max(2048),
25079
+ passed: z39.boolean(),
25080
+ total: z39.number().int().nonnegative().max(5e4),
25081
+ failures: z39.number().int().nonnegative().max(5e4),
25082
+ apiRequestCount: z39.number().int().nonnegative().max(1e7),
25083
+ scenarios: z39.array(z39.object({
25084
+ id: z39.string().min(1).max(128),
25085
+ pageUrl: z39.string().url().max(2048),
25086
+ passed: z39.boolean(),
25087
+ durationMs: z39.number().int().nonnegative().max(864e5),
25088
+ apiRequestCount: z39.number().int().nonnegative().max(1e7),
25089
+ failure: z39.string().max(2e4).optional(),
25090
+ requests: z39.array(z39.object({ method: z39.string().min(1).max(16), path: z39.string().min(1).max(2048), status: z39.number().int().min(0).max(599) }).strict()).max(1e4).optional()
24532
25091
  }).strict()).max(5e4),
24533
- evidenceMode: z37.enum(["contract", "autonomous", "contract-fallback"]).optional()
25092
+ evidenceMode: z39.enum(["contract", "autonomous", "contract-fallback"]).optional()
24534
25093
  }).strict();
24535
- var QualityJudgmentSchema = z37.object({
24536
- schema: z37.literal(1),
24537
- runAt: z37.iso.datetime(),
24538
- model: z37.string().min(1).max(256),
24539
- visualScore: z37.number().min(0).max(100),
24540
- interactionScore: z37.number().min(0).max(100),
24541
- rawVisualScore: z37.number().min(0).max(100).optional(),
24542
- rawInteractionScore: z37.number().min(0).max(100).optional(),
24543
- staticVisualScore: z37.number().min(0).max(100),
24544
- deterministicInteractionPassed: z37.boolean(),
24545
- overallScore: z37.number().min(0).max(100),
24546
- threshold: z37.number().min(0).max(100),
24547
- verdict: z37.enum(["pass", "fail"]),
24548
- confidence: z37.enum(["high", "medium", "low"]),
24549
- summary: z37.string().min(1).max(4e3),
24550
- strengths: z37.array(z37.string().min(1).max(1e3)).max(20),
24551
- evidenceMode: z37.enum(["contract", "autonomous", "contract-fallback"]).optional(),
24552
- issues: z37.array(z37.object({
24553
- category: z37.enum(["visual", "interaction", "accessibility", "reliability"]),
24554
- severity: z37.enum(["minor", "major", "critical"]),
24555
- description: z37.string().min(1).max(2e3),
24556
- evidence: z37.string().min(1).max(2e3).optional(),
24557
- recommendation: z37.string().min(1).max(2e3),
24558
- selector: z37.string().min(1).max(2048).optional(),
24559
- scoreImpact: z37.number().min(0).max(30).optional(),
24560
- id: z37.string().regex(/^quality-[a-f0-9]{20}$/).optional(),
24561
- decision: z37.enum(["pending", "skipped", "fixing"]).optional(),
24562
- updatedAt: z37.iso.datetime().optional()
25094
+ var QualityJudgmentSchema = z39.object({
25095
+ schema: z39.literal(1),
25096
+ runAt: z39.iso.datetime(),
25097
+ model: z39.string().min(1).max(256),
25098
+ visualScore: z39.number().min(0).max(100),
25099
+ interactionScore: z39.number().min(0).max(100),
25100
+ rawVisualScore: z39.number().min(0).max(100).optional(),
25101
+ rawInteractionScore: z39.number().min(0).max(100).optional(),
25102
+ staticVisualScore: z39.number().min(0).max(100),
25103
+ deterministicInteractionPassed: z39.boolean(),
25104
+ overallScore: z39.number().min(0).max(100),
25105
+ threshold: z39.number().min(0).max(100),
25106
+ verdict: z39.enum(["pass", "fail"]),
25107
+ confidence: z39.enum(["high", "medium", "low"]),
25108
+ summary: z39.string().min(1).max(4e3),
25109
+ strengths: z39.array(z39.string().min(1).max(1e3)).max(20),
25110
+ evidenceMode: z39.enum(["contract", "autonomous", "contract-fallback"]).optional(),
25111
+ issues: z39.array(z39.object({
25112
+ category: z39.enum(["visual", "interaction", "accessibility", "reliability"]),
25113
+ severity: z39.enum(["minor", "major", "critical"]),
25114
+ description: z39.string().min(1).max(2e3),
25115
+ evidence: z39.string().min(1).max(2e3).optional(),
25116
+ recommendation: z39.string().min(1).max(2e3),
25117
+ selector: z39.string().min(1).max(2048).optional(),
25118
+ scoreImpact: z39.number().min(0).max(30).optional(),
25119
+ id: z39.string().regex(/^quality-[a-f0-9]{20}$/).optional(),
25120
+ decision: z39.enum(["pending", "skipped", "fixing"]).optional(),
25121
+ updatedAt: z39.iso.datetime().optional()
24563
25122
  }).strict()).max(100)
24564
25123
  }).strict();
24565
- var WorkflowSchema = z37.object({
24566
- schema: z37.literal(1),
24567
- task: z37.string().regex(D2C_TASK_PATTERN),
24568
- revision: z37.number().int().nonnegative(),
24569
- stage: z37.enum(["visual-review", "api-mapping", "integrating", "interaction-review", "quality-judge", "completed"]),
24570
- framework: z37.enum(["vue", "react"]),
24571
- activeReportId: z37.string().min(1).max(128),
24572
- activeBatchId: z37.string().min(1).max(128).optional(),
24573
- implementationDir: z37.string().min(1).max(32768),
24574
- reviews: z37.array(ReviewSchema2).max(1e4),
24575
- openapi: z37.object({
24576
- sourceName: z37.string().min(1).max(255),
24577
- importedAt: z37.iso.datetime(),
24578
- hash: z37.string().regex(/^[a-f0-9]{64}$/),
24579
- version: z37.string().min(1).max(32),
24580
- title: z37.string().min(1).max(500),
24581
- baseUrl: z37.string().max(4096).optional()
25124
+ var WorkflowSchema = z39.object({
25125
+ schema: z39.literal(1),
25126
+ task: z39.string().regex(D2C_TASK_PATTERN),
25127
+ revision: z39.number().int().nonnegative(),
25128
+ stage: z39.enum(["visual-review", "api-mapping", "integrating", "interaction-review", "quality-judge", "completed"]),
25129
+ framework: z39.enum(["vue", "react"]),
25130
+ activeReportId: z39.string().min(1).max(128),
25131
+ activeBatchId: z39.string().min(1).max(128).optional(),
25132
+ implementationDir: z39.string().min(1).max(32768),
25133
+ reviews: z39.array(ReviewSchema2).max(1e4),
25134
+ openapi: z39.object({
25135
+ sourceName: z39.string().min(1).max(255),
25136
+ importedAt: z39.iso.datetime(),
25137
+ hash: z39.string().regex(/^[a-f0-9]{64}$/),
25138
+ version: z39.string().min(1).max(32),
25139
+ title: z39.string().min(1).max(500),
25140
+ baseUrl: z39.string().max(4096).optional()
24582
25141
  }).strict().optional(),
24583
- mappings: z37.array(z37.unknown()).max(5e3).optional(),
24584
- integrationFiles: z37.array(z37.string().min(1).max(2048)).max(1e3).optional(),
24585
- interaction: z37.object({ manualDecision: z37.enum(["pending", "accepted"]), automated: InteractionRunSchema.optional(), updatedAt: z37.iso.datetime() }).strict().optional(),
25142
+ mappings: z39.array(z39.unknown()).max(5e3).optional(),
25143
+ integrationFiles: z39.array(z39.string().min(1).max(2048)).max(1e3).optional(),
25144
+ interaction: z39.object({ manualDecision: z39.enum(["pending", "accepted"]), automated: InteractionRunSchema.optional(), updatedAt: z39.iso.datetime() }).strict().optional(),
24586
25145
  quality: QualityJudgmentSchema.optional(),
24587
- qualityWaivers: z37.array(z37.object({ issueId: z37.string().regex(/^quality-[a-f0-9]{20}$/), updatedAt: z37.iso.datetime() }).strict()).max(100).optional(),
24588
- updatedAt: z37.iso.datetime()
25146
+ qualityWaivers: z39.array(z39.object({ issueId: z39.string().regex(/^quality-[a-f0-9]{20}$/), updatedAt: z39.iso.datetime() }).strict()).max(100).optional(),
25147
+ updatedAt: z39.iso.datetime()
24589
25148
  }).strict();
24590
25149
  function pageId(report) {
24591
25150
  return report.page?.id ?? "index";
@@ -25002,16 +25561,16 @@ function confirmApiMapping(mapping, operationKey, operations) {
25002
25561
  // src/d2c/modules.ts
25003
25562
  import { readFile as readFile26 } from "fs/promises";
25004
25563
  import { isAbsolute as isAbsolute15, join as join31, normalize as normalize2, posix, sep as sep23, win32 as win322 } from "path";
25005
- import { z as z38 } from "zod";
25006
- var ModuleSchema = z38.object({
25007
- id: z38.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
25008
- label: z38.string().trim().min(1).max(200),
25009
- sourceFiles: z38.array(z38.string().trim().min(1).max(2048)).min(1).max(64),
25010
- keywords: z38.array(z38.string().trim().min(1).max(100)).max(100).optional(),
25011
- dataNeeds: z38.array(z38.string().trim().min(1).max(100)).max(100).optional(),
25012
- actions: z38.array(z38.string().trim().min(1).max(100)).max(100).optional()
25564
+ import { z as z40 } from "zod";
25565
+ var ModuleSchema = z40.object({
25566
+ id: z40.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/),
25567
+ label: z40.string().trim().min(1).max(200),
25568
+ sourceFiles: z40.array(z40.string().trim().min(1).max(2048)).min(1).max(64),
25569
+ keywords: z40.array(z40.string().trim().min(1).max(100)).max(100).optional(),
25570
+ dataNeeds: z40.array(z40.string().trim().min(1).max(100)).max(100).optional(),
25571
+ actions: z40.array(z40.string().trim().min(1).max(100)).max(100).optional()
25013
25572
  }).strict();
25014
- var ManifestSchema3 = z38.object({ schema: z38.literal(1), modules: z38.array(ModuleSchema).min(1).max(500) }).passthrough();
25573
+ var ManifestSchema3 = z40.object({ schema: z40.literal(1), modules: z40.array(ModuleSchema).min(1).max(500) }).passthrough();
25015
25574
  function safeSource(path) {
25016
25575
  if (isAbsolute15(path) || posix.isAbsolute(path) || win322.isAbsolute(path) || path.includes("\0")) return false;
25017
25576
  const value = normalize2(path);
@@ -25453,7 +26012,7 @@ ${managed.output().slice(-4e3)}`);
25453
26012
  import { createHash as createHash19, randomUUID as randomUUID23 } from "crypto";
25454
26013
  import { copyFile as copyFile2, mkdir as mkdir25, readFile as readFile30, rename as rename13, stat as stat12, unlink as unlink6, writeFile as writeFile15 } from "fs/promises";
25455
26014
  import { join as join34 } from "path";
25456
- import { z as z39 } from "zod";
26015
+ import { z as z41 } from "zod";
25457
26016
 
25458
26017
  // src/e2e/prd-governance.ts
25459
26018
  import { createHash as createHash18, randomUUID as randomUUID22 } from "crypto";
@@ -25572,38 +26131,38 @@ var RelativePrototypePath = "product/prototype/index.html";
25572
26131
  var RelativeInteractionPath = "product/prototype/interaction-manifest.json";
25573
26132
  var defaultPlanFileOperations = { rename: rename13, copyFile: copyFile2, unlink: unlink6 };
25574
26133
  var planWriteQueues = /* @__PURE__ */ new Map();
25575
- var PlanSchema2 = z39.object({
25576
- schema: z39.literal(1),
25577
- task: z39.string().regex(D2C_TASK_PATTERN),
25578
- revision: z39.number().int().nonnegative(),
25579
- phase: z39.enum(["prd-generating", "prd-review", "design-generating", "design-review", "ready-for-d2c"]),
25580
- framework: z39.enum(["vue", "react"]),
25581
- technology: z39.object({
25582
- frontend: z39.string().trim().min(1).max(64),
25583
- backend: z39.string().trim().min(1).max(64),
25584
- frontendSource: z39.enum(["default", "requirement"]),
25585
- backendSource: z39.enum(["default", "requirement"])
26134
+ var PlanSchema2 = z41.object({
26135
+ schema: z41.literal(1),
26136
+ task: z41.string().regex(D2C_TASK_PATTERN),
26137
+ revision: z41.number().int().nonnegative(),
26138
+ phase: z41.enum(["prd-generating", "prd-review", "design-generating", "design-review", "ready-for-d2c"]),
26139
+ framework: z41.enum(["vue", "react"]),
26140
+ technology: z41.object({
26141
+ frontend: z41.string().trim().min(1).max(64),
26142
+ backend: z41.string().trim().min(1).max(64),
26143
+ frontendSource: z41.enum(["default", "requirement"]),
26144
+ backendSource: z41.enum(["default", "requirement"])
25586
26145
  }).strict().optional(),
25587
- requirement: z39.string().trim().min(2).max(5e4),
25588
- prd: z39.object({ path: z39.literal(RelativePrdPath), updatedAt: z39.iso.datetime(), contentHash: z39.string().regex(/^[a-f0-9]{64}$/).optional() }).strict().optional(),
25589
- approvedPrd: z39.object({
25590
- hash: z39.string().regex(/^[a-f0-9]{64}$/),
25591
- approvedAt: z39.iso.datetime(),
25592
- criteria: z39.array(z39.object({ id: z39.string().regex(/^AC-\d{3,}$/), text: z39.string().trim().min(1).max(4e3) }).strict()).min(1).max(1e4)
26146
+ requirement: z41.string().trim().min(2).max(5e4),
26147
+ prd: z41.object({ path: z41.literal(RelativePrdPath), updatedAt: z41.iso.datetime(), contentHash: z41.string().regex(/^[a-f0-9]{64}$/).optional() }).strict().optional(),
26148
+ approvedPrd: z41.object({
26149
+ hash: z41.string().regex(/^[a-f0-9]{64}$/),
26150
+ approvedAt: z41.iso.datetime(),
26151
+ criteria: z41.array(z41.object({ id: z41.string().regex(/^AC-\d{3,}$/), text: z41.string().trim().min(1).max(4e3) }).strict()).min(1).max(1e4)
25593
26152
  }).strict().optional(),
25594
- prototype: z39.object({
25595
- entryHtml: z39.literal(RelativePrototypePath),
25596
- interactionManifest: z39.literal(RelativeInteractionPath),
25597
- updatedAt: z39.iso.datetime(),
25598
- contentHash: z39.string().regex(/^[a-f0-9]{64}$/).optional()
26153
+ prototype: z41.object({
26154
+ entryHtml: z41.literal(RelativePrototypePath),
26155
+ interactionManifest: z41.literal(RelativeInteractionPath),
26156
+ updatedAt: z41.iso.datetime(),
26157
+ contentHash: z41.string().regex(/^[a-f0-9]{64}$/).optional()
25599
26158
  }).strict().optional(),
25600
- feedback: z39.object({
25601
- stage: z39.enum(["prd", "design"]),
25602
- message: z39.string().trim().min(1).max(1e4),
25603
- updatedAt: z39.iso.datetime()
26159
+ feedback: z41.object({
26160
+ stage: z41.enum(["prd", "design"]),
26161
+ message: z41.string().trim().min(1).max(1e4),
26162
+ updatedAt: z41.iso.datetime()
25604
26163
  }).strict().optional(),
25605
- createdAt: z39.iso.datetime(),
25606
- updatedAt: z39.iso.datetime()
26164
+ createdAt: z41.iso.datetime(),
26165
+ updatedAt: z41.iso.datetime()
25607
26166
  }).strict();
25608
26167
  function d2cProductDirectory(workspace, task) {
25609
26168
  if (!D2C_TASK_PATTERN.test(task)) throw new Error("Invalid D2C task name");
@@ -25764,10 +26323,10 @@ async function writeD2cProductPlan(workspace, plan, operations = defaultPlanFile
25764
26323
  return parsed;
25765
26324
  }
25766
26325
  async function createD2cProductPlan(workspace, input, now = () => /* @__PURE__ */ new Date()) {
25767
- const parsed = z39.object({
25768
- task: z39.string().regex(D2C_TASK_PATTERN),
25769
- framework: z39.enum(["vue", "react"]),
25770
- requirement: z39.string().trim().min(2).max(5e4)
26326
+ const parsed = z41.object({
26327
+ task: z41.string().regex(D2C_TASK_PATTERN),
26328
+ framework: z41.enum(["vue", "react"]),
26329
+ requirement: z41.string().trim().min(2).max(5e4)
25771
26330
  }).strict().parse(input);
25772
26331
  const timestamp2 = now().toISOString();
25773
26332
  if (await readD2cProductPlan(workspace, parsed.task) !== void 0) {
@@ -25999,31 +26558,31 @@ function createAcceptanceEvidence(coverage, run, now = /* @__PURE__ */ new Date(
25999
26558
  // src/e2e/delivery-run.ts
26000
26559
  import { createHash as createHash21 } from "crypto";
26001
26560
  import { join as join35 } from "path";
26002
- import { z as z40 } from "zod";
26561
+ import { z as z42 } from "zod";
26003
26562
  var DELIVERY_NODE_IDS = ["requirement", "prd", "design", "d2c", "api", "acceptance", "delivery"];
26004
- var ArtifactSchema = z40.object({
26005
- path: z40.string().min(1).max(32768),
26006
- hash: z40.string().regex(/^[a-f0-9]{64}$/),
26007
- bytes: z40.number().int().nonnegative(),
26008
- createdAt: z40.iso.datetime()
26563
+ var ArtifactSchema = z42.object({
26564
+ path: z42.string().min(1).max(32768),
26565
+ hash: z42.string().regex(/^[a-f0-9]{64}$/),
26566
+ bytes: z42.number().int().nonnegative(),
26567
+ createdAt: z42.iso.datetime()
26009
26568
  }).strict();
26010
- var NodeSchema = z40.object({
26011
- id: z40.enum(DELIVERY_NODE_IDS),
26012
- status: z40.enum(["pending", "running", "waiting-approval", "succeeded", "failed", "stale"]),
26013
- attempt: z40.number().int().nonnegative(),
26014
- inputs: z40.array(ArtifactSchema).max(1e4),
26015
- outputs: z40.array(ArtifactSchema).max(1e4),
26016
- startedAt: z40.iso.datetime().optional(),
26017
- completedAt: z40.iso.datetime().optional(),
26018
- error: z40.string().max(2e4).optional()
26569
+ var NodeSchema = z42.object({
26570
+ id: z42.enum(DELIVERY_NODE_IDS),
26571
+ status: z42.enum(["pending", "running", "waiting-approval", "succeeded", "failed", "stale"]),
26572
+ attempt: z42.number().int().nonnegative(),
26573
+ inputs: z42.array(ArtifactSchema).max(1e4),
26574
+ outputs: z42.array(ArtifactSchema).max(1e4),
26575
+ startedAt: z42.iso.datetime().optional(),
26576
+ completedAt: z42.iso.datetime().optional(),
26577
+ error: z42.string().max(2e4).optional()
26019
26578
  }).strict();
26020
- var DeliveryRunSchema = z40.object({
26021
- schema: z40.literal(1),
26022
- task: z40.string().regex(D2C_TASK_PATTERN),
26023
- revision: z40.number().int().nonnegative(),
26024
- nodes: z40.record(z40.enum(DELIVERY_NODE_IDS), NodeSchema),
26025
- createdAt: z40.iso.datetime(),
26026
- updatedAt: z40.iso.datetime()
26579
+ var DeliveryRunSchema = z42.object({
26580
+ schema: z42.literal(1),
26581
+ task: z42.string().regex(D2C_TASK_PATTERN),
26582
+ revision: z42.number().int().nonnegative(),
26583
+ nodes: z42.record(z42.enum(DELIVERY_NODE_IDS), NodeSchema),
26584
+ createdAt: z42.iso.datetime(),
26585
+ updatedAt: z42.iso.datetime()
26027
26586
  }).strict();
26028
26587
  var dependencies = {
26029
26588
  requirement: [],
@@ -27253,11 +27812,12 @@ var DesktopRuntimeController = class {
27253
27812
  ].join("\n");
27254
27813
  const delivery = await readDeliveryRun(workspace, task);
27255
27814
  if (delivery?.nodes.api.status === "running") {
27815
+ const apiArtifacts = await Promise.all(generated.files.map(async (file) => artifactRef(file, await readFile33(join39(project, file)))));
27256
27816
  const completed = await updateDeliveryRun(
27257
27817
  workspace,
27258
27818
  task,
27259
27819
  delivery.revision,
27260
- (run) => completeDeliveryNode(run, "api", generated.files.map((file) => artifactRef(file, file)))
27820
+ (run) => completeDeliveryNode(run, "api", apiArtifacts)
27261
27821
  );
27262
27822
  await updateDeliveryRun(
27263
27823
  workspace,
@@ -27533,6 +28093,12 @@ VITE_API_BASE_URL=${running.url}
27533
28093
  });
27534
28094
  return readD2cProductPlanView(workspace, task).then((view) => view);
27535
28095
  }
28096
+ /** Read-only snapshot of the seven-node E2E delivery run; undefined when the task never started a delivery. */
28097
+ async getE2eDeliveryRun(task) {
28098
+ const workspace = this.#workspace;
28099
+ if (workspace === void 0) return void 0;
28100
+ return readDeliveryRun(workspace, task);
28101
+ }
27536
28102
  async #assertProductPrdLocked(workspace, task) {
27537
28103
  const current = await readD2cProductPlanView(workspace, task);
27538
28104
  if (current?.plan.approvedPrd === void 0) return;
@@ -27862,7 +28428,69 @@ function desktopWindowChrome(platform = process.platform) {
27862
28428
  };
27863
28429
  }
27864
28430
 
28431
+ // src/utils/crash-guard.ts
28432
+ import { mkdirSync as mkdirSync2, writeFileSync } from "fs";
28433
+ import { join as join40 } from "path";
28434
+ var installed = false;
28435
+ function installCrashGuard(options = {}) {
28436
+ if (installed) return;
28437
+ installed = true;
28438
+ const crashLogDir = () => {
28439
+ try {
28440
+ return join40((options.workspace ?? process.cwd)(), ".flavor");
28441
+ } catch {
28442
+ return process.cwd();
28443
+ }
28444
+ };
28445
+ const writeCrashLog = (kind, detail) => {
28446
+ try {
28447
+ const dir = crashLogDir();
28448
+ mkdirSync2(dir, { recursive: true });
28449
+ const path = join40(dir, `crash-${(/* @__PURE__ */ new Date()).toISOString().replace(/[^0-9]/g, "")}-${process.pid}.log`);
28450
+ writeFileSync(path, [
28451
+ `kind: ${kind}`,
28452
+ `version: ${process.version}`,
28453
+ `platform: ${process.platform}`,
28454
+ `time: ${(/* @__PURE__ */ new Date()).toISOString()}`,
28455
+ "",
28456
+ detail
28457
+ ].join("\n"), { encoding: "utf8", mode: 384 });
28458
+ return path;
28459
+ } catch {
28460
+ return void 0;
28461
+ }
28462
+ };
28463
+ const restoreTerminal = () => {
28464
+ try {
28465
+ if (process.stdout.isTTY === true) process.stdout.write("\x1B[?25h\x1B[?1049l");
28466
+ } catch {
28467
+ }
28468
+ };
28469
+ const describe = (reason) => {
28470
+ if (reason instanceof Error) return `${reason.name}: ${reason.message}
28471
+ ${reason.stack ?? ""}`;
28472
+ return String(reason);
28473
+ };
28474
+ const crash = (kind, reason) => {
28475
+ const detail = describe(reason);
28476
+ const logPath = writeCrashLog(kind, detail);
28477
+ restoreTerminal();
28478
+ try {
28479
+ const safe = redactErrorText(detail.split("\n").slice(0, 3).join("\n"));
28480
+ process.stderr.write(`flavor crashed (${kind}): ${safe}
28481
+ `);
28482
+ if (logPath !== void 0) process.stderr.write(`crash log: ${logPath}
28483
+ `);
28484
+ } catch {
28485
+ }
28486
+ process.exit(1);
28487
+ };
28488
+ process.on("unhandledRejection", (reason) => crash("unhandledRejection", reason));
28489
+ process.on("uncaughtException", (error) => crash("uncaughtException", error));
28490
+ }
28491
+
27865
28492
  // src/desktop/main.ts
28493
+ installCrashGuard();
27866
28494
  var moduleDirectory = dirname23(fileURLToPath4(import.meta.url));
27867
28495
  var developmentUrl = process.env.FLAVOR_DESKTOP_DEV_URL;
27868
28496
  var mainWindow;
@@ -27870,7 +28498,7 @@ var appMenu;
27870
28498
  var quitting = false;
27871
28499
  function logStartup(step, detail) {
27872
28500
  try {
27873
- const logPath = join40(dirname23(process.execPath), "flavor-code-startup.log");
28501
+ const logPath = join41(dirname23(process.execPath), "flavor-code-startup.log");
27874
28502
  const ts = (/* @__PURE__ */ new Date()).toISOString();
27875
28503
  appendFileSync(logPath, `[${ts}] ${step}${detail ? ` | ${detail}` : ""}
27876
28504
  `);
@@ -27895,7 +28523,7 @@ var d2cEmbedded = createEmbeddedD2cAutomation(() => {
27895
28523
  };
27896
28524
  });
27897
28525
  var d2cJudgeClient = createD2cJudgeClient();
27898
- var judgeStore = () => createD2cJudgeConfigStore(join40(app.getPath("userData"), "d2c-judge.json"));
28526
+ var judgeStore = () => createD2cJudgeConfigStore(join41(app.getPath("userData"), "d2c-judge.json"));
27899
28527
  function judgeImage(png) {
27900
28528
  const image = nativeImage.createFromBuffer(png);
27901
28529
  const size = image.getSize();
@@ -27945,7 +28573,7 @@ var controller = new DesktopRuntimeController({
27945
28573
  })
27946
28574
  });
27947
28575
  function statePath() {
27948
- return join40(app.getPath("userData"), "desktop-state.json");
28576
+ return join41(app.getPath("userData"), "desktop-state.json");
27949
28577
  }
27950
28578
  async function loadPersistedWorkspace() {
27951
28579
  try {
@@ -27980,7 +28608,7 @@ async function chooseAndOpenWorkspace() {
27980
28608
  var cachedAppIconDataUrl;
27981
28609
  function appIconDataUrl() {
27982
28610
  if (cachedAppIconDataUrl !== void 0) return cachedAppIconDataUrl;
27983
- const icon = nativeImage.createFromPath(join40(app.getAppPath(), "assets", "icon.png"));
28611
+ const icon = nativeImage.createFromPath(join41(app.getAppPath(), "assets", "icon.png"));
27984
28612
  if (icon.isEmpty()) return void 0;
27985
28613
  cachedAppIconDataUrl = icon.toDataURL();
27986
28614
  return cachedAppIconDataUrl;
@@ -28195,6 +28823,9 @@ function installIpcHandlers() {
28195
28823
  const input = D2cQualityIssueDecisionInputSchema.parse(value);
28196
28824
  return controller.resolveD2cQualityIssue(input.task, input.issueId, input.decision);
28197
28825
  });
28826
+ ipcMain.handle(DESKTOP_CHANNELS.e2eGetDeliveryRun, async (_event, value) => {
28827
+ return controller.getE2eDeliveryRun(D2cTaskActionInputSchema.parse(value).task);
28828
+ });
28198
28829
  }
28199
28830
  function applicationMenu() {
28200
28831
  return Menu.buildFromTemplate([
@@ -28225,7 +28856,7 @@ function applicationMenu() {
28225
28856
  ]);
28226
28857
  }
28227
28858
  async function createWindow() {
28228
- const rendererPath = join40(app.getAppPath(), "dist", "desktop-renderer", "index.html");
28859
+ const rendererPath = join41(app.getAppPath(), "dist", "desktop-renderer", "index.html");
28229
28860
  mainWindow = new BrowserWindow2({
28230
28861
  title: "Flavor Code",
28231
28862
  width: 1280,
@@ -28236,14 +28867,14 @@ async function createWindow() {
28236
28867
  show: false,
28237
28868
  ...desktopWindowChrome(),
28238
28869
  webPreferences: {
28239
- preload: join40(moduleDirectory, "preload.cjs"),
28870
+ preload: join41(moduleDirectory, "preload.cjs"),
28240
28871
  contextIsolation: true,
28241
28872
  nodeIntegration: false,
28242
28873
  sandbox: false,
28243
28874
  webSecurity: true
28244
28875
  }
28245
28876
  });
28246
- const iconPath = join40(app.getAppPath(), "assets", "icon.png");
28877
+ const iconPath = join41(app.getAppPath(), "assets", "icon.png");
28247
28878
  const icon = nativeImage.createFromPath(iconPath);
28248
28879
  if (!icon.isEmpty()) {
28249
28880
  mainWindow.setIcon(icon);