syntaur 0.74.0 → 0.76.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/dashboard/dist/assets/{_basePickBy-CBNQaqzq.js → _basePickBy-BiwSunXO.js} +1 -1
  3. package/dashboard/dist/assets/{_baseUniq-Bqwz8hnN.js → _baseUniq-DsjKPXxP.js} +1 -1
  4. package/dashboard/dist/assets/{arc-B6lVW0Fc.js → arc-DlEs4wsF.js} +1 -1
  5. package/dashboard/dist/assets/{architectureDiagram-2XIMDMQ5-eKpHkGki.js → architectureDiagram-2XIMDMQ5-DPvCrO57.js} +1 -1
  6. package/dashboard/dist/assets/{blockDiagram-WCTKOSBZ-D3sd7ccQ.js → blockDiagram-WCTKOSBZ-CpNdCY-r.js} +1 -1
  7. package/dashboard/dist/assets/{c4Diagram-IC4MRINW-0qW21hVQ.js → c4Diagram-IC4MRINW-CC29QJCs.js} +1 -1
  8. package/dashboard/dist/assets/channel-IutbH48W.js +1 -0
  9. package/dashboard/dist/assets/{chunk-4BX2VUAB-tDdoFSYw.js → chunk-4BX2VUAB-DKyy-k2D.js} +1 -1
  10. package/dashboard/dist/assets/{chunk-55IACEB6-BU45eS64.js → chunk-55IACEB6-DjobngQk.js} +1 -1
  11. package/dashboard/dist/assets/{chunk-FMBD7UC4-C0iT8QWM.js → chunk-FMBD7UC4-BUftm7dV.js} +1 -1
  12. package/dashboard/dist/assets/{chunk-JSJVCQXG-CELv9Y6Y.js → chunk-JSJVCQXG-Nv7rQv4t.js} +1 -1
  13. package/dashboard/dist/assets/{chunk-KX2RTZJC-CQA_hH8g.js → chunk-KX2RTZJC-Dg6UhNB9.js} +1 -1
  14. package/dashboard/dist/assets/{chunk-NQ4KR5QH-BDv-d6qz.js → chunk-NQ4KR5QH-D8neQrJ_.js} +1 -1
  15. package/dashboard/dist/assets/{chunk-QZHKN3VN-BUOeJd34.js → chunk-QZHKN3VN-Uj9c1naA.js} +1 -1
  16. package/dashboard/dist/assets/{chunk-WL4C6EOR-DBc-Hsx0.js → chunk-WL4C6EOR-DfeSsP3z.js} +1 -1
  17. package/dashboard/dist/assets/classDiagram-VBA2DB6C-8IywRj9I.js +1 -0
  18. package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-8IywRj9I.js +1 -0
  19. package/dashboard/dist/assets/clone-C6saGiCd.js +1 -0
  20. package/dashboard/dist/assets/{cose-bilkent-S5V4N54A-C_Q4c3xo.js → cose-bilkent-S5V4N54A-CLfZNKcO.js} +1 -1
  21. package/dashboard/dist/assets/{dagre-KLK3FWXG-DdI10bBF.js → dagre-KLK3FWXG-DyJLICZx.js} +1 -1
  22. package/dashboard/dist/assets/{diagram-E7M64L7V-DtCF4Ea9.js → diagram-E7M64L7V-DhQc7Ta3.js} +1 -1
  23. package/dashboard/dist/assets/{diagram-IFDJBPK2-BVmpBmIK.js → diagram-IFDJBPK2-C6kFO7hB.js} +1 -1
  24. package/dashboard/dist/assets/{diagram-P4PSJMXO-BH4XFc0W.js → diagram-P4PSJMXO-B6oCiOXk.js} +1 -1
  25. package/dashboard/dist/assets/{erDiagram-INFDFZHY-CCjG3Ewp.js → erDiagram-INFDFZHY-BsMPaSwJ.js} +1 -1
  26. package/dashboard/dist/assets/{flowDiagram-PKNHOUZH-V0PT07-Y.js → flowDiagram-PKNHOUZH-DLxEqKtZ.js} +1 -1
  27. package/dashboard/dist/assets/{ganttDiagram-A5KZAMGK-y_85pJZf.js → ganttDiagram-A5KZAMGK-D70pvqxG.js} +1 -1
  28. package/dashboard/dist/assets/{gitGraphDiagram-K3NZZRJ6-B2maPPcL.js → gitGraphDiagram-K3NZZRJ6-D74VHtlE.js} +1 -1
  29. package/dashboard/dist/assets/{graph-DO1oCTrt.js → graph-C8bz_IEO.js} +1 -1
  30. package/dashboard/dist/assets/{index-BZwPAi8K.css → index-BetqH_3H.css} +1 -1
  31. package/dashboard/dist/assets/index-h-X_8om3.js +675 -0
  32. package/dashboard/dist/assets/{infoDiagram-LFFYTUFH-BIaqpTlK.js → infoDiagram-LFFYTUFH-DivBd0Pz.js} +1 -1
  33. package/dashboard/dist/assets/{ishikawaDiagram-PHBUUO56-BaBqTUzg.js → ishikawaDiagram-PHBUUO56-BGihUeOE.js} +1 -1
  34. package/dashboard/dist/assets/{journeyDiagram-4ABVD52K-CS2l7gmE.js → journeyDiagram-4ABVD52K-C7U4cWHQ.js} +1 -1
  35. package/dashboard/dist/assets/{kanban-definition-K7BYSVSG-B3Viag1o.js → kanban-definition-K7BYSVSG-CFp_hDTm.js} +1 -1
  36. package/dashboard/dist/assets/{layout-BQu5nxr5.js → layout-DMSDPqCs.js} +1 -1
  37. package/dashboard/dist/assets/{linear-DliLQN5_.js → linear-CCC-meYc.js} +1 -1
  38. package/dashboard/dist/assets/{mermaid.core-y_G2N_4o.js → mermaid.core-BDa2cc2K.js} +4 -4
  39. package/dashboard/dist/assets/{mindmap-definition-YRQLILUH-EZz-bEA_.js → mindmap-definition-YRQLILUH-DLKvONhO.js} +1 -1
  40. package/dashboard/dist/assets/{pieDiagram-SKSYHLDU-E67ZAs-E.js → pieDiagram-SKSYHLDU-DAJoGZ93.js} +1 -1
  41. package/dashboard/dist/assets/{quadrantDiagram-337W2JSQ-GU25jLyr.js → quadrantDiagram-337W2JSQ-Bo7haX1W.js} +1 -1
  42. package/dashboard/dist/assets/{requirementDiagram-Z7DCOOCP-4Jfq0mB9.js → requirementDiagram-Z7DCOOCP-uEvGz33v.js} +1 -1
  43. package/dashboard/dist/assets/{sankeyDiagram-WA2Y5GQK-C22SY4ul.js → sankeyDiagram-WA2Y5GQK-cjYoCGCM.js} +1 -1
  44. package/dashboard/dist/assets/{sequenceDiagram-2WXFIKYE-CkBh7V9t.js → sequenceDiagram-2WXFIKYE-CYXcNklt.js} +1 -1
  45. package/dashboard/dist/assets/{stateDiagram-RAJIS63D-n4DRlbfF.js → stateDiagram-RAJIS63D-B5We7jAw.js} +1 -1
  46. package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-CX9-EpBi.js +1 -0
  47. package/dashboard/dist/assets/{timeline-definition-YZTLITO2-CGD5ojK7.js → timeline-definition-YZTLITO2-CEqVmnVQ.js} +1 -1
  48. package/dashboard/dist/assets/{treemap-KZPCXAKY-EZfHxNz6.js → treemap-KZPCXAKY-CE1puPeN.js} +1 -1
  49. package/dashboard/dist/assets/{vennDiagram-LZ73GAT5-B9x6fx-l.js → vennDiagram-LZ73GAT5-CiiuRUjK.js} +1 -1
  50. package/dashboard/dist/assets/{xychartDiagram-JWTSCODW-ufzpkH1I.js → xychartDiagram-JWTSCODW-B0OuxFm9.js} +1 -1
  51. package/dashboard/dist/index.html +2 -2
  52. package/dist/dashboard/server.js +509 -221
  53. package/dist/dashboard/server.js.map +1 -1
  54. package/dist/index.js +1210 -823
  55. package/dist/index.js.map +1 -1
  56. package/dist/launch/index.d.ts +69 -7
  57. package/dist/launch/index.js +229 -24
  58. package/dist/launch/index.js.map +1 -1
  59. package/package.json +1 -1
  60. package/platforms/claude-code/.claude-plugin/plugin.json +1 -1
  61. package/platforms/codex/.codex-plugin/plugin.json +1 -1
  62. package/platforms/hermes/plugins/syntaur/__pycache__/__init__.cpython-312.pyc +0 -0
  63. package/platforms/hermes/plugins/syntaur/__pycache__/boundary.cpython-312.pyc +0 -0
  64. package/dashboard/dist/assets/channel-BDsImlpM.js +0 -1
  65. package/dashboard/dist/assets/classDiagram-VBA2DB6C-BhdNnCQ2.js +0 -1
  66. package/dashboard/dist/assets/classDiagram-v2-RAHNMMFH-BhdNnCQ2.js +0 -1
  67. package/dashboard/dist/assets/clone-B5RwQsX7.js +0 -1
  68. package/dashboard/dist/assets/index-CG8rQF5o.js +0 -670
  69. package/dashboard/dist/assets/stateDiagram-v2-FVOUBMTO-RpTmT3-9.js +0 -1
@@ -2543,6 +2543,10 @@ function modelFlagArgs(agent) {
2543
2543
  const m = agent.model?.trim();
2544
2544
  return m ? ["--model", m] : [];
2545
2545
  }
2546
+ function agentNameArgs(agent) {
2547
+ const n = agent.agentName?.trim();
2548
+ return n ? ["--agent", n] : [];
2549
+ }
2546
2550
  function stripModelFlags(args) {
2547
2551
  const out = [];
2548
2552
  for (let i = 0; i < args.length; i++) {
@@ -3898,6 +3902,26 @@ function validateAgentList(agents) {
3898
3902
  `agent "${agent.id}" has invalid launchPrompt \u2014 must be a single line (no newlines)`
3899
3903
  );
3900
3904
  }
3905
+ if (agent.agentName !== void 0 && /[\r\n]/.test(agent.agentName)) {
3906
+ throw new AgentConfigError(
3907
+ `agent "${agent.id}" has invalid agentName \u2014 must be a single line (no newlines)`
3908
+ );
3909
+ }
3910
+ if (agent.workdir !== void 0 && /[\r\n]/.test(agent.workdir)) {
3911
+ throw new AgentConfigError(
3912
+ `agent "${agent.id}" has invalid workdir \u2014 must be a single line (no newlines)`
3913
+ );
3914
+ }
3915
+ if (agent.agentName !== void 0 && agent.agentName.trim() !== "" && agent.workdir !== void 0 && agent.workdir.trim() !== "") {
3916
+ throw new AgentConfigError(
3917
+ `agent "${agent.id}" sets both agentName and workdir \u2014 these are mutually exclusive`
3918
+ );
3919
+ }
3920
+ if (agent.agentName !== void 0 && agent.agentName.trim() !== "" && agent.model !== void 0 && agent.model.trim() !== "") {
3921
+ throw new AgentConfigError(
3922
+ `agent "${agent.id}" sets both agentName and model \u2014 the agent definition's own model is authoritative; remove the profile model`
3923
+ );
3924
+ }
3901
3925
  validateSessionInvocation(agent, "resume", agent.resume);
3902
3926
  validateSessionInvocation(agent, "fork", agent.fork);
3903
3927
  if (agent.default) defaults++;
@@ -4718,6 +4742,8 @@ function parseAgentsConfig(content) {
4718
4742
  ...current.model ? { model: current.model } : {},
4719
4743
  ...current.playbook ? { playbook: current.playbook } : {},
4720
4744
  ...current.launchPrompt ? { launchPrompt: current.launchPrompt } : {},
4745
+ ...current.agentName ? { agentName: current.agentName } : {},
4746
+ ...current.workdir ? { workdir: current.workdir } : {},
4721
4747
  ...current.resume ? { resume: current.resume } : {},
4722
4748
  ...current.fork ? { fork: current.fork } : {}
4723
4749
  });
@@ -4909,6 +4935,12 @@ function assignAgentField(target, key, rawValue) {
4909
4935
  case "launchPrompt":
4910
4936
  target.launchPrompt = value;
4911
4937
  break;
4938
+ case "agentName":
4939
+ target.agentName = value;
4940
+ break;
4941
+ case "workdir":
4942
+ target.workdir = value;
4943
+ break;
4912
4944
  }
4913
4945
  }
4914
4946
  function yamlQuoteScalar(value) {
@@ -4938,6 +4970,12 @@ function serializeAgentsConfig(agents) {
4938
4970
  if (a.launchPrompt) {
4939
4971
  lines.push(` launchPrompt: ${yamlQuoteScalar(a.launchPrompt)}`);
4940
4972
  }
4973
+ if (a.agentName) {
4974
+ lines.push(` agentName: ${yamlQuoteScalar(a.agentName)}`);
4975
+ }
4976
+ if (a.workdir) {
4977
+ lines.push(` workdir: ${yamlQuoteScalar(a.workdir)}`);
4978
+ }
4941
4979
  if (a.args && a.args.length > 0) {
4942
4980
  lines.push(` args:`);
4943
4981
  for (const arg of a.args) {
@@ -5585,7 +5623,9 @@ var init_config2 = __esm({
5585
5623
  "resolveFromShellAliases",
5586
5624
  "model",
5587
5625
  "playbook",
5588
- "launchPrompt"
5626
+ "launchPrompt",
5627
+ "agentName",
5628
+ "workdir"
5589
5629
  ]);
5590
5630
  migratedConfigPaths = /* @__PURE__ */ new Set();
5591
5631
  TerminalConfigError = class extends Error {
@@ -6013,6 +6053,21 @@ function resolveWorkspaceCwd(input) {
6013
6053
  invalidReason: `workspace path invalid for ${assignmentSlug}: tried worktreePath ${shown(worktreePath)} and repository ${shown(repository)} \u2014 neither is an existing directory`
6014
6054
  };
6015
6055
  }
6056
+ function resolveLaunchCwd(agent, worktreeCwd) {
6057
+ const wd = agent.workdir?.trim();
6058
+ if (wd) {
6059
+ const expanded = expandHome(wd);
6060
+ if (!isExistingDir(expanded)) {
6061
+ return {
6062
+ spawnCwd: worktreeCwd,
6063
+ worktreePath: worktreeCwd,
6064
+ invalidReason: `agent "${agent.id}" workdir ${agent.workdir} (resolved ${expanded}) is not an existing directory`
6065
+ };
6066
+ }
6067
+ return { spawnCwd: expanded, worktreePath: worktreeCwd, invalidReason: null };
6068
+ }
6069
+ return { spawnCwd: worktreeCwd, worktreePath: worktreeCwd, invalidReason: null };
6070
+ }
6016
6071
  function formatFallbackCwdWarning(opts) {
6017
6072
  const missing = [];
6018
6073
  if (!opts.worktreePath) missing.push("worktreePath");
@@ -6024,6 +6079,7 @@ function formatFallbackCwdWarning(opts) {
6024
6079
  var init_cwd = __esm({
6025
6080
  "src/launch/cwd.ts"() {
6026
6081
  "use strict";
6082
+ init_paths();
6027
6083
  }
6028
6084
  });
6029
6085
 
@@ -7857,8 +7913,8 @@ async function migrateFromMarkdown(projectsDir) {
7857
7913
  return allSessions.length;
7858
7914
  }
7859
7915
  async function parseMarkdownSessionsIndex(filePath, projectSlug) {
7860
- const { readFile: readFile31 } = await import("fs/promises");
7861
- const raw2 = await readFile31(filePath, "utf-8");
7916
+ const { readFile: readFile32 } = await import("fs/promises");
7917
+ const raw2 = await readFile32(filePath, "utf-8");
7862
7918
  const sessions = [];
7863
7919
  const lines = raw2.split("\n");
7864
7920
  let inTable = false;
@@ -12472,69 +12528,6 @@ var init_session_id = __esm({
12472
12528
  }
12473
12529
  });
12474
12530
 
12475
- // src/utils/assignment-todos.ts
12476
- var assignment_todos_exports = {};
12477
- __export(assignment_todos_exports, {
12478
- appendTodosToAssignmentBody: () => appendTodosToAssignmentBody,
12479
- touchAssignmentUpdated: () => touchAssignmentUpdated
12480
- });
12481
- function setTopLevelField2(content, key, value) {
12482
- const fieldRegex = new RegExp(`^(${key}:)\\s*.*$`, "m");
12483
- if (fieldRegex.test(content)) {
12484
- return content.replace(fieldRegex, `$1 ${value}`);
12485
- }
12486
- return content;
12487
- }
12488
- function appendTodosToAssignmentBody(body, todos) {
12489
- if (todos.length === 0) return body;
12490
- const lines = todos.map((t) => {
12491
- const base = `- [ ] ${t.description.trim()}`;
12492
- return t.trace ? `${base} <!-- ${t.trace} -->` : base;
12493
- });
12494
- const block = lines.join("\n");
12495
- const todosHeading = /^## Todos\s*$/m;
12496
- if (todosHeading.test(body)) {
12497
- return body.replace(
12498
- /(^## Todos[\s\S]*?)(\n## |\n*$)/m,
12499
- (_m, section, nextHeading) => {
12500
- return `${section.trimEnd()}
12501
- ${block}
12502
- ${nextHeading}`;
12503
- }
12504
- );
12505
- }
12506
- return `${body.trimEnd()}
12507
-
12508
- ## Todos
12509
-
12510
- ${block}
12511
- `;
12512
- }
12513
- function touchAssignmentUpdated(content, timestamp) {
12514
- return setTopLevelField2(content, "updated", `"${timestamp}"`);
12515
- }
12516
- var init_assignment_todos = __esm({
12517
- "src/utils/assignment-todos.ts"() {
12518
- "use strict";
12519
- }
12520
- });
12521
-
12522
- // src/utils/path-canon.ts
12523
- import { realpathSync as realpathSync2 } from "fs";
12524
- import { resolve as resolve44 } from "path";
12525
- function canonicalPath(p) {
12526
- try {
12527
- return realpathSync2(resolve44(p));
12528
- } catch {
12529
- return resolve44(p).replace(/\/+$/, "");
12530
- }
12531
- }
12532
- var init_path_canon = __esm({
12533
- "src/utils/path-canon.ts"() {
12534
- "use strict";
12535
- }
12536
- });
12537
-
12538
12531
  // src/targets/renderers.ts
12539
12532
  var RENDERERS;
12540
12533
  var init_renderers = __esm({
@@ -12555,8 +12548,8 @@ var init_renderers = __esm({
12555
12548
  });
12556
12549
 
12557
12550
  // src/targets/user-descriptors.ts
12558
- import { resolve as resolve45 } from "path";
12559
- import { readFile as readFile30, readdir as readdir18 } from "fs/promises";
12551
+ import { resolve as resolve26 } from "path";
12552
+ import { readFile as readFile19, readdir as readdir14 } from "fs/promises";
12560
12553
  var VALID_RENDERER_KEYS;
12561
12554
  var init_user_descriptors = __esm({
12562
12555
  "src/targets/user-descriptors.ts"() {
@@ -12569,21 +12562,21 @@ var init_user_descriptors = __esm({
12569
12562
  });
12570
12563
 
12571
12564
  // src/targets/registry.ts
12572
- import { homedir as homedir7 } from "os";
12573
- import { join as join10, resolve as resolve46 } from "path";
12565
+ import { homedir as homedir4 } from "os";
12566
+ import { join as join5, resolve as resolve27 } from "path";
12574
12567
  function home(...segments) {
12575
- return resolve46(homedir7(), ...segments);
12568
+ return resolve27(homedir4(), ...segments);
12576
12569
  }
12577
12570
  function hermesHome() {
12578
12571
  const env = process.env.HERMES_HOME;
12579
- return env && env.length > 0 ? resolve46(env) : home(".hermes");
12572
+ return env && env.length > 0 ? resolve27(env) : home(".hermes");
12580
12573
  }
12581
12574
  function hermesSkillsDir() {
12582
- return resolve46(hermesHome(), "skills");
12575
+ return resolve27(hermesHome(), "skills");
12583
12576
  }
12584
12577
  function codexHome() {
12585
12578
  const env = process.env.CODEX_HOME;
12586
- return env && env.length > 0 ? resolve46(env) : home(".codex");
12579
+ return env && env.length > 0 ? resolve27(env) : home(".codex");
12587
12580
  }
12588
12581
  function toDiscovered(meta) {
12589
12582
  if (!meta) return null;
@@ -12595,6 +12588,9 @@ function toDiscovered(meta) {
12595
12588
  transcriptPath: meta.path
12596
12589
  };
12597
12590
  }
12591
+ function getAgentTarget(id) {
12592
+ return AGENT_TARGETS_BY_ID[id];
12593
+ }
12598
12594
  var detectDir, claudeSessions, codexSessions, piSessions, AGENT_TARGETS, AGENT_TARGETS_BY_ID;
12599
12595
  var init_registry = __esm({
12600
12596
  "src/targets/registry.ts"() {
@@ -12604,7 +12600,7 @@ var init_registry = __esm({
12604
12600
  init_user_descriptors();
12605
12601
  detectDir = (dir) => () => fileExists(dir);
12606
12602
  claudeSessions = {
12607
- globs: (root) => [join10(root ?? home(".claude", "projects"), "*", "*.jsonl")],
12603
+ globs: (root) => [join5(root ?? home(".claude", "projects"), "*", "*.jsonl")],
12608
12604
  parse: async (file) => toDiscovered(await extractClaudeSessionMeta(file)),
12609
12605
  walk: async function* (opts = {}) {
12610
12606
  for await (const meta of walkClaudeProjects({ root: opts.root, sinceMtimeMs: opts.sinceMtimeMs })) {
@@ -12614,7 +12610,7 @@ var init_registry = __esm({
12614
12610
  }
12615
12611
  };
12616
12612
  codexSessions = {
12617
- globs: (root) => [join10(root ?? resolveCodexSessionsRoot(), "**", "*.jsonl")],
12613
+ globs: (root) => [join5(root ?? resolveCodexSessionsRoot(), "**", "*.jsonl")],
12618
12614
  parse: async (file) => toDiscovered(await extractCodexSessionMeta(file)),
12619
12615
  walk: async function* (opts = {}) {
12620
12616
  for await (const meta of walkCodexSessions({ root: opts.root, sinceMtimeMs: opts.sinceMtimeMs })) {
@@ -12624,7 +12620,7 @@ var init_registry = __esm({
12624
12620
  }
12625
12621
  };
12626
12622
  piSessions = {
12627
- globs: (root) => [join10(root ?? resolvePiSessionsRoot(), "*", "*.jsonl")],
12623
+ globs: (root) => [join5(root ?? resolvePiSessionsRoot(), "*", "*.jsonl")],
12628
12624
  parse: async (file) => toDiscovered(await extractPiSessionMeta(file)),
12629
12625
  walk: async function* (opts = {}) {
12630
12626
  for await (const meta of walkPiSessions({ root: opts.root, sinceMtimeMs: opts.sinceMtimeMs })) {
@@ -12654,7 +12650,7 @@ var init_registry = __esm({
12654
12650
  skillsShAgentId: "codex",
12655
12651
  nativePlugin: "codex",
12656
12652
  detect: detectDir(codexHome()),
12657
- skillsDir: { global: resolve46(codexHome(), "skills") },
12653
+ skillsDir: { global: resolve27(codexHome(), "skills") },
12658
12654
  instructions: { files: [{ path: "AGENTS.md", renderer: "codexAgents" }] },
12659
12655
  sessions: codexSessions
12660
12656
  },
@@ -12680,7 +12676,8 @@ var init_registry = __esm({
12680
12676
  nativePlugin: "claude",
12681
12677
  detect: detectDir(home(".claude")),
12682
12678
  skillsDir: { global: home(".claude", "skills") },
12683
- sessions: claudeSessions
12679
+ sessions: claudeSessions,
12680
+ agentsDir: home(".claude", "agents")
12684
12681
  },
12685
12682
  {
12686
12683
  id: "pi",
@@ -12723,7 +12720,7 @@ var init_registry = __esm({
12723
12720
  tier3: {
12724
12721
  kind: "hermes-plugin",
12725
12722
  source: "platforms/hermes/plugins/syntaur",
12726
- installDir: () => resolve46(hermesHome(), "plugins", "syntaur"),
12723
+ installDir: () => resolve27(hermesHome(), "plugins", "syntaur"),
12727
12724
  entry: "plugin.yaml"
12728
12725
  }
12729
12726
  }
@@ -12734,6 +12731,69 @@ var init_registry = __esm({
12734
12731
  }
12735
12732
  });
12736
12733
 
12734
+ // src/utils/assignment-todos.ts
12735
+ var assignment_todos_exports = {};
12736
+ __export(assignment_todos_exports, {
12737
+ appendTodosToAssignmentBody: () => appendTodosToAssignmentBody,
12738
+ touchAssignmentUpdated: () => touchAssignmentUpdated
12739
+ });
12740
+ function setTopLevelField2(content, key, value) {
12741
+ const fieldRegex = new RegExp(`^(${key}:)\\s*.*$`, "m");
12742
+ if (fieldRegex.test(content)) {
12743
+ return content.replace(fieldRegex, `$1 ${value}`);
12744
+ }
12745
+ return content;
12746
+ }
12747
+ function appendTodosToAssignmentBody(body, todos) {
12748
+ if (todos.length === 0) return body;
12749
+ const lines = todos.map((t) => {
12750
+ const base = `- [ ] ${t.description.trim()}`;
12751
+ return t.trace ? `${base} <!-- ${t.trace} -->` : base;
12752
+ });
12753
+ const block = lines.join("\n");
12754
+ const todosHeading = /^## Todos\s*$/m;
12755
+ if (todosHeading.test(body)) {
12756
+ return body.replace(
12757
+ /(^## Todos[\s\S]*?)(\n## |\n*$)/m,
12758
+ (_m, section, nextHeading) => {
12759
+ return `${section.trimEnd()}
12760
+ ${block}
12761
+ ${nextHeading}`;
12762
+ }
12763
+ );
12764
+ }
12765
+ return `${body.trimEnd()}
12766
+
12767
+ ## Todos
12768
+
12769
+ ${block}
12770
+ `;
12771
+ }
12772
+ function touchAssignmentUpdated(content, timestamp) {
12773
+ return setTopLevelField2(content, "updated", `"${timestamp}"`);
12774
+ }
12775
+ var init_assignment_todos = __esm({
12776
+ "src/utils/assignment-todos.ts"() {
12777
+ "use strict";
12778
+ }
12779
+ });
12780
+
12781
+ // src/utils/path-canon.ts
12782
+ import { realpathSync as realpathSync2 } from "fs";
12783
+ import { resolve as resolve46 } from "path";
12784
+ function canonicalPath(p) {
12785
+ try {
12786
+ return realpathSync2(resolve46(p));
12787
+ } catch {
12788
+ return resolve46(p).replace(/\/+$/, "");
12789
+ }
12790
+ }
12791
+ var init_path_canon = __esm({
12792
+ "src/utils/path-canon.ts"() {
12793
+ "use strict";
12794
+ }
12795
+ });
12796
+
12737
12797
  // src/sessions/agent-view.ts
12738
12798
  import { execFile as execFile3 } from "child_process";
12739
12799
  import { promisify as promisify3 } from "util";
@@ -18143,6 +18203,55 @@ function createAgentSessionsRouter(projectsDir, broadcast, assignmentsDir2) {
18143
18203
  init_config2();
18144
18204
  init_agents_schema();
18145
18205
  import { Router as Router5 } from "express";
18206
+
18207
+ // src/targets/agent-definitions.ts
18208
+ init_parser();
18209
+ init_registry();
18210
+ import { readdir as readdir15, readFile as readFile20 } from "fs/promises";
18211
+ import { join as join6 } from "path";
18212
+ async function collectMarkdown(dir, out) {
18213
+ let entries;
18214
+ try {
18215
+ entries = await readdir15(dir, { withFileTypes: true });
18216
+ } catch {
18217
+ return;
18218
+ }
18219
+ for (const entry of entries) {
18220
+ const full = join6(dir, entry.name);
18221
+ if (entry.isDirectory()) {
18222
+ await collectMarkdown(full, out);
18223
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
18224
+ out.push(full);
18225
+ }
18226
+ }
18227
+ }
18228
+ async function discoverClaudeAgents(root) {
18229
+ const dir = root ?? getAgentTarget("claude")?.agentsDir;
18230
+ if (!dir) return [];
18231
+ const files = [];
18232
+ await collectMarkdown(dir, files);
18233
+ files.sort();
18234
+ const byName = /* @__PURE__ */ new Map();
18235
+ for (const file of files) {
18236
+ let content;
18237
+ try {
18238
+ content = await readFile20(file, "utf-8");
18239
+ } catch {
18240
+ continue;
18241
+ }
18242
+ const [frontmatter] = extractFrontmatter2(content);
18243
+ if (!frontmatter) continue;
18244
+ const name = getField(frontmatter, "name")?.trim();
18245
+ if (!name) continue;
18246
+ if (byName.has(name)) continue;
18247
+ const description = getField(frontmatter, "description")?.trim() || void 0;
18248
+ const model = getField(frontmatter, "model")?.trim() || void 0;
18249
+ byName.set(name, { name, description, model, path: file });
18250
+ }
18251
+ return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
18252
+ }
18253
+
18254
+ // src/dashboard/api-agents.ts
18146
18255
  function mapAgentErrorToFieldErrors(err) {
18147
18256
  const message = err.message;
18148
18257
  let match = message.match(/^agent id "([^"]*)" is invalid/);
@@ -18230,6 +18339,38 @@ function mapAgentErrorToFieldErrors(err) {
18230
18339
  ]
18231
18340
  };
18232
18341
  }
18342
+ match = message.match(/^agent "([^"]+)" has invalid agentName/);
18343
+ if (match) {
18344
+ return {
18345
+ error: message,
18346
+ fieldErrors: [{ id: match[1], field: "agentName", message: "must be a single line" }]
18347
+ };
18348
+ }
18349
+ match = message.match(/^agent "([^"]+)" has invalid workdir/);
18350
+ if (match) {
18351
+ return {
18352
+ error: message,
18353
+ fieldErrors: [{ id: match[1], field: "workdir", message: "must be a single line" }]
18354
+ };
18355
+ }
18356
+ match = message.match(/^agent "([^"]+)" sets both agentName and workdir/);
18357
+ if (match) {
18358
+ return {
18359
+ error: message,
18360
+ fieldErrors: [
18361
+ { id: match[1], field: "workdir", message: "agentName and workdir are mutually exclusive" }
18362
+ ]
18363
+ };
18364
+ }
18365
+ match = message.match(/^agent "([^"]+)" sets both agentName and model/);
18366
+ if (match) {
18367
+ return {
18368
+ error: message,
18369
+ fieldErrors: [
18370
+ { id: match[1], field: "model", message: "remove the profile model; the agent defines its own" }
18371
+ ]
18372
+ };
18373
+ }
18233
18374
  return { error: message };
18234
18375
  }
18235
18376
  function coerceAgentRow(raw2, index) {
@@ -18377,10 +18518,47 @@ function coerceAgentRow(raw2, index) {
18377
18518
  }
18378
18519
  if (entry.launchPrompt.trim()) cleaned.launchPrompt = entry.launchPrompt;
18379
18520
  }
18521
+ if (entry.agentName !== void 0) {
18522
+ if (typeof entry.agentName !== "string") {
18523
+ return {
18524
+ ok: false,
18525
+ status: 400,
18526
+ body: {
18527
+ error: `agents[${index}].agentName must be a string`,
18528
+ fieldErrors: [{ id, field: "agentName", message: "agentName must be a string" }]
18529
+ }
18530
+ };
18531
+ }
18532
+ const agentName = entry.agentName.trim();
18533
+ if (agentName) cleaned.agentName = agentName;
18534
+ }
18535
+ if (entry.workdir !== void 0) {
18536
+ if (typeof entry.workdir !== "string") {
18537
+ return {
18538
+ ok: false,
18539
+ status: 400,
18540
+ body: {
18541
+ error: `agents[${index}].workdir must be a string`,
18542
+ fieldErrors: [{ id, field: "workdir", message: "workdir must be a string" }]
18543
+ }
18544
+ };
18545
+ }
18546
+ const workdir = entry.workdir.trim();
18547
+ if (workdir) cleaned.workdir = workdir;
18548
+ }
18380
18549
  return { ok: true, value: cleaned };
18381
18550
  }
18382
18551
  function createAgentsRouter() {
18383
18552
  const router = Router5();
18553
+ router.get("/claude-discovered", async (_req, res) => {
18554
+ try {
18555
+ const agents = await discoverClaudeAgents();
18556
+ res.json({ agents });
18557
+ } catch (err) {
18558
+ console.error("Error discovering Claude agents:", err);
18559
+ res.status(500).json({ error: "Failed to discover Claude agents" });
18560
+ }
18561
+ });
18384
18562
  router.get("/", async (_req, res) => {
18385
18563
  try {
18386
18564
  const config = await readConfig();
@@ -18443,8 +18621,8 @@ import { Router as Router6 } from "express";
18443
18621
  // src/utils/terminal-probe.ts
18444
18622
  import { spawnSync as spawnSync4 } from "child_process";
18445
18623
  import { existsSync as existsSync2 } from "fs";
18446
- import { homedir as homedir4 } from "os";
18447
- import { join as join5 } from "path";
18624
+ import { homedir as homedir5 } from "os";
18625
+ import { join as join7 } from "path";
18448
18626
  var APP_BUNDLE_IDS = {
18449
18627
  "terminal-app": "com.apple.Terminal",
18450
18628
  iterm: "com.googlecode.iterm2",
@@ -18461,7 +18639,7 @@ var APP_FIXED_PATHS = {
18461
18639
  "terminal-app": "/System/Applications/Utilities/Terminal.app"
18462
18640
  };
18463
18641
  function defaultApplicationsDirs() {
18464
- return ["/Applications", join5(homedir4(), "Applications")];
18642
+ return ["/Applications", join7(homedir5(), "Applications")];
18465
18643
  }
18466
18644
  function findAppBundle(terminal, dirs = defaultApplicationsDirs()) {
18467
18645
  const fixed = APP_FIXED_PATHS[terminal];
@@ -18469,7 +18647,7 @@ function findAppBundle(terminal, dirs = defaultApplicationsDirs()) {
18469
18647
  const bundleName = APP_BUNDLE_NAMES[terminal];
18470
18648
  if (bundleName) {
18471
18649
  for (const dir of dirs) {
18472
- const candidate = join5(dir, bundleName);
18650
+ const candidate = join7(dir, bundleName);
18473
18651
  if (existsSync2(candidate)) return candidate;
18474
18652
  }
18475
18653
  }
@@ -18499,11 +18677,11 @@ var defaultCmuxLsappinfoRunner = () => {
18499
18677
  function resolveCmuxCli(applicationsDirsOverride, cliDirsOverride, lsappinfoRunnerOverride) {
18500
18678
  const bundle = findAppBundle("cmux", applicationsDirsOverride);
18501
18679
  if (bundle) {
18502
- const cli = join5(bundle, "Contents/Resources/bin/cmux");
18680
+ const cli = join7(bundle, "Contents/Resources/bin/cmux");
18503
18681
  if (existsSync2(cli)) return cli;
18504
18682
  }
18505
18683
  for (const dir of cliDirsOverride ?? CMUX_CLI_DIRS) {
18506
- const cli = join5(dir, "cmux");
18684
+ const cli = join7(dir, "cmux");
18507
18685
  if (existsSync2(cli)) return cli;
18508
18686
  }
18509
18687
  if (process.platform === "darwin") {
@@ -18512,7 +18690,7 @@ function resolveCmuxCli(applicationsDirsOverride, cliDirsOverride, lsappinfoRunn
18512
18690
  if (stdout) {
18513
18691
  const match = stdout.match(/"LSBundlePath"="([^"]+)"/);
18514
18692
  if (match) {
18515
- const cli = join5(match[1], "Contents/Resources/bin/cmux");
18693
+ const cli = join7(match[1], "Contents/Resources/bin/cmux");
18516
18694
  if (existsSync2(cli)) return cli;
18517
18695
  }
18518
18696
  }
@@ -18594,8 +18772,19 @@ function resolveTemplate(template, ctx) {
18594
18772
  const warnings = [];
18595
18773
  const prompt = template.replace(TOKEN_RE, (_match, boundary, token) => {
18596
18774
  if (token === "assignment") {
18775
+ if (!ctx.assignmentDir) {
18776
+ warnings.push(`launchPrompt: "@assignment" has no assignment context here \u2014 left as literal text.`);
18777
+ return boundary + "@assignment";
18778
+ }
18597
18779
  return boundary + assignmentPointer(ctx.id, ctx.assignmentDir);
18598
18780
  }
18781
+ if (token === "worktree") {
18782
+ if (!ctx.worktreePath) {
18783
+ warnings.push(`launchPrompt: "@worktree" has no worktree path here \u2014 left as literal text.`);
18784
+ return boundary + "@worktree";
18785
+ }
18786
+ return boundary + ctx.worktreePath;
18787
+ }
18599
18788
  if (!isValidSlug(token)) {
18600
18789
  warnings.push(`launchPrompt: "@${token}" is not a valid playbook token \u2014 left as literal text.`);
18601
18790
  return boundary + "@" + token;
@@ -18609,16 +18798,37 @@ function resolveTemplate(template, ctx) {
18609
18798
  return { prompt, warnings };
18610
18799
  }
18611
18800
  function resolveLaunchPrompt(input) {
18612
- const { template, playbook, id, assignmentDir, projectSlug, assignmentSlug, knownPlaybookSlugs } = input;
18801
+ const {
18802
+ template,
18803
+ playbook,
18804
+ id,
18805
+ assignmentDir,
18806
+ projectSlug,
18807
+ assignmentSlug,
18808
+ worktreePath,
18809
+ spawnCwd,
18810
+ knownPlaybookSlugs
18811
+ } = input;
18613
18812
  if (template && template.trim()) {
18614
- return resolveTemplate(template, { id, assignmentDir, knownPlaybookSlugs });
18813
+ return resolveTemplate(template, { id, assignmentDir, worktreePath, knownPlaybookSlugs });
18615
18814
  }
18616
18815
  const pb = playbook?.trim();
18617
18816
  if (pb) {
18618
- const pointer = assignmentPointer(id, assignmentDir);
18619
- return { prompt: `${pointer} Run ${runPlaybookClause(pb)} end-to-end.`, warnings: [] };
18817
+ const clause = runPlaybookClause(pb);
18818
+ const prompt = assignmentDir ? `${assignmentPointer(id, assignmentDir)} Run ${clause} end-to-end.` : `Run ${clause} end-to-end.`;
18819
+ return { prompt, warnings: [] };
18820
+ }
18821
+ if (worktreePath && spawnCwd && worktreePath !== spawnCwd) {
18822
+ const grab = bareGrabSeed({ projectSlug, assignmentSlug: assignmentSlug ?? "", id });
18823
+ return {
18824
+ prompt: `The assignment's worktree is at ${worktreePath}. cd there, then grab the assignment with ${grab} and work it end-to-end.`,
18825
+ warnings: []
18826
+ };
18827
+ }
18828
+ if (!assignmentSlug && !id) {
18829
+ return { prompt: "", warnings: [] };
18620
18830
  }
18621
- return { prompt: bareGrabSeed({ projectSlug, assignmentSlug, id }), warnings: [] };
18831
+ return { prompt: bareGrabSeed({ projectSlug, assignmentSlug: assignmentSlug ?? "", id }), warnings: [] };
18622
18832
  }
18623
18833
  function effectiveLaunchTemplate(input) {
18624
18834
  if (input.launchPrompt && input.launchPrompt.trim()) {
@@ -18628,6 +18838,14 @@ function effectiveLaunchTemplate(input) {
18628
18838
  if (pb) {
18629
18839
  return `@assignment Run ${runPlaybookClause(pb)} end-to-end.`;
18630
18840
  }
18841
+ if (input.workdir && input.workdir.trim()) {
18842
+ const grab = bareGrabSeed({
18843
+ projectSlug: input.projectSlug,
18844
+ assignmentSlug: input.assignmentSlug,
18845
+ id: input.id
18846
+ });
18847
+ return `The assignment's worktree is at @worktree. cd there, then grab the assignment with ${grab} and work it end-to-end.`;
18848
+ }
18631
18849
  return bareGrabSeed({
18632
18850
  projectSlug: input.projectSlug,
18633
18851
  assignmentSlug: input.assignmentSlug,
@@ -18651,7 +18869,7 @@ init_agents_schema();
18651
18869
  init_cwd();
18652
18870
  import { spawn as spawn2 } from "child_process";
18653
18871
  import { mkdir as mkdir2, writeFile as writeFile4 } from "fs/promises";
18654
- import { isAbsolute as isAbsolute5, resolve as resolve26 } from "path";
18872
+ import { isAbsolute as isAbsolute5, resolve as resolve28 } from "path";
18655
18873
  init_paths();
18656
18874
  init_playbooks();
18657
18875
  init_cwd();
@@ -18661,8 +18879,10 @@ function shellQuote(arg) {
18661
18879
  }
18662
18880
  function buildAgentArgv(agent, prompt, env = process.env) {
18663
18881
  const position = agent.promptArgPosition ?? "first";
18664
- const baseArgs = applyModelFlag(agent, [...agent.args ?? []]);
18665
- const agentArgs = position === "first" ? [prompt, ...baseArgs] : position === "last" ? [...baseArgs, prompt] : baseArgs;
18882
+ const prefix = agentNameArgs(agent);
18883
+ const baseArgs = agent.agentName ? [...agent.args ?? []] : applyModelFlag(agent, [...agent.args ?? []]);
18884
+ const positioned = position === "first" ? [prompt, ...baseArgs] : position === "last" ? [...baseArgs, prompt] : baseArgs;
18885
+ const agentArgs = [...prefix, ...positioned];
18666
18886
  if (agent.resolveFromShellAliases) {
18667
18887
  const requested = env.SHELL;
18668
18888
  let shell = requested;
@@ -18742,8 +18962,60 @@ async function resolveLaunchPlan(input) {
18742
18962
  if (input.kind === "assignment") {
18743
18963
  return resolveAssignmentPlan(input, terminal);
18744
18964
  }
18965
+ if (input.kind === "standalone") {
18966
+ return resolveStandalonePlan(input, terminal);
18967
+ }
18745
18968
  return resolveSessionPlan(input, terminal);
18746
18969
  }
18970
+ async function resolveStandalonePlan(input, terminal) {
18971
+ const agentId = input.agentId ?? input.id;
18972
+ if (!agentId) {
18973
+ throw new LaunchError(
18974
+ "agent-not-configured",
18975
+ "A standalone launch requires an agent id."
18976
+ );
18977
+ }
18978
+ const agent = getAgents(input.config).find((a) => a.id === agentId);
18979
+ if (!agent) {
18980
+ throw new LaunchError(
18981
+ "agent-not-configured",
18982
+ `Agent "${agentId}" requested for a standalone launch is not in your agents list.`
18983
+ );
18984
+ }
18985
+ const wd = agent.workdir?.trim();
18986
+ if (!wd) {
18987
+ throw new LaunchError(
18988
+ "workspace-path-invalid",
18989
+ `Agent "${agent.id}" has no workdir \u2014 a standalone launch requires a valid workdir.`
18990
+ );
18991
+ }
18992
+ const expanded = expandHome(wd);
18993
+ if (!isExistingDir(expanded)) {
18994
+ throw new LaunchError(
18995
+ "workspace-path-invalid",
18996
+ `Agent "${agent.id}" workdir ${agent.workdir} (resolved ${expanded}) is not an existing directory \u2014 a standalone launch requires a valid workdir.`
18997
+ );
18998
+ }
18999
+ const knownPlaybookSlugs = await listPlaybookSlugs(playbooksDir());
19000
+ const template = input.promptOverride !== void 0 ? input.promptOverride : agent.launchPrompt;
19001
+ const { prompt, warnings: promptWarnings } = resolveLaunchPrompt({
19002
+ template,
19003
+ playbook: agent.playbook,
19004
+ projectSlug: null,
19005
+ knownPlaybookSlugs
19006
+ });
19007
+ const { argv, shellFallbackWarning } = buildFreshArgv(agent, prompt);
19008
+ return {
19009
+ terminal,
19010
+ cwd: expanded,
19011
+ argv,
19012
+ env: process.env,
19013
+ agentId: agent.id,
19014
+ fallbackWarning: null,
19015
+ shellFallbackWarning,
19016
+ promptWarnings
19017
+ };
19018
+ }
18747
19019
  async function resolveAssignmentPlan(input, terminal) {
18748
19020
  const resolved = await resolveAssignmentById(
18749
19021
  input.projectsDir,
@@ -18767,17 +19039,6 @@ async function resolveAssignmentPlan(input, terminal) {
18767
19039
  `Assignment ${input.id} resolver returned a directory but detail could not be loaded`
18768
19040
  );
18769
19041
  }
18770
- const picked = resolveWorkspaceCwd({
18771
- worktreePath: detail.workspace.worktreePath,
18772
- repository: detail.workspace.repository,
18773
- branch: detail.workspace.branch,
18774
- assignmentSlug: resolved.assignmentSlug
18775
- });
18776
- if (picked.cwd === null) {
18777
- throw new LaunchError("workspace-path-invalid", picked.invalidReason);
18778
- }
18779
- const cwd = picked.cwd;
18780
- const fallbackWarning = picked.fallbackWarning;
18781
19042
  let agent;
18782
19043
  if (input.agentId) {
18783
19044
  const found = getAgents(input.config).find((a) => a.id === input.agentId);
@@ -18791,6 +19052,30 @@ async function resolveAssignmentPlan(input, terminal) {
18791
19052
  } else {
18792
19053
  agent = pickAgent(input.config);
18793
19054
  }
19055
+ if (input.agentName !== void 0) {
19056
+ agent = { ...agent, agentName: input.agentName };
19057
+ }
19058
+ const picked = resolveWorkspaceCwd({
19059
+ worktreePath: detail.workspace.worktreePath,
19060
+ repository: detail.workspace.repository,
19061
+ branch: detail.workspace.branch,
19062
+ assignmentSlug: resolved.assignmentSlug
19063
+ });
19064
+ if (picked.cwd === null) {
19065
+ throw new LaunchError("workspace-path-invalid", picked.invalidReason);
19066
+ }
19067
+ const launchCwd = resolveLaunchCwd(agent, picked.cwd);
19068
+ if (launchCwd.invalidReason) {
19069
+ throw new LaunchError("workspace-path-invalid", launchCwd.invalidReason);
19070
+ }
19071
+ const cwd = launchCwd.spawnCwd;
19072
+ const fallbackWarning = picked.fallbackWarning;
19073
+ const promptWarningsExtra = [];
19074
+ if (input.agentName !== void 0 && input.agentName.trim() && agent.model?.trim()) {
19075
+ promptWarningsExtra.push(
19076
+ `profile model "${agent.model.trim()}" suppressed: agent "${input.agentName.trim()}" defines its own model`
19077
+ );
19078
+ }
18794
19079
  const knownPlaybookSlugs = await listPlaybookSlugs(playbooksDir());
18795
19080
  const template = input.promptOverride !== void 0 ? input.promptOverride : agent.launchPrompt;
18796
19081
  const { prompt, warnings: promptWarnings } = resolveLaunchPrompt({
@@ -18800,6 +19085,8 @@ async function resolveAssignmentPlan(input, terminal) {
18800
19085
  assignmentDir: resolved.assignmentDir,
18801
19086
  projectSlug: resolved.projectSlug,
18802
19087
  assignmentSlug: resolved.assignmentSlug,
19088
+ worktreePath: launchCwd.worktreePath,
19089
+ spawnCwd: launchCwd.spawnCwd,
18803
19090
  knownPlaybookSlugs
18804
19091
  });
18805
19092
  const { argv, shellFallbackWarning } = buildFreshArgv(agent, prompt);
@@ -18811,7 +19098,7 @@ async function resolveAssignmentPlan(input, terminal) {
18811
19098
  agentId: agent.id,
18812
19099
  fallbackWarning,
18813
19100
  shellFallbackWarning,
18814
- promptWarnings
19101
+ promptWarnings: [...promptWarningsExtra, ...promptWarnings]
18815
19102
  };
18816
19103
  }
18817
19104
  async function resolveSessionPlan(input, terminal) {
@@ -18887,8 +19174,8 @@ async function resolveSessionPlan(input, terminal) {
18887
19174
 
18888
19175
  // src/launch/execute.ts
18889
19176
  import { spawn as spawn3 } from "child_process";
18890
- import { homedir as homedir5 } from "os";
18891
- import { basename as basename5, join as join6, resolve as resolve27 } from "path";
19177
+ import { homedir as homedir6 } from "os";
19178
+ import { basename as basename5, join as join8, resolve as resolve29 } from "path";
18892
19179
  init_fs();
18893
19180
  init_config2();
18894
19181
  init_session_id();
@@ -18994,7 +19281,7 @@ async function registerLaunchAtBirth(plan, child) {
18994
19281
  const sessionId = plan.session?.sessionId ?? null;
18995
19282
  const procStart = captureProcessStartedAt(pid);
18996
19283
  const envDir = process.env.SYNTAUR_RUNTIME_SESSIONS_DIR;
18997
- const markerDir = envDir && envDir.length > 0 ? envDir : join6(homedir5(), ".syntaur", "runtime", "sessions");
19284
+ const markerDir = envDir && envDir.length > 0 ? envDir : join8(homedir6(), ".syntaur", "runtime", "sessions");
18998
19285
  writeRuntimeMarker(
18999
19286
  pid,
19000
19287
  {
@@ -19007,7 +19294,7 @@ async function registerLaunchAtBirth(plan, child) {
19007
19294
  markerDir
19008
19295
  );
19009
19296
  if (!sessionId) return;
19010
- if (autoTrack === "workspaces-only" && !await fileExists(resolve27(plan.cwd, ".syntaur", "context.json"))) {
19297
+ if (autoTrack === "workspaces-only" && !await fileExists(resolve29(plan.cwd, ".syntaur", "context.json"))) {
19011
19298
  return;
19012
19299
  }
19013
19300
  const { initSessionDb: initSessionDb2 } = await Promise.resolve().then(() => (init_session_db(), session_db_exports));
@@ -19183,7 +19470,7 @@ function appleScriptString(value) {
19183
19470
  init_paths();
19184
19471
  init_fs();
19185
19472
  import { fileURLToPath } from "url";
19186
- import { dirname as dirname6, resolve as resolve28, join as join7 } from "path";
19473
+ import { dirname as dirname6, resolve as resolve30, join as join9 } from "path";
19187
19474
  import { realpathSync, readFileSync as readFileSync3, mkdirSync as mkdirSync2 } from "fs";
19188
19475
 
19189
19476
  // src/dashboard/api-launch-preflight.ts
@@ -19344,7 +19631,8 @@ function createLaunchPreflightRouter(projectsDir, assignmentsDir2) {
19344
19631
  playbook: agent.playbook,
19345
19632
  projectSlug: resolved.projectSlug,
19346
19633
  assignmentSlug: resolved.assignmentSlug,
19347
- id: resolved.id
19634
+ id: resolved.id,
19635
+ workdir: agent.workdir
19348
19636
  });
19349
19637
  res.json({ template, knownPlaybookSlugs });
19350
19638
  } catch (error) {
@@ -19588,7 +19876,7 @@ init_frontmatter();
19588
19876
  init_event_emit();
19589
19877
  init_assignment_walk();
19590
19878
  init_timestamp();
19591
- import { readFile as readFile19, writeFile as writeFile5, rm as rm2 } from "fs/promises";
19879
+ import { readFile as readFile21, writeFile as writeFile5, rm as rm2 } from "fs/promises";
19592
19880
  import { dirname as dirname7 } from "path";
19593
19881
  var StatusResolutionError = class extends Error {
19594
19882
  constructor(message, code) {
@@ -19607,7 +19895,7 @@ async function scanAssignmentsByStatus(projectsDir, standaloneDir, ids) {
19607
19895
  const assignmentPath = `${entry.assignmentDir}/assignment.md`;
19608
19896
  let content;
19609
19897
  try {
19610
- content = await readFile19(assignmentPath, "utf-8");
19898
+ content = await readFile21(assignmentPath, "utf-8");
19611
19899
  } catch (err) {
19612
19900
  const code = err?.code;
19613
19901
  if (code === "ENOENT") {
@@ -19670,7 +19958,7 @@ async function applyStatusResolutions(resolutions, affected, validTargets) {
19670
19958
  const list = affected.get(r.id) ?? [];
19671
19959
  for (const a of list) {
19672
19960
  try {
19673
- const content = await readFile19(a.path, "utf-8");
19961
+ const content = await readFile21(a.path, "utf-8");
19674
19962
  buffer.set(a.path, content);
19675
19963
  } catch (err) {
19676
19964
  const code = err?.code;
@@ -19699,7 +19987,7 @@ async function applyStatusResolutions(resolutions, affected, validTargets) {
19699
19987
  for (const a of list) {
19700
19988
  let current;
19701
19989
  try {
19702
- current = await readFile19(a.path, "utf-8");
19990
+ current = await readFile21(a.path, "utf-8");
19703
19991
  } catch (err) {
19704
19992
  const code = err?.code;
19705
19993
  if (code === "ENOENT") {
@@ -19770,7 +20058,7 @@ async function applyStatusResolutions(resolutions, affected, validTargets) {
19770
20058
  const list = affected.get(r.id) ?? [];
19771
20059
  for (const a of list) {
19772
20060
  try {
19773
- const current = await readFile19(a.path, "utf-8");
20061
+ const current = await readFile21(a.path, "utf-8");
19774
20062
  const fm = parseAssignmentFrontmatter(current);
19775
20063
  if (fm.status !== r.id) {
19776
20064
  console.warn(
@@ -20250,7 +20538,7 @@ import { Router as Router12 } from "express";
20250
20538
  init_paths();
20251
20539
  import Database3 from "better-sqlite3";
20252
20540
  import { randomUUID as randomUUID3 } from "crypto";
20253
- import { resolve as resolve29 } from "path";
20541
+ import { resolve as resolve31 } from "path";
20254
20542
  var db3 = null;
20255
20543
  var LEASE_SCHEMA_VERSION = "1";
20256
20544
  var SCHEMA_SQL3 = `
@@ -20337,7 +20625,7 @@ function isBusyError(err) {
20337
20625
  }
20338
20626
  function initLeasesDb(dbPath) {
20339
20627
  if (db3) return db3;
20340
- const finalPath = dbPath ?? resolve29(syntaurRoot(), "syntaur.db");
20628
+ const finalPath = dbPath ?? resolve31(syntaurRoot(), "syntaur.db");
20341
20629
  db3 = new Database3(finalPath);
20342
20630
  db3.pragma("journal_mode = WAL");
20343
20631
  db3.pragma("busy_timeout = 5000");
@@ -20489,15 +20777,15 @@ init_fs();
20489
20777
  init_paths();
20490
20778
  init_timestamp();
20491
20779
  import { randomUUID as randomUUID4 } from "crypto";
20492
- import { readFile as readFile20, readdir as readdir14, rm as rm3 } from "fs/promises";
20493
- import { resolve as resolve30 } from "path";
20780
+ import { readFile as readFile22, readdir as readdir16, rm as rm3 } from "fs/promises";
20781
+ import { resolve as resolve32 } from "path";
20494
20782
  function schedulesDir() {
20495
20783
  const override3 = process.env.SYNTAUR_SCHEDULES_DIR;
20496
- if (override3 && override3.length > 0) return resolve30(override3);
20497
- return resolve30(syntaurRoot(), "schedules");
20784
+ if (override3 && override3.length > 0) return resolve32(override3);
20785
+ return resolve32(syntaurRoot(), "schedules");
20498
20786
  }
20499
20787
  function jobPath(id) {
20500
- return resolve30(schedulesDir(), `${jobFileSafe(id)}.md`);
20788
+ return resolve32(schedulesDir(), `${jobFileSafe(id)}.md`);
20501
20789
  }
20502
20790
  function jobFileSafe(id) {
20503
20791
  if (!/^[A-Za-z0-9_-]+$/.test(id)) {
@@ -20622,7 +20910,7 @@ function validateJob(raw2) {
20622
20910
  async function readJob(id) {
20623
20911
  const path = jobPath(id);
20624
20912
  if (!await fileExists(path)) return null;
20625
- return parseJobFile(await readFile20(path, "utf-8"));
20913
+ return parseJobFile(await readFile22(path, "utf-8"));
20626
20914
  }
20627
20915
  async function writeJob(job) {
20628
20916
  const next = { ...job, updatedAt: nowTimestamp() };
@@ -20632,7 +20920,7 @@ async function writeJob(job) {
20632
20920
  async function listJobs() {
20633
20921
  let names;
20634
20922
  try {
20635
- names = await readdir14(schedulesDir());
20923
+ names = await readdir16(schedulesDir());
20636
20924
  } catch {
20637
20925
  return [];
20638
20926
  }
@@ -20640,7 +20928,7 @@ async function listJobs() {
20640
20928
  for (const name of names) {
20641
20929
  if (!name.endsWith(".md")) continue;
20642
20930
  try {
20643
- jobs.push(parseJobFile(await readFile20(resolve30(schedulesDir(), name), "utf-8")));
20931
+ jobs.push(parseJobFile(await readFile22(resolve32(schedulesDir(), name), "utf-8")));
20644
20932
  } catch {
20645
20933
  }
20646
20934
  }
@@ -20650,13 +20938,13 @@ async function listJobs() {
20650
20938
 
20651
20939
  // src/schedules/event-log.ts
20652
20940
  init_timestamp();
20653
- import { appendFile, readFile as readFile21, mkdir as mkdir3 } from "fs/promises";
20654
- import { dirname as dirname8, resolve as resolve31 } from "path";
20941
+ import { appendFile, readFile as readFile23, mkdir as mkdir3 } from "fs/promises";
20942
+ import { dirname as dirname8, resolve as resolve33 } from "path";
20655
20943
  function eventLogPath(jobId) {
20656
20944
  if (!/^[A-Za-z0-9_-]+$/.test(jobId)) {
20657
20945
  throw new Error(`Unsafe schedule id: ${JSON.stringify(jobId)}`);
20658
20946
  }
20659
- return resolve31(schedulesDir(), `${jobId}.jsonl`);
20947
+ return resolve33(schedulesDir(), `${jobId}.jsonl`);
20660
20948
  }
20661
20949
  async function appendEvent(jobId, type, data) {
20662
20950
  const event = { type, at: nowTimestamp(), ...data ? { data } : {} };
@@ -20669,7 +20957,7 @@ async function appendEvent(jobId, type, data) {
20669
20957
  async function readEvents(jobId) {
20670
20958
  let content;
20671
20959
  try {
20672
- content = await readFile21(eventLogPath(jobId), "utf-8");
20960
+ content = await readFile23(eventLogPath(jobId), "utf-8");
20673
20961
  } catch {
20674
20962
  return [];
20675
20963
  }
@@ -20688,8 +20976,8 @@ async function readEvents(jobId) {
20688
20976
 
20689
20977
  // src/schedules/attempt.ts
20690
20978
  import { createHash as createHash3 } from "crypto";
20691
- import { open as open4, readFile as readFile22, stat as stat5, unlink as unlink6 } from "fs/promises";
20692
- import { resolve as resolve32 } from "path";
20979
+ import { open as open4, readFile as readFile24, stat as stat5, unlink as unlink6 } from "fs/promises";
20980
+ import { resolve as resolve34 } from "path";
20693
20981
 
20694
20982
  // src/schedules/triggers.ts
20695
20983
  import { Cron } from "croner";
@@ -20868,7 +21156,7 @@ var LOCK_WAIT_MS2 = 50;
20868
21156
  var LOCK_MAX_WAITS2 = 100;
20869
21157
  var MAX_CONSUMED_EDGES = 50;
20870
21158
  async function acquireJobLock(id) {
20871
- const lockPath = resolve32(schedulesDir(), `${id}.lock`);
21159
+ const lockPath = resolve34(schedulesDir(), `${id}.lock`);
20872
21160
  const token = `${process.pid}:${createHash3("sha256").update(`${Math.random()}${Date.now()}`).digest("hex").slice(0, 12)}`;
20873
21161
  for (let attempt = 0; attempt <= LOCK_MAX_WAITS2; attempt++) {
20874
21162
  try {
@@ -20877,7 +21165,7 @@ async function acquireJobLock(id) {
20877
21165
  await handle.close();
20878
21166
  return async () => {
20879
21167
  try {
20880
- const current = await readFile22(lockPath, "utf-8");
21168
+ const current = await readFile24(lockPath, "utf-8");
20881
21169
  if (current === token) await unlink6(lockPath);
20882
21170
  } catch {
20883
21171
  }
@@ -21183,7 +21471,7 @@ async function reapStale(jobs, deps) {
21183
21471
 
21184
21472
  // src/schedules/unattended.ts
21185
21473
  import { existsSync as existsSync3 } from "fs";
21186
- import { resolve as resolve33 } from "path";
21474
+ import { resolve as resolve35 } from "path";
21187
21475
  var UnattendedRefusalError = class extends Error {
21188
21476
  constructor(message) {
21189
21477
  super(message);
@@ -21199,7 +21487,7 @@ function assertUnattendedTerminalSupported(terminal) {
21199
21487
  }
21200
21488
  function isKillSwitchEngaged() {
21201
21489
  if (process.env.SYNTAUR_SCHEDULES_DISABLED === "1") return true;
21202
- return existsSync3(resolve33(schedulesDir(), "KILL"));
21490
+ return existsSync3(resolve35(schedulesDir(), "KILL"));
21203
21491
  }
21204
21492
  function canFire(job, deps) {
21205
21493
  const killSwitch = deps.killSwitch ?? isKillSwitchEngaged;
@@ -21350,20 +21638,20 @@ init_config2();
21350
21638
  init_paths();
21351
21639
  init_assignment_resolver();
21352
21640
  init_frontmatter();
21353
- import { readFile as readFile23 } from "fs/promises";
21354
- import { resolve as resolve34 } from "path";
21641
+ import { readFile as readFile25 } from "fs/promises";
21642
+ import { resolve as resolve36 } from "path";
21355
21643
 
21356
21644
  // src/schedules/launch-ack.ts
21357
21645
  init_session_id();
21358
21646
  import { readdirSync as readdirSync2 } from "fs";
21359
- import { homedir as homedir6 } from "os";
21360
- import { join as join8 } from "path";
21647
+ import { homedir as homedir7 } from "os";
21648
+ import { join as join10 } from "path";
21361
21649
  function defaultSleep(ms) {
21362
21650
  return new Promise((r) => setTimeout(r, ms));
21363
21651
  }
21364
21652
  function runtimeSessionsDir() {
21365
21653
  const override3 = process.env.SYNTAUR_RUNTIME_SESSIONS_DIR;
21366
- return override3 && override3.length > 0 ? override3 : join8(homedir6(), ".syntaur", "runtime", "sessions");
21654
+ return override3 && override3.length > 0 ? override3 : join10(homedir7(), ".syntaur", "runtime", "sessions");
21367
21655
  }
21368
21656
  function defaultAckProbe(handle) {
21369
21657
  const dir = runtimeSessionsDir();
@@ -21411,7 +21699,7 @@ async function defaultReadAssignment(assignmentId) {
21411
21699
  const resolved = await resolveAssignmentById(projectsDir, assignmentsDir(), assignmentId);
21412
21700
  if (!resolved) return null;
21413
21701
  try {
21414
- const content = await readFile23(resolve34(resolved.assignmentDir, "assignment.md"), "utf-8");
21702
+ const content = await readFile25(resolve36(resolved.assignmentDir, "assignment.md"), "utf-8");
21415
21703
  return parseAssignmentFrontmatter(content);
21416
21704
  } catch {
21417
21705
  return null;
@@ -21503,7 +21791,7 @@ import { Router as Router14 } from "express";
21503
21791
  // src/db/usage-db.ts
21504
21792
  init_paths();
21505
21793
  import Database4 from "better-sqlite3";
21506
- import { resolve as resolve35 } from "path";
21794
+ import { resolve as resolve37 } from "path";
21507
21795
  var db4 = null;
21508
21796
  var USAGE_SCHEMA_VERSION = "1";
21509
21797
  var SCHEMA_SQL4 = `
@@ -21577,7 +21865,7 @@ function nowIso2() {
21577
21865
  }
21578
21866
  function initUsageDb(dbPath) {
21579
21867
  if (db4) return db4;
21580
- const finalPath = dbPath ?? resolve35(syntaurRoot(), "syntaur.db");
21868
+ const finalPath = dbPath ?? resolve37(syntaurRoot(), "syntaur.db");
21581
21869
  db4 = new Database4(finalPath);
21582
21870
  db4.pragma("journal_mode = WAL");
21583
21871
  db4.pragma("busy_timeout = 5000");
@@ -22190,14 +22478,14 @@ init_fs();
22190
22478
  init_parser();
22191
22479
  init_events_db();
22192
22480
  import { Router as Router15 } from "express";
22193
- import { resolve as resolve36 } from "path";
22194
- import { readFile as readFile24 } from "fs/promises";
22481
+ import { resolve as resolve38 } from "path";
22482
+ import { readFile as readFile26 } from "fs/promises";
22195
22483
  function createEventsRouter(projectsDir, assignmentsDir2) {
22196
22484
  const router = Router15();
22197
22485
  router.get("/projects/:slug/assignments/:aslug/events", async (req2, res) => {
22198
22486
  try {
22199
22487
  const { slug, aslug } = req2.params;
22200
- const assignmentMdPath = resolve36(
22488
+ const assignmentMdPath = resolve38(
22201
22489
  projectsDir,
22202
22490
  slug,
22203
22491
  "assignments",
@@ -22218,7 +22506,7 @@ function createEventsRouter(projectsDir, assignmentsDir2) {
22218
22506
  router.get("/standalone/assignments/:id/events", async (req2, res) => {
22219
22507
  try {
22220
22508
  const { id: dirId } = req2.params;
22221
- const assignmentMdPath = resolve36(assignmentsDir2, dirId, "assignment.md");
22509
+ const assignmentMdPath = resolve38(assignmentsDir2, dirId, "assignment.md");
22222
22510
  const id = await readAssignmentId2(assignmentMdPath) ?? dirId;
22223
22511
  res.json({ events: loadEvents(id, req2.query) });
22224
22512
  } catch (error) {
@@ -22230,7 +22518,7 @@ function createEventsRouter(projectsDir, assignmentsDir2) {
22230
22518
  }
22231
22519
  async function readAssignmentId2(assignmentMdPath) {
22232
22520
  if (!await fileExists(assignmentMdPath)) return null;
22233
- const content = await readFile24(assignmentMdPath, "utf-8");
22521
+ const content = await readFile26(assignmentMdPath, "utf-8");
22234
22522
  const [fm] = extractFrontmatter2(content);
22235
22523
  const id = getField(fm, "id");
22236
22524
  return id && id.length > 0 ? id : null;
@@ -22275,8 +22563,8 @@ init_assignment_walk();
22275
22563
  init_parser();
22276
22564
  init_facts();
22277
22565
  init_state_machine();
22278
- import { resolve as resolve37 } from "path";
22279
- import { readFile as readFile25 } from "fs/promises";
22566
+ import { resolve as resolve39 } from "path";
22567
+ import { readFile as readFile27 } from "fs/promises";
22280
22568
 
22281
22569
  // src/inbox/types.ts
22282
22570
  var INBOX_CATEGORIES = [
@@ -22456,7 +22744,7 @@ async function computeInbox(opts) {
22456
22744
  if (opts.project !== void 0 && entry.projectSlug !== opts.project) continue;
22457
22745
  let parsed;
22458
22746
  try {
22459
- const content = await readFile25(resolve37(entry.assignmentDir, "assignment.md"), "utf-8");
22747
+ const content = await readFile27(resolve39(entry.assignmentDir, "assignment.md"), "utf-8");
22460
22748
  parsed = parseAssignmentFull(content);
22461
22749
  } catch {
22462
22750
  continue;
@@ -22499,10 +22787,10 @@ async function computeInbox(opts) {
22499
22787
  });
22500
22788
  }
22501
22789
  if (!typeFilter || typeFilter.has("question")) {
22502
- const commentsPath = resolve37(entry.assignmentDir, "comments.md");
22790
+ const commentsPath = resolve39(entry.assignmentDir, "comments.md");
22503
22791
  if (await fileExists(commentsPath)) {
22504
22792
  try {
22505
- const content = await readFile25(commentsPath, "utf-8");
22793
+ const content = await readFile27(commentsPath, "utf-8");
22506
22794
  const parsedComments = parseComments(content);
22507
22795
  for (const c of unresolvedQuestions(parsedComments.entries)) {
22508
22796
  const since = resolveSince("question", parsed, now, c);
@@ -22613,8 +22901,8 @@ init_slug();
22613
22901
  init_timestamp();
22614
22902
  init_fs();
22615
22903
  import { Router as Router17 } from "express";
22616
- import { resolve as resolve38 } from "path";
22617
- import { readFile as readFile26 } from "fs/promises";
22904
+ import { resolve as resolve40 } from "path";
22905
+ import { readFile as readFile28 } from "fs/promises";
22618
22906
  init_playbooks();
22619
22907
  function statusForPlaybookError(code) {
22620
22908
  switch (code) {
@@ -22696,8 +22984,8 @@ function createPlaybooksRouter(playbooksDir2) {
22696
22984
  res.status(404).json({ error: `Playbook "${req2.params.slug}" not found` });
22697
22985
  return;
22698
22986
  }
22699
- const filePath = resolve38(playbooksDir2, resolved.filename);
22700
- const content = await readFile26(filePath, "utf-8");
22987
+ const filePath = resolve40(playbooksDir2, resolved.filename);
22988
+ const content = await readFile28(filePath, "utf-8");
22701
22989
  res.json({
22702
22990
  documentType: "playbook",
22703
22991
  title: `Edit Playbook: ${resolved.slug}`,
@@ -22722,7 +23010,7 @@ function createPlaybooksRouter(playbooksDir2) {
22722
23010
  return;
22723
23011
  }
22724
23012
  await ensureDir(playbooksDir2);
22725
- const filePath = resolve38(playbooksDir2, `${slug}.md`);
23013
+ const filePath = resolve40(playbooksDir2, `${slug}.md`);
22726
23014
  if (await fileExists(filePath)) {
22727
23015
  res.status(409).json({ error: `Playbook "${slug}" already exists` });
22728
23016
  return;
@@ -22746,7 +23034,7 @@ function createPlaybooksRouter(playbooksDir2) {
22746
23034
  res.status(404).json({ error: `Playbook "${req2.params.slug}" not found` });
22747
23035
  return;
22748
23036
  }
22749
- const filePath = resolve38(playbooksDir2, resolved.filename);
23037
+ const filePath = resolve40(playbooksDir2, resolved.filename);
22750
23038
  await writeFileForce(filePath, content);
22751
23039
  await rebuildPlaybookManifest(playbooksDir2);
22752
23040
  res.json({ slug: resolved.slug, path: filePath });
@@ -22794,7 +23082,7 @@ init_parser2();
22794
23082
  init_fs();
22795
23083
  init_paths();
22796
23084
  import { Router as Router19 } from "express";
22797
- import { readdir as readdir16 } from "fs/promises";
23085
+ import { readdir as readdir18 } from "fs/promises";
22798
23086
  import { resolve as resolvePath, dirname as dirname10 } from "path";
22799
23087
  import { rename as rename6, mkdir as mkdir5 } from "fs/promises";
22800
23088
  init_slug();
@@ -22809,7 +23097,7 @@ init_uuid();
22809
23097
  init_paths();
22810
23098
  init_fs();
22811
23099
  init_config2();
22812
- import { resolve as resolve39 } from "path";
23100
+ import { resolve as resolve41 } from "path";
22813
23101
  async function createAssignmentCommand(title, options) {
22814
23102
  if (!title.trim()) {
22815
23103
  throw new Error("Assignment title cannot be empty.");
@@ -22884,14 +23172,14 @@ async function createAssignmentCommand(title, options) {
22884
23172
  if (options.oneOff) {
22885
23173
  const standaloneRoot = assignmentsDir();
22886
23174
  folderName = id;
22887
- assignmentDir = resolve39(standaloneRoot, folderName);
23175
+ assignmentDir = resolve41(standaloneRoot, folderName);
22888
23176
  projectSlug = null;
22889
23177
  await ensureDir(standaloneRoot);
22890
23178
  } else {
22891
23179
  const baseDir = options.dir ? expandHome(options.dir) : config.defaultProjectDir;
22892
23180
  projectSlug = options.project;
22893
- const projectDir = resolve39(baseDir, projectSlug);
22894
- const projectMdPath = resolve39(projectDir, "project.md");
23181
+ const projectDir = resolve41(baseDir, projectSlug);
23182
+ const projectMdPath = resolve41(projectDir, "project.md");
22895
23183
  if (!await fileExists(projectDir) || !await fileExists(projectMdPath)) {
22896
23184
  throw new Error(
22897
23185
  `Project "${projectSlug}" not found at ${projectDir}.
@@ -22899,9 +23187,9 @@ Run 'syntaur create-project' first or use --one-off.`
22899
23187
  );
22900
23188
  }
22901
23189
  if (dependsOn.length > 0) {
22902
- const depDirBase = resolve39(projectDir, "assignments");
23190
+ const depDirBase = resolve41(projectDir, "assignments");
22903
23191
  for (const dep of dependsOn) {
22904
- const depDir = resolve39(depDirBase, dep);
23192
+ const depDir = resolve41(depDirBase, dep);
22905
23193
  if (!await fileExists(depDir)) {
22906
23194
  console.warn(
22907
23195
  `Warning: dependency "${dep}" does not exist in project "${projectSlug}" yet.`
@@ -22910,7 +23198,7 @@ Run 'syntaur create-project' first or use --one-off.`
22910
23198
  }
22911
23199
  }
22912
23200
  folderName = assignmentSlug;
22913
- assignmentDir = resolve39(projectDir, "assignments", folderName);
23201
+ assignmentDir = resolve41(projectDir, "assignments", folderName);
22914
23202
  }
22915
23203
  if (await fileExists(assignmentDir)) {
22916
23204
  throw new Error(
@@ -22922,7 +23210,7 @@ Use --slug to specify a different slug.`
22922
23210
  const companionAssignmentRef = projectSlug === null ? id : assignmentSlug;
22923
23211
  const files = [
22924
23212
  [
22925
- resolve39(assignmentDir, "assignment.md"),
23213
+ resolve41(assignmentDir, "assignment.md"),
22926
23214
  renderAssignment({
22927
23215
  id,
22928
23216
  slug: assignmentSlug,
@@ -22940,35 +23228,35 @@ Use --slug to specify a different slug.`
22940
23228
  })
22941
23229
  ],
22942
23230
  [
22943
- resolve39(assignmentDir, "scratchpad.md"),
23231
+ resolve41(assignmentDir, "scratchpad.md"),
22944
23232
  renderScratchpad({
22945
23233
  assignmentSlug: companionAssignmentRef,
22946
23234
  timestamp
22947
23235
  })
22948
23236
  ],
22949
23237
  [
22950
- resolve39(assignmentDir, "handoff.md"),
23238
+ resolve41(assignmentDir, "handoff.md"),
22951
23239
  renderHandoff({
22952
23240
  assignmentSlug: companionAssignmentRef,
22953
23241
  timestamp
22954
23242
  })
22955
23243
  ],
22956
23244
  [
22957
- resolve39(assignmentDir, "decision-record.md"),
23245
+ resolve41(assignmentDir, "decision-record.md"),
22958
23246
  renderDecisionRecord({
22959
23247
  assignmentSlug: companionAssignmentRef,
22960
23248
  timestamp
22961
23249
  })
22962
23250
  ],
22963
23251
  [
22964
- resolve39(assignmentDir, "progress.md"),
23252
+ resolve41(assignmentDir, "progress.md"),
22965
23253
  renderProgress({
22966
23254
  assignment: companionAssignmentRef,
22967
23255
  timestamp
22968
23256
  })
22969
23257
  ],
22970
23258
  [
22971
- resolve39(assignmentDir, "comments.md"),
23259
+ resolve41(assignmentDir, "comments.md"),
22972
23260
  renderComments({
22973
23261
  assignment: companionAssignmentRef,
22974
23262
  timestamp
@@ -23141,8 +23429,8 @@ init_api();
23141
23429
  import { raw } from "express";
23142
23430
 
23143
23431
  // src/todos/attachments.ts
23144
- import { mkdir as mkdir4, readdir as readdir15, stat as stat6, rename as rename5, rm as rm4, unlink as unlink7, writeFile as writeFile6, cp } from "fs/promises";
23145
- import { resolve as resolve40, basename as basename6, dirname as dirname9, extname } from "path";
23432
+ import { mkdir as mkdir4, readdir as readdir17, stat as stat6, rename as rename5, rm as rm4, unlink as unlink7, writeFile as writeFile6, cp } from "fs/promises";
23433
+ import { resolve as resolve42, basename as basename6, dirname as dirname9, extname } from "path";
23146
23434
 
23147
23435
  // src/utils/proof-artifact-id.ts
23148
23436
  import { randomBytes as randomBytes2 } from "crypto";
@@ -23229,12 +23517,12 @@ function sanitizeAttachmentName(name) {
23229
23517
  return n;
23230
23518
  }
23231
23519
  function attachmentsRootDir(todosDir2) {
23232
- return resolve40(todosDir2, "attachments");
23520
+ return resolve42(todosDir2, "attachments");
23233
23521
  }
23234
23522
  function attachmentDirFor(todosDir2, scopeId, todoId) {
23235
23523
  assertScope(scopeId);
23236
23524
  assertTodoId(todoId);
23237
- return resolve40(attachmentsRootDir(todosDir2), scopeId, todoId);
23525
+ return resolve42(attachmentsRootDir(todosDir2), scopeId, todoId);
23238
23526
  }
23239
23527
  async function dirExists(p) {
23240
23528
  try {
@@ -23248,7 +23536,7 @@ async function writeAttachment(todosDir2, scopeId, todoId, originalName, bytes)
23248
23536
  await mkdir4(dir, { recursive: true });
23249
23537
  const id = generateArtifactId();
23250
23538
  const filename = sanitizeAttachmentName(originalName);
23251
- await writeFile6(resolve40(dir, `${id}__${filename}`), bytes);
23539
+ await writeFile6(resolve42(dir, `${id}__${filename}`), bytes);
23252
23540
  return {
23253
23541
  id,
23254
23542
  filename,
@@ -23261,7 +23549,7 @@ async function listAttachments(todosDir2, scopeId, todoId) {
23261
23549
  const dir = attachmentDirFor(todosDir2, scopeId, todoId);
23262
23550
  let names;
23263
23551
  try {
23264
- names = await readdir15(dir);
23552
+ names = await readdir17(dir);
23265
23553
  } catch {
23266
23554
  return [];
23267
23555
  }
@@ -23273,7 +23561,7 @@ async function listAttachments(todosDir2, scopeId, todoId) {
23273
23561
  if (!ATTACHMENT_ID_RE.test(id)) continue;
23274
23562
  const filename = stored.slice(sep2 + 2);
23275
23563
  try {
23276
- const st = await stat6(resolve40(dir, stored));
23564
+ const st = await stat6(resolve42(dir, stored));
23277
23565
  if (!st.isFile()) continue;
23278
23566
  out.push({ id, filename, mime: mimeForName(filename), size: st.size, createdAt: st.mtime.toISOString() });
23279
23567
  } catch {
@@ -23284,10 +23572,10 @@ async function listAttachments(todosDir2, scopeId, todoId) {
23284
23572
  }
23285
23573
  async function readScopeAttachments(todosDir2, scopeId) {
23286
23574
  assertScope(scopeId);
23287
- const scopeDir = resolve40(attachmentsRootDir(todosDir2), scopeId);
23575
+ const scopeDir = resolve42(attachmentsRootDir(todosDir2), scopeId);
23288
23576
  let todoIds;
23289
23577
  try {
23290
- todoIds = await readdir15(scopeDir);
23578
+ todoIds = await readdir17(scopeDir);
23291
23579
  } catch {
23292
23580
  return {};
23293
23581
  }
@@ -23304,7 +23592,7 @@ async function resolveAttachmentFile(todosDir2, scopeId, todoId, attachmentId) {
23304
23592
  const dir = attachmentDirFor(todosDir2, scopeId, todoId);
23305
23593
  let names;
23306
23594
  try {
23307
- names = await readdir15(dir);
23595
+ names = await readdir17(dir);
23308
23596
  } catch {
23309
23597
  return null;
23310
23598
  }
@@ -23312,7 +23600,7 @@ async function resolveAttachmentFile(todosDir2, scopeId, todoId, attachmentId) {
23312
23600
  const stored = names.find((n) => n.startsWith(prefix));
23313
23601
  if (!stored) return null;
23314
23602
  const filename = stored.slice(prefix.length);
23315
- return { path: resolve40(dir, stored), filename, mime: mimeForName(filename) };
23603
+ return { path: resolve42(dir, stored), filename, mime: mimeForName(filename) };
23316
23604
  }
23317
23605
  async function deleteAttachment(todosDir2, scopeId, todoId, attachmentId) {
23318
23606
  const resolved = await resolveAttachmentFile(todosDir2, scopeId, todoId, attachmentId);
@@ -23608,7 +23896,7 @@ function createTodosRouter(todosDir2, broadcast, projectsDir) {
23608
23896
  router.get("/", async (_req, res) => {
23609
23897
  try {
23610
23898
  await ensureDir(todosDir2);
23611
- const files = await readdir16(todosDir2).catch(() => []);
23899
+ const files = await readdir18(todosDir2).catch(() => []);
23612
23900
  const workspaces = [];
23613
23901
  for (const file of files) {
23614
23902
  if (typeof file !== "string") continue;
@@ -23729,7 +24017,7 @@ function createTodosRouter(todosDir2, broadcast, projectsDir) {
23729
24017
  try {
23730
24018
  const { archivePath: archivePath2 } = await Promise.resolve().then(() => (init_parser2(), parser_exports));
23731
24019
  const { resolve: resolve49 } = await import("path");
23732
- const { readFile: readFile31 } = await import("fs/promises");
24020
+ const { readFile: readFile32 } = await import("fs/promises");
23733
24021
  const { writeFileForce: writeFileForce2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
23734
24022
  const workspace = getWorkspaceParam(req2.params.workspace);
23735
24023
  const outcome = await wsLock(workspace, async () => {
@@ -23748,7 +24036,7 @@ function createTodosRouter(todosDir2, broadcast, projectsDir) {
23748
24036
  await ensureDir(resolve49(todosDir2, "archive"));
23749
24037
  let archContent = "";
23750
24038
  if (await fileExists(archFile)) {
23751
- archContent = await readFile31(archFile, "utf-8");
24039
+ archContent = await readFile32(archFile, "utf-8");
23752
24040
  archContent = archContent.trimEnd() + "\n\n";
23753
24041
  } else {
23754
24042
  archContent = `---
@@ -24049,7 +24337,7 @@ workspace: ${workspace}
24049
24337
  const { readConfig: readConfig2 } = await Promise.resolve().then(() => (init_config2(), config_exports));
24050
24338
  const { assignmentsDir: assignmentsDirFn } = await Promise.resolve().then(() => (init_paths(), paths_exports));
24051
24339
  const { fileExists: fileExists2, writeFileForce: writeFileForce2 } = await Promise.resolve().then(() => (init_fs(), fs_exports));
24052
- const { readFile: readFile31 } = await import("fs/promises");
24340
+ const { readFile: readFile32 } = await import("fs/promises");
24053
24341
  const { appendTodosToAssignmentBody: appendTodosToAssignmentBody2, touchAssignmentUpdated: touchAssignmentUpdated2 } = await Promise.resolve().then(() => (init_assignment_todos(), assignment_todos_exports));
24054
24342
  const { nowTimestamp: nowTimestamp3 } = await Promise.resolve().then(() => (init_timestamp(), timestamp_exports));
24055
24343
  let assignmentRef;
@@ -24070,7 +24358,7 @@ workspace: ${workspace}
24070
24358
  }
24071
24359
  const assignmentMdPath = resolvePath2(assignmentDir, "assignment.md");
24072
24360
  if (!await fileExists2(assignmentMdPath)) return { error: `Target assignment not found: ${assignmentMdPath}` };
24073
- let content = await readFile31(assignmentMdPath, "utf-8");
24361
+ let content = await readFile32(assignmentMdPath, "utf-8");
24074
24362
  content = appendTodosToAssignmentBody2(
24075
24363
  content,
24076
24364
  items.map((it) => ({
@@ -24265,8 +24553,8 @@ init_fs();
24265
24553
  init_paths();
24266
24554
  init_slug();
24267
24555
  import { Router as Router20 } from "express";
24268
- import { mkdir as mkdir6, readFile as readFile27, rename as rename7 } from "fs/promises";
24269
- import { resolve as resolve41, dirname as dirname11 } from "path";
24556
+ import { mkdir as mkdir6, readFile as readFile29, rename as rename7 } from "fs/promises";
24557
+ import { resolve as resolve43, dirname as dirname11 } from "path";
24270
24558
  init_api();
24271
24559
  var WORKSPACE_REGEX2 = /^[a-z0-9_][a-z0-9-]*$/;
24272
24560
  function touchItem4(item) {
@@ -24282,7 +24570,7 @@ function params(req2) {
24282
24570
  return req2.params;
24283
24571
  }
24284
24572
  async function projectExists(projectsDir, slug) {
24285
- return fileExists(resolve41(projectsDir, slug, "project.md"));
24573
+ return fileExists(resolve43(projectsDir, slug, "project.md"));
24286
24574
  }
24287
24575
  async function ensureProjectTodosDir(projectsDir, slug) {
24288
24576
  const todosDir2 = projectTodosDir(projectsDir, slug);
@@ -24299,7 +24587,7 @@ async function ensureProjectTodosDir(projectsDir, slug) {
24299
24587
  throw err;
24300
24588
  }
24301
24589
  try {
24302
- await mkdir6(resolve41(todosDir2, "archive"), { recursive: false });
24590
+ await mkdir6(resolve43(todosDir2, "archive"), { recursive: false });
24303
24591
  } catch (err) {
24304
24592
  const code = err.code;
24305
24593
  if (code === "EEXIST") return;
@@ -24507,7 +24795,7 @@ function createProjectTodosRouter(projectsDir, broadcast, workspaceTodosDir) {
24507
24795
  const archFile = archivePath(todosDir2, slug, checklist.archiveInterval);
24508
24796
  let archContent = "";
24509
24797
  if (await fileExists(archFile)) {
24510
- archContent = await readFile27(archFile, "utf-8");
24798
+ archContent = await readFile29(archFile, "utf-8");
24511
24799
  archContent = archContent.trimEnd() + "\n\n";
24512
24800
  } else {
24513
24801
  archContent = `---
@@ -24978,17 +25266,17 @@ workspace: ${slug}
24978
25266
  if (tg.includes("/")) {
24979
25267
  const parts = tg.split("/");
24980
25268
  if (parts.length !== 2) return { error: `Invalid target.assignment "${tg}"` };
24981
- assignmentDir = resolve41(projectsDir, parts[0], "assignments", parts[1]);
25269
+ assignmentDir = resolve43(projectsDir, parts[0], "assignments", parts[1]);
24982
25270
  assignmentRef = `${parts[0]}/${parts[1]}`;
24983
25271
  } else if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(tg)) {
24984
- assignmentDir = resolve41(assignmentsDirFn(), tg);
25272
+ assignmentDir = resolve43(assignmentsDirFn(), tg);
24985
25273
  assignmentRef = tg;
24986
25274
  } else {
24987
25275
  return { error: `Invalid target.assignment "${tg}"` };
24988
25276
  }
24989
- const assignmentMdPath = resolve41(assignmentDir, "assignment.md");
25277
+ const assignmentMdPath = resolve43(assignmentDir, "assignment.md");
24990
25278
  if (!await fileExists(assignmentMdPath)) return { error: `Target assignment not found: ${assignmentMdPath}` };
24991
- let content = await readFile27(assignmentMdPath, "utf-8");
25279
+ let content = await readFile29(assignmentMdPath, "utf-8");
24992
25280
  content = appendTodosToAssignmentBody2(
24993
25281
  content,
24994
25282
  items.map((it) => ({
@@ -25191,7 +25479,7 @@ workspace: ${slug}
25191
25479
 
25192
25480
  // src/dashboard/api-bundles.ts
25193
25481
  import { Router as Router21 } from "express";
25194
- import { readdir as readdir17 } from "fs/promises";
25482
+ import { readdir as readdir19 } from "fs/promises";
25195
25483
 
25196
25484
  // src/todos/bundle-parser.ts
25197
25485
  init_parser();
@@ -25199,7 +25487,7 @@ init_fs();
25199
25487
  init_paths();
25200
25488
  init_parser2();
25201
25489
  import { randomBytes as randomBytes3 } from "crypto";
25202
- import { readFile as readFile28 } from "fs/promises";
25490
+ import { readFile as readFile30 } from "fs/promises";
25203
25491
  var BUNDLE_ID_REGEX = /^[a-f0-9]{4}$/;
25204
25492
  var SCOPE_VALUES = /* @__PURE__ */ new Set(["workspace", "project", "global"]);
25205
25493
  var SCOPE_ID_REGEX = /^[a-z0-9_][a-z0-9_-]*$/;
@@ -25266,7 +25554,7 @@ function parseBundles(content) {
25266
25554
  async function readBundles(todosDir2) {
25267
25555
  const path = bundlesPath(todosDir2);
25268
25556
  if (!await fileExists(path)) return [];
25269
- const content = await readFile28(path, "utf-8");
25557
+ const content = await readFile30(path, "utf-8");
25270
25558
  return parseBundles(content).bundles;
25271
25559
  }
25272
25560
 
@@ -25315,7 +25603,7 @@ function createBundlesRouter(todosDir2, broadcast) {
25315
25603
  try {
25316
25604
  await ensureDir(todosDir2);
25317
25605
  const bundles = await readBundles(todosDir2);
25318
- const workspaceFiles = await readdir17(todosDir2).catch(() => []);
25606
+ const workspaceFiles = await readdir19(todosDir2).catch(() => []);
25319
25607
  const itemsByKey = /* @__PURE__ */ new Map();
25320
25608
  for (const f of workspaceFiles) {
25321
25609
  if (typeof f !== "string") continue;
@@ -25368,7 +25656,7 @@ init_fs();
25368
25656
  init_paths();
25369
25657
  init_slug();
25370
25658
  import { Router as Router22 } from "express";
25371
- import { resolve as resolve42 } from "path";
25659
+ import { resolve as resolve44 } from "path";
25372
25660
  init_parser2();
25373
25661
  function deriveStatus2(bundle, items) {
25374
25662
  const members = bundle.todoIds.map((id) => items.find((i) => i.id === id)).filter((i) => i !== void 0);
@@ -25410,7 +25698,7 @@ function createProjectBundlesRouter(projectsDir, broadcast) {
25410
25698
  router.get("/", async (req2, res) => {
25411
25699
  try {
25412
25700
  const slug = getProjectIdParam2(req2.params.projectId);
25413
- const projectMd = resolve42(projectsDir, slug, "project.md");
25701
+ const projectMd = resolve44(projectsDir, slug, "project.md");
25414
25702
  if (!await fileExists(projectMd)) {
25415
25703
  notFound2(res, slug);
25416
25704
  return;
@@ -25439,8 +25727,8 @@ init_fs();
25439
25727
  init_config2();
25440
25728
  import { execFile as execFile2 } from "child_process";
25441
25729
  import { promisify as promisify2 } from "util";
25442
- import { cp as cp2, mkdtemp, rm as rm5, readFile as readFile29, writeFile as writeFile7, unlink as unlink8, stat as stat7, open as open5, rename as rename8 } from "fs/promises";
25443
- import { resolve as resolve43, join as join9 } from "path";
25730
+ import { cp as cp2, mkdtemp, rm as rm5, readFile as readFile31, writeFile as writeFile7, unlink as unlink8, stat as stat7, open as open5, rename as rename8 } from "fs/promises";
25731
+ import { resolve as resolve45, join as join11 } from "path";
25444
25732
  import { tmpdir } from "os";
25445
25733
  var exec2 = promisify2(execFile2);
25446
25734
  var VALID_CATEGORIES = ["projects", "playbooks", "todos", "servers", "config"];
@@ -25480,7 +25768,7 @@ async function resolveCategoryPath(category) {
25480
25768
  case "servers":
25481
25769
  return { sourcePath: serversDir(), repoPath: "servers", isFile: false };
25482
25770
  case "config":
25483
- return { sourcePath: resolve43(syntaurRoot(), "config.md"), repoPath: "config.md", isFile: true };
25771
+ return { sourcePath: resolve45(syntaurRoot(), "config.md"), repoPath: "config.md", isFile: true };
25484
25772
  }
25485
25773
  }
25486
25774
  async function checkGitInstalled() {
@@ -25491,7 +25779,7 @@ async function checkGitInstalled() {
25491
25779
  }
25492
25780
  }
25493
25781
  async function acquireLock2() {
25494
- const lockPath = resolve43(syntaurRoot(), LOCK_FILE_NAME);
25782
+ const lockPath = resolve45(syntaurRoot(), LOCK_FILE_NAME);
25495
25783
  await ensureDir(syntaurRoot());
25496
25784
  try {
25497
25785
  const handle = await open5(lockPath, "wx");
@@ -25500,7 +25788,7 @@ async function acquireLock2() {
25500
25788
  return lockPath;
25501
25789
  } catch (err) {
25502
25790
  if (err.code === "EEXIST") {
25503
- const pid = await readFile29(lockPath, "utf-8").catch(() => "");
25791
+ const pid = await readFile31(lockPath, "utf-8").catch(() => "");
25504
25792
  throw new Error(
25505
25793
  `Backup operation already in progress (lock file at ${lockPath}, pid ${pid.trim() || "unknown"}). If stale, delete the file and retry.`
25506
25794
  );
@@ -25538,7 +25826,7 @@ async function copyRecursive(src, dest) {
25538
25826
  await ensureDir(dest);
25539
25827
  await cp2(src, dest, { recursive: true, force: true });
25540
25828
  } else {
25541
- await ensureDir(resolve43(dest, ".."));
25829
+ await ensureDir(resolve45(dest, ".."));
25542
25830
  await cp2(src, dest, { force: true });
25543
25831
  }
25544
25832
  }
@@ -25547,7 +25835,7 @@ function resolveCategoriesStrict(csv) {
25547
25835
  return parseCategoriesStrict(parts);
25548
25836
  }
25549
25837
  async function readSanitizedConfig(configPath) {
25550
- const content = await readFile29(configPath, "utf-8");
25838
+ const content = await readFile31(configPath, "utf-8");
25551
25839
  return content.replace(/^(\s*lastBackup:\s*).*$/m, "$1null").replace(/^(\s*lastRestore:\s*).*$/m, "$1null");
25552
25840
  }
25553
25841
  async function backupToGithub(overrides) {
@@ -25570,11 +25858,11 @@ async function backupToGithub(overrides) {
25570
25858
  let tmpDir = null;
25571
25859
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
25572
25860
  try {
25573
- tmpDir = await mkdtemp(join9(tmpdir(), "syntaur-backup-"));
25861
+ tmpDir = await mkdtemp(join11(tmpdir(), "syntaur-backup-"));
25574
25862
  await cloneOrInit(repo, tmpDir);
25575
25863
  for (const category of categories) {
25576
25864
  const { sourcePath, repoPath, isFile } = await resolveCategoryPath(category);
25577
- const destPath = join9(tmpDir, repoPath);
25865
+ const destPath = join11(tmpDir, repoPath);
25578
25866
  if (isFile) {
25579
25867
  await rm5(destPath, { force: true });
25580
25868
  } else {
@@ -25586,7 +25874,7 @@ async function backupToGithub(overrides) {
25586
25874
  }
25587
25875
  if (category === "config") {
25588
25876
  const sanitized = await readSanitizedConfig(sourcePath);
25589
- await ensureDir(resolve43(destPath, ".."));
25877
+ await ensureDir(resolve45(destPath, ".."));
25590
25878
  await writeFile7(destPath, sanitized, "utf-8");
25591
25879
  } else {
25592
25880
  await copyRecursive(sourcePath, destPath);
@@ -25640,7 +25928,7 @@ async function backupToGithub(overrides) {
25640
25928
  }
25641
25929
  async function safeRestoreCategory(localPath, repoSrcPath, isFile) {
25642
25930
  if (isFile) {
25643
- await ensureDir(resolve43(localPath, ".."));
25931
+ await ensureDir(resolve45(localPath, ".."));
25644
25932
  await cp2(repoSrcPath, localPath, { force: true });
25645
25933
  return;
25646
25934
  }
@@ -25702,7 +25990,7 @@ async function restoreFromGithub(overrides) {
25702
25990
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
25703
25991
  try {
25704
25992
  await updateBackupConfig({ lastRestore: timestamp });
25705
- tmpDir = await mkdtemp(join9(tmpdir(), "syntaur-restore-"));
25993
+ tmpDir = await mkdtemp(join11(tmpdir(), "syntaur-restore-"));
25706
25994
  await cloneOrInit(repo, tmpDir);
25707
25995
  for (const category of categories) {
25708
25996
  if (category === "config") {
@@ -25711,7 +25999,7 @@ async function restoreFromGithub(overrides) {
25711
25999
  }
25712
26000
  try {
25713
26001
  const { sourcePath: localPath, repoPath, isFile } = await resolveCategoryPath(category);
25714
- const repoSrcPath = join9(tmpDir, repoPath);
26002
+ const repoSrcPath = join11(tmpDir, repoPath);
25715
26003
  if (!await fileExists(repoSrcPath)) {
25716
26004
  console.warn(`Category "${category}" not found in backup repo, skipping.`);
25717
26005
  continue;
@@ -25741,7 +26029,7 @@ async function restoreFromGithub(overrides) {
25741
26029
  }
25742
26030
  async function getBackupStatus() {
25743
26031
  const config = await readConfig();
25744
- const lockPath = resolve43(syntaurRoot(), LOCK_FILE_NAME);
26032
+ const lockPath = resolve45(syntaurRoot(), LOCK_FILE_NAME);
25745
26033
  const locked = await fileExists(lockPath);
25746
26034
  return {
25747
26035
  repo: config.backup?.repo ?? null,