create-egregore 0.19.21 → 0.19.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/assets/egregore-launcher.js +29 -3
  2. package/bin/cli.js +3 -4
  3. package/lib/auth.js +3 -4
  4. package/lib/path-lookup.js +59 -0
  5. package/lib/setup.js +52 -6
  6. package/package.json +2 -2
  7. package/runtime/codex/.claude/context/notification-consent.md +66 -0
  8. package/runtime/codex/.codex/hooks/branch-guard.js +14 -3
  9. package/runtime/codex/.codex/skills/add/SKILL.md +8 -4
  10. package/runtime/codex/.codex/skills/announce/SKILL.md +21 -8
  11. package/runtime/codex/.codex/skills/answer/SKILL.md +8 -4
  12. package/runtime/codex/.codex/skills/archive/SKILL.md +8 -4
  13. package/runtime/codex/.codex/skills/ask/SKILL.md +14 -6
  14. package/runtime/codex/.codex/skills/audit/SKILL.md +29 -0
  15. package/runtime/codex/.codex/skills/autosave/SKILL.md +29 -0
  16. package/runtime/codex/.codex/skills/branch/SKILL.md +8 -4
  17. package/runtime/codex/.codex/skills/checkup/SKILL.md +8 -4
  18. package/runtime/codex/.codex/skills/commit/SKILL.md +8 -4
  19. package/runtime/codex/.codex/skills/contribute/SKILL.md +8 -4
  20. package/runtime/codex/.codex/skills/dark-mode/SKILL.md +8 -4
  21. package/runtime/codex/.codex/skills/delete-user/SKILL.md +8 -4
  22. package/runtime/codex/.codex/skills/demo-mode/SKILL.md +29 -0
  23. package/runtime/codex/.codex/skills/deploy-bridge/SKILL.md +8 -4
  24. package/runtime/codex/.codex/skills/design/SKILL.md +29 -0
  25. package/runtime/codex/.codex/skills/egregore-voice/SKILL.md +8 -4
  26. package/runtime/codex/.codex/skills/emissary/SKILL.md +8 -4
  27. package/runtime/codex/.codex/skills/env/SKILL.md +8 -4
  28. package/runtime/codex/.codex/skills/handoff/SKILL.md +15 -6
  29. package/runtime/codex/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
  30. package/runtime/codex/.codex/skills/harvest/SKILL.md +30 -6
  31. package/runtime/codex/.codex/skills/ingest/SKILL.md +8 -4
  32. package/runtime/codex/.codex/skills/ingest-google/SKILL.md +8 -4
  33. package/runtime/codex/.codex/skills/ingest-user-interview/SKILL.md +8 -4
  34. package/runtime/codex/.codex/skills/invite/SKILL.md +6 -2
  35. package/runtime/codex/.codex/skills/issue/SKILL.md +8 -4
  36. package/runtime/codex/.codex/skills/me/SKILL.md +8 -4
  37. package/runtime/codex/.codex/skills/meeting/SKILL.md +8 -4
  38. package/runtime/codex/.codex/skills/minion/SKILL.md +8 -4
  39. package/runtime/codex/.codex/skills/mock/SKILL.md +29 -0
  40. package/runtime/codex/.codex/skills/note/SKILL.md +8 -4
  41. package/runtime/codex/.codex/skills/onboarding/SKILL.md +8 -4
  42. package/runtime/codex/.codex/skills/pr/SKILL.md +8 -4
  43. package/runtime/codex/.codex/skills/product-voice/SKILL.md +29 -0
  44. package/runtime/codex/.codex/skills/project/SKILL.md +8 -4
  45. package/runtime/codex/.codex/skills/pull/SKILL.md +8 -4
  46. package/runtime/codex/.codex/skills/push/SKILL.md +8 -4
  47. package/runtime/codex/.codex/skills/quest/SKILL.md +6 -3
  48. package/runtime/codex/.codex/skills/quest-suggest/SKILL.md +8 -4
  49. package/runtime/codex/.codex/skills/reflect/SKILL.md +8 -4
  50. package/runtime/codex/.codex/skills/review-pr/SKILL.md +8 -4
  51. package/runtime/codex/.codex/skills/save/SKILL.md +6 -4
  52. package/runtime/codex/.codex/skills/scroll/SKILL.md +92 -23
  53. package/runtime/codex/.codex/skills/scroll/assets/shell.html +381 -52
  54. package/runtime/codex/.codex/skills/session-view/SKILL.md +8 -4
  55. package/runtime/codex/.codex/skills/setup/SKILL.md +8 -4
  56. package/runtime/codex/.codex/skills/summon/SKILL.md +8 -4
  57. package/runtime/codex/.codex/skills/sync-repos/SKILL.md +8 -4
  58. package/runtime/codex/.codex/skills/task/SKILL.md +9 -5
  59. package/runtime/codex/.codex/skills/teams-connect/SKILL.md +29 -0
  60. package/runtime/codex/.codex/skills/telegram-connect/SKILL.md +8 -4
  61. package/runtime/codex/.codex/skills/telemetry/SKILL.md +8 -4
  62. package/runtime/codex/.codex/skills/test/SKILL.md +8 -4
  63. package/runtime/codex/.codex/skills/thread/SKILL.md +8 -4
  64. package/runtime/codex/.codex/skills/todo/SKILL.md +8 -4
  65. package/runtime/codex/.codex/skills/tui-design/SKILL.md +8 -4
  66. package/runtime/codex/.codex/skills/tutorial/SKILL.md +8 -4
  67. package/runtime/codex/.codex/skills/update/SKILL.md +8 -4
  68. package/runtime/codex/.codex/skills/visual-explain/SKILL.md +8 -4
  69. package/runtime/codex/.codex/spec-manifest.json +4 -4
  70. package/runtime/codex/AGENTS.md +36 -14
  71. package/runtime/codex/bin/activity-data.sh +1 -1
  72. package/runtime/codex/bin/agent.sh +38 -19
  73. package/runtime/codex/bin/attendant.sh +8 -2
  74. package/runtime/codex/bin/autosave.sh +1 -1
  75. package/runtime/codex/bin/capture-reconcile.sh +8 -6
  76. package/runtime/codex/bin/capture-run.sh +1 -1
  77. package/runtime/codex/bin/codex-install-skills.sh +1 -1
  78. package/runtime/codex/bin/codex-render-spec.mjs +12 -5
  79. package/runtime/codex/bin/codex-session-start.sh +1 -1
  80. package/runtime/codex/bin/codex-sync-skills.sh +9 -5
  81. package/runtime/codex/bin/dashboard-data.sh +1 -1
  82. package/runtime/codex/bin/graph-batch.sh +1 -1
  83. package/runtime/codex/bin/graph-op.sh +1 -1
  84. package/runtime/codex/bin/graph-wal.sh +1 -1
  85. package/runtime/codex/bin/graph.sh +1 -1
  86. package/runtime/codex/bin/handoff-pr-backfill.sh +1 -1
  87. package/runtime/codex/bin/handoff-run.sh +53 -39
  88. package/runtime/codex/bin/handoff-save-egregore.sh +62 -32
  89. package/runtime/codex/bin/index-handoff.sh +1 -1
  90. package/runtime/codex/bin/ingest-graph.sh +1 -1
  91. package/runtime/codex/bin/ingest.sh +1 -1
  92. package/runtime/codex/bin/lib/artifact-id.sh +1 -1
  93. package/runtime/codex/bin/lib/config.sh +56 -20
  94. package/runtime/codex/bin/lib/context.sh +7 -1
  95. package/runtime/codex/bin/lib/ensure-develop.sh +1 -1
  96. package/runtime/codex/bin/lib/git-sync.sh +145 -59
  97. package/runtime/codex/bin/lib/greeting.sh +14 -0
  98. package/runtime/codex/bin/lib/hash.sh +1 -1
  99. package/runtime/codex/bin/lib/noncode.sh +1 -1
  100. package/runtime/codex/bin/lib/time.sh +1 -1
  101. package/runtime/codex/bin/notify.sh +492 -153
  102. package/runtime/codex/bin/person.sh +1 -1
  103. package/runtime/codex/bin/publish-artifact.sh +39 -4
  104. package/runtime/codex/bin/publish-references.sh +1 -1
  105. package/runtime/codex/bin/repo-state.sh +7 -10
  106. package/runtime/codex/bin/search.sh +1 -1
  107. package/runtime/codex/bin/session-autosave.sh +1 -1
  108. package/runtime/codex/bin/session-log.sh +1 -1
  109. package/runtime/codex/bin/settings.sh +32 -2
  110. package/runtime/codex/bin/telemetry.sh +1 -1
  111. package/runtime/codex/bin/worktree-create.sh +14 -4
  112. package/runtime/codex/bin/worktree-remove.sh +1 -1
  113. package/runtime/codex/bin/worktree.sh +1 -1
  114. package/runtime/codex/manifest.json +18 -1
  115. package/runtime/pi/.claude/context/notification-consent.md +66 -0
  116. package/runtime/pi/.codex/hooks/branch-guard.js +14 -3
  117. package/runtime/pi/.codex/skills/add/SKILL.md +8 -4
  118. package/runtime/pi/.codex/skills/announce/SKILL.md +21 -8
  119. package/runtime/pi/.codex/skills/answer/SKILL.md +8 -4
  120. package/runtime/pi/.codex/skills/archive/SKILL.md +8 -4
  121. package/runtime/pi/.codex/skills/ask/SKILL.md +14 -6
  122. package/runtime/pi/.codex/skills/audit/SKILL.md +29 -0
  123. package/runtime/pi/.codex/skills/autosave/SKILL.md +29 -0
  124. package/runtime/pi/.codex/skills/branch/SKILL.md +8 -4
  125. package/runtime/pi/.codex/skills/checkup/SKILL.md +8 -4
  126. package/runtime/pi/.codex/skills/commit/SKILL.md +8 -4
  127. package/runtime/pi/.codex/skills/contribute/SKILL.md +8 -4
  128. package/runtime/pi/.codex/skills/dark-mode/SKILL.md +8 -4
  129. package/runtime/pi/.codex/skills/delete-user/SKILL.md +8 -4
  130. package/runtime/pi/.codex/skills/demo-mode/SKILL.md +29 -0
  131. package/runtime/pi/.codex/skills/deploy-bridge/SKILL.md +8 -4
  132. package/runtime/pi/.codex/skills/design/SKILL.md +29 -0
  133. package/runtime/pi/.codex/skills/egregore-voice/SKILL.md +8 -4
  134. package/runtime/pi/.codex/skills/emissary/SKILL.md +8 -4
  135. package/runtime/pi/.codex/skills/env/SKILL.md +8 -4
  136. package/runtime/pi/.codex/skills/handoff/SKILL.md +15 -6
  137. package/runtime/pi/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
  138. package/runtime/pi/.codex/skills/harvest/SKILL.md +30 -6
  139. package/runtime/pi/.codex/skills/ingest/SKILL.md +8 -4
  140. package/runtime/pi/.codex/skills/ingest-google/SKILL.md +8 -4
  141. package/runtime/pi/.codex/skills/ingest-user-interview/SKILL.md +8 -4
  142. package/runtime/pi/.codex/skills/invite/SKILL.md +6 -2
  143. package/runtime/pi/.codex/skills/issue/SKILL.md +8 -4
  144. package/runtime/pi/.codex/skills/me/SKILL.md +8 -4
  145. package/runtime/pi/.codex/skills/meeting/SKILL.md +8 -4
  146. package/runtime/pi/.codex/skills/minion/SKILL.md +8 -4
  147. package/runtime/pi/.codex/skills/mock/SKILL.md +29 -0
  148. package/runtime/pi/.codex/skills/note/SKILL.md +8 -4
  149. package/runtime/pi/.codex/skills/onboarding/SKILL.md +8 -4
  150. package/runtime/pi/.codex/skills/pr/SKILL.md +8 -4
  151. package/runtime/pi/.codex/skills/product-voice/SKILL.md +29 -0
  152. package/runtime/pi/.codex/skills/project/SKILL.md +8 -4
  153. package/runtime/pi/.codex/skills/pull/SKILL.md +8 -4
  154. package/runtime/pi/.codex/skills/push/SKILL.md +8 -4
  155. package/runtime/pi/.codex/skills/quest/SKILL.md +6 -3
  156. package/runtime/pi/.codex/skills/quest-suggest/SKILL.md +8 -4
  157. package/runtime/pi/.codex/skills/reflect/SKILL.md +8 -4
  158. package/runtime/pi/.codex/skills/review-pr/SKILL.md +8 -4
  159. package/runtime/pi/.codex/skills/save/SKILL.md +6 -4
  160. package/runtime/pi/.codex/skills/scroll/SKILL.md +92 -23
  161. package/runtime/pi/.codex/skills/scroll/assets/shell.html +381 -52
  162. package/runtime/pi/.codex/skills/session-view/SKILL.md +8 -4
  163. package/runtime/pi/.codex/skills/setup/SKILL.md +8 -4
  164. package/runtime/pi/.codex/skills/summon/SKILL.md +8 -4
  165. package/runtime/pi/.codex/skills/sync-repos/SKILL.md +8 -4
  166. package/runtime/pi/.codex/skills/task/SKILL.md +9 -5
  167. package/runtime/pi/.codex/skills/teams-connect/SKILL.md +29 -0
  168. package/runtime/pi/.codex/skills/telegram-connect/SKILL.md +8 -4
  169. package/runtime/pi/.codex/skills/telemetry/SKILL.md +8 -4
  170. package/runtime/pi/.codex/skills/test/SKILL.md +8 -4
  171. package/runtime/pi/.codex/skills/thread/SKILL.md +8 -4
  172. package/runtime/pi/.codex/skills/todo/SKILL.md +8 -4
  173. package/runtime/pi/.codex/skills/tui-design/SKILL.md +8 -4
  174. package/runtime/pi/.codex/skills/tutorial/SKILL.md +8 -4
  175. package/runtime/pi/.codex/skills/update/SKILL.md +8 -4
  176. package/runtime/pi/.codex/skills/visual-explain/SKILL.md +8 -4
  177. package/runtime/pi/.codex/spec-manifest.json +4 -4
  178. package/runtime/pi/.pi/APPEND_SYSTEM.md +34 -12
  179. package/runtime/pi/.pi/extensions/egregore.ts +8 -1
  180. package/runtime/pi/.pi/spec-manifest.json +2 -2
  181. package/runtime/pi/AGENTS.md +36 -14
  182. package/runtime/pi/bin/activity-data.sh +1 -1
  183. package/runtime/pi/bin/agent.sh +38 -19
  184. package/runtime/pi/bin/attendant.sh +8 -2
  185. package/runtime/pi/bin/autosave.sh +1 -1
  186. package/runtime/pi/bin/capture-reconcile.sh +8 -6
  187. package/runtime/pi/bin/capture-run.sh +1 -1
  188. package/runtime/pi/bin/codex-install-skills.sh +1 -1
  189. package/runtime/pi/bin/codex-render-spec.mjs +12 -5
  190. package/runtime/pi/bin/codex-session-start.sh +1 -1
  191. package/runtime/pi/bin/codex-sync-skills.sh +9 -5
  192. package/runtime/pi/bin/dashboard-data.sh +1 -1
  193. package/runtime/pi/bin/graph-batch.sh +1 -1
  194. package/runtime/pi/bin/graph-op.sh +1 -1
  195. package/runtime/pi/bin/graph-wal.sh +1 -1
  196. package/runtime/pi/bin/graph.sh +1 -1
  197. package/runtime/pi/bin/handoff-pr-backfill.sh +1 -1
  198. package/runtime/pi/bin/handoff-run.sh +53 -39
  199. package/runtime/pi/bin/handoff-save-egregore.sh +62 -32
  200. package/runtime/pi/bin/index-handoff.sh +1 -1
  201. package/runtime/pi/bin/ingest-graph.sh +1 -1
  202. package/runtime/pi/bin/ingest.sh +1 -1
  203. package/runtime/pi/bin/lib/artifact-id.sh +1 -1
  204. package/runtime/pi/bin/lib/config.sh +56 -20
  205. package/runtime/pi/bin/lib/context.sh +7 -1
  206. package/runtime/pi/bin/lib/ensure-develop.sh +1 -1
  207. package/runtime/pi/bin/lib/git-sync.sh +145 -59
  208. package/runtime/pi/bin/lib/greeting.sh +14 -0
  209. package/runtime/pi/bin/lib/hash.sh +1 -1
  210. package/runtime/pi/bin/lib/noncode.sh +1 -1
  211. package/runtime/pi/bin/lib/time.sh +1 -1
  212. package/runtime/pi/bin/notify.sh +492 -153
  213. package/runtime/pi/bin/person.sh +1 -1
  214. package/runtime/pi/bin/pi-session-start.sh +1 -1
  215. package/runtime/pi/bin/publish-artifact.sh +39 -4
  216. package/runtime/pi/bin/publish-references.sh +1 -1
  217. package/runtime/pi/bin/repo-state.sh +7 -10
  218. package/runtime/pi/bin/search.sh +1 -1
  219. package/runtime/pi/bin/session-autosave.sh +1 -1
  220. package/runtime/pi/bin/session-log.sh +1 -1
  221. package/runtime/pi/bin/settings.sh +32 -2
  222. package/runtime/pi/bin/telemetry.sh +1 -1
  223. package/runtime/pi/bin/worktree-create.sh +14 -4
  224. package/runtime/pi/bin/worktree-remove.sh +1 -1
  225. package/runtime/pi/bin/worktree.sh +1 -1
  226. package/runtime/pi/manifest.json +18 -1
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // egregore-launcher-version: 0.19.21
2
+ // egregore-launcher-version: 0.19.22
3
3
  //
4
4
  // egregore — launch and browse Egregore instances from your terminal.
5
5
  // Installed by create-egregore. Reads ~/.egregore/instances.json.
@@ -33,7 +33,7 @@ const crypto = require("node:crypto");
33
33
  const { spawnSync, spawn } = require("node:child_process");
34
34
  const readline = require("node:readline");
35
35
 
36
- const VERSION = "0.19.21";
36
+ const VERSION = "0.19.22";
37
37
  const REGISTRY = path.join(os.homedir(), ".egregore", "instances.json");
38
38
  const DEFAULT_FILE = path.join(os.homedir(), ".egregore", "default");
39
39
  const UPDATE_CACHE_FILE = path.join(os.homedir(), ".egregore", "update-check.json");
@@ -435,7 +435,33 @@ function piTrustArgs() {
435
435
  }
436
436
 
437
437
  function commandExists(bin) {
438
- return spawnSync("which", [bin], { stdio: "pipe" }).status === 0;
438
+ if (typeof bin !== "string" || bin.length === 0) return false;
439
+ const pathValue = process.env.PATH || process.env.Path || process.env.path || "";
440
+ const separator = process.platform === "win32" ? ";" : ":";
441
+ const names =
442
+ process.platform === "win32" && !path.extname(bin)
443
+ ? (process.env.PATHEXT || ".COM;.EXE;.BAT;.CMD")
444
+ .split(";")
445
+ .filter(Boolean)
446
+ .map((extension) => `${bin}${extension.toLowerCase()}`)
447
+ : [bin];
448
+
449
+ return pathValue.split(separator).some((entry) => {
450
+ const directory = entry ? entry.replace(/^"(.*)"$/, "$1") : process.cwd();
451
+ return names.some((name) => {
452
+ const candidate = path.join(directory, name);
453
+ try {
454
+ if (!fs.statSync(candidate).isFile()) return false;
455
+ fs.accessSync(
456
+ candidate,
457
+ process.platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK,
458
+ );
459
+ return true;
460
+ } catch {
461
+ return false;
462
+ }
463
+ });
464
+ });
439
465
  }
440
466
 
441
467
  function runtimeChoiceDescription(runtime, inst, stored) {
package/bin/cli.js CHANGED
@@ -44,6 +44,7 @@ const {
44
44
  redactToken,
45
45
  } = require("../lib/setup");
46
46
  const { detectContext, isWritable, isSystemDir } = require("../lib/context");
47
+ const { commandExists } = require("../lib/path-lookup");
47
48
 
48
49
  const API_URL = process.env.EGREGORE_API_URL || "https://egregore-production-55f2.up.railway.app";
49
50
  const INSTANCES_FILE = path.join(os.homedir(), ".egregore", "instances.json");
@@ -97,7 +98,7 @@ function detectCwdEgregore(cwd) {
97
98
  }
98
99
 
99
100
  function binaryOnPath(bin) {
100
- return spawnSync("which", [bin], { stdio: "pipe" }).status === 0;
101
+ return commandExists(bin);
101
102
  }
102
103
 
103
104
  function assistantLabel(runtime) {
@@ -406,7 +407,6 @@ async function preflight() {
406
407
  // Verify prerequisites before starting. Fast fail with specific fix hints
407
408
  // beats discovering missing tools mid-install. Claude Code is checked
408
409
  // separately at auto-exec time since users can install it after.
409
- const { spawnSync } = require("node:child_process");
410
410
  const checks = [
411
411
  { bin: "git", hint: "install Xcode command-line tools or https://git-scm.com" },
412
412
  { bin: "jq", hint: "brew install jq (or https://stedolan.github.io/jq/)" },
@@ -417,8 +417,7 @@ async function preflight() {
417
417
  missing.push({ bin: "node >=18", hint: `you're on Node ${process.versions.node}; upgrade at https://nodejs.org` });
418
418
  }
419
419
  for (const c of checks) {
420
- const r = spawnSync("which", [c.bin], { stdio: "pipe" });
421
- if (r.status !== 0) missing.push(c);
420
+ if (!commandExists(c.bin)) missing.push(c);
422
421
  }
423
422
  if (missing.length === 0) return;
424
423
 
package/lib/auth.js CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  const https = require("node:https");
7
7
  const { spawnSync } = require("node:child_process");
8
+ const { commandExists } = require("./path-lookup");
8
9
 
9
10
  /**
10
11
  * Try to get a token from the user's `gh` CLI, if installed and authenticated.
@@ -31,8 +32,7 @@ function envGhAuth() {
31
32
 
32
33
  function ghCliExists() {
33
34
  if (process.env.EGREGORE_SKIP_GH === "1") return false;
34
- const which = spawnSync("which", ["gh"], { stdio: "pipe" });
35
- return which.status === 0;
35
+ return commandExists("gh");
36
36
  }
37
37
 
38
38
  function canUseInteractiveBrowserFlow() {
@@ -46,8 +46,7 @@ const GH_INSTALL_URL = "https://cli.github.com";
46
46
  // and repos vary too much for a single command, so we point at the canonical
47
47
  // page there (and always print GH_INSTALL_URL alongside on every platform).
48
48
  function _has(b) {
49
- try { return spawnSync("which", [b], { stdio: "pipe" }).status === 0; }
50
- catch { return false; }
49
+ return commandExists(b);
51
50
  }
52
51
 
53
52
  // True on a machine with no way to open a browser (server / SSH). macOS and
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ const fs = require("node:fs");
4
+ const path = require("node:path");
5
+
6
+ function executableFile(candidate, platform) {
7
+ try {
8
+ if (!fs.statSync(candidate).isFile()) return false;
9
+ fs.accessSync(
10
+ candidate,
11
+ platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK,
12
+ );
13
+ return true;
14
+ } catch {
15
+ return false;
16
+ }
17
+ }
18
+
19
+ function executableNames(command, env, platform) {
20
+ if (platform !== "win32" || path.extname(command)) return [command];
21
+ const pathExt = env.PATHEXT || ".COM;.EXE;.BAT;.CMD";
22
+ return pathExt
23
+ .split(";")
24
+ .filter(Boolean)
25
+ .map((extension) => `${command}${extension.toLowerCase()}`);
26
+ }
27
+
28
+ /**
29
+ * Resolve a command from PATH without relying on the external `which` utility.
30
+ *
31
+ * NixOS provides declared executables through PATH but does not guarantee
32
+ * `which` is installed. Keeping this lookup in Node also avoids spawning a
33
+ * subprocess for every prerequisite and harness check.
34
+ */
35
+ function commandExists(command, options = {}) {
36
+ if (typeof command !== "string" || command.length === 0) return false;
37
+
38
+ const env = options.env || process.env;
39
+ const platform = options.platform || process.platform;
40
+ const cwd = options.cwd || process.cwd();
41
+ const separator = platform === "win32" ? ";" : ":";
42
+ const pathValue = env.PATH || env.Path || env.path || "";
43
+ const names = executableNames(command, env, platform);
44
+ const hasPathSeparator =
45
+ path.isAbsolute(command) || command.includes("/") || command.includes("\\");
46
+
47
+ if (hasPathSeparator) {
48
+ return names.some((name) =>
49
+ executableFile(path.isAbsolute(name) ? name : path.resolve(cwd, name), platform),
50
+ );
51
+ }
52
+
53
+ return pathValue.split(separator).some((entry) => {
54
+ const directory = entry ? entry.replace(/^"(.*)"$/, "$1") : cwd;
55
+ return names.some((name) => executableFile(path.join(directory, name), platform));
56
+ });
57
+ }
58
+
59
+ module.exports = { commandExists };
package/lib/setup.js CHANGED
@@ -17,6 +17,7 @@ const {
17
17
  installPiRuntime,
18
18
  reportPiRuntimeSummary,
19
19
  } = require("./pi-runtime");
20
+ const { commandExists } = require("./path-lookup");
20
21
 
21
22
  const https = require("node:https");
22
23
 
@@ -154,6 +155,45 @@ function slugifyName(name) {
154
155
  .replace(/^-|-$/g, "");
155
156
  }
156
157
 
158
+ /**
159
+ * Choose an install directory without ever adopting an unrelated checkout.
160
+ *
161
+ * Most Egregore forks are named "egregore", so deriving the target only from
162
+ * the fork basename makes different organizations collide in the same parent
163
+ * directory. If that default path is already a Git checkout with another
164
+ * origin, leave it untouched and use egregore-{org-slug}. The fallback must
165
+ * also be absent or point at the requested fork; otherwise stop rather than
166
+ * guessing at another path.
167
+ */
168
+ function resolveEgregoreInstallDir(base, forkUrl, slug) {
169
+ const forkDirName = forkUrl.split("/").pop().replace(/\.git$/, "");
170
+ const requestedDir = path.join(base, forkDirName);
171
+ const requestedGitPath = path.join(requestedDir, ".git");
172
+
173
+ if (!fs.existsSync(requestedGitPath) || gitRemoteMatches(requestedDir, forkUrl)) {
174
+ return { egregoreDir: requestedDir, redirectedFrom: null };
175
+ }
176
+
177
+ const safeSlug = slugifyName(slug) || "instance";
178
+ const fallbackDir = path.join(base, `egregore-${safeSlug}`);
179
+ if (path.resolve(fallbackDir) === path.resolve(requestedDir)) {
180
+ throw new Error(
181
+ `Refusing to install into ${requestedDir}: its Git origin does not match ${forkUrl}`
182
+ );
183
+ }
184
+
185
+ if (fs.existsSync(fallbackDir)) {
186
+ const fallbackGitPath = path.join(fallbackDir, ".git");
187
+ if (!fs.existsSync(fallbackGitPath) || !gitRemoteMatches(fallbackDir, forkUrl)) {
188
+ throw new Error(
189
+ `Refusing to install into ${fallbackDir}: the fallback path already belongs to another checkout or directory`
190
+ );
191
+ }
192
+ }
193
+
194
+ return { egregoreDir: fallbackDir, redirectedFrom: requestedDir };
195
+ }
196
+
157
197
  function normalizeUsageType(data = {}) {
158
198
  if (data.usage_type === "founder_group" || data.usage_type === "joiner_group") {
159
199
  return data.usage_type;
@@ -341,8 +381,17 @@ async function install(data, ui, targetDir, opts = {}) {
341
381
  const preferredRuntime = normalizeRuntime(opts.runtime);
342
382
 
343
383
  // Directory name from fork URL (what git clone would use), e.g. "egregore"
344
- const forkDirName = fork_url.split("/").pop().replace(/\.git$/, "");
345
- const egregoreDir = path.join(base, forkDirName);
384
+ let forkDirName = fork_url.split("/").pop().replace(/\.git$/, "");
385
+ const {
386
+ egregoreDir,
387
+ redirectedFrom,
388
+ } = resolveEgregoreInstallDir(base, fork_url, slug || github_org || org_name);
389
+ if (redirectedFrom) {
390
+ forkDirName = path.basename(egregoreDir);
391
+ ui.warn(
392
+ `${redirectedFrom} belongs to another Git origin — leaving it untouched and installing at ${egregoreDir}`
393
+ );
394
+ }
346
395
  const memoryDirName = memory_url
347
396
  .split("/")
348
397
  .pop()
@@ -953,10 +1002,6 @@ function installCodexSkills(egregoreDir) {
953
1002
  return false;
954
1003
  }
955
1004
 
956
- function commandExists(bin) {
957
- return spawnSync("which", [bin], { stdio: "pipe" }).status === 0;
958
- }
959
-
960
1005
  function registerInstance(slug, name, egregoreDir, runtime) {
961
1006
  const registryDir = path.join(os.homedir(), ".egregore");
962
1007
  const registryFile = path.join(registryDir, "instances.json");
@@ -1433,5 +1478,6 @@ module.exports = {
1433
1478
  initMemoryDirs,
1434
1479
  ensureDevelop,
1435
1480
  ensureConnectedConfig,
1481
+ resolveEgregoreInstallDir,
1436
1482
  run,
1437
1483
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-egregore",
3
- "version": "0.19.21",
3
+ "version": "0.19.22",
4
4
  "description": "Set up Egregore for your team in one command — installs the egregore launcher and your choice of Claude Code, Codex, or Pi.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -12,7 +12,7 @@
12
12
  "scripts": {
13
13
  "build:runtime": "node scripts/build-runtime-bundle.mjs && node scripts/build-pi-runtime-bundle.mjs",
14
14
  "build:pi-runtime": "node scripts/build-pi-runtime-bundle.mjs",
15
- "test": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/context.test.js test/parse-join-target.test.js test/skip-repos.test.js test/onboarding-shortcircuit.test.js test/welcome-screen.test.js test/runtime-selection.test.js test/command-generation.test.js test/auth-gh.test.js test/gauntlet-fixes.test.js test/codex-runtime.test.js test/pi-runtime.test.js test/pi-product-workflows.test.js test/installer-runtime-source.test.js test/scroll-repro.test.js test/launcher-refocus-redraw.test.js test/multiselect-remote-search.test.js test/back-navigation.test.js test/manifest-form.test.js test/launcher-delete.test.js test/launcher-connect.test.js test/launcher-connected-status.test.js test/launcher-permissions.test.js test/launcher-update.test.js test/connected-config.test.js",
15
+ "test": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/context.test.js test/path-lookup.test.js test/nixos-portability.test.js test/parse-join-target.test.js test/skip-repos.test.js test/install-origin-guard.test.js test/onboarding-shortcircuit.test.js test/welcome-screen.test.js test/runtime-selection.test.js test/command-generation.test.js test/auth-gh.test.js test/gauntlet-fixes.test.js test/codex-runtime.test.js test/pi-runtime.test.js test/pi-product-workflows.test.js test/installer-runtime-source.test.js test/scroll-repro.test.js test/launcher-refocus-redraw.test.js test/multiselect-remote-search.test.js test/back-navigation.test.js test/manifest-form.test.js test/launcher-delete.test.js test/launcher-connect.test.js test/launcher-connected-status.test.js test/launcher-permissions.test.js test/launcher-update.test.js test/connected-config.test.js",
16
16
  "test:e2e": "node --test test/e2e-local.test.js",
17
17
  "test:all": "node scripts/build-runtime-bundle.mjs --check && node scripts/build-pi-runtime-bundle.mjs --check && node --test test/"
18
18
  },
@@ -0,0 +1,66 @@
1
+ # External notification consent
2
+
3
+ This protocol applies to every Telegram, Teams, or other external notification
4
+ in every harness. It applies even when the user asked to announce, notify,
5
+ handoff, invite, or message someone, and even when the harness is running with
6
+ broad tool permissions.
7
+
8
+ ## Invariant
9
+
10
+ Never dispatch an external notification until the human has approved that one
11
+ exact delivery in a dedicated checkpoint. The checkpoint must show:
12
+
13
+ - the organization;
14
+ - the final recipient or group;
15
+ - every channel that will receive it;
16
+ - the exact final message, including links.
17
+
18
+ A workflow request, plan approval, batch approval, prior approval, broad
19
+ permission mode, or approval of a related action is not notification consent.
20
+ There is no standing "always allow" choice. One approval authorizes one attempt
21
+ to send one immutable message.
22
+
23
+ ## Required flow
24
+
25
+ 1. Finish the message first. Publish any artifact and insert its real URL
26
+ before planning; never change the message after preview.
27
+ 2. Resolve the exact delivery without sending:
28
+
29
+ ```bash
30
+ PLAN_JSON=$(bash bin/notify.sh plan send "$RECIPIENT" "$MESSAGE")
31
+ # or
32
+ PLAN_JSON=$(bash bin/notify.sh plan group "$MESSAGE")
33
+ ```
34
+
35
+ 3. Read `plan_id` and `digest` from `PLAN_JSON`. Show the organization,
36
+ recipient, all `channels`/`deliveries`, and exact `message` in a dedicated
37
+ Send / Edit / Cancel question. Use the harness's structured question UI
38
+ when available. Otherwise show the same fields in plain text and stop for
39
+ the user's answer.
40
+ 4. Only if the user selects Send for that exact preview:
41
+
42
+ ```bash
43
+ APPROVAL_JSON=$(bash bin/notify.sh approve \
44
+ "$PLAN_ID" "$DIGEST" APPROVE_EXACT_NOTIFICATION)
45
+ APPROVAL_TOKEN=$(printf '%s' "$APPROVAL_JSON" | jq -r '.approval_token')
46
+ bash bin/notify.sh dispatch "$PLAN_ID" "$APPROVAL_TOKEN"
47
+ ```
48
+
49
+ 5. If the user chooses Edit, cancel the old plan, edit, create a new plan, and
50
+ preview again. If they choose Cancel, cancel it and do not send. If the plan
51
+ expires or dispatch fails, create a new plan and obtain new consent; never
52
+ retry from the old approval.
53
+
54
+ ## Hard rules
55
+
56
+ - Never call notification API endpoints directly. Use `bin/notify.sh`.
57
+ - Never use legacy `notify.sh send` or `notify.sh group`; they only create a
58
+ proposal and intentionally cannot dispatch.
59
+ - Never substitute a group when a direct message cannot be delivered.
60
+ - Never add a channel after preview.
61
+ - Never approve or dispatch from a detached/background process, hook, cron
62
+ job, batch execution, or unattended agent. Those paths may create a plan and
63
+ report that human approval is pending.
64
+ - Multiple direct recipients require a separate preview and approval for each
65
+ exact message. A group fanout may use one approval only when every receiving
66
+ channel is listed in the preview.
@@ -145,8 +145,19 @@ function currentAuthor(projectDir) {
145
145
  }
146
146
  }
147
147
 
148
- function isProtectedBranch(branch) {
149
- return branch === "develop" || branch === "main" || branch === "master";
148
+ function configuredBaseBranch(projectDir) {
149
+ try {
150
+ const raw = fs.readFileSync(path.join(projectDir, "egregore.json"), "utf-8");
151
+ const value = JSON.parse(raw).base_branch;
152
+ return typeof value === "string" && value.trim() ? value.trim() : "develop";
153
+ } catch {
154
+ return "develop";
155
+ }
156
+ }
157
+
158
+ function isProtectedBranch(branch, projectDir) {
159
+ return branch === configuredBaseBranch(projectDir) ||
160
+ branch === "develop" || branch === "main" || branch === "master";
150
161
  }
151
162
 
152
163
  function isExemptPath(rawPath, projectDir, memoryDir) {
@@ -403,7 +414,7 @@ function main() {
403
414
  if (context.external) return;
404
415
  const projectDir = context.projectDir;
405
416
  const branch = currentBranch(projectDir);
406
- if (!isProtectedBranch(branch)) return;
417
+ if (!isProtectedBranch(branch, projectDir)) return;
407
418
 
408
419
  // Consent bypass: the user explicitly chose to work on this protected branch.
409
420
  // Written only after they pick "Proceed on <branch>"; cleared on session start,
@@ -17,9 +17,13 @@ when it is available; otherwise render compact numbered choices with an
17
17
 
18
18
  1. Read `.claude/skills/add/SKILL.md` for the workflow details.
19
19
  2. Run the referenced `bin/` scripts directly from Codex.
20
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
21
- explicitly says they are required.
22
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
20
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
21
+ says they are required.
22
+ 4. For every external notification, follow
23
+ `.claude/context/notification-consent.md`: plan without sending, then show
24
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
25
+ consent from the workflow request or a batch approval.
26
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
23
27
  calls when `egregore.json` declares `"mode": "local"`.
24
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
28
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
25
29
  handoffs.
@@ -22,33 +22,46 @@ bash bin/publish-artifact.sh document "$FILE_PATH" --title "$TITLE" --author "$A
22
22
  Use `handoff`, `quest`, or `document` as the artifact type when appropriate.
23
23
  Never fabricate a URL.
24
24
 
25
- 3. Preview the exact message. Confirm with structured Codex question tooling
26
- when available; otherwise render:
25
+ 3. Follow `.claude/context/notification-consent.md`. Create a plan without
26
+ sending:
27
+
28
+ ```bash
29
+ PLAN_JSON=$(bash bin/notify.sh plan group "$MESSAGE")
30
+ ```
31
+
32
+ 4. Preview the plan's exact organization, all deliveries/channels, and exact
33
+ final message. Confirm in a separate checkpoint with structured Codex
34
+ question tooling when available; otherwise render those fields followed by:
27
35
 
28
36
  ```text
29
37
  Send this announcement?
30
38
  1. Send
31
39
  2. Edit
32
- Other:
40
+ 3. Cancel
33
41
  ```
34
42
 
35
- 4. If the user edits, redraft and preview again. If they approve, run:
43
+ 5. If the user edits, cancel the old plan, redraft, plan, and preview again.
44
+ If they cancel, cancel the plan and stop. Only after they select Send for
45
+ that exact preview, run:
36
46
 
37
47
  ```bash
38
- bash bin/notify.sh group "$MESSAGE"
48
+ APPROVAL_JSON=$(bash bin/notify.sh approve "$PLAN_ID" "$DIGEST" APPROVE_EXACT_NOTIFICATION)
49
+ APPROVAL_TOKEN=$(printf '%s' "$APPROVAL_JSON" | jq -r '.approval_token')
50
+ bash bin/notify.sh dispatch "$PLAN_ID" "$APPROVAL_TOKEN"
39
51
  ```
40
52
 
41
- 5. Emit telemetry in the background:
53
+ 6. Emit telemetry in the background:
42
54
 
43
55
  ```bash
44
56
  bash bin/telemetry.sh emit "command" '{"command":"announce"}' >/dev/null 2>&1 &
45
57
  ```
46
58
 
47
- 6. Confirm whether the group send succeeded.
59
+ 7. Confirm whether the exact approved group send succeeded.
48
60
 
49
61
  ## Rules
50
62
 
51
- - Always preview before sending.
63
+ - The request to announce is not dispatch consent. Always use a dedicated
64
+ exact-delivery checkpoint.
52
65
  - Do not expose notification credentials.
53
66
  - Use `bin/notify.sh`; do not call Telegram directly.
54
67
  - Do not use Claude Code commands.
@@ -17,9 +17,13 @@ when it is available; otherwise render compact numbered choices with an
17
17
 
18
18
  1. Read `.claude/skills/answer/SKILL.md` for the workflow details.
19
19
  2. Run the referenced `bin/` scripts directly from Codex.
20
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
21
- explicitly says they are required.
22
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
20
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
21
+ says they are required.
22
+ 4. For every external notification, follow
23
+ `.claude/context/notification-consent.md`: plan without sending, then show
24
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
25
+ consent from the workflow request or a batch approval.
26
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
23
27
  calls when `egregore.json` declares `"mode": "local"`.
24
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
28
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
25
29
  handoffs.
@@ -33,9 +33,13 @@ reading `.claude/skills/archive/SKILL.md`, reproduce the same visible UX in Code
33
33
 
34
34
  1. Read `.claude/skills/archive/SKILL.md` for the workflow details.
35
35
  2. Run the referenced `bin/` scripts directly from Codex.
36
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
37
- explicitly says they are required.
38
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
36
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
37
+ says they are required.
38
+ 4. For every external notification, follow
39
+ `.claude/context/notification-consent.md`: plan without sending, then show
40
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
41
+ consent from the workflow request or a batch approval.
42
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
39
43
  calls when `egregore.json` declares `"mode": "local"`.
40
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
44
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
41
45
  handoffs.
@@ -21,8 +21,8 @@ question, run a topic by someone, or inspect pending questions for themselves.
21
21
  tooling when available; otherwise render:
22
22
 
23
23
  ```text
24
- Send these questions?
25
- 1. Send as-is
24
+ Save these questions?
25
+ 1. Save as-is
26
26
  2. Edit
27
27
  Other:
28
28
  ```
@@ -37,13 +37,20 @@ Add harvest flags only when this ask is part of a harvest:
37
37
  `--harvest-id`, `--harvest-session-id`, `--turn`, `--question-intent`, and
38
38
  `--context-mode`.
39
39
 
40
- 7. In connected mode, notify best-effort with:
40
+ 7. In connected mode, follow
41
+ `.claude/context/notification-consent.md`. Saving the questions is not
42
+ notification consent. Prepare without sending:
41
43
 
42
44
  ```bash
43
- bash bin/notify.sh send "$TARGET" "$AUTHOR has a question about \"$TOPIC\". Ask for \$activity to answer."
45
+ PLAN_JSON=$(bash bin/notify.sh plan send "$TARGET" "$AUTHOR has a question about \"$TOPIC\". Ask for \$activity to answer.")
44
46
  ```
45
47
 
46
- 8. Report the created `memory/knowledge/questions/...` path.
48
+ Show the exact organization, recipient, channel, and message in a separate
49
+ Send / Edit / Cancel checkpoint. Only a Send response to that preview permits
50
+ one approve + dispatch.
51
+
52
+ 8. Report the created `memory/knowledge/questions/...` path and the truthful
53
+ notification state.
47
54
 
48
55
  ## Inward Mode
49
56
 
@@ -54,6 +61,7 @@ answers.
54
61
 
55
62
  ## Rules
56
63
 
57
- - Person-targeted asks are asynchronous: store, optionally notify, then stop.
64
+ - Person-targeted asks are asynchronous: store first; notification is a
65
+ separate exact-consent action.
58
66
  - Local mode is filesystem-only; skip graph and notification calls.
59
67
  - Do not use Claude Code commands.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: audit
3
+ description: 'Fallback Codex adapter for the Egregore audit workflow.'
4
+ ---
5
+
6
+ <!-- generated-by: bin/codex-sync-skills.sh -->
7
+
8
+ # Egregore audit Adapter
9
+
10
+ This is fallback coverage for a long-tail Egregore workflow that has not been
11
+ ported to a hand-written Codex-native skill yet.
12
+
13
+ Use the project shell and filesystem directly. Do not invoke Claude Code
14
+ commands. Translate interactive choices to structured Codex question tooling
15
+ when it is available; otherwise render compact numbered choices with an
16
+ `Other:` option and wait for the user.
17
+
18
+ 1. Read `.claude/skills/audit/SKILL.md` for the workflow details.
19
+ 2. Run the referenced `bin/` scripts directly from Codex.
20
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
21
+ says they are required.
22
+ 4. For every external notification, follow
23
+ `.claude/context/notification-consent.md`: plan without sending, then show
24
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
25
+ consent from the workflow request or a batch approval.
26
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
27
+ calls when `egregore.json` declares `"mode": "local"`.
28
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
29
+ handoffs.
@@ -0,0 +1,29 @@
1
+ ---
2
+ name: autosave
3
+ description: 'View or change your personal autosave settings, and merge staged auto-save PRs. The consent surface for ambient session capture.'
4
+ ---
5
+
6
+ <!-- generated-by: bin/codex-sync-skills.sh -->
7
+
8
+ # Egregore autosave Adapter
9
+
10
+ This is fallback coverage for a long-tail Egregore workflow that has not been
11
+ ported to a hand-written Codex-native skill yet.
12
+
13
+ Use the project shell and filesystem directly. Do not invoke Claude Code
14
+ commands. Translate interactive choices to structured Codex question tooling
15
+ when it is available; otherwise render compact numbered choices with an
16
+ `Other:` option and wait for the user.
17
+
18
+ 1. Read `.claude/skills/autosave/SKILL.md` for the workflow details.
19
+ 2. Run the referenced `bin/` scripts directly from Codex.
20
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
21
+ says they are required.
22
+ 4. For every external notification, follow
23
+ `.claude/context/notification-consent.md`: plan without sending, then show
24
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
25
+ consent from the workflow request or a batch approval.
26
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
27
+ calls when `egregore.json` declares `"mode": "local"`.
28
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
29
+ handoffs.
@@ -17,9 +17,13 @@ when it is available; otherwise render compact numbered choices with an
17
17
 
18
18
  1. Read `.claude/skills/branch/SKILL.md` for the workflow details.
19
19
  2. Run the referenced `bin/` scripts directly from Codex.
20
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
21
- explicitly says they are required.
22
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
20
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
21
+ says they are required.
22
+ 4. For every external notification, follow
23
+ `.claude/context/notification-consent.md`: plan without sending, then show
24
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
25
+ consent from the workflow request or a batch approval.
26
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
23
27
  calls when `egregore.json` declares `"mode": "local"`.
24
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
28
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
25
29
  handoffs.
@@ -33,9 +33,13 @@ reading `.claude/skills/checkup/SKILL.md`, reproduce the same visible UX in Code
33
33
 
34
34
  1. Read `.claude/skills/checkup/SKILL.md` for the workflow details.
35
35
  2. Run the referenced `bin/` scripts directly from Codex.
36
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
37
- explicitly says they are required.
38
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
36
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
37
+ says they are required.
38
+ 4. For every external notification, follow
39
+ `.claude/context/notification-consent.md`: plan without sending, then show
40
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
41
+ consent from the workflow request or a batch approval.
42
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
39
43
  calls when `egregore.json` declares `"mode": "local"`.
40
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
44
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
41
45
  handoffs.
@@ -17,9 +17,13 @@ when it is available; otherwise render compact numbered choices with an
17
17
 
18
18
  1. Read `.claude/skills/commit/SKILL.md` for the workflow details.
19
19
  2. Run the referenced `bin/` scripts directly from Codex.
20
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
21
- explicitly says they are required.
22
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
20
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
21
+ says they are required.
22
+ 4. For every external notification, follow
23
+ `.claude/context/notification-consent.md`: plan without sending, then show
24
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
25
+ consent from the workflow request or a batch approval.
26
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
23
27
  calls when `egregore.json` declares `"mode": "local"`.
24
- 5. Never call the deprecated `egregore-handoff` CLI for Egregore project
28
+ 6. Never call the deprecated `egregore-handoff` CLI for Egregore project
25
29
  handoffs.