sisyphi 1.1.32 → 1.1.33

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.
package/dist/daemon.js CHANGED
@@ -51,9 +51,12 @@ __export(paths_exports, {
51
51
  legacyLogsPath: () => legacyLogsPath,
52
52
  logsDir: () => logsDir,
53
53
  messagesDir: () => messagesDir,
54
+ projectAgentPluginDir: () => projectAgentPluginDir,
54
55
  projectConfigPath: () => projectConfigPath,
55
56
  projectDir: () => projectDir,
57
+ projectOrchestratorPluginDir: () => projectOrchestratorPluginDir,
56
58
  projectOrchestratorPromptPath: () => projectOrchestratorPromptPath,
59
+ projectOrchestratorSettingsPath: () => projectOrchestratorSettingsPath,
57
60
  promptsDir: () => promptsDir,
58
61
  reportFilePath: () => reportFilePath,
59
62
  reportsDir: () => reportsDir,
@@ -69,7 +72,11 @@ __export(paths_exports, {
69
72
  strategyPath: () => strategyPath,
70
73
  tmuxSessionDisplayName: () => tmuxSessionDisplayName,
71
74
  tmuxSessionName: () => tmuxSessionName,
72
- tuiScratchDir: () => tuiScratchDir
75
+ tuiScratchDir: () => tuiScratchDir,
76
+ userAgentPluginDir: () => userAgentPluginDir,
77
+ userOrchestratorPluginDir: () => userOrchestratorPluginDir,
78
+ userOrchestratorPromptPath: () => userOrchestratorPromptPath,
79
+ userOrchestratorSettingsPath: () => userOrchestratorSettingsPath
73
80
  });
74
81
  import { homedir } from "os";
75
82
  import { basename, join } from "path";
@@ -100,6 +107,27 @@ function projectConfigPath(cwd) {
100
107
  function projectOrchestratorPromptPath(cwd) {
101
108
  return join(projectDir(cwd), "orchestrator.md");
102
109
  }
110
+ function userOrchestratorPromptPath() {
111
+ return join(globalDir(), "orchestrator.md");
112
+ }
113
+ function projectOrchestratorSettingsPath(cwd) {
114
+ return join(projectDir(cwd), "orchestrator-settings.json");
115
+ }
116
+ function userOrchestratorSettingsPath() {
117
+ return join(globalDir(), "orchestrator-settings.json");
118
+ }
119
+ function projectAgentPluginDir(cwd) {
120
+ return join(projectDir(cwd), "agent-plugin");
121
+ }
122
+ function userAgentPluginDir() {
123
+ return join(globalDir(), "agent-plugin");
124
+ }
125
+ function projectOrchestratorPluginDir(cwd) {
126
+ return join(projectDir(cwd), "orchestrator-plugin");
127
+ }
128
+ function userOrchestratorPluginDir() {
129
+ return join(globalDir(), "orchestrator-plugin");
130
+ }
103
131
  function sessionsDir(cwd) {
104
132
  return join(projectDir(cwd), "sessions");
105
133
  }
@@ -255,7 +283,7 @@ var init_paths = __esm({
255
283
 
256
284
  // src/daemon/index.ts
257
285
  init_paths();
258
- import { mkdirSync as mkdirSync12, readFileSync as readFileSync23, writeFileSync as writeFileSync16, unlinkSync as unlinkSync5, existsSync as existsSync23 } from "fs";
286
+ import { mkdirSync as mkdirSync13, readFileSync as readFileSync24, writeFileSync as writeFileSync17, unlinkSync as unlinkSync5, existsSync as existsSync24 } from "fs";
259
287
  import { execSync as execSync7 } from "child_process";
260
288
  import { setTimeout as sleep } from "timers/promises";
261
289
 
@@ -317,8 +345,8 @@ function loadConfig(cwd) {
317
345
  // src/daemon/server.ts
318
346
  init_paths();
319
347
  import { createServer } from "net";
320
- import { unlinkSync as unlinkSync3, existsSync as existsSync19, writeFileSync as writeFileSync14, readFileSync as readFileSync20, mkdirSync as mkdirSync10, readdirSync as readdirSync11, rmSync as rmSync7, chmodSync } from "fs";
321
- import { join as join18 } from "path";
348
+ import { unlinkSync as unlinkSync3, existsSync as existsSync20, writeFileSync as writeFileSync15, readFileSync as readFileSync21, mkdirSync as mkdirSync11, readdirSync as readdirSync12, rmSync as rmSync8, chmodSync } from "fs";
349
+ import { join as join19 } from "path";
322
350
 
323
351
  // src/shared/shell.ts
324
352
  function shellQuote(s) {
@@ -337,7 +365,7 @@ function escapeAppleScript(s) {
337
365
 
338
366
  // src/daemon/session-manager.ts
339
367
  import { v4 as uuidv4 } from "uuid";
340
- import { existsSync as existsSync17, readFileSync as readFileSync18, readdirSync as readdirSync10, rmSync as rmSync5 } from "fs";
368
+ import { existsSync as existsSync18, readFileSync as readFileSync19, readdirSync as readdirSync11, rmSync as rmSync6 } from "fs";
341
369
 
342
370
  // src/daemon/state.ts
343
371
  import { copyFileSync, cpSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync3, readdirSync, rmSync, statSync, writeFileSync as writeFileSync3 } from "fs";
@@ -356,16 +384,16 @@ function atomicWrite(filePath, data) {
356
384
  var locks = /* @__PURE__ */ new Map();
357
385
  async function withLock(key, fn) {
358
386
  const prev = locks.get(key) ?? Promise.resolve();
359
- let resolve11;
387
+ let resolve12;
360
388
  const next = new Promise((r) => {
361
- resolve11 = r;
389
+ resolve12 = r;
362
390
  });
363
391
  locks.set(key, next);
364
392
  await prev;
365
393
  try {
366
394
  return fn();
367
395
  } finally {
368
- resolve11();
396
+ resolve12();
369
397
  if (locks.get(key) === next) {
370
398
  locks.delete(key);
371
399
  }
@@ -468,6 +496,13 @@ function getSession(cwd, sessionId) {
468
496
  function saveSession(session) {
469
497
  atomicWrite(statePath(session.cwd, session.id), JSON.stringify(session, null, 2));
470
498
  }
499
+ function isSessionDangerous(cwd, sessionId) {
500
+ try {
501
+ return getSession(cwd, sessionId).dangerousMode === true;
502
+ } catch {
503
+ return false;
504
+ }
505
+ }
471
506
  async function addAgent(cwd, sessionId, agent) {
472
507
  return withSessionLock(sessionId, () => {
473
508
  const session = getSession(cwd, sessionId);
@@ -836,10 +871,10 @@ async function createCloneState(sourceCwd, sourceId, cloneId, goal, context, con
836
871
  }
837
872
 
838
873
  // src/daemon/orchestrator.ts
839
- import { existsSync as existsSync15, readdirSync as readdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "fs";
874
+ import { existsSync as existsSync16, readdirSync as readdirSync10, readFileSync as readFileSync15, writeFileSync as writeFileSync13 } from "fs";
840
875
  import { execSync as execSync5 } from "child_process";
841
876
  import { randomUUID as randomUUID6 } from "crypto";
842
- import { resolve as resolve6, join as join15, relative as relative2 } from "path";
877
+ import { resolve as resolve7, join as join16, relative as relative3 } from "path";
843
878
 
844
879
  // src/daemon/spawn-helpers.ts
845
880
  import { writeFileSync as writeFileSync4, existsSync as existsSync3 } from "fs";
@@ -951,6 +986,7 @@ function resetColors(sessionId) {
951
986
  }
952
987
 
953
988
  // src/daemon/frontmatter.ts
989
+ init_paths();
954
990
  import { readFileSync as readFileSync4, existsSync as existsSync4, readdirSync as readdirSync2 } from "fs";
955
991
  import { homedir as homedir2 } from "os";
956
992
  import { join as join5, basename as basename2 } from "path";
@@ -1025,6 +1061,8 @@ function resolveAgentTypePath(agentType, pluginDir, cwd) {
1025
1061
  searchPaths.push(join5(installPath, "agents", `${name}.md`));
1026
1062
  }
1027
1063
  } else {
1064
+ searchPaths.push(join5(projectAgentPluginDir(cwd), "agents", `${name}.md`));
1065
+ searchPaths.push(join5(userAgentPluginDir(), "agents", `${name}.md`));
1028
1066
  searchPaths.push(join5(cwd, ".claude", "agents", `${name}.md`));
1029
1067
  searchPaths.push(join5(homedir2(), ".claude", "agents", `${name}.md`));
1030
1068
  searchPaths.push(join5(pluginDir, "agents", `${name}.md`));
@@ -1059,6 +1097,8 @@ function discoverAgentTypes(pluginDir, cwd) {
1059
1097
  }
1060
1098
  }
1061
1099
  }
1100
+ scanDir(join5(projectAgentPluginDir(cwd), "agents"), null, "project-sis");
1101
+ scanDir(join5(userAgentPluginDir(), "agents"), null, "user-sis");
1062
1102
  scanDir(join5(cwd, ".claude", "agents"), null, "project");
1063
1103
  scanDir(join5(homedir2(), ".claude", "agents"), null, "user");
1064
1104
  scanDir(join5(pluginDir, "agents"), "sisyphus", "bundled");
@@ -1098,6 +1138,8 @@ function resolveAgentConfig(agentType, pluginDir, cwd) {
1098
1138
  // src/daemon/orchestrator-modes.ts
1099
1139
  import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync5 } from "fs";
1100
1140
  import { resolve as resolve3, join as join6 } from "path";
1141
+ init_paths();
1142
+ import { homedir as homedir3 } from "os";
1101
1143
  function resolveTemplatesDir() {
1102
1144
  const distLayout = resolve3(import.meta.dirname, "../templates");
1103
1145
  if (existsSync5(distLayout)) return distLayout;
@@ -1105,18 +1147,46 @@ function resolveTemplatesDir() {
1105
1147
  if (existsSync5(srcLayout)) return srcLayout;
1106
1148
  return void 0;
1107
1149
  }
1108
- function discoverOrchestratorModes() {
1109
- const templatesDir = resolveTemplatesDir();
1110
- if (!templatesDir) return [];
1111
- const files = readdirSync3(templatesDir).filter(
1112
- (f) => f.startsWith("orchestrator-") && f.endsWith(".md") && f !== "orchestrator-base.md"
1113
- );
1114
- return files.map((file) => {
1115
- const content = readFileSync5(join6(templatesDir, file), "utf-8");
1116
- const fm = parseAgentFrontmatter(content);
1117
- const name = fm.name ?? file.replace(/^orchestrator-/, "").replace(/\.md$/, "");
1118
- return { name, description: fm.description, filePath: join6(templatesDir, file) };
1119
- });
1150
+ function modeLayers(cwd) {
1151
+ const layers = [];
1152
+ const project = projectDir(cwd);
1153
+ if (existsSync5(project)) layers.push({ source: "project", dir: project });
1154
+ const user = join6(homedir3(), ".sisyphus");
1155
+ if (existsSync5(user)) layers.push({ source: "user", dir: user });
1156
+ const bundled = resolveTemplatesDir();
1157
+ if (bundled) layers.push({ source: "bundled", dir: bundled });
1158
+ return layers;
1159
+ }
1160
+ function discoverOrchestratorModes(cwd) {
1161
+ const layers = cwd ? modeLayers(cwd) : modeLayers(process.cwd());
1162
+ const seen = /* @__PURE__ */ new Map();
1163
+ for (const layer of layers) {
1164
+ let files;
1165
+ try {
1166
+ files = readdirSync3(layer.dir);
1167
+ } catch {
1168
+ continue;
1169
+ }
1170
+ const modeFiles = files.filter(
1171
+ (f) => f.startsWith("orchestrator-") && f.endsWith(".md") && f !== "orchestrator-base.md"
1172
+ );
1173
+ for (const file of modeFiles) {
1174
+ const filePath = join6(layer.dir, file);
1175
+ let content = "";
1176
+ try {
1177
+ content = readFileSync5(filePath, "utf-8");
1178
+ } catch {
1179
+ continue;
1180
+ }
1181
+ const fm = parseAgentFrontmatter(content);
1182
+ const name = fm.name ?? file.replace(/^orchestrator-/, "").replace(/\.md$/, "");
1183
+ if (seen.has(name)) continue;
1184
+ const entry = { name, filePath, source: layer.source };
1185
+ if (fm.description !== void 0) entry.description = fm.description;
1186
+ seen.set(name, entry);
1187
+ }
1188
+ }
1189
+ return Array.from(seen.values());
1120
1190
  }
1121
1191
 
1122
1192
  // src/daemon/lib/effort-render.ts
@@ -1181,6 +1251,249 @@ function walk(src, dest, tier) {
1181
1251
  }
1182
1252
  }
1183
1253
 
1254
+ // src/daemon/extensions.ts
1255
+ init_paths();
1256
+ import { existsSync as existsSync7, readFileSync as readFileSync7, readdirSync as readdirSync5, copyFileSync as copyFileSync3, mkdirSync as mkdirSync3, statSync as statSync2, rmSync as rmSync3, writeFileSync as writeFileSync6 } from "fs";
1257
+ import { resolve as resolve4, join as join8, basename as basename3, relative } from "path";
1258
+ function resolveBundledTemplateDir(kind) {
1259
+ const built = resolve4(import.meta.dirname, "../templates", kind);
1260
+ if (existsSync7(built)) return built;
1261
+ const src = resolve4(import.meta.dirname, "../../templates", kind);
1262
+ if (existsSync7(src)) return src;
1263
+ return void 0;
1264
+ }
1265
+ function agentPluginLayers(cwd) {
1266
+ const layers = [];
1267
+ const project = projectAgentPluginDir(cwd);
1268
+ if (existsSync7(project)) layers.push({ source: "project", root: project });
1269
+ const user = userAgentPluginDir();
1270
+ if (existsSync7(user)) layers.push({ source: "user", root: user });
1271
+ const bundled = resolveBundledTemplateDir("agent-plugin");
1272
+ if (bundled) layers.push({ source: "bundled", root: bundled });
1273
+ return layers;
1274
+ }
1275
+ function orchestratorPluginLayers(cwd) {
1276
+ const layers = [];
1277
+ const project = projectOrchestratorPluginDir(cwd);
1278
+ if (existsSync7(project)) layers.push({ source: "project", root: project });
1279
+ const user = userOrchestratorPluginDir();
1280
+ if (existsSync7(user)) layers.push({ source: "user", root: user });
1281
+ const bundled = resolveBundledTemplateDir("orchestrator-plugin");
1282
+ if (bundled) layers.push({ source: "bundled", root: bundled });
1283
+ return layers;
1284
+ }
1285
+ function readManifest(layerRoot) {
1286
+ const path = join8(layerRoot, "hooks", "hooks.json");
1287
+ if (!existsSync7(path)) return null;
1288
+ try {
1289
+ const raw = readFileSync7(path, "utf-8");
1290
+ const parsed = JSON.parse(raw);
1291
+ return parsed;
1292
+ } catch (err) {
1293
+ console.warn(`[sisyphus] Failed to parse hooks manifest at ${path}: ${err instanceof Error ? err.message : err}`);
1294
+ return null;
1295
+ }
1296
+ }
1297
+ function commandScriptName(command2) {
1298
+ const match = command2.match(/([\w.-]+\.[\w]+)\s*$/);
1299
+ return match ? match[1] : null;
1300
+ }
1301
+ function groupApplies(group, ctx) {
1302
+ const types = group.agentTypes ?? ["all"];
1303
+ const matchesType = types.includes("all") || types.includes(ctx.agentType);
1304
+ if (!matchesType) return false;
1305
+ if (group.condition === "non-interactive" && ctx.interactive) return false;
1306
+ return true;
1307
+ }
1308
+ function mergeHookManifests(layers, ctx) {
1309
+ const disabled = /* @__PURE__ */ new Set();
1310
+ for (const layer of layers) {
1311
+ const manifest = readManifest(layer.root);
1312
+ if (!manifest?.disable) continue;
1313
+ for (const name of manifest.disable) disabled.add(name);
1314
+ }
1315
+ const merged = {};
1316
+ for (const layer of layers) {
1317
+ const manifest = readManifest(layer.root);
1318
+ if (!manifest?.hooks) continue;
1319
+ for (const [event, groups] of Object.entries(manifest.hooks)) {
1320
+ if (!Array.isArray(groups)) continue;
1321
+ for (const group of groups) {
1322
+ if (!groupApplies(group, ctx)) continue;
1323
+ const filteredHooks = group.hooks.filter((h) => {
1324
+ const script = commandScriptName(h.command);
1325
+ return !script || !disabled.has(script);
1326
+ });
1327
+ if (filteredHooks.length === 0) continue;
1328
+ const cleaned = {
1329
+ ...group.matcher !== void 0 && { matcher: group.matcher },
1330
+ hooks: filteredHooks
1331
+ };
1332
+ if (!merged[event]) merged[event] = [];
1333
+ merged[event].push(cleaned);
1334
+ }
1335
+ }
1336
+ }
1337
+ return merged;
1338
+ }
1339
+ var defaultFilter = (name) => name !== "CLAUDE.md" && name !== "hooks.json";
1340
+ function copyLayered(layers, opts) {
1341
+ mkdirSync3(opts.destDir, { recursive: true });
1342
+ const filter = opts.filter ?? defaultFilter;
1343
+ const written = /* @__PURE__ */ new Set();
1344
+ for (const layer of layers) {
1345
+ const layerSubdir = join8(layer.root, opts.subdir);
1346
+ if (!existsSync7(layerSubdir)) continue;
1347
+ let entries;
1348
+ try {
1349
+ entries = readdirSync5(layerSubdir);
1350
+ } catch {
1351
+ continue;
1352
+ }
1353
+ for (const name of entries) {
1354
+ if (!filter(name)) continue;
1355
+ if (opts.skipFiles?.has(name)) continue;
1356
+ if (written.has(name)) continue;
1357
+ const src = join8(layerSubdir, name);
1358
+ const dest = join8(opts.destDir, name);
1359
+ const stat = statSync2(src);
1360
+ if (stat.isDirectory()) {
1361
+ if (!opts.recurse) continue;
1362
+ copyDirRecursive(src, dest);
1363
+ } else if (stat.isFile()) {
1364
+ copyFileSync3(src, dest);
1365
+ }
1366
+ written.add(name);
1367
+ }
1368
+ }
1369
+ }
1370
+ function copyDirRecursive(src, dest) {
1371
+ mkdirSync3(dest, { recursive: true });
1372
+ for (const name of readdirSync5(src)) {
1373
+ const s = join8(src, name);
1374
+ const d = join8(dest, name);
1375
+ const stat = statSync2(s);
1376
+ if (stat.isDirectory()) {
1377
+ copyDirRecursive(s, d);
1378
+ } else if (stat.isFile()) {
1379
+ copyFileSync3(s, d);
1380
+ }
1381
+ }
1382
+ }
1383
+ function collectReferencedHookScripts(layers, ctx) {
1384
+ const scripts = /* @__PURE__ */ new Set();
1385
+ for (const layer of layers) {
1386
+ const manifest = readManifest(layer.root);
1387
+ if (!manifest?.hooks) continue;
1388
+ for (const groups of Object.values(manifest.hooks)) {
1389
+ if (!Array.isArray(groups)) continue;
1390
+ for (const group of groups) {
1391
+ if (!groupApplies(group, ctx)) continue;
1392
+ for (const h of group.hooks) {
1393
+ const name = commandScriptName(h.command);
1394
+ if (name) scripts.add(name);
1395
+ }
1396
+ }
1397
+ }
1398
+ }
1399
+ return scripts;
1400
+ }
1401
+ function collectDisabledHookScripts(layers) {
1402
+ const disabled = /* @__PURE__ */ new Set();
1403
+ for (const layer of layers) {
1404
+ const manifest = readManifest(layer.root);
1405
+ if (!manifest?.disable) continue;
1406
+ for (const name of manifest.disable) disabled.add(name);
1407
+ }
1408
+ return disabled;
1409
+ }
1410
+ function indexAvailableSkills(layers) {
1411
+ const index = /* @__PURE__ */ new Map();
1412
+ for (const layer of layers) {
1413
+ const skillsRoot = join8(layer.root, "skills");
1414
+ if (!existsSync7(skillsRoot)) continue;
1415
+ let entries;
1416
+ try {
1417
+ entries = readdirSync5(skillsRoot);
1418
+ } catch {
1419
+ continue;
1420
+ }
1421
+ for (const name of entries) {
1422
+ if (index.has(name)) continue;
1423
+ const path = join8(skillsRoot, name);
1424
+ try {
1425
+ if (statSync2(path).isDirectory()) index.set(name, path);
1426
+ } catch {
1427
+ }
1428
+ }
1429
+ }
1430
+ return index;
1431
+ }
1432
+ function copySkill(layers, skillName, destSkillsDir) {
1433
+ const index = indexAvailableSkills(layers);
1434
+ const src = index.get(skillName);
1435
+ if (!src) return false;
1436
+ copyDirRecursive(src, join8(destSkillsDir, skillName));
1437
+ return true;
1438
+ }
1439
+ var FILTERED_RENDER_EXTS = /* @__PURE__ */ new Set([".md"]);
1440
+ function isRenderable(name) {
1441
+ for (const ext of FILTERED_RENDER_EXTS) {
1442
+ if (name.endsWith(ext)) return true;
1443
+ }
1444
+ return false;
1445
+ }
1446
+ function collectOverlay(layers) {
1447
+ const overlay = /* @__PURE__ */ new Map();
1448
+ for (const layer of layers) {
1449
+ if (!existsSync7(layer.root)) continue;
1450
+ walkRelative(layer.root, "", (relPath, absPath) => {
1451
+ if (overlay.has(relPath)) return;
1452
+ overlay.set(relPath, { src: absPath, source: layer.source });
1453
+ });
1454
+ }
1455
+ return overlay;
1456
+ }
1457
+ function walkRelative(root, prefix, visit) {
1458
+ const dir = prefix ? join8(root, prefix) : root;
1459
+ let entries;
1460
+ try {
1461
+ entries = readdirSync5(dir);
1462
+ } catch {
1463
+ return;
1464
+ }
1465
+ for (const name of entries) {
1466
+ const childPrefix = prefix ? join8(prefix, name) : name;
1467
+ const abs = join8(dir, name);
1468
+ let stat;
1469
+ try {
1470
+ stat = statSync2(abs);
1471
+ } catch {
1472
+ continue;
1473
+ }
1474
+ if (stat.isDirectory()) {
1475
+ walkRelative(root, childPrefix, visit);
1476
+ } else if (stat.isFile()) {
1477
+ visit(childPrefix, abs);
1478
+ }
1479
+ }
1480
+ }
1481
+ function renderLayeredPluginDir(layers, destDir, tier) {
1482
+ rmSync3(destDir, { recursive: true, force: true });
1483
+ mkdirSync3(destDir, { recursive: true });
1484
+ const overlay = collectOverlay(layers);
1485
+ for (const [relPath, entry] of overlay) {
1486
+ const destPath = join8(destDir, relPath);
1487
+ mkdirSync3(join8(destPath, ".."), { recursive: true });
1488
+ if (isRenderable(basename3(relPath))) {
1489
+ const rendered = renderEffortMarkers(readFileSync7(entry.src, "utf-8"), tier);
1490
+ writeFileSync6(destPath, rendered, "utf-8");
1491
+ } else {
1492
+ copyFileSync3(entry.src, destPath);
1493
+ }
1494
+ }
1495
+ }
1496
+
1184
1497
  // src/daemon/tmux.ts
1185
1498
  import { execSync as execSync2 } from "child_process";
1186
1499
  var t = (target) => shellQuote(target);
@@ -1443,10 +1756,10 @@ function getSessionPanes(sessionId) {
1443
1756
  }
1444
1757
 
1445
1758
  // src/daemon/agent.ts
1446
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync8, copyFileSync as copyFileSync3, mkdirSync as mkdirSync6, readdirSync as readdirSync7, existsSync as existsSync10, unlinkSync } from "fs";
1759
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync9, mkdirSync as mkdirSync7, readdirSync as readdirSync8, existsSync as existsSync11, unlinkSync } from "fs";
1447
1760
  import { execSync as execSync4 } from "child_process";
1448
1761
  import { randomUUID as randomUUID3 } from "crypto";
1449
- import { resolve as resolve4, relative, dirname as dirname3, join as join11 } from "path";
1762
+ import { resolve as resolve5, relative as relative2, dirname as dirname3, join as join12 } from "path";
1450
1763
  init_paths();
1451
1764
 
1452
1765
  // src/daemon/haiku.ts
@@ -1602,17 +1915,17 @@ ${reportText.slice(0, 3e3)}`
1602
1915
  }
1603
1916
 
1604
1917
  // src/daemon/plugins.ts
1605
- import { readFileSync as readFileSync7 } from "fs";
1918
+ import { readFileSync as readFileSync8 } from "fs";
1606
1919
  import { execFileSync } from "child_process";
1607
- import { homedir as homedir3 } from "os";
1608
- import { join as join8 } from "path";
1920
+ import { homedir as homedir4 } from "os";
1921
+ import { join as join9 } from "path";
1609
1922
  function installedPluginsPath() {
1610
- return join8(homedir3(), ".claude", "plugins", "installed_plugins.json");
1923
+ return join9(homedir4(), ".claude", "plugins", "installed_plugins.json");
1611
1924
  }
1612
1925
  function resolveInstalledPlugin(name) {
1613
1926
  let data;
1614
1927
  try {
1615
- data = JSON.parse(readFileSync7(installedPluginsPath(), "utf-8"));
1928
+ data = JSON.parse(readFileSync8(installedPluginsPath(), "utf-8"));
1616
1929
  } catch {
1617
1930
  return null;
1618
1931
  }
@@ -1670,13 +1983,13 @@ function resolveAgentPluginDirs(plugins) {
1670
1983
 
1671
1984
  // src/daemon/history.ts
1672
1985
  init_paths();
1673
- import { appendFileSync, mkdirSync as mkdirSync3, writeFileSync as writeFileSync6, renameSync as renameSync2, readdirSync as readdirSync5, readFileSync as readFileSync8, rmSync as rmSync3, statSync as statSync2 } from "fs";
1986
+ import { appendFileSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync7, renameSync as renameSync2, readdirSync as readdirSync6, readFileSync as readFileSync9, rmSync as rmSync4, statSync as statSync3 } from "fs";
1674
1987
  import { randomUUID as randomUUID2 } from "crypto";
1675
- import { dirname as dirname2, join as join9 } from "path";
1988
+ import { dirname as dirname2, join as join10 } from "path";
1676
1989
  var knownDirs = /* @__PURE__ */ new Set();
1677
1990
  function ensureDir(sessionId) {
1678
1991
  if (knownDirs.has(sessionId)) return;
1679
- mkdirSync3(historySessionDir(sessionId), { recursive: true });
1992
+ mkdirSync4(historySessionDir(sessionId), { recursive: true });
1680
1993
  knownDirs.add(sessionId);
1681
1994
  }
1682
1995
  function emitHistoryEvent(sessionId, event, data) {
@@ -1744,8 +2057,8 @@ function writeSessionSummary(session, extra) {
1744
2057
  sentiment: extra?.sentiment ?? null
1745
2058
  };
1746
2059
  const filePath = historySessionSummaryPath(session.id);
1747
- const tmp = join9(dirname2(filePath), `.session-${randomUUID2()}.tmp`);
1748
- writeFileSync6(tmp, JSON.stringify(summary, null, 2), "utf-8");
2060
+ const tmp = join10(dirname2(filePath), `.session-${randomUUID2()}.tmp`);
2061
+ writeFileSync7(tmp, JSON.stringify(summary, null, 2), "utf-8");
1749
2062
  renameSync2(tmp, filePath);
1750
2063
  } catch (err) {
1751
2064
  console.error(`[history] Failed to write session summary for ${session.id}:`, err);
@@ -1756,14 +2069,14 @@ function getRecentSentiments(count = 5, scanLimit = 30, overrideBaseDir) {
1756
2069
  const base = overrideBaseDir ?? historyBaseDir();
1757
2070
  let entries;
1758
2071
  try {
1759
- entries = readdirSync5(base);
2072
+ entries = readdirSync6(base);
1760
2073
  } catch {
1761
2074
  return [];
1762
2075
  }
1763
2076
  const withMtime = [];
1764
2077
  for (const name of entries) {
1765
2078
  try {
1766
- const st = statSync2(join9(base, name));
2079
+ const st = statSync3(join10(base, name));
1767
2080
  if (st.isDirectory()) withMtime.push({ name, mtime: st.mtimeMs });
1768
2081
  } catch {
1769
2082
  continue;
@@ -1774,7 +2087,7 @@ function getRecentSentiments(count = 5, scanLimit = 30, overrideBaseDir) {
1774
2087
  const limit = Math.min(withMtime.length, scanLimit);
1775
2088
  for (let i = 0; i < limit && results.length < count; i++) {
1776
2089
  try {
1777
- const raw = readFileSync8(join9(base, withMtime[i].name, "session.json"), "utf-8");
2090
+ const raw = readFileSync9(join10(base, withMtime[i].name, "session.json"), "utf-8");
1778
2091
  const summary = JSON.parse(raw);
1779
2092
  if (summary.sentiment && summary.completedAt) {
1780
2093
  results.push({
@@ -1799,27 +2112,27 @@ function pruneHistory() {
1799
2112
  const base = historyBaseDir();
1800
2113
  let entries;
1801
2114
  try {
1802
- entries = readdirSync5(base);
2115
+ entries = readdirSync6(base);
1803
2116
  } catch {
1804
2117
  return;
1805
2118
  }
1806
2119
  const sessions = [];
1807
2120
  for (const name of entries) {
1808
- const dir = join9(base, name);
2121
+ const dir = join10(base, name);
1809
2122
  try {
1810
- const summaryPath = join9(dir, "session.json");
1811
- const raw = readFileSync8(summaryPath, "utf-8");
2123
+ const summaryPath = join10(dir, "session.json");
2124
+ const raw = readFileSync9(summaryPath, "utf-8");
1812
2125
  const summary = JSON.parse(raw);
1813
2126
  sessions.push({ dir, startedAt: new Date(summary.startedAt ?? 0).getTime() });
1814
2127
  } catch {
1815
2128
  try {
1816
- const eventsPath = join9(dir, "events.jsonl");
1817
- const firstLine = readFileSync8(eventsPath, "utf-8").split("\n")[0];
2129
+ const eventsPath = join10(dir, "events.jsonl");
2130
+ const firstLine = readFileSync9(eventsPath, "utf-8").split("\n")[0];
1818
2131
  const firstEvent = JSON.parse(firstLine);
1819
2132
  sessions.push({ dir, startedAt: new Date(firstEvent.ts ?? 0).getTime() });
1820
2133
  } catch {
1821
2134
  try {
1822
- const st = statSync2(dir);
2135
+ const st = statSync3(dir);
1823
2136
  sessions.push({ dir, startedAt: st.mtimeMs });
1824
2137
  } catch {
1825
2138
  continue;
@@ -1832,7 +2145,7 @@ function pruneHistory() {
1832
2145
  const cutoff = Date.now() - PRUNE_KEEP_DAYS * 24 * 60 * 60 * 1e3;
1833
2146
  for (let i = PRUNE_KEEP_COUNT; i < sessions.length; i++) {
1834
2147
  if (sessions[i].startedAt < cutoff) {
1835
- rmSync3(sessions[i].dir, { recursive: true, force: true });
2148
+ rmSync4(sessions[i].dir, { recursive: true, force: true });
1836
2149
  }
1837
2150
  }
1838
2151
  } catch {
@@ -1844,13 +2157,13 @@ import { ulid } from "ulid";
1844
2157
 
1845
2158
  // src/daemon/ask-store.ts
1846
2159
  init_paths();
1847
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync9, readdirSync as readdirSync6 } from "fs";
2160
+ import { existsSync as existsSync9, mkdirSync as mkdirSync6, readFileSync as readFileSync10, readdirSync as readdirSync7 } from "fs";
1848
2161
 
1849
2162
  // src/daemon/notify.ts
1850
2163
  import { spawn, execFile } from "child_process";
1851
- import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync4, existsSync as existsSync7 } from "fs";
1852
- import { join as join10 } from "path";
1853
- import { homedir as homedir4 } from "os";
2164
+ import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync5, existsSync as existsSync8 } from "fs";
2165
+ import { join as join11 } from "path";
2166
+ import { homedir as homedir5 } from "os";
1854
2167
  var TMUX_SOCKET = `/tmp/tmux-${process.getuid?.() ?? 0}/default`;
1855
2168
  var SWITCH_SCRIPT = [
1856
2169
  "#!/bin/bash",
@@ -1892,24 +2205,24 @@ var SWITCH_SCRIPT = [
1892
2205
  ""
1893
2206
  ].join("\n");
1894
2207
  function ensureSwitchScript() {
1895
- const dir = join10(homedir4(), ".sisyphus");
1896
- const scriptPath = join10(dir, "notify-switch.sh");
2208
+ const dir = join11(homedir5(), ".sisyphus");
2209
+ const scriptPath = join11(dir, "notify-switch.sh");
1897
2210
  try {
1898
- mkdirSync4(dir, { recursive: true });
1899
- writeFileSync7(scriptPath, SWITCH_SCRIPT, { mode: 493 });
2211
+ mkdirSync5(dir, { recursive: true });
2212
+ writeFileSync8(scriptPath, SWITCH_SCRIPT, { mode: 493 });
1900
2213
  } catch {
1901
2214
  }
1902
2215
  }
1903
2216
  var notifyProcess = null;
1904
2217
  function getNotifyBinary() {
1905
- return join10(homedir4(), ".sisyphus", "SisyphusNotify.app", "Contents", "MacOS", "sisyphus-notify");
2218
+ return join11(homedir5(), ".sisyphus", "SisyphusNotify.app", "Contents", "MacOS", "sisyphus-notify");
1906
2219
  }
1907
2220
  function ensureNotifyProcess() {
1908
2221
  if (notifyProcess && !notifyProcess.killed && notifyProcess.stdin?.writable) {
1909
2222
  return notifyProcess;
1910
2223
  }
1911
2224
  const binary = getNotifyBinary();
1912
- if (!existsSync7(binary)) {
2225
+ if (!existsSync8(binary)) {
1913
2226
  return null;
1914
2227
  }
1915
2228
  notifyProcess = spawn(binary, [], {
@@ -1989,7 +2302,7 @@ function maybeNotifyOnAskCreated(cwd, sessionId, meta) {
1989
2302
  }
1990
2303
  }
1991
2304
  function createAsk(cwd, sessionId, params) {
1992
- mkdirSync5(askVisualsDir(cwd, sessionId, params.askId), { recursive: true });
2305
+ mkdirSync6(askVisualsDir(cwd, sessionId, params.askId), { recursive: true });
1993
2306
  const askedAt = (/* @__PURE__ */ new Date()).toISOString();
1994
2307
  const meta = {
1995
2308
  askId: params.askId,
@@ -2018,11 +2331,12 @@ function createAsk(cwd, sessionId, params) {
2018
2331
  }
2019
2332
  function writeDecisions(cwd, sessionId, askId, deck) {
2020
2333
  atomicWrite(askDecisionsPath(cwd, sessionId, askId), JSON.stringify(deck, null, 2));
2334
+ void maybeAutoResolveAsk(cwd, sessionId, askId, deck);
2021
2335
  }
2022
2336
  function readDecisions(cwd, sessionId, askId) {
2023
2337
  const p = askDecisionsPath(cwd, sessionId, askId);
2024
2338
  try {
2025
- return JSON.parse(readFileSync9(p, { encoding: "utf-8" }));
2339
+ return JSON.parse(readFileSync10(p, { encoding: "utf-8" }));
2026
2340
  } catch (_e) {
2027
2341
  return null;
2028
2342
  }
@@ -2035,10 +2349,10 @@ function writeOutput(cwd, sessionId, askId, responses, completedAt) {
2035
2349
  }
2036
2350
  function readMeta(cwd, sessionId, askId) {
2037
2351
  const p = askMetaPath(cwd, sessionId, askId);
2038
- if (!existsSync8(p)) {
2352
+ if (!existsSync9(p)) {
2039
2353
  return null;
2040
2354
  }
2041
- return JSON.parse(readFileSync9(p, "utf-8"));
2355
+ return JSON.parse(readFileSync10(p, "utf-8"));
2042
2356
  }
2043
2357
  async function updateMeta(cwd, sessionId, askId, patch) {
2044
2358
  return withLock(askId, () => {
@@ -2053,10 +2367,44 @@ async function updateMeta(cwd, sessionId, askId, patch) {
2053
2367
  }
2054
2368
  function listAsks(cwd, sessionId) {
2055
2369
  const dir = askDir(cwd, sessionId);
2056
- if (!existsSync8(dir)) {
2370
+ if (!existsSync9(dir)) {
2057
2371
  return [];
2058
2372
  }
2059
- return readdirSync6(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
2373
+ return readdirSync7(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
2374
+ }
2375
+ function buildAutoResponses(deck) {
2376
+ const out = [];
2377
+ for (const interaction of deck.interactions) {
2378
+ const first = interaction.options[0];
2379
+ if (!first) continue;
2380
+ out.push({ id: interaction.id, selectedOptionId: first.id });
2381
+ }
2382
+ return out;
2383
+ }
2384
+ async function autoResolveAsk(cwd, sessionId, askId, deck) {
2385
+ try {
2386
+ if (existsSync9(askOutputPath(cwd, sessionId, askId))) return false;
2387
+ const d = deck ?? readDecisions(cwd, sessionId, askId);
2388
+ if (!d) return false;
2389
+ const responses = buildAutoResponses(d);
2390
+ if (responses.length === 0) return false;
2391
+ writeOutput(cwd, sessionId, askId, responses);
2392
+ await updateMeta(cwd, sessionId, askId, {
2393
+ status: "answered",
2394
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
2395
+ });
2396
+ return true;
2397
+ } catch (err) {
2398
+ console.warn(`[sisyphus] dangerous-mode auto-resolve failed for ask ${askId}:`, err instanceof Error ? err.message : err);
2399
+ return false;
2400
+ }
2401
+ }
2402
+ async function maybeAutoResolveAsk(cwd, sessionId, askId, deck) {
2403
+ try {
2404
+ if (!isSessionDangerous(cwd, sessionId)) return;
2405
+ await autoResolveAsk(cwd, sessionId, askId, deck);
2406
+ } catch {
2407
+ }
2060
2408
  }
2061
2409
  function listOpenAsksFor(cwd, sessionId, askedBy) {
2062
2410
  const out = [];
@@ -2067,7 +2415,7 @@ function listOpenAsksFor(cwd, sessionId, askedBy) {
2067
2415
  if (meta.orphaned) continue;
2068
2416
  if (!meta.blocking) continue;
2069
2417
  if (meta.status !== "pending" && meta.status !== "in-progress") continue;
2070
- if (existsSync8(askOutputPath(cwd, sessionId, askId))) continue;
2418
+ if (existsSync9(askOutputPath(cwd, sessionId, askId))) continue;
2071
2419
  out.push({ askId, status: meta.status, ...meta.title !== void 0 ? { title: meta.title } : {} });
2072
2420
  }
2073
2421
  return out;
@@ -2266,7 +2614,7 @@ async function resolveOrchestratorOrphanAsks(cwd, sessionId, selectedOptionId) {
2266
2614
  }
2267
2615
 
2268
2616
  // src/daemon/orphan-sweep.ts
2269
- import { existsSync as existsSync9 } from "fs";
2617
+ import { existsSync as existsSync10 } from "fs";
2270
2618
  import { execSync as execSync3 } from "child_process";
2271
2619
  init_paths();
2272
2620
 
@@ -2315,7 +2663,7 @@ async function capturePanePidLstart(paneId) {
2315
2663
  async function sweepOrphans(registry) {
2316
2664
  const reg = registry ?? loadSessionRegistry();
2317
2665
  for (const [sessionId, cwd] of Object.entries(reg)) {
2318
- if (!existsSync9(statePath(cwd, sessionId))) continue;
2666
+ if (!existsSync10(statePath(cwd, sessionId))) continue;
2319
2667
  try {
2320
2668
  await sweepSessionAgents(cwd, sessionId);
2321
2669
  await sweepSessionAsks(cwd, sessionId);
@@ -2384,10 +2732,10 @@ function substituteSisyphusVars(text, sessionId, agentId, sesDir) {
2384
2732
  return text.replace(/\$SISYPHUS_SESSION_DIR/g, sesDir).replace(/\$SISYPHUS_SESSION_ID/g, sessionId).replace(/\$SISYPHUS_AGENT_ID/g, agentId);
2385
2733
  }
2386
2734
  function renderAgentSuffix(sessionId, instruction, contextDirRel) {
2387
- const templatePath = resolve4(import.meta.dirname, "../templates/agent-suffix.md");
2735
+ const templatePath = resolve5(import.meta.dirname, "../templates/agent-suffix.md");
2388
2736
  let template;
2389
2737
  try {
2390
- template = readFileSync10(templatePath, "utf-8");
2738
+ template = readFileSync11(templatePath, "utf-8");
2391
2739
  } catch {
2392
2740
  template = `# Sisyphus Agent
2393
2741
  Session: {{SESSION_ID}}
@@ -2397,10 +2745,11 @@ Task: {{INSTRUCTION}}`;
2397
2745
  }
2398
2746
  function createAgentPlugin(cwd, sessionId, agentId, agentType, agentConfig) {
2399
2747
  const base = `${promptsDir(cwd, sessionId)}/${agentId}-plugin`;
2400
- mkdirSync6(`${base}/.claude-plugin`, { recursive: true });
2401
- mkdirSync6(`${base}/agents`, { recursive: true });
2402
- mkdirSync6(`${base}/hooks`, { recursive: true });
2403
- writeFileSync8(
2748
+ mkdirSync7(`${base}/.claude-plugin`, { recursive: true });
2749
+ mkdirSync7(`${base}/agents`, { recursive: true });
2750
+ mkdirSync7(`${base}/hooks`, { recursive: true });
2751
+ mkdirSync7(`${base}/skills`, { recursive: true });
2752
+ writeFileSync9(
2404
2753
  `${base}/.claude-plugin/plugin.json`,
2405
2754
  JSON.stringify({ name: `sisyphus-agent-${agentId}`, version: "1.0.0" }),
2406
2755
  "utf-8"
@@ -2409,65 +2758,39 @@ function createAgentPlugin(cwd, sessionId, agentId, agentType, agentConfig) {
2409
2758
  const substituteEnvVars = (text) => substituteSisyphusVars(text, sessionId, agentId, sesDir);
2410
2759
  if (agentConfig?.filePath && agentType && agentType !== "worker") {
2411
2760
  const shortName = agentType.replace(/^sisyphus:/, "");
2412
- const subAgentDir = join11(dirname3(agentConfig.filePath), shortName);
2413
- if (existsSync10(subAgentDir)) {
2414
- for (const f of readdirSync7(subAgentDir)) {
2761
+ const subAgentDir = join12(dirname3(agentConfig.filePath), shortName);
2762
+ if (existsSync11(subAgentDir)) {
2763
+ for (const f of readdirSync8(subAgentDir)) {
2415
2764
  if (f.endsWith(".md") && f !== "CLAUDE.md") {
2416
- writeFileSync8(`${base}/agents/${f}`, substituteEnvVars(readFileSync10(join11(subAgentDir, f), "utf-8")), "utf-8");
2765
+ writeFileSync9(`${base}/agents/${f}`, substituteEnvVars(readFileSync11(join12(subAgentDir, f), "utf-8")), "utf-8");
2417
2766
  }
2418
2767
  }
2419
2768
  }
2420
2769
  }
2421
- const srcHooks = resolve4(import.meta.dirname, "../templates/agent-plugin/hooks");
2422
- for (const f of ["require-submit.sh", "intercept-send-message.sh", "register-bg-task.sh", "ask-background-guard.sh"]) {
2423
- copyFileSync3(`${srcHooks}/${f}`, `${base}/hooks/${f}`);
2424
- }
2425
- const hooksConfig = {
2426
- PreToolUse: [
2427
- { matcher: "SendMessage", hooks: [{ type: "command", command: "bash ${CLAUDE_PLUGIN_ROOT}/hooks/intercept-send-message.sh" }] },
2428
- { matcher: "Bash", hooks: [{ type: "command", command: "bash ${CLAUDE_PLUGIN_ROOT}/hooks/ask-background-guard.sh" }] }
2429
- ],
2430
- PostToolUse: [
2431
- { matcher: "Task", hooks: [{ type: "command", command: "bash ${CLAUDE_PLUGIN_ROOT}/hooks/register-bg-task.sh" }] }
2432
- ]
2433
- };
2434
- if (!agentConfig?.frontmatter.interactive) {
2435
- hooksConfig.Stop = [
2436
- { hooks: [{ type: "command", command: "bash ${CLAUDE_PLUGIN_ROOT}/hooks/require-submit.sh" }] }
2437
- ];
2438
- }
2770
+ const layers = agentPluginLayers(cwd);
2439
2771
  const normalizedType = agentType?.replace(/^sisyphus:/, "") ?? "";
2440
- const userPromptHooks = {
2441
- "problem": "problem-user-prompt.sh",
2442
- "plan": "plan-user-prompt.sh",
2443
- "spec": "spec-user-prompt.sh",
2444
- "review": "review-user-prompt.sh",
2445
- "review-plan": "review-plan-user-prompt.sh",
2446
- "debug": "debug-user-prompt.sh",
2447
- "operator": "operator-user-prompt.sh",
2448
- "test-spec": "test-spec-user-prompt.sh",
2449
- "explore": "explore-user-prompt.sh"
2772
+ const filterCtx = {
2773
+ agentType: normalizedType,
2774
+ interactive: agentConfig?.frontmatter.interactive === true
2450
2775
  };
2451
- const hookScript = userPromptHooks[normalizedType];
2452
- if (hookScript) {
2453
- hooksConfig.UserPromptSubmit = [
2454
- { hooks: [{ type: "command", command: `bash \${CLAUDE_PLUGIN_ROOT}/hooks/${hookScript}` }] }
2455
- ];
2456
- copyFileSync3(`${srcHooks}/${hookScript}`, `${base}/hooks/${hookScript}`);
2457
- }
2458
- if (normalizedType === "plan") {
2459
- hooksConfig.PreToolUse.push({
2460
- matcher: "Bash",
2461
- hooks: [{ type: "command", command: "bash ${CLAUDE_PLUGIN_ROOT}/hooks/plan-validate.sh" }]
2462
- });
2463
- copyFileSync3(`${srcHooks}/plan-validate.sh`, `${base}/hooks/plan-validate.sh`);
2464
- hooksConfig.PreToolUse.push({
2465
- matcher: "Write|Edit|MultiEdit",
2466
- hooks: [{ type: "command", command: "bash ${CLAUDE_PLUGIN_ROOT}/hooks/plan-write-path.sh" }]
2467
- });
2468
- copyFileSync3(`${srcHooks}/plan-write-path.sh`, `${base}/hooks/plan-write-path.sh`);
2776
+ const referenced = collectReferencedHookScripts(layers, filterCtx);
2777
+ const disabled = collectDisabledHookScripts(layers);
2778
+ const skipFiles = new Set(disabled);
2779
+ copyLayered(layers, {
2780
+ subdir: "hooks",
2781
+ destDir: `${base}/hooks`,
2782
+ filter: (name) => name !== "CLAUDE.md" && name !== "hooks.json" && (referenced.has(name) || !name.endsWith(".sh")),
2783
+ skipFiles
2784
+ });
2785
+ const mergedHooks = mergeHookManifests(layers, filterCtx);
2786
+ writeFileSync9(`${base}/hooks/hooks.json`, JSON.stringify({ hooks: mergedHooks }, null, 2), "utf-8");
2787
+ const requestedSkills = agentConfig?.frontmatter.skills ?? [];
2788
+ for (const skillName of requestedSkills) {
2789
+ const ok = copySkill(layers, skillName, `${base}/skills`);
2790
+ if (!ok) {
2791
+ console.warn(`[sisyphus] Agent ${agentId} (${normalizedType}) requested skill '${skillName}' but no layer provides it.`);
2792
+ }
2469
2793
  }
2470
- writeFileSync8(`${base}/hooks/hooks.json`, JSON.stringify({ hooks: hooksConfig }, null, 2), "utf-8");
2471
2794
  return base;
2472
2795
  }
2473
2796
  function setupAgentPane(opts) {
@@ -2480,9 +2803,9 @@ function setupAgentPane(opts) {
2480
2803
  const agentTitle = `ssph:${sessionLabel} ${paneLabel} c${cycleNum}`;
2481
2804
  setPaneTitle(paneId, agentTitle);
2482
2805
  setPaneStyle(paneId, color, { role: paneLabel, session: sessionLabel, cycle: `c${cycleNum}` });
2483
- const ctxDirRel = relative(paneCwd, contextDir(cwd, sessionId));
2806
+ const ctxDirRel = relative2(paneCwd, contextDir(cwd, sessionId));
2484
2807
  if (agentType === "plan") {
2485
- mkdirSync6(join11(contextDir(cwd, sessionId), agentId), { recursive: true });
2808
+ mkdirSync7(join12(contextDir(cwd, sessionId), agentId), { recursive: true });
2486
2809
  }
2487
2810
  const sesDir = sessionDir(cwd, sessionId);
2488
2811
  const substitute = (text) => substituteSisyphusVars(text, sessionId, agentId, sesDir);
@@ -2496,7 +2819,7 @@ function setupAgentPane(opts) {
2496
2819
  }
2497
2820
  systemParts.push(suffix);
2498
2821
  const suffixFilePath = `${promptsDir(cwd, sessionId)}/${agentId}-system.md`;
2499
- writeFileSync8(suffixFilePath, systemParts.join("\n\n"), "utf-8");
2822
+ writeFileSync9(suffixFilePath, systemParts.join("\n\n"), "utf-8");
2500
2823
  const bannerCmd = resolveBannerCmd();
2501
2824
  const npmBinDir = resolveNpmBinDir();
2502
2825
  const envExports = buildEnvExports([
@@ -2517,7 +2840,7 @@ function setupAgentPane(opts) {
2517
2840
  parts.push(`## Task
2518
2841
 
2519
2842
  ${instruction}`);
2520
- writeFileSync8(codexPromptPath, parts.join("\n\n"), "utf-8");
2843
+ writeFileSync9(codexPromptPath, parts.join("\n\n"), "utf-8");
2521
2844
  const model = agentConfig?.frontmatter.model ?? "codex-mini";
2522
2845
  mainCmd = `codex -m ${shellQuote(model)} --dangerously-bypass-approvals-and-sandbox "$(cat '${codexPromptPath}')"`;
2523
2846
  } else {
@@ -2536,7 +2859,7 @@ ${instruction}`);
2536
2859
  const sessionIdFlag = claudeSessionId ? ` --session-id "${claudeSessionId}"` : "";
2537
2860
  const promptFlag = agentConfig?.frontmatter.systemPrompt === "replace" ? "--system-prompt" : "--append-system-prompt";
2538
2861
  const siblingSettingsPath = agentConfig?.filePath ? agentConfig.filePath.replace(/\.md$/, ".settings.json") : null;
2539
- const settingsFlag = siblingSettingsPath && existsSync10(siblingSettingsPath) ? ` --settings "${siblingSettingsPath}"` : "";
2862
+ const settingsFlag = siblingSettingsPath && existsSync11(siblingSettingsPath) ? ` --settings "${siblingSettingsPath}"` : "";
2540
2863
  mainCmd = `claude${permFlag} --effort ${effort}${modelFlag} --plugin-dir "${pluginPath}"${sessionIdFlag}${extraPluginFlags ? ` ${extraPluginFlags}` : ""}${settingsFlag} --name ${shellQuote(agentTitle)} ${promptFlag} "$(cat '${suffixFilePath}')" ${shellQuote(instruction)}`;
2541
2864
  resumeArgs = `${permFlag.trimStart()} --effort ${effort}${modelFlag} --plugin-dir "${pluginPath}"${extraPluginFlags ? ` ${extraPluginFlags}` : ""}${settingsFlag}`;
2542
2865
  }
@@ -2555,7 +2878,7 @@ async function spawnAgent(opts) {
2555
2878
  const count = (agentCounters.get(sessionId) ?? 0) + 1;
2556
2879
  agentCounters.set(sessionId, count);
2557
2880
  const agentId = `agent-${String(count).padStart(3, "0")}`;
2558
- const bundledPluginPath = resolve4(import.meta.dirname, "../templates/agent-plugin");
2881
+ const bundledPluginPath = resolve5(import.meta.dirname, "../templates/agent-plugin");
2559
2882
  const agentConfig = resolveAgentConfig(agentType, bundledPluginPath, cwd);
2560
2883
  let provider = detectProvider(agentConfig?.frontmatter.model);
2561
2884
  const color = (agentConfig?.frontmatter.color ? normalizeTmuxColor(agentConfig.frontmatter.color) : null) ?? getNextColor(sessionId);
@@ -2579,7 +2902,7 @@ async function spawnAgent(opts) {
2579
2902
  }
2580
2903
  }
2581
2904
  const repo = opts.repo !== void 0 ? opts.repo : ".";
2582
- const repoRoot = repo === "." ? cwd : join11(cwd, repo);
2905
+ const repoRoot = repo === "." ? cwd : join12(cwd, repo);
2583
2906
  const paneCwd = repoRoot;
2584
2907
  const claudeSessionId = provider !== "openai" ? randomUUID3() : void 0;
2585
2908
  const { paneId, fullCmd, resumeEnv, resumeArgs } = setupAgentPane({
@@ -2640,12 +2963,12 @@ async function restartAgent(sessionId, cwd, agentId, windowId) {
2640
2963
  });
2641
2964
  }
2642
2965
  const { instruction, agentType, name, color } = agent;
2643
- const bundledPluginPath = resolve4(import.meta.dirname, "../templates/agent-plugin");
2966
+ const bundledPluginPath = resolve5(import.meta.dirname, "../templates/agent-plugin");
2644
2967
  const agentConfig = resolveAgentConfig(agentType, bundledPluginPath, cwd);
2645
2968
  const provider = detectProvider(agentConfig?.frontmatter.model);
2646
2969
  let paneCwd = cwd;
2647
2970
  if (agent.repo !== ".") {
2648
- paneCwd = join11(cwd, agent.repo);
2971
+ paneCwd = join12(cwd, agent.repo);
2649
2972
  }
2650
2973
  if (agent.paneId) {
2651
2974
  try {
@@ -2696,7 +3019,7 @@ async function restartAgent(sessionId, cwd, agentId, windowId) {
2696
3019
  function nextReportNumber(cwd, sessionId, agentId) {
2697
3020
  const dir = reportsDir(cwd, sessionId);
2698
3021
  try {
2699
- const files = readdirSync7(dir).filter((f) => f.startsWith(`${agentId}-`) && !f.endsWith("-final.md"));
3022
+ const files = readdirSync8(dir).filter((f) => f.startsWith(`${agentId}-`) && !f.endsWith("-final.md"));
2700
3023
  return String(files.length + 1).padStart(3, "0");
2701
3024
  } catch {
2702
3025
  return "001";
@@ -2704,10 +3027,10 @@ function nextReportNumber(cwd, sessionId, agentId) {
2704
3027
  }
2705
3028
  async function handleAgentReport(cwd, sessionId, agentId, content) {
2706
3029
  const dir = reportsDir(cwd, sessionId);
2707
- mkdirSync6(dir, { recursive: true });
3030
+ mkdirSync7(dir, { recursive: true });
2708
3031
  const num = nextReportNumber(cwd, sessionId, agentId);
2709
3032
  const filePath = reportFilePath(cwd, sessionId, agentId, num);
2710
- writeFileSync8(filePath, content, "utf-8");
3033
+ writeFileSync9(filePath, content, "utf-8");
2711
3034
  const entry = {
2712
3035
  type: "update",
2713
3036
  filePath,
@@ -2725,9 +3048,9 @@ async function handleAgentReport(cwd, sessionId, agentId, content) {
2725
3048
  }
2726
3049
  function gcBgTasks(cwd, sessionId, agentId) {
2727
3050
  const file = `${sessionDir(cwd, sessionId)}/runtime/bg-tasks/${agentId}.txt`;
2728
- if (!existsSync10(file)) return;
3051
+ if (!existsSync11(file)) return;
2729
3052
  try {
2730
- const leftover = readFileSync10(file, "utf-8").split("\n").map((s) => s.trim()).filter(Boolean);
3053
+ const leftover = readFileSync11(file, "utf-8").split("\n").map((s) => s.trim()).filter(Boolean);
2731
3054
  if (leftover.length > 0) {
2732
3055
  console.warn(`[bg-tasks] ${agentId} exited with ${leftover.length} untracked background task(s): ${leftover.join(", ")}`);
2733
3056
  emitHistoryEvent(sessionId, "bg-tasks-leftover", { agentId, leftover });
@@ -2739,9 +3062,9 @@ function gcBgTasks(cwd, sessionId, agentId) {
2739
3062
  }
2740
3063
  async function handleAgentSubmit(cwd, sessionId, agentId, report) {
2741
3064
  const dir = reportsDir(cwd, sessionId);
2742
- mkdirSync6(dir, { recursive: true });
3065
+ mkdirSync7(dir, { recursive: true });
2743
3066
  const filePath = reportFilePath(cwd, sessionId, agentId, "final");
2744
- writeFileSync8(filePath, report, "utf-8");
3067
+ writeFileSync9(filePath, report, "utf-8");
2745
3068
  const entry = {
2746
3069
  type: "final",
2747
3070
  filePath,
@@ -2811,7 +3134,7 @@ async function handleAwait(cwd, sessionId, agentId) {
2811
3134
  const POLL_MS = 250;
2812
3135
  let agent = initialAgent;
2813
3136
  while (agent.status === "running") {
2814
- await new Promise((resolve11) => setTimeout(resolve11, POLL_MS));
3137
+ await new Promise((resolve12) => setTimeout(resolve12, POLL_MS));
2815
3138
  const session = getSession(cwd, sessionId);
2816
3139
  const found = session.agents.find((a) => a.id === agentId);
2817
3140
  if (!found) return null;
@@ -2832,9 +3155,9 @@ var respawningSessions = /* @__PURE__ */ new Set();
2832
3155
 
2833
3156
  // src/daemon/companion.ts
2834
3157
  init_paths();
2835
- import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync12, renameSync as renameSync4, writeFileSync as writeFileSync10 } from "fs";
3158
+ import { existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync13, renameSync as renameSync4, writeFileSync as writeFileSync11 } from "fs";
2836
3159
  import { randomUUID as randomUUID5 } from "crypto";
2837
- import { dirname as dirname5, join as join13 } from "path";
3160
+ import { dirname as dirname5, join as join14 } from "path";
2838
3161
 
2839
3162
  // src/shared/companion-normalize.ts
2840
3163
  function emptyStats() {
@@ -2965,8 +3288,8 @@ var ACHIEVEMENTS = [
2965
3288
 
2966
3289
  // src/daemon/companion-memory.ts
2967
3290
  init_paths();
2968
- import { existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync11, renameSync as renameSync3, writeFileSync as writeFileSync9 } from "fs";
2969
- import { dirname as dirname4, join as join12 } from "path";
3291
+ import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync12, renameSync as renameSync3, writeFileSync as writeFileSync10 } from "fs";
3292
+ import { dirname as dirname4, join as join13 } from "path";
2970
3293
  import { randomUUID as randomUUID4 } from "crypto";
2971
3294
  import { z } from "zod";
2972
3295
  var MAX_OBSERVATIONS = 200;
@@ -3003,10 +3326,10 @@ function fillDefaults(state) {
3003
3326
  }
3004
3327
  function loadMemoryStrict() {
3005
3328
  const path = resolvedMemoryPath();
3006
- if (!existsSync11(path)) return defaultMemoryState();
3329
+ if (!existsSync12(path)) return defaultMemoryState();
3007
3330
  let raw;
3008
3331
  try {
3009
- raw = readFileSync11(path, "utf-8");
3332
+ raw = readFileSync12(path, "utf-8");
3010
3333
  } catch (err) {
3011
3334
  throw new MemoryStoreParseError(err);
3012
3335
  }
@@ -3039,9 +3362,9 @@ function loadMemory() {
3039
3362
  function saveMemory(store) {
3040
3363
  const path = resolvedMemoryPath();
3041
3364
  const dir = dirname4(path);
3042
- mkdirSync7(dir, { recursive: true });
3043
- const tmp = join12(dir, `.companion-memory.${randomUUID4()}.tmp`);
3044
- writeFileSync9(tmp, JSON.stringify(store, null, 2), "utf-8");
3365
+ mkdirSync8(dir, { recursive: true });
3366
+ const tmp = join13(dir, `.companion-memory.${randomUUID4()}.tmp`);
3367
+ writeFileSync10(tmp, JSON.stringify(store, null, 2), "utf-8");
3045
3368
  renameSync3(tmp, path);
3046
3369
  }
3047
3370
  function appendObservations(records, detectorUpdates) {
@@ -3468,21 +3791,21 @@ function zScore(value, stats, metric) {
3468
3791
  }
3469
3792
  function loadCompanion() {
3470
3793
  const path = companionPath();
3471
- if (!existsSync12(path)) {
3794
+ if (!existsSync13(path)) {
3472
3795
  const state2 = createDefaultCompanion();
3473
3796
  saveCompanion(state2);
3474
3797
  return state2;
3475
3798
  }
3476
- const raw = readFileSync12(path, "utf-8");
3799
+ const raw = readFileSync13(path, "utf-8");
3477
3800
  const state = JSON.parse(raw);
3478
3801
  return normalizeCompanion(state);
3479
3802
  }
3480
3803
  function saveCompanion(state) {
3481
3804
  const path = companionPath();
3482
3805
  const dir = dirname5(path);
3483
- mkdirSync8(dir, { recursive: true });
3484
- const tmp = join13(dir, `.companion.${randomUUID5()}.tmp`);
3485
- writeFileSync10(tmp, JSON.stringify(state, null, 2), "utf-8");
3806
+ mkdirSync9(dir, { recursive: true });
3807
+ const tmp = join14(dir, `.companion.${randomUUID5()}.tmp`);
3808
+ writeFileSync11(tmp, JSON.stringify(state, null, 2), "utf-8");
3486
3809
  renameSync4(tmp, path);
3487
3810
  }
3488
3811
  var MAX_COMMENTARY_HISTORY = 1e3;
@@ -4069,7 +4392,7 @@ async function runPostSessionObservations(companion, session, prev) {
4069
4392
  }
4070
4393
 
4071
4394
  // src/daemon/companion-commentary.ts
4072
- import { basename as basename3 } from "path";
4395
+ import { basename as basename4 } from "path";
4073
4396
  import { z as z2 } from "zod";
4074
4397
  var COMMENTARY_JSON_SCHEMA = {
4075
4398
  type: "object",
@@ -4880,9 +5203,9 @@ Generate a single agent nickname. One word only. No quotes, no explanation.`;
4880
5203
  }
4881
5204
 
4882
5205
  // src/daemon/companion-popup.ts
4883
- import { writeFileSync as writeFileSync11, readFileSync as readFileSync13, unlinkSync as unlinkSync2, existsSync as existsSync13 } from "fs";
5206
+ import { writeFileSync as writeFileSync12, readFileSync as readFileSync14, unlinkSync as unlinkSync2, existsSync as existsSync14 } from "fs";
4884
5207
  import { tmpdir } from "os";
4885
- import { join as join14, resolve as resolve5 } from "path";
5208
+ import { join as join15, resolve as resolve6 } from "path";
4886
5209
 
4887
5210
  // src/shared/companion-render.ts
4888
5211
  import stringWidth from "string-width";
@@ -5178,10 +5501,10 @@ function applyColor(result, fields, facePart, mood, opts) {
5178
5501
  var POPUP_WIDTH = 38;
5179
5502
  var INNER_WIDTH = POPUP_WIDTH - 6;
5180
5503
  var POPUP_DURATION = 15;
5181
- var POPUP_TMP_PREFIX = join14(tmpdir(), "sisyphus-popup");
5182
- var POPUP_SCRIPT = join14(tmpdir(), "sisyphus-popup.sh");
5183
- var POPUP_RESULT_PREFIX = join14(tmpdir(), "sisyphus-popup-result");
5184
- var WHIP_ANIMATION_PATH = resolve5(import.meta.dirname, "../templates/whip-animation.sh");
5504
+ var POPUP_TMP_PREFIX = join15(tmpdir(), "sisyphus-popup");
5505
+ var POPUP_SCRIPT = join15(tmpdir(), "sisyphus-popup.sh");
5506
+ var POPUP_RESULT_PREFIX = join15(tmpdir(), "sisyphus-popup-result");
5507
+ var WHIP_ANIMATION_PATH = resolve6(import.meta.dirname, "../templates/whip-animation.sh");
5185
5508
  var WHIP_ANIMATION_ROWS = 12;
5186
5509
  function wrapText(text, width) {
5187
5510
  const words = text.split(" ");
@@ -5222,9 +5545,9 @@ function showCommentaryPopupQueue(pages) {
5222
5545
  const contentLineCount = content.split("\n").length - 1;
5223
5546
  const contentHeight = Math.max(contentLineCount + 2, 5);
5224
5547
  if (contentHeight > maxContentHeight) maxContentHeight = contentHeight;
5225
- writeFileSync11(`${POPUP_TMP_PREFIX}-${i}.txt`, content);
5548
+ writeFileSync12(`${POPUP_TMP_PREFIX}-${i}.txt`, content);
5226
5549
  }
5227
- const whipAvailable = existsSync13(WHIP_ANIMATION_PATH);
5550
+ const whipAvailable = existsSync14(WHIP_ANIMATION_PATH);
5228
5551
  if (whipAvailable && maxContentHeight < WHIP_ANIMATION_ROWS + 2) {
5229
5552
  maxContentHeight = WHIP_ANIMATION_ROWS + 2;
5230
5553
  }
@@ -5271,7 +5594,7 @@ if [ ! -f "$RESULT_FILE" ]; then
5271
5594
  printf 'neutral' > "$RESULT_FILE"
5272
5595
  fi
5273
5596
  `;
5274
- writeFileSync11(POPUP_SCRIPT, script, { mode: 493 });
5597
+ writeFileSync12(POPUP_SCRIPT, script, { mode: 493 });
5275
5598
  try {
5276
5599
  unlinkSync2(POPUP_RESULT_PREFIX);
5277
5600
  } catch {
@@ -5298,7 +5621,7 @@ fi
5298
5621
  }
5299
5622
  let raw;
5300
5623
  try {
5301
- raw = readFileSync13(POPUP_RESULT_PREFIX, "utf8").trim();
5624
+ raw = readFileSync14(POPUP_RESULT_PREFIX, "utf8").trim();
5302
5625
  } catch {
5303
5626
  return null;
5304
5627
  } finally {
@@ -5734,7 +6057,7 @@ async function pollSession(sessionId, cwd, windowId, increment, sessionCache) {
5734
6057
  }
5735
6058
 
5736
6059
  // src/daemon/mode-notify.ts
5737
- import { existsSync as existsSync14 } from "fs";
6060
+ import { existsSync as existsSync15 } from "fs";
5738
6061
  import { ulid as ulid2 } from "ulid";
5739
6062
  init_paths();
5740
6063
  function capitalize(s) {
@@ -5757,7 +6080,7 @@ function findOpenModeTransitionAsk(cwd, sessionId) {
5757
6080
  if (meta.modeTransition !== true) continue;
5758
6081
  if (meta.status === "answered") continue;
5759
6082
  if (meta.orphaned === true) continue;
5760
- if (existsSync14(askOutputPath(cwd, sessionId, askId))) continue;
6083
+ if (existsSync15(askOutputPath(cwd, sessionId, askId))) continue;
5761
6084
  return askId;
5762
6085
  }
5763
6086
  return null;
@@ -5776,9 +6099,9 @@ function buildNextChain(prevChain, prevMode, nextMode, prevModeStats) {
5776
6099
  }
5777
6100
  return [{ mode: "unknown" }, { mode: nextMode }];
5778
6101
  }
5779
- function renderBody(chain) {
6102
+ function renderBody(chain, cwd) {
5780
6103
  const current = chain[chain.length - 1];
5781
- const description = discoverOrchestratorModes().find((m) => m.name === current.mode)?.description?.trim();
6104
+ const description = discoverOrchestratorModes(cwd).find((m) => m.name === current.mode)?.description?.trim();
5782
6105
  const lines = [];
5783
6106
  if (description) {
5784
6107
  lines.push(`**${capitalize(current.mode)}** \u2014 ${description}`);
@@ -5812,7 +6135,7 @@ async function emitModeTransitionNotify(cwd, sessionId, prevMode, nextMode, prev
5812
6135
  const subtitle = chain.map((e) => e.mode).join(" \u2192 ");
5813
6136
  const title = "Mode change";
5814
6137
  const deckTitle = `Mode: ${subtitle}`;
5815
- const body = renderBody(chain);
6138
+ const body = renderBody(chain, cwd);
5816
6139
  const interaction = {
5817
6140
  id: "mode-transition",
5818
6141
  title,
@@ -5864,19 +6187,19 @@ async function emitModeTransitionNotify(cwd, sessionId, prevMode, nextMode, prev
5864
6187
  function detectRepos(cwd) {
5865
6188
  const config = loadConfig(cwd);
5866
6189
  const repos = [];
5867
- if (existsSync15(join15(cwd, ".git"))) {
6190
+ if (existsSync16(join16(cwd, ".git"))) {
5868
6191
  try {
5869
6192
  repos.push(getRepoInfo(cwd, "."));
5870
6193
  } catch {
5871
6194
  }
5872
6195
  }
5873
6196
  try {
5874
- const entries = readdirSync9(cwd, { withFileTypes: true });
6197
+ const entries = readdirSync10(cwd, { withFileTypes: true });
5875
6198
  for (const entry of entries) {
5876
6199
  if (!entry.isDirectory()) continue;
5877
6200
  if (entry.name.startsWith(".")) continue;
5878
- const childPath = join15(cwd, entry.name);
5879
- if (existsSync15(join15(childPath, ".git"))) {
6201
+ const childPath = join16(cwd, entry.name);
6202
+ if (existsSync16(join16(childPath, ".git"))) {
5880
6203
  try {
5881
6204
  repos.push(getRepoInfo(childPath, entry.name));
5882
6205
  } catch {
@@ -5912,19 +6235,44 @@ function getOrchestratorPaneId(sessionId) {
5912
6235
  function setOrchestratorPaneId(sessionId, paneId) {
5913
6236
  sessionOrchestratorPane.set(sessionId, paneId);
5914
6237
  }
6238
+ function resolveOrchestratorSettings(cwd, sessionId) {
6239
+ const bundled = resolve7(import.meta.dirname, "../templates/orchestrator-settings.json");
6240
+ const projectSettings = projectOrchestratorSettingsPath(cwd);
6241
+ const userSettings = userOrchestratorSettingsPath();
6242
+ const hasProject = existsSync16(projectSettings);
6243
+ const hasUser = existsSync16(userSettings);
6244
+ if (!hasProject && !hasUser) return bundled;
6245
+ let merged = {};
6246
+ for (const path of [bundled, hasUser ? userSettings : null, hasProject ? projectSettings : null]) {
6247
+ if (!path || !existsSync16(path)) continue;
6248
+ try {
6249
+ const parsed = JSON.parse(readFileSync15(path, "utf-8"));
6250
+ merged = { ...merged, ...parsed };
6251
+ } catch (err) {
6252
+ console.warn(`[sisyphus] Failed to parse settings layer ${path}: ${err instanceof Error ? err.message : err}`);
6253
+ }
6254
+ }
6255
+ const out = join16(promptsDir(cwd, sessionId), "orchestrator-settings.merged.json");
6256
+ writeFileSync13(out, JSON.stringify(merged, null, 2), "utf-8");
6257
+ return out;
6258
+ }
5915
6259
  function loadOrchestratorPrompt(cwd, sessionId, mode) {
5916
6260
  const projectPath = projectOrchestratorPromptPath(cwd);
5917
- if (existsSync15(projectPath)) {
5918
- return readFileSync14(projectPath, "utf-8");
6261
+ if (existsSync16(projectPath)) {
6262
+ return readFileSync15(projectPath, "utf-8");
5919
6263
  }
5920
- const basePath = resolve6(import.meta.dirname, "../templates/orchestrator-base.md");
5921
- const base = readFileSync14(basePath, "utf-8");
5922
- const modes = discoverOrchestratorModes();
6264
+ const userPath = userOrchestratorPromptPath();
6265
+ if (existsSync16(userPath)) {
6266
+ return readFileSync15(userPath, "utf-8");
6267
+ }
6268
+ const basePath = resolve7(import.meta.dirname, "../templates/orchestrator-base.md");
6269
+ const base = readFileSync15(basePath, "utf-8");
6270
+ const modes = discoverOrchestratorModes(cwd);
5923
6271
  const selected = modes.find((m) => m.name === mode) ?? modes.find((m) => m.name === "discovery");
5924
6272
  if (!selected) {
5925
6273
  throw new Error(`Unknown orchestrator mode '${mode}' and no fallback found. Available: ${modes.map((m) => m.name).join(", ")}`);
5926
6274
  }
5927
- const modeContent = readFileSync14(selected.filePath, "utf-8");
6275
+ const modeContent = readFileSync15(selected.filePath, "utf-8");
5928
6276
  const modeBody = extractAgentBody(modeContent);
5929
6277
  return base + "\n\n" + modeBody;
5930
6278
  }
@@ -5945,8 +6293,8 @@ function buildCompletionContent(session) {
5945
6293
  lines.push("");
5946
6294
  }
5947
6295
  const logsDirPath = logsDir(session.cwd, session.id);
5948
- if (existsSync15(logsDirPath)) {
5949
- const logFiles = readdirSync9(logsDirPath).filter((f) => f.startsWith("cycle-") && f.endsWith(".md")).sort();
6296
+ if (existsSync16(logsDirPath)) {
6297
+ const logFiles = readdirSync10(logsDirPath).filter((f) => f.startsWith("cycle-") && f.endsWith(".md")).sort();
5950
6298
  if (logFiles.length > 0) {
5951
6299
  lines.push("### Cycle Logs\n");
5952
6300
  const cycleByNum = new Map(session.orchestratorCycles.map((c) => [c.cycle, c]));
@@ -5970,7 +6318,7 @@ function buildCompletionContent(session) {
5970
6318
  while (j < entries.length && entries[j].idle && entries[j].mode === e.mode) j++;
5971
6319
  const runEntries = entries.slice(i, j);
5972
6320
  if (runEntries.length === 1) {
5973
- const content = readFileSync14(join15(logsDirPath, e.file), "utf-8").trim();
6321
+ const content = readFileSync15(join16(logsDirPath, e.file), "utf-8").trim();
5974
6322
  if (content) {
5975
6323
  lines.push(content);
5976
6324
  lines.push("");
@@ -5986,7 +6334,7 @@ function buildCompletionContent(session) {
5986
6334
  }
5987
6335
  i = j;
5988
6336
  } else {
5989
- const content = readFileSync14(join15(logsDirPath, e.file), "utf-8").trim();
6337
+ const content = readFileSync15(join16(logsDirPath, e.file), "utf-8").trim();
5990
6338
  if (content) {
5991
6339
  lines.push(content);
5992
6340
  lines.push("");
@@ -5997,11 +6345,11 @@ function buildCompletionContent(session) {
5997
6345
  }
5998
6346
  }
5999
6347
  const reportsDirPath = reportsDir(session.cwd, session.id);
6000
- if (existsSync15(reportsDirPath)) {
6001
- const reportFiles = readdirSync9(reportsDirPath).filter((f) => f.endsWith(".md"));
6348
+ if (existsSync16(reportsDirPath)) {
6349
+ const reportFiles = readdirSync10(reportsDirPath).filter((f) => f.endsWith(".md"));
6002
6350
  if (reportFiles.length > 0) {
6003
6351
  lines.push("### Detailed Reports\n");
6004
- lines.push(`Full agent reports: @${relative2(session.cwd, reportsDirPath)}
6352
+ lines.push(`Full agent reports: @${relative3(session.cwd, reportsDirPath)}
6005
6353
  `);
6006
6354
  }
6007
6355
  }
@@ -6023,21 +6371,21 @@ ${session.context}
6023
6371
  }
6024
6372
  } else {
6025
6373
  let ctxFiles = [];
6026
- if (existsSync15(ctxDir)) {
6027
- ctxFiles = readdirSync9(ctxDir).filter((f) => f !== "CLAUDE.md");
6374
+ if (existsSync16(ctxDir)) {
6375
+ ctxFiles = readdirSync10(ctxDir).filter((f) => f !== "CLAUDE.md");
6028
6376
  }
6029
6377
  if (ctxFiles.length > 0) {
6030
6378
  contextSection = `
6031
6379
  ## Context
6032
6380
 
6033
- @${relative2(session.cwd, ctxDir)}
6381
+ @${relative3(session.cwd, ctxDir)}
6034
6382
  `;
6035
6383
  }
6036
6384
  }
6037
6385
  const messages = session.messages ?? [];
6038
6386
  const messagesSection = messages.length > 0 ? "\n### Messages\n\n" + messages.map((m) => {
6039
6387
  const sourceLabel = m.source.type === "agent" ? `agent:${m.source.agentId}` : m.source.type === "system" && m.source.detail ? `system:${m.source.detail}` : m.source.type;
6040
- const fileRef = m.filePath ? ` \u2192 ${relative2(session.cwd, m.filePath)}` : "";
6388
+ const fileRef = m.filePath ? ` \u2192 ${relative3(session.cwd, m.filePath)}` : "";
6041
6389
  return `- [${sourceLabel} @ ${m.timestamp}] "${m.summary}"${fileRef}`;
6042
6390
  }).join("\n") + "\n" : "";
6043
6391
  let mostRecentCycleSection = "";
@@ -6054,7 +6402,7 @@ ${session.context}
6054
6402
  if (!agent) return `- **${id}**: unknown (no agent data)`;
6055
6403
  const finalReport = agent.reports.find((r) => r.type === "final");
6056
6404
  const reportToUse = finalReport ?? agent.reports[agent.reports.length - 1];
6057
- const reportRef = reportToUse ? `@${relative2(session.cwd, reportToUse.filePath)}` : "(no reports)";
6405
+ const reportRef = reportToUse ? `@${relative3(session.cwd, reportToUse.filePath)}` : "(no reports)";
6058
6406
  return `- **${id}** (${agent.name}) [${agent.status}]: ${reportRef}`;
6059
6407
  }).join("\n");
6060
6408
  mostRecentCycleSection = `
@@ -6065,10 +6413,10 @@ ${agentLines}
6065
6413
  }
6066
6414
  }
6067
6415
  const strategyFile = strategyPath(session.cwd, session.id);
6068
- const strategyRef = existsSync15(strategyFile) ? `@${relative2(session.cwd, strategyFile)}` : "(empty)";
6069
- const roadmapRef = existsSync15(roadmapFile) ? `@${relative2(session.cwd, roadmapFile)}` : "(empty)";
6416
+ const strategyRef = existsSync16(strategyFile) ? `@${relative3(session.cwd, strategyFile)}` : "(empty)";
6417
+ const roadmapRef = existsSync16(roadmapFile) ? `@${relative3(session.cwd, roadmapFile)}` : "(empty)";
6070
6418
  const digestFile = digestPath(session.cwd, session.id);
6071
- const digestRef = existsSync15(digestFile) ? `@${relative2(session.cwd, digestFile)}` : "(not yet created)";
6419
+ const digestRef = existsSync16(digestFile) ? `@${relative3(session.cwd, digestFile)}` : "(not yet created)";
6072
6420
  const repos = detectRepos(session.cwd);
6073
6421
  let repositoriesSection = "\n\n## Repositories\n";
6074
6422
  if (repos.length === 0) {
@@ -6095,7 +6443,7 @@ ${agentLines}
6095
6443
  }
6096
6444
  }
6097
6445
  const goalFile = goalPath(session.cwd, session.id);
6098
- const goalContent = existsSync15(goalFile) ? readFileSync14(goalFile, "utf-8").trim() : session.task;
6446
+ const goalContent = existsSync16(goalFile) ? readFileSync15(goalFile, "utf-8").trim() : session.task;
6099
6447
  const modeContent = modeContentBuilders[mode]?.(session) ?? "";
6100
6448
  return `## Goal
6101
6449
 
@@ -6103,7 +6451,7 @@ ${goalContent}
6103
6451
  ${contextSection}${messagesSection}
6104
6452
  ### Cycle Log
6105
6453
 
6106
- Write your cycle summary to: ${relative2(session.cwd, logFile)}
6454
+ Write your cycle summary to: ${relative3(session.cwd, logFile)}
6107
6455
  ${mostRecentCycleSection}${modeContent}
6108
6456
  ## Strategy
6109
6457
 
@@ -6129,7 +6477,7 @@ async function spawnOrchestrator(sessionId, cwd, windowId, message, forceMode) {
6129
6477
  const mode = forceMode ?? (lastCycle?.mode ?? "discovery");
6130
6478
  const basePrompt = loadOrchestratorPrompt(cwd, sessionId, mode);
6131
6479
  const formattedState = formatStateForOrchestrator(session, mode);
6132
- const agentPluginPath = resolve6(import.meta.dirname, "../templates/agent-plugin");
6480
+ const agentPluginPath = resolve7(import.meta.dirname, "../templates/agent-plugin");
6133
6481
  const agentTypes = discoverAgentTypes(agentPluginPath, session.cwd).filter((t2) => t2.source === "bundled");
6134
6482
  const agentTypeLines = agentTypes.length > 0 ? agentTypes.map((t2) => {
6135
6483
  const modelTag = t2.model ? ` (${t2.model})` : "";
@@ -6138,7 +6486,7 @@ async function spawnOrchestrator(sessionId, cwd, windowId, message, forceMode) {
6138
6486
  }).join("\n") : " (none)";
6139
6487
  const sesDir = sessionDir(cwd, sessionId);
6140
6488
  const substituteEnvVars = (text) => text.replace(/\$SISYPHUS_SESSION_DIR/g, sesDir).replace(/\$SISYPHUS_SESSION_ID/g, sessionId);
6141
- const modes = discoverOrchestratorModes();
6489
+ const modes = discoverOrchestratorModes(cwd);
6142
6490
  const modeLines = modes.map((m) => {
6143
6491
  const desc = m.description ? ` \u2014 ${m.description}` : "";
6144
6492
  return `- \`${m.name}\`${desc}`;
@@ -6150,7 +6498,7 @@ async function spawnOrchestrator(sessionId, cwd, windowId, message, forceMode) {
6150
6498
  const systemPrompt = renderEffortMarkers(substitutedPrompt, sessionEffort);
6151
6499
  const cycleNum = session.orchestratorCycles.length + 1;
6152
6500
  const promptFilePath = `${promptsDir(cwd, sessionId)}/orchestrator-system-${cycleNum}.md`;
6153
- writeFileSync12(promptFilePath, systemPrompt, "utf-8");
6501
+ writeFileSync13(promptFilePath, systemPrompt, "utf-8");
6154
6502
  sessionWindowMap.set(sessionId, windowId);
6155
6503
  const npmBinDir = resolveNpmBinDir();
6156
6504
  const envExports = buildEnvExports([
@@ -6187,14 +6535,19 @@ ${continuationText}`;
6187
6535
  The previous cycle waited ~${hours}h for a \`sis ask\` answer. Repository state and any in-flight context may have drifted during that window. Briefly verify before acting on the answer.`;
6188
6536
  }
6189
6537
  const userPromptFilePath = `${promptsDir(cwd, sessionId)}/orchestrator-user-${cycleNum}.md`;
6190
- writeFileSync12(userPromptFilePath, substituteEnvVars(userPrompt), "utf-8");
6538
+ writeFileSync13(userPromptFilePath, substituteEnvVars(userPrompt), "utf-8");
6191
6539
  if (session.messages && session.messages.length > 0) {
6192
6540
  await drainMessages(cwd, sessionId, session.messages.length);
6193
6541
  }
6194
- const pluginSrcPath = resolve6(import.meta.dirname, "../templates/orchestrator-plugin");
6195
- const pluginPath = join15(sesDir, ".orchestrator-plugin");
6196
- renderPluginDir(pluginSrcPath, pluginPath, sessionEffort);
6197
- const settingsPath = resolve6(import.meta.dirname, "../templates/orchestrator-settings.json");
6542
+ const pluginPath = join16(sesDir, ".orchestrator-plugin");
6543
+ const orchLayers = orchestratorPluginLayers(cwd);
6544
+ if (orchLayers.length === 0) {
6545
+ const pluginSrcPath = resolve7(import.meta.dirname, "../templates/orchestrator-plugin");
6546
+ renderPluginDir(pluginSrcPath, pluginPath, sessionEffort);
6547
+ } else {
6548
+ renderLayeredPluginDir(orchLayers, pluginPath, sessionEffort);
6549
+ }
6550
+ const settingsPath = resolveOrchestratorSettings(cwd, sessionId);
6198
6551
  const config = loadConfig(cwd);
6199
6552
  const effort = config.orchestratorEffort ?? "xhigh";
6200
6553
  const model = config.model;
@@ -6307,7 +6660,7 @@ function cleanupSessionMaps(sessionId) {
6307
6660
  init_paths();
6308
6661
 
6309
6662
  // src/daemon/status-dots.ts
6310
- import { readFileSync as readFileSync15 } from "fs";
6663
+ import { readFileSync as readFileSync16 } from "fs";
6311
6664
  var CLAUDE_STATE_DIR = "/tmp/claude-tmux-state";
6312
6665
  var DOT_MAP = {
6313
6666
  "orchestrator:processing": { icon: "\u25CF", color: "#d4ad6a" },
@@ -6333,7 +6686,7 @@ function renderDots(dots) {
6333
6686
  function readClaudeState(paneId) {
6334
6687
  const numericId = paneId.replace("%", "");
6335
6688
  try {
6336
- const content = readFileSync15(`${CLAUDE_STATE_DIR}/${numericId}`, "utf-8").trim();
6689
+ const content = readFileSync16(`${CLAUDE_STATE_DIR}/${numericId}`, "utf-8").trim();
6337
6690
  if (content === "idle" || content === "processing" || content === "stopped") {
6338
6691
  return content;
6339
6692
  }
@@ -6491,21 +6844,21 @@ function buildManifest(args) {
6491
6844
  init_paths();
6492
6845
  import { execFile as execFile2 } from "child_process";
6493
6846
  import { promisify } from "util";
6494
- import { existsSync as existsSync16, readFileSync as readFileSync16, mkdirSync as mkdirSync9, symlinkSync, rmSync as rmSync4, writeFileSync as writeFileSync13 } from "fs";
6495
- import { homedir as homedir5 } from "os";
6496
- import { join as join16 } from "path";
6847
+ import { existsSync as existsSync17, readFileSync as readFileSync17, mkdirSync as mkdirSync10, symlinkSync, rmSync as rmSync5, writeFileSync as writeFileSync14 } from "fs";
6848
+ import { homedir as homedir6 } from "os";
6849
+ import { join as join17 } from "path";
6497
6850
  function sanitizeName(name) {
6498
6851
  return name.replace(/[^a-zA-Z0-9-_]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
6499
6852
  }
6500
6853
  function buildOutputPath(label, dir) {
6501
6854
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
6502
- mkdirSync9(dir, { recursive: true });
6855
+ mkdirSync10(dir, { recursive: true });
6503
6856
  const base = `sisyphus-${label}-${date}`;
6504
- let candidate = join16(dir, `${base}.zip`);
6857
+ let candidate = join17(dir, `${base}.zip`);
6505
6858
  let counter = 1;
6506
- while (existsSync16(candidate)) {
6859
+ while (existsSync17(candidate)) {
6507
6860
  counter++;
6508
- candidate = join16(dir, `${base}-${counter}.zip`);
6861
+ candidate = join17(dir, `${base}-${counter}.zip`);
6509
6862
  }
6510
6863
  return candidate;
6511
6864
  }
@@ -6567,38 +6920,38 @@ async function exportSessionToZip(sessionId, cwd, options) {
6567
6920
  const reveal = options?.reveal ?? true;
6568
6921
  const sessDir = sessionDir(cwd, sessionId);
6569
6922
  const histDir = historySessionDir(sessionId);
6570
- const sessExists = existsSync16(sessDir);
6571
- const histExists = existsSync16(histDir);
6923
+ const sessExists = existsSync17(sessDir);
6924
+ const histExists = existsSync17(histDir);
6572
6925
  if (!sessExists && !histExists) {
6573
6926
  throw new Error(`No data found for session ${sessionId}`);
6574
6927
  }
6575
6928
  let label = sessionId.slice(0, 8);
6576
6929
  const stPath = statePath(cwd, sessionId);
6577
- if (existsSync16(stPath)) {
6930
+ if (existsSync17(stPath)) {
6578
6931
  try {
6579
- const state = JSON.parse(readFileSync16(stPath, "utf-8"));
6932
+ const state = JSON.parse(readFileSync17(stPath, "utf-8"));
6580
6933
  if (state.name) {
6581
6934
  label = sanitizeName(state.name);
6582
6935
  }
6583
6936
  } catch {
6584
6937
  }
6585
6938
  }
6586
- const dir = options?.outputDir ?? join16(homedir5(), "Downloads");
6939
+ const dir = options?.outputDir ?? join17(homedir6(), "Downloads");
6587
6940
  const outputPath = buildOutputPath(label, dir);
6588
6941
  const tmpDir = `/tmp/sisyphus-export-${sessionId.slice(0, 8)}-${Date.now()}`;
6589
6942
  try {
6590
- mkdirSync9(tmpDir, { recursive: true });
6591
- writeFileSync13(join16(tmpDir, "CLAUDE.md"), generateGuide(), "utf-8");
6943
+ mkdirSync10(tmpDir, { recursive: true });
6944
+ writeFileSync14(join17(tmpDir, "CLAUDE.md"), generateGuide(), "utf-8");
6592
6945
  if (sessExists) {
6593
- symlinkSync(sessDir, join16(tmpDir, "session"));
6946
+ symlinkSync(sessDir, join17(tmpDir, "session"));
6594
6947
  }
6595
6948
  if (histExists) {
6596
- symlinkSync(histDir, join16(tmpDir, "history"));
6949
+ symlinkSync(histDir, join17(tmpDir, "history"));
6597
6950
  }
6598
6951
  const parts = ["CLAUDE.md", sessExists ? "session/" : "", histExists ? "history/" : ""].filter(Boolean);
6599
6952
  await execFileAsync("zip", ["-rq", outputPath, ...parts], { cwd: tmpDir });
6600
6953
  } finally {
6601
- rmSync4(tmpDir, { recursive: true, force: true });
6954
+ rmSync5(tmpDir, { recursive: true, force: true });
6602
6955
  }
6603
6956
  if (reveal) {
6604
6957
  try {
@@ -6672,12 +7025,12 @@ async function runSessionUploadAndPersist(args) {
6672
7025
  }
6673
7026
 
6674
7027
  // src/shared/version.ts
6675
- import { readFileSync as readFileSync17 } from "fs";
6676
- import { resolve as resolve7 } from "path";
7028
+ import { readFileSync as readFileSync18 } from "fs";
7029
+ import { resolve as resolve8 } from "path";
6677
7030
  function readSisyphusVersion() {
6678
7031
  for (const rel of ["../package.json", "../../package.json"]) {
6679
7032
  try {
6680
- const raw = readFileSync17(resolve7(import.meta.dirname, rel), "utf-8");
7033
+ const raw = readFileSync18(resolve8(import.meta.dirname, rel), "utf-8");
6681
7034
  const pkg = JSON.parse(raw);
6682
7035
  if (pkg.name === "sisyphi" && pkg.version) return pkg.version;
6683
7036
  } catch {
@@ -6718,7 +7071,7 @@ function truncate(s, max) {
6718
7071
  function readGoal(cwd, sessionId, fallback) {
6719
7072
  try {
6720
7073
  const p = goalPath(cwd, sessionId);
6721
- if (existsSync17(p)) return readFileSync18(p, "utf-8").trim();
7074
+ if (existsSync18(p)) return readFileSync19(p, "utf-8").trim();
6722
7075
  } catch {
6723
7076
  }
6724
7077
  return fallback;
@@ -6959,8 +7312,8 @@ var PRUNE_KEEP_DAYS2 = 7;
6959
7312
  function pruneOldSessions(cwd) {
6960
7313
  try {
6961
7314
  const dir = sessionsDir(cwd);
6962
- if (!existsSync17(dir)) return;
6963
- const entries = readdirSync10(dir, { withFileTypes: true });
7315
+ if (!existsSync18(dir)) return;
7316
+ const entries = readdirSync11(dir, { withFileTypes: true });
6964
7317
  const candidates = [];
6965
7318
  for (const entry of entries) {
6966
7319
  if (!entry.isDirectory()) continue;
@@ -6983,7 +7336,7 @@ function pruneOldSessions(cwd) {
6983
7336
  }
6984
7337
  for (const c of candidates) {
6985
7338
  if (keep.has(c.id)) continue;
6986
- rmSync5(sessionDir(cwd, c.id), { recursive: true, force: true });
7339
+ rmSync6(sessionDir(cwd, c.id), { recursive: true, force: true });
6987
7340
  }
6988
7341
  } catch (err) {
6989
7342
  console.error("[sisyphus] Session pruning failed:", err);
@@ -7097,8 +7450,8 @@ function getSessionStatus(cwd, sessionId) {
7097
7450
  }
7098
7451
  function listSessions(cwd) {
7099
7452
  const dir = sessionsDir(cwd);
7100
- if (!existsSync17(dir)) return [];
7101
- const entries = readdirSync10(dir, { withFileTypes: true });
7453
+ if (!existsSync18(dir)) return [];
7454
+ const entries = readdirSync11(dir, { withFileTypes: true });
7102
7455
  const sessions = [];
7103
7456
  for (const entry of entries) {
7104
7457
  if (!entry.isDirectory()) continue;
@@ -7165,8 +7518,8 @@ function onAllAgentsDone2(sessionId, cwd, windowId) {
7165
7518
  Agents: ${truncate(spawnedThisCycle, 200)}`;
7166
7519
  try {
7167
7520
  const logPath = cycleLogPath(cwd, sessionId, cycleNumber);
7168
- if (existsSync17(logPath)) {
7169
- const log = readFileSync18(logPath, "utf-8").trim();
7521
+ if (existsSync18(logPath)) {
7522
+ const log = readFileSync19(logPath, "utf-8").trim();
7170
7523
  if (log) cycleCtx += `
7171
7524
  Cycle log: ${truncate(log, 200)}`;
7172
7525
  }
@@ -7633,7 +7986,7 @@ import { spawn as spawn2 } from "child_process";
7633
7986
  import {
7634
7987
  closeSync as closeSync2,
7635
7988
  constants,
7636
- existsSync as existsSync18,
7989
+ existsSync as existsSync19,
7637
7990
  fstatSync as fstatSync2,
7638
7991
  lstatSync,
7639
7992
  openSync as openSync2,
@@ -7641,15 +7994,15 @@ import {
7641
7994
  writeSync
7642
7995
  } from "fs";
7643
7996
  import * as fs from "fs";
7644
- import { resolve as resolve8, dirname as dirname6, isAbsolute, sep } from "path";
7997
+ import { resolve as resolve9, dirname as dirname6, isAbsolute, sep } from "path";
7645
7998
  import { fileURLToPath } from "url";
7646
7999
  import { z as z3 } from "zod";
7647
8000
  import { tool } from "@r-cli/sdk";
7648
8001
 
7649
8002
  // src/daemon/transcript-digest.ts
7650
8003
  import { openSync, fstatSync, readSync, closeSync } from "fs";
7651
- import { homedir as homedir6 } from "os";
7652
- import { join as join17 } from "path";
8004
+ import { homedir as homedir7 } from "os";
8005
+ import { join as join18 } from "path";
7653
8006
  var BYTE_CAP = 8 * 1024;
7654
8007
  var TAIL_BYTES = 64 * 1024;
7655
8008
  var TOOL_USE_INPUT_CAP = 200;
@@ -7662,8 +8015,8 @@ function digestTranscript(opts) {
7662
8015
  warnOnce("transcript-digest: no claudeSessionId; falling back to empty context");
7663
8016
  return "";
7664
8017
  }
7665
- const home = opts.homeDir ?? homedir6();
7666
- const path = join17(home, ".claude", "projects", encodeCwd(opts.cwd), `${opts.claudeSessionId}.jsonl`);
8018
+ const home = opts.homeDir ?? homedir7();
8019
+ const path = join18(home, ".claude", "projects", encodeCwd(opts.cwd), `${opts.claudeSessionId}.jsonl`);
7667
8020
  let raw;
7668
8021
  let fd;
7669
8022
  try {
@@ -7746,11 +8099,11 @@ init_paths();
7746
8099
  var READ_FILE_CAP = 50 * 1024;
7747
8100
  var ANSI_CAP = 256 * 1024;
7748
8101
  var SYSTEM_PROMPT_CANDIDATES = [
7749
- resolve8(dirname6(fileURLToPath(import.meta.url)), "templates/termrender-haiku-system.md"),
8102
+ resolve9(dirname6(fileURLToPath(import.meta.url)), "templates/termrender-haiku-system.md"),
7750
8103
  // dist/templates/
7751
- resolve8(dirname6(fileURLToPath(import.meta.url)), "../templates/termrender-haiku-system.md"),
8104
+ resolve9(dirname6(fileURLToPath(import.meta.url)), "../templates/termrender-haiku-system.md"),
7752
8105
  // <sisyphus>/templates/ from dist/
7753
- resolve8(dirname6(fileURLToPath(import.meta.url)), "../../templates/termrender-haiku-system.md")
8106
+ resolve9(dirname6(fileURLToPath(import.meta.url)), "../../templates/termrender-haiku-system.md")
7754
8107
  // src/daemon/ → <sisyphus>/templates/
7755
8108
  ];
7756
8109
  var cachedSystemPrompt;
@@ -7763,7 +8116,7 @@ async function generateVisualForQuestion(opts) {
7763
8116
  if (!question) return { ok: false, error: `qid ${opts.qid} not found in decisions` };
7764
8117
  const mdPath = askVisualMarkdownPath(opts.cwd, opts.sessionId, opts.askId, opts.qid);
7765
8118
  const ansiPath = askVisualAnsiPath(opts.cwd, opts.sessionId, opts.askId, opts.qid);
7766
- if (!opts.force && existsSync18(mdPath) && existsSync18(ansiPath)) {
8119
+ if (!opts.force && existsSync19(mdPath) && existsSync19(ansiPath)) {
7767
8120
  return { ok: true, markdownPath: mdPath, ansiPath, turns: 0 };
7768
8121
  }
7769
8122
  if (opts.force) {
@@ -7837,7 +8190,7 @@ function buildUserPrompt(q, askedBy, ctx) {
7837
8190
  }
7838
8191
  function readSystemPrompt() {
7839
8192
  if (cachedSystemPrompt !== void 0) return cachedSystemPrompt;
7840
- const found = SYSTEM_PROMPT_CANDIDATES.find((p) => existsSync18(p));
8193
+ const found = SYSTEM_PROMPT_CANDIDATES.find((p) => existsSync19(p));
7841
8194
  if (found === void 0) {
7842
8195
  throw new Error(
7843
8196
  `termrender-haiku-system.md not found in any candidate location: ${SYSTEM_PROMPT_CANDIDATES.join(", ")}`
@@ -7850,7 +8203,7 @@ function readFileHandler(realSessionCwd, requestedPath) {
7850
8203
  if (isAbsolute(requestedPath)) {
7851
8204
  return Promise.resolve(errorResult("path must be relative to session cwd"));
7852
8205
  }
7853
- const joined = resolve8(realSessionCwd, requestedPath);
8206
+ const joined = resolve9(realSessionCwd, requestedPath);
7854
8207
  let realPath;
7855
8208
  try {
7856
8209
  const r = { p: fs.realpathSync(joined, { encoding: "utf-8" }) };
@@ -7907,23 +8260,23 @@ function errorResult(msg) {
7907
8260
  return { content: [{ type: "text", text: msg }], isError: true };
7908
8261
  }
7909
8262
  function spawnAsync(cmd, args, input, timeoutMs) {
7910
- return new Promise((resolve11) => {
8263
+ return new Promise((resolve12) => {
7911
8264
  const chunks = [];
7912
8265
  const errChunks = [];
7913
8266
  const proc = spawn2(cmd, args, { stdio: ["pipe", "pipe", "pipe"], env: execEnv() });
7914
8267
  const timer = setTimeout(() => {
7915
8268
  proc.kill();
7916
- resolve11({ stdout: "", stderr: "", status: null, error: new Error(`timed out after ${timeoutMs}ms`) });
8269
+ resolve12({ stdout: "", stderr: "", status: null, error: new Error(`timed out after ${timeoutMs}ms`) });
7917
8270
  }, timeoutMs);
7918
8271
  proc.stdout.on("data", (d) => chunks.push(d));
7919
8272
  proc.stderr.on("data", (d) => errChunks.push(d));
7920
8273
  proc.on("error", (err) => {
7921
8274
  clearTimeout(timer);
7922
- resolve11({ stdout: "", stderr: "", status: null, error: err });
8275
+ resolve12({ stdout: "", stderr: "", status: null, error: err });
7923
8276
  });
7924
8277
  proc.on("close", (code) => {
7925
8278
  clearTimeout(timer);
7926
- resolve11({ stdout: Buffer.concat(chunks).toString("utf-8"), stderr: Buffer.concat(errChunks).toString("utf-8"), status: code });
8279
+ resolve12({ stdout: Buffer.concat(chunks).toString("utf-8"), stderr: Buffer.concat(errChunks).toString("utf-8"), status: code });
7927
8280
  });
7928
8281
  proc.stdin.end(input, "utf-8");
7929
8282
  });
@@ -7998,22 +8351,22 @@ function setCompositor(c) {
7998
8351
  }
7999
8352
  var sessionTrackingMap = /* @__PURE__ */ new Map();
8000
8353
  function registryPath() {
8001
- return join18(globalDir(), "session-registry.json");
8354
+ return join19(globalDir(), "session-registry.json");
8002
8355
  }
8003
8356
  function persistSessionRegistry() {
8004
8357
  const dir = globalDir();
8005
- mkdirSync10(dir, { recursive: true });
8358
+ mkdirSync11(dir, { recursive: true });
8006
8359
  const registry = {};
8007
8360
  for (const [id, tracking] of sessionTrackingMap) {
8008
8361
  registry[id] = tracking.cwd;
8009
8362
  }
8010
- writeFileSync14(registryPath(), JSON.stringify(registry, null, 2), "utf-8");
8363
+ writeFileSync15(registryPath(), JSON.stringify(registry, null, 2), "utf-8");
8011
8364
  }
8012
8365
  function loadSessionRegistry() {
8013
8366
  const p = registryPath();
8014
- if (!existsSync19(p)) return {};
8367
+ if (!existsSync20(p)) return {};
8015
8368
  try {
8016
- return JSON.parse(readFileSync20(p, "utf-8"));
8369
+ return JSON.parse(readFileSync21(p, "utf-8"));
8017
8370
  } catch (err) {
8018
8371
  console.warn("[sisyphus] Failed to parse session registry:", err instanceof Error ? err.message : err);
8019
8372
  return {};
@@ -8060,8 +8413,8 @@ function collectAllSessionIds() {
8060
8413
  scannedCwds.add(cwd);
8061
8414
  try {
8062
8415
  const dir = sessionsDir(cwd);
8063
- if (!existsSync19(dir)) continue;
8064
- for (const entry of readdirSync11(dir, { withFileTypes: true })) {
8416
+ if (!existsSync20(dir)) continue;
8417
+ for (const entry of readdirSync12(dir, { withFileTypes: true })) {
8065
8418
  if (entry.isDirectory() && !idToCwd.has(entry.name)) {
8066
8419
  idToCwd.set(entry.name, cwd);
8067
8420
  }
@@ -8261,7 +8614,7 @@ async function handleRequest(req) {
8261
8614
  let tracking = sessionTrackingMap.get(req.sessionId);
8262
8615
  if (!tracking) {
8263
8616
  const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
8264
- if (existsSync19(stateFile)) {
8617
+ if (existsSync20(stateFile)) {
8265
8618
  tracking = { cwd: req.cwd, messageCounter: 0 };
8266
8619
  sessionTrackingMap.set(req.sessionId, tracking);
8267
8620
  persistSessionRegistry();
@@ -8276,7 +8629,7 @@ async function handleRequest(req) {
8276
8629
  }
8277
8630
  case "clear-orphan": {
8278
8631
  const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
8279
- if (!existsSync19(stateFile)) {
8632
+ if (!existsSync20(stateFile)) {
8280
8633
  return { ok: false, error: `Unknown session: ${req.sessionId}. No state.json at ${stateFile}.` };
8281
8634
  }
8282
8635
  await Promise.all([
@@ -8327,7 +8680,7 @@ async function handleRequest(req) {
8327
8680
  let tracking = sessionTrackingMap.get(req.sessionId);
8328
8681
  if (!tracking) {
8329
8682
  const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
8330
- if (existsSync19(stateFile)) {
8683
+ if (existsSync20(stateFile)) {
8331
8684
  registerSessionCwd(req.sessionId, req.cwd);
8332
8685
  tracking = sessionTrackingMap.get(req.sessionId);
8333
8686
  } else {
@@ -8341,7 +8694,7 @@ async function handleRequest(req) {
8341
8694
  let tracking = sessionTrackingMap.get(req.sessionId);
8342
8695
  if (!tracking) {
8343
8696
  const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
8344
- if (existsSync19(stateFile)) {
8697
+ if (existsSync20(stateFile)) {
8345
8698
  registerSessionCwd(req.sessionId, req.cwd);
8346
8699
  tracking = sessionTrackingMap.get(req.sessionId);
8347
8700
  } else {
@@ -8358,7 +8711,7 @@ async function handleRequest(req) {
8358
8711
  let tracking = sessionTrackingMap.get(req.sessionId);
8359
8712
  if (!tracking) {
8360
8713
  const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
8361
- if (existsSync19(stateFile)) {
8714
+ if (existsSync20(stateFile)) {
8362
8715
  tracking = { cwd: req.cwd, messageCounter: 0 };
8363
8716
  sessionTrackingMap.set(req.sessionId, tracking);
8364
8717
  persistSessionRegistry();
@@ -8382,7 +8735,7 @@ async function handleRequest(req) {
8382
8735
  persistSessionRegistry();
8383
8736
  }
8384
8737
  const { sessionDir: sessionDir2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
8385
- rmSync7(sessionDir2(req.cwd, req.sessionId), { recursive: true, force: true });
8738
+ rmSync8(sessionDir2(req.cwd, req.sessionId), { recursive: true, force: true });
8386
8739
  return { ok: true };
8387
8740
  }
8388
8741
  case "pane-exited": {
@@ -8409,9 +8762,26 @@ async function handleRequest(req) {
8409
8762
  await updateSession(tracking.cwd, req.sessionId, { effort: req.effort });
8410
8763
  return { ok: true };
8411
8764
  }
8765
+ case "set-dangerous-mode": {
8766
+ const tracking = sessionTrackingMap.get(req.sessionId);
8767
+ if (!tracking) return unknownSessionError(req.sessionId);
8768
+ await updateSession(tracking.cwd, req.sessionId, { dangerousMode: req.enabled });
8769
+ let flushed = 0;
8770
+ if (req.enabled) {
8771
+ for (const askId of listAsks(tracking.cwd, req.sessionId)) {
8772
+ const meta = readMeta(tracking.cwd, req.sessionId, askId);
8773
+ if (!meta) continue;
8774
+ if (meta.status !== "pending" && meta.status !== "in-progress") continue;
8775
+ if (meta.orphaned) continue;
8776
+ const ok = await autoResolveAsk(tracking.cwd, req.sessionId, askId);
8777
+ if (ok) flushed += 1;
8778
+ }
8779
+ }
8780
+ return { ok: true, data: { enabled: req.enabled, flushed } };
8781
+ }
8412
8782
  case "set-upload-status": {
8413
8783
  const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
8414
- if (!existsSync19(stateFile)) {
8784
+ if (!existsSync20(stateFile)) {
8415
8785
  return unknownSessionError(req.sessionId);
8416
8786
  }
8417
8787
  try {
@@ -8434,19 +8804,19 @@ async function handleRequest(req) {
8434
8804
  const source = req.source ?? { type: "user" };
8435
8805
  const summary = req.content.length > 200 ? req.content.slice(0, 200) + "..." : req.content;
8436
8806
  if (req.agentId) {
8437
- const dir = join18(messagesDir(tracking.cwd, req.sessionId), req.agentId);
8438
- mkdirSync10(dir, { recursive: true });
8439
- const filePath2 = join18(dir, `${id}.md`);
8440
- writeFileSync14(filePath2, req.content, "utf-8");
8807
+ const dir = join19(messagesDir(tracking.cwd, req.sessionId), req.agentId);
8808
+ mkdirSync11(dir, { recursive: true });
8809
+ const filePath2 = join19(dir, `${id}.md`);
8810
+ writeFileSync15(filePath2, req.content, "utf-8");
8441
8811
  emitHistoryEvent(req.sessionId, "message", { source: source.type, agentId: req.agentId, content: req.content });
8442
8812
  return { ok: true };
8443
8813
  }
8444
8814
  let filePath;
8445
8815
  if (req.content.length > 200) {
8446
8816
  const dir = messagesDir(tracking.cwd, req.sessionId);
8447
- mkdirSync10(dir, { recursive: true });
8448
- filePath = join18(dir, `${id}.md`);
8449
- writeFileSync14(filePath, req.content, "utf-8");
8817
+ mkdirSync11(dir, { recursive: true });
8818
+ filePath = join19(dir, `${id}.md`);
8819
+ writeFileSync15(filePath, req.content, "utf-8");
8450
8820
  }
8451
8821
  await appendMessage(tracking.cwd, req.sessionId, {
8452
8822
  id,
@@ -8622,9 +8992,9 @@ async function handleRequest(req) {
8622
8992
  }
8623
8993
  }
8624
8994
  function startServer() {
8625
- return new Promise((resolve11, reject) => {
8995
+ return new Promise((resolve12, reject) => {
8626
8996
  const sock = socketPath();
8627
- if (existsSync19(sock)) {
8997
+ if (existsSync20(sock)) {
8628
8998
  unlinkSync3(sock);
8629
8999
  }
8630
9000
  server = createServer((conn) => {
@@ -8667,23 +9037,23 @@ function startServer() {
8667
9037
  } catch {
8668
9038
  }
8669
9039
  console.log(`[sisyphus] Daemon listening on ${sock}`);
8670
- resolve11(server);
9040
+ resolve12(server);
8671
9041
  });
8672
9042
  });
8673
9043
  }
8674
9044
  function stopServer() {
8675
- return new Promise((resolve11) => {
9045
+ return new Promise((resolve12) => {
8676
9046
  if (!server) {
8677
- resolve11();
9047
+ resolve12();
8678
9048
  return;
8679
9049
  }
8680
9050
  server.close(() => {
8681
9051
  const sock = socketPath();
8682
- if (existsSync19(sock)) {
9052
+ if (existsSync20(sock)) {
8683
9053
  unlinkSync3(sock);
8684
9054
  }
8685
9055
  server = null;
8686
- resolve11();
9056
+ resolve12();
8687
9057
  });
8688
9058
  });
8689
9059
  }
@@ -8691,7 +9061,7 @@ function stopServer() {
8691
9061
  // src/daemon/heartbeat-asks.ts
8692
9062
  import { ulid as ulid3 } from "ulid";
8693
9063
  init_paths();
8694
- import { existsSync as existsSync20 } from "fs";
9064
+ import { existsSync as existsSync21 } from "fs";
8695
9065
  var HEARTBEAT_ASKED_BY2 = "system:heartbeat";
8696
9066
  var HEARTBEAT_THRESHOLD_MS = 60 * 60 * 1e3;
8697
9067
  var HEARTBEAT_SCAN_INTERVAL_MS = 15 * 60 * 1e3;
@@ -8774,7 +9144,7 @@ async function scanSessionForStaleAsks(cwd, sessionId) {
8774
9144
  async function scanAllSessionsForStaleAsks() {
8775
9145
  const reg = loadSessionRegistry();
8776
9146
  for (const [sessionId, cwd] of Object.entries(reg)) {
8777
- if (!existsSync20(statePath(cwd, sessionId))) continue;
9147
+ if (!existsSync21(statePath(cwd, sessionId))) continue;
8778
9148
  try {
8779
9149
  await scanSessionForStaleAsks(cwd, sessionId);
8780
9150
  } catch (err) {
@@ -8829,15 +9199,15 @@ var DEFAULT_STATUS_BAR_CONFIG = {
8829
9199
  };
8830
9200
 
8831
9201
  // src/daemon/segments/compositor.ts
8832
- import { readFileSync as readFileSync21, existsSync as existsSync21 } from "fs";
8833
- import { homedir as homedir7 } from "os";
8834
- import { join as join19 } from "path";
9202
+ import { readFileSync as readFileSync22, existsSync as existsSync22 } from "fs";
9203
+ import { homedir as homedir8 } from "os";
9204
+ import { join as join20 } from "path";
8835
9205
  var STATUS_BAR_BG = "#1d1e21";
8836
- var SESSION_ORDER_PATH = join19(homedir7(), ".config", "tmux", "session-order");
9206
+ var SESSION_ORDER_PATH = join20(homedir8(), ".config", "tmux", "session-order");
8837
9207
  function getSessionOrder() {
8838
9208
  try {
8839
- if (!existsSync21(SESSION_ORDER_PATH)) return [];
8840
- return readFileSync21(SESSION_ORDER_PATH, "utf-8").split("\n").filter(Boolean);
9209
+ if (!existsSync22(SESSION_ORDER_PATH)) return [];
9210
+ return readFileSync22(SESSION_ORDER_PATH, "utf-8").split("\n").filter(Boolean);
8841
9211
  } catch {
8842
9212
  return [];
8843
9213
  }
@@ -9374,8 +9744,8 @@ function writeEmptyManifest() {
9374
9744
  // src/daemon/updater.ts
9375
9745
  init_paths();
9376
9746
  import { execSync as execSync6 } from "child_process";
9377
- import { writeFileSync as writeFileSync15, unlinkSync as unlinkSync4, lstatSync as lstatSync2 } from "fs";
9378
- import { resolve as resolve9 } from "path";
9747
+ import { writeFileSync as writeFileSync16, unlinkSync as unlinkSync4, lstatSync as lstatSync2 } from "fs";
9748
+ import { resolve as resolve10 } from "path";
9379
9749
  import { get } from "https";
9380
9750
  function isNewer(latest, current) {
9381
9751
  const a = latest.split(".").map(Number);
@@ -9389,10 +9759,10 @@ function isNewer(latest, current) {
9389
9759
  return false;
9390
9760
  }
9391
9761
  function checkForUpdate() {
9392
- return new Promise((resolve11) => {
9762
+ return new Promise((resolve12) => {
9393
9763
  const timeout = setTimeout(() => {
9394
9764
  console.error("[sisyphus] Update check timed out (5s)");
9395
- resolve11(null);
9765
+ resolve12(null);
9396
9766
  }, 5e3);
9397
9767
  const req = get("https://registry.npmjs.org/sisyphi/latest", (res) => {
9398
9768
  let data = "";
@@ -9404,26 +9774,26 @@ function checkForUpdate() {
9404
9774
  try {
9405
9775
  const { version: latest } = JSON.parse(data);
9406
9776
  if (latest && isNewer(latest, getSisyphusVersion())) {
9407
- resolve11({ current: getSisyphusVersion(), latest });
9777
+ resolve12({ current: getSisyphusVersion(), latest });
9408
9778
  } else {
9409
- resolve11(null);
9779
+ resolve12(null);
9410
9780
  }
9411
9781
  } catch (err) {
9412
9782
  console.error("[sisyphus] Failed to parse registry response:", err);
9413
- resolve11(null);
9783
+ resolve12(null);
9414
9784
  }
9415
9785
  });
9416
9786
  });
9417
9787
  req.on("error", (err) => {
9418
9788
  clearTimeout(timeout);
9419
9789
  console.error("[sisyphus] Update check failed:", err.message);
9420
- resolve11(null);
9790
+ resolve12(null);
9421
9791
  });
9422
9792
  });
9423
9793
  }
9424
9794
  function applyUpdate(expectedVersion) {
9425
9795
  try {
9426
- const nodeDir = resolve9(process.execPath, "..");
9796
+ const nodeDir = resolve10(process.execPath, "..");
9427
9797
  const env = { ...process.env, PATH: `${nodeDir}:${process.env.PATH ?? ""}` };
9428
9798
  execSync6("npm install -g sisyphi", { timeout: 15e3, stdio: "pipe", env });
9429
9799
  const result = execSync6("npm ls -g sisyphi --json --depth=0", {
@@ -9445,7 +9815,7 @@ function applyUpdate(expectedVersion) {
9445
9815
  }
9446
9816
  function markUpdating(version) {
9447
9817
  try {
9448
- writeFileSync15(daemonUpdatingPath(), version, "utf-8");
9818
+ writeFileSync16(daemonUpdatingPath(), version, "utf-8");
9449
9819
  } catch {
9450
9820
  }
9451
9821
  }
@@ -9457,9 +9827,9 @@ function clearUpdating() {
9457
9827
  }
9458
9828
  function isLinkedInstall() {
9459
9829
  try {
9460
- const nodeDir = resolve9(process.execPath, "..");
9830
+ const nodeDir = resolve10(process.execPath, "..");
9461
9831
  const globalPrefix = execSync6("npm prefix -g", { timeout: 5e3, encoding: "utf-8", env: { ...process.env, PATH: `${nodeDir}:${process.env.PATH ?? ""}` } }).trim();
9462
- const globalPkgDir = resolve9(globalPrefix, "lib", "node_modules", "sisyphi");
9832
+ const globalPkgDir = resolve10(globalPrefix, "lib", "node_modules", "sisyphi");
9463
9833
  return lstatSync2(globalPkgDir).isSymbolicLink();
9464
9834
  } catch {
9465
9835
  return false;
@@ -9501,48 +9871,48 @@ function stopPeriodicUpdateCheck() {
9501
9871
  }
9502
9872
 
9503
9873
  // src/daemon/plugin-install.ts
9504
- import { copyFileSync as copyFileSync4, mkdirSync as mkdirSync11, readdirSync as readdirSync12, statSync as statSync3, existsSync as existsSync22, readFileSync as readFileSync22, chmodSync as chmodSync2 } from "fs";
9505
- import { join as join20, resolve as resolve10 } from "path";
9506
- import { homedir as homedir8 } from "os";
9874
+ import { copyFileSync as copyFileSync5, mkdirSync as mkdirSync12, readdirSync as readdirSync13, statSync as statSync4, existsSync as existsSync23, readFileSync as readFileSync23, chmodSync as chmodSync2 } from "fs";
9875
+ import { join as join21, resolve as resolve11 } from "path";
9876
+ import { homedir as homedir9 } from "os";
9507
9877
  var PLUGIN_NAME = "sisyphus-tmux";
9508
- var INSTALL_DIR = join20(homedir8(), ".claude", "plugins", PLUGIN_NAME);
9878
+ var INSTALL_DIR = join21(homedir9(), ".claude", "plugins", PLUGIN_NAME);
9509
9879
  function copyDir(src, dest) {
9510
- mkdirSync11(dest, { recursive: true });
9511
- for (const entry of readdirSync12(src)) {
9512
- const srcPath = join20(src, entry);
9513
- const destPath = join20(dest, entry);
9514
- if (statSync3(srcPath).isDirectory()) {
9880
+ mkdirSync12(dest, { recursive: true });
9881
+ for (const entry of readdirSync13(src)) {
9882
+ const srcPath = join21(src, entry);
9883
+ const destPath = join21(dest, entry);
9884
+ if (statSync4(srcPath).isDirectory()) {
9515
9885
  copyDir(srcPath, destPath);
9516
9886
  } else {
9517
- const srcMtime = statSync3(srcPath).mtimeMs;
9518
- const destMtime = existsSync22(destPath) ? statSync3(destPath).mtimeMs : 0;
9887
+ const srcMtime = statSync4(srcPath).mtimeMs;
9888
+ const destMtime = existsSync23(destPath) ? statSync4(destPath).mtimeMs : 0;
9519
9889
  if (srcMtime > destMtime) {
9520
- copyFileSync4(srcPath, destPath);
9890
+ copyFileSync5(srcPath, destPath);
9521
9891
  }
9522
9892
  }
9523
9893
  }
9524
9894
  }
9525
9895
  function pluginNeedsUpdate(sourceDir) {
9526
- const srcHooks = join20(sourceDir, "hooks", "hooks.json");
9527
- const destHooks = join20(INSTALL_DIR, "hooks", "hooks.json");
9528
- if (!existsSync22(destHooks)) return true;
9896
+ const srcHooks = join21(sourceDir, "hooks", "hooks.json");
9897
+ const destHooks = join21(INSTALL_DIR, "hooks", "hooks.json");
9898
+ if (!existsSync23(destHooks)) return true;
9529
9899
  try {
9530
- return readFileSync22(srcHooks, "utf-8") !== readFileSync22(destHooks, "utf-8");
9900
+ return readFileSync23(srcHooks, "utf-8") !== readFileSync23(destHooks, "utf-8");
9531
9901
  } catch {
9532
9902
  return true;
9533
9903
  }
9534
9904
  }
9535
9905
  function installPlugin() {
9536
- const sourceDir = resolve10(import.meta.dirname, "../templates/sisyphus-tmux-plugin");
9537
- if (!existsSync22(sourceDir)) {
9906
+ const sourceDir = resolve11(import.meta.dirname, "../templates/sisyphus-tmux-plugin");
9907
+ if (!existsSync23(sourceDir)) {
9538
9908
  console.error(`[plugin-install] Source dir not found: ${sourceDir}`);
9539
9909
  return;
9540
9910
  }
9541
9911
  if (!pluginNeedsUpdate(sourceDir)) return;
9542
9912
  try {
9543
9913
  copyDir(sourceDir, INSTALL_DIR);
9544
- const hookScript = join20(INSTALL_DIR, "hooks", "tmux-state.sh");
9545
- if (existsSync22(hookScript)) {
9914
+ const hookScript = join21(INSTALL_DIR, "hooks", "tmux-state.sh");
9915
+ if (existsSync23(hookScript)) {
9546
9916
  try {
9547
9917
  chmodSync2(hookScript, 493);
9548
9918
  } catch {
@@ -9566,12 +9936,12 @@ var origError = console.error.bind(console);
9566
9936
  console.log = (...args) => origLog(`[${ts()}]`, ...args);
9567
9937
  console.error = (...args) => origError(`[${ts()}]`, ...args);
9568
9938
  function ensureDirs() {
9569
- mkdirSync12(globalDir(), { recursive: true });
9939
+ mkdirSync13(globalDir(), { recursive: true });
9570
9940
  }
9571
9941
  function readPid() {
9572
9942
  const pidFile = daemonPidPath();
9573
9943
  try {
9574
- const pid = parseInt(readFileSync23(pidFile, "utf-8").trim(), 10);
9944
+ const pid = parseInt(readFileSync24(pidFile, "utf-8").trim(), 10);
9575
9945
  return pid && isProcessAlive(pid) ? pid : null;
9576
9946
  } catch {
9577
9947
  return null;
@@ -9583,7 +9953,7 @@ function acquirePidLock() {
9583
9953
  console.error(`[sisyphus] Daemon already running (pid ${pid}). Use 'sisyphusd restart' or 'sisyphusd stop' first.`);
9584
9954
  process.exit(0);
9585
9955
  }
9586
- writeFileSync16(daemonPidPath(), String(process.pid), "utf-8");
9956
+ writeFileSync17(daemonPidPath(), String(process.pid), "utf-8");
9587
9957
  }
9588
9958
  function isLaunchdManaged() {
9589
9959
  try {
@@ -9642,11 +10012,11 @@ async function recoverSessions() {
9642
10012
  let recovered = 0;
9643
10013
  for (const [sessionId, cwd] of entries) {
9644
10014
  const stateFile = statePath(cwd, sessionId);
9645
- if (!existsSync23(stateFile)) {
10015
+ if (!existsSync24(stateFile)) {
9646
10016
  continue;
9647
10017
  }
9648
10018
  try {
9649
- const session = JSON.parse(readFileSync23(stateFile, "utf-8"));
10019
+ const session = JSON.parse(readFileSync24(stateFile, "utf-8"));
9650
10020
  if (session.status === "active" || session.status === "paused") {
9651
10021
  registerSessionCwd(sessionId, cwd);
9652
10022
  resetAgentCounterFromState(sessionId, session.agents ?? []);