create-egregore 0.19.21 → 0.19.23

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 (229) 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 +81 -10
  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-skill-render.mjs +5 -0
  81. package/runtime/codex/bin/codex-sync-skills.sh +9 -5
  82. package/runtime/codex/bin/dashboard-data.sh +1 -1
  83. package/runtime/codex/bin/graph-batch.sh +1 -1
  84. package/runtime/codex/bin/graph-op.sh +1 -1
  85. package/runtime/codex/bin/graph-wal.sh +1 -1
  86. package/runtime/codex/bin/graph.sh +1 -1
  87. package/runtime/codex/bin/handoff-pr-backfill.sh +1 -1
  88. package/runtime/codex/bin/handoff-run.sh +117 -119
  89. package/runtime/codex/bin/handoff-save-egregore.sh +62 -32
  90. package/runtime/codex/bin/index-handoff.sh +3 -2
  91. package/runtime/codex/bin/ingest-graph.sh +1 -1
  92. package/runtime/codex/bin/ingest.sh +1 -1
  93. package/runtime/codex/bin/lib/artifact-id.sh +1 -1
  94. package/runtime/codex/bin/lib/config.sh +56 -20
  95. package/runtime/codex/bin/lib/context.sh +7 -1
  96. package/runtime/codex/bin/lib/ensure-develop.sh +1 -1
  97. package/runtime/codex/bin/lib/git-sync.sh +145 -59
  98. package/runtime/codex/bin/lib/greeting.sh +14 -0
  99. package/runtime/codex/bin/lib/hash.sh +1 -1
  100. package/runtime/codex/bin/lib/noncode.sh +1 -1
  101. package/runtime/codex/bin/lib/time.sh +1 -1
  102. package/runtime/codex/bin/notify.sh +492 -153
  103. package/runtime/codex/bin/person.sh +1 -1
  104. package/runtime/codex/bin/publish-artifact.sh +64 -8
  105. package/runtime/codex/bin/publish-references.sh +1 -1
  106. package/runtime/codex/bin/repo-state.sh +7 -10
  107. package/runtime/codex/bin/search.sh +1 -1
  108. package/runtime/codex/bin/session-autosave.sh +1 -1
  109. package/runtime/codex/bin/session-log.sh +1 -1
  110. package/runtime/codex/bin/settings.sh +32 -2
  111. package/runtime/codex/bin/telemetry.sh +1 -1
  112. package/runtime/codex/bin/worktree-create.sh +14 -4
  113. package/runtime/codex/bin/worktree-remove.sh +1 -1
  114. package/runtime/codex/bin/worktree.sh +1 -1
  115. package/runtime/codex/manifest.json +18 -1
  116. package/runtime/pi/.claude/context/notification-consent.md +66 -0
  117. package/runtime/pi/.codex/hooks/branch-guard.js +14 -3
  118. package/runtime/pi/.codex/skills/add/SKILL.md +8 -4
  119. package/runtime/pi/.codex/skills/announce/SKILL.md +21 -8
  120. package/runtime/pi/.codex/skills/answer/SKILL.md +8 -4
  121. package/runtime/pi/.codex/skills/archive/SKILL.md +8 -4
  122. package/runtime/pi/.codex/skills/ask/SKILL.md +14 -6
  123. package/runtime/pi/.codex/skills/audit/SKILL.md +29 -0
  124. package/runtime/pi/.codex/skills/autosave/SKILL.md +29 -0
  125. package/runtime/pi/.codex/skills/branch/SKILL.md +8 -4
  126. package/runtime/pi/.codex/skills/checkup/SKILL.md +8 -4
  127. package/runtime/pi/.codex/skills/commit/SKILL.md +8 -4
  128. package/runtime/pi/.codex/skills/contribute/SKILL.md +8 -4
  129. package/runtime/pi/.codex/skills/dark-mode/SKILL.md +8 -4
  130. package/runtime/pi/.codex/skills/delete-user/SKILL.md +8 -4
  131. package/runtime/pi/.codex/skills/demo-mode/SKILL.md +29 -0
  132. package/runtime/pi/.codex/skills/deploy-bridge/SKILL.md +8 -4
  133. package/runtime/pi/.codex/skills/design/SKILL.md +29 -0
  134. package/runtime/pi/.codex/skills/egregore-voice/SKILL.md +8 -4
  135. package/runtime/pi/.codex/skills/emissary/SKILL.md +8 -4
  136. package/runtime/pi/.codex/skills/env/SKILL.md +8 -4
  137. package/runtime/pi/.codex/skills/handoff/SKILL.md +81 -10
  138. package/runtime/pi/.codex/skills/harvest/QUESTION_PALETTE.md +76 -0
  139. package/runtime/pi/.codex/skills/harvest/SKILL.md +30 -6
  140. package/runtime/pi/.codex/skills/ingest/SKILL.md +8 -4
  141. package/runtime/pi/.codex/skills/ingest-google/SKILL.md +8 -4
  142. package/runtime/pi/.codex/skills/ingest-user-interview/SKILL.md +8 -4
  143. package/runtime/pi/.codex/skills/invite/SKILL.md +6 -2
  144. package/runtime/pi/.codex/skills/issue/SKILL.md +8 -4
  145. package/runtime/pi/.codex/skills/me/SKILL.md +8 -4
  146. package/runtime/pi/.codex/skills/meeting/SKILL.md +8 -4
  147. package/runtime/pi/.codex/skills/minion/SKILL.md +8 -4
  148. package/runtime/pi/.codex/skills/mock/SKILL.md +29 -0
  149. package/runtime/pi/.codex/skills/note/SKILL.md +8 -4
  150. package/runtime/pi/.codex/skills/onboarding/SKILL.md +8 -4
  151. package/runtime/pi/.codex/skills/pr/SKILL.md +8 -4
  152. package/runtime/pi/.codex/skills/product-voice/SKILL.md +29 -0
  153. package/runtime/pi/.codex/skills/project/SKILL.md +8 -4
  154. package/runtime/pi/.codex/skills/pull/SKILL.md +8 -4
  155. package/runtime/pi/.codex/skills/push/SKILL.md +8 -4
  156. package/runtime/pi/.codex/skills/quest/SKILL.md +6 -3
  157. package/runtime/pi/.codex/skills/quest-suggest/SKILL.md +8 -4
  158. package/runtime/pi/.codex/skills/reflect/SKILL.md +8 -4
  159. package/runtime/pi/.codex/skills/review-pr/SKILL.md +8 -4
  160. package/runtime/pi/.codex/skills/save/SKILL.md +6 -4
  161. package/runtime/pi/.codex/skills/scroll/SKILL.md +92 -23
  162. package/runtime/pi/.codex/skills/scroll/assets/shell.html +381 -52
  163. package/runtime/pi/.codex/skills/session-view/SKILL.md +8 -4
  164. package/runtime/pi/.codex/skills/setup/SKILL.md +8 -4
  165. package/runtime/pi/.codex/skills/summon/SKILL.md +8 -4
  166. package/runtime/pi/.codex/skills/sync-repos/SKILL.md +8 -4
  167. package/runtime/pi/.codex/skills/task/SKILL.md +9 -5
  168. package/runtime/pi/.codex/skills/teams-connect/SKILL.md +29 -0
  169. package/runtime/pi/.codex/skills/telegram-connect/SKILL.md +8 -4
  170. package/runtime/pi/.codex/skills/telemetry/SKILL.md +8 -4
  171. package/runtime/pi/.codex/skills/test/SKILL.md +8 -4
  172. package/runtime/pi/.codex/skills/thread/SKILL.md +8 -4
  173. package/runtime/pi/.codex/skills/todo/SKILL.md +8 -4
  174. package/runtime/pi/.codex/skills/tui-design/SKILL.md +8 -4
  175. package/runtime/pi/.codex/skills/tutorial/SKILL.md +8 -4
  176. package/runtime/pi/.codex/skills/update/SKILL.md +8 -4
  177. package/runtime/pi/.codex/skills/visual-explain/SKILL.md +8 -4
  178. package/runtime/pi/.codex/spec-manifest.json +4 -4
  179. package/runtime/pi/.pi/APPEND_SYSTEM.md +34 -12
  180. package/runtime/pi/.pi/extensions/egregore.ts +8 -1
  181. package/runtime/pi/.pi/spec-manifest.json +2 -2
  182. package/runtime/pi/AGENTS.md +36 -14
  183. package/runtime/pi/bin/activity-data.sh +1 -1
  184. package/runtime/pi/bin/agent.sh +38 -19
  185. package/runtime/pi/bin/attendant.sh +8 -2
  186. package/runtime/pi/bin/autosave.sh +1 -1
  187. package/runtime/pi/bin/capture-reconcile.sh +8 -6
  188. package/runtime/pi/bin/capture-run.sh +1 -1
  189. package/runtime/pi/bin/codex-install-skills.sh +1 -1
  190. package/runtime/pi/bin/codex-render-spec.mjs +12 -5
  191. package/runtime/pi/bin/codex-session-start.sh +1 -1
  192. package/runtime/pi/bin/codex-skill-render.mjs +5 -0
  193. package/runtime/pi/bin/codex-sync-skills.sh +9 -5
  194. package/runtime/pi/bin/dashboard-data.sh +1 -1
  195. package/runtime/pi/bin/graph-batch.sh +1 -1
  196. package/runtime/pi/bin/graph-op.sh +1 -1
  197. package/runtime/pi/bin/graph-wal.sh +1 -1
  198. package/runtime/pi/bin/graph.sh +1 -1
  199. package/runtime/pi/bin/handoff-pr-backfill.sh +1 -1
  200. package/runtime/pi/bin/handoff-run.sh +117 -119
  201. package/runtime/pi/bin/handoff-save-egregore.sh +62 -32
  202. package/runtime/pi/bin/index-handoff.sh +3 -2
  203. package/runtime/pi/bin/ingest-graph.sh +1 -1
  204. package/runtime/pi/bin/ingest.sh +1 -1
  205. package/runtime/pi/bin/lib/artifact-id.sh +1 -1
  206. package/runtime/pi/bin/lib/config.sh +56 -20
  207. package/runtime/pi/bin/lib/context.sh +7 -1
  208. package/runtime/pi/bin/lib/ensure-develop.sh +1 -1
  209. package/runtime/pi/bin/lib/git-sync.sh +145 -59
  210. package/runtime/pi/bin/lib/greeting.sh +14 -0
  211. package/runtime/pi/bin/lib/hash.sh +1 -1
  212. package/runtime/pi/bin/lib/noncode.sh +1 -1
  213. package/runtime/pi/bin/lib/time.sh +1 -1
  214. package/runtime/pi/bin/notify.sh +492 -153
  215. package/runtime/pi/bin/person.sh +1 -1
  216. package/runtime/pi/bin/pi-product-workflows.mjs +14 -5
  217. package/runtime/pi/bin/pi-session-start.sh +1 -1
  218. package/runtime/pi/bin/publish-artifact.sh +64 -8
  219. package/runtime/pi/bin/publish-references.sh +1 -1
  220. package/runtime/pi/bin/repo-state.sh +7 -10
  221. package/runtime/pi/bin/search.sh +1 -1
  222. package/runtime/pi/bin/session-autosave.sh +1 -1
  223. package/runtime/pi/bin/session-log.sh +1 -1
  224. package/runtime/pi/bin/settings.sh +32 -2
  225. package/runtime/pi/bin/telemetry.sh +1 -1
  226. package/runtime/pi/bin/worktree-create.sh +14 -4
  227. package/runtime/pi/bin/worktree-remove.sh +1 -1
  228. package/runtime/pi/bin/worktree.sh +1 -1
  229. package/runtime/pi/manifest.json +18 -1
@@ -179,11 +179,18 @@ const ON_LAUNCH_BODY = `The \`egregore\` launcher renders the Egregore startup c
179
179
 
180
180
  const AFTER_GREETING_BODY = `**Mandatory behavioral rule.** When the user describes work, your **first action** — before reading files, exploring code, or anything else — is to get onto a working branch:
181
181
 
182
+ The integration branch is \`develop\` by default. When top-level
183
+ \`egregore.json.base_branch\` is set, that configured branch replaces
184
+ \`develop\` as the branch point, rebase target, PR base, and protected
185
+ integration branch.
186
+
182
187
  1. Derive a topic slug from what the user said (kebab-case, 2–4 words)
183
- 2. Run \`bin/agent.sh branch --topic "<topic>"\` — it creates a work branch from \`origin/develop\` in a task worktree (\`dev/{author}/{slug}\`, or \`feature/{slug}\` / \`bugfix/{slug}\` when the topic reads as a feature or fix) and prints the worktree path. Continue all file work from that printed path.
188
+ 2. Run \`bin/agent.sh branch --topic "<topic>"\` — it resolves the configured base and creates a work branch from \`origin/{base}\` in a task worktree (\`dev/{author}/{slug}\`, or \`feature/{slug}\` / \`bugfix/{slug}\` when the topic reads as a feature or fix). Continue all file work from the printed path.
184
189
  3. Confirm: \`On {branch} (worktree).\`
185
190
 
186
- **Fallback:** If \`bin/agent.sh branch\` fails, use \`git checkout -b dev/{author}/{slug} origin/develop\`.
191
+ **Fallback:** If \`bin/agent.sh branch\` fails, resolve \`{base}\` with
192
+ \`_get_base_branch\`, then use
193
+ \`git checkout -b dev/{author}/{slug} origin/{base}\`.
187
194
 
188
195
  4. Update graph (fire-and-forget): \`bash bin/graph-op.sh set-topic "$(cat .egregore-session-id 2>/dev/null)" "topic from slug" "dev/author/slug" 2>/dev/null &\`
189
196
 
@@ -215,11 +222,11 @@ Report results: \`✓ Checked out {branch} in {repo1}, {repo2}\`. If a branch no
215
222
 
216
223
  **Topic pivot while on a working branch:** If the user describes work **unrelated** to the current branch's topic, treat it as a new topic and create a new branch (\`bin/agent.sh branch --topic "<new topic>"\`). Do NOT mix unrelated work on one branch.
217
224
 
218
- If on develop after two messages, create a branch immediately from whatever context you have.
225
+ If still on the configured base branch after two messages, create a branch immediately from whatever context you have.
219
226
 
220
227
  ### Branch-guard protocol
221
228
 
222
- The \`.codex/hooks/branch-guard.js\` PreToolUse hook (enabled by the launcher via \`--enable hooks\`) protects project writes on \`develop\`/\`main\`/\`master\`. Its block message is operational guidance, not a reason to interrupt the user with routine Git choices:
229
+ The \`.codex/hooks/branch-guard.js\` PreToolUse hook (enabled by the launcher via \`--enable hooks\`) protects project writes on the configured base branch as well as \`develop\`/\`main\`/\`master\`. Its block message is operational guidance, not a reason to interrupt the user with routine Git choices:
223
230
 
224
231
  - **Topic is clear** (the user said "fix X", "add Y feature") → run \`bin/agent.sh branch --topic "<topic>"\` automatically, continue in the printed worktree, and say one short sentence so the branch change is visible. Do not ask the user to approve routine branching.
225
232
  - **Topic is genuinely ambiguous** → ask only for the topic, using compact numbered options:
@@ -236,7 +243,7 @@ The \`.codex/hooks/branch-guard.js\` PreToolUse hook (enabled by the launcher vi
236
243
 
237
244
  Memory, managed-repo, and runtime-state writes should bypass the project guard. If one triggers it, correct the operation target/context instead of asking for protected-branch consent.
238
245
 
239
- If this Codex build does not support hooks, follow the same discipline as a standing instruction: never write or commit on develop/main/master.
246
+ If this Codex build does not support hooks, follow the same discipline as a standing instruction: never write or commit on the configured base, develop, main, or master.
240
247
 
241
248
  ### Onboarding exception
242
249
 
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -o pipefail
3
3
 
4
4
  # Codex does not run Claude Code SessionStart hooks. This is the runtime-neutral
@@ -309,6 +309,7 @@ function renderHandoff(data) {
309
309
  data.graphStatus ? `graph=${data.graphStatus}` : '',
310
310
  data.memoryStatus ? `memory=${data.memoryStatus}` : '',
311
311
  data.notifyStatus ? `notify=${data.notifyStatus}` : '',
312
+ data.publishStatus ? `publish=${data.publishStatus}` : '',
312
313
  ].filter(Boolean).join(' · ');
313
314
 
314
315
  const lines = [topRule(), padLine('⇌ HANDOFF', data.author || ''), rule()];
@@ -317,6 +318,10 @@ function renderHandoff(data) {
317
318
  if (file) lines.push(padLine(`Path: ${file}`));
318
319
  if (data.artifactUrl) lines.push(padLine(`Link: ${data.artifactUrl}`));
319
320
  if (statuses) lines.push(padLine(statuses));
321
+ if (data.publishStatus === 'fidelity-failed') {
322
+ lines.push(rule());
323
+ lines.push(padLine('Artifact not published — restore missing content and preview again.'));
324
+ }
320
325
  lines.push(bottomRule());
321
326
  return lines.join('\n');
322
327
  }
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
 
4
4
  SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
@@ -162,11 +162,15 @@ EOF
162
162
  cat <<EOF
163
163
  1. Read \`${source}\` for the workflow details.
164
164
  2. Run the referenced \`bin/\` scripts directly from Codex.
165
- 3. Treat graph, publish, and notify steps as best-effort unless that workflow
166
- explicitly says they are required.
167
- 4. Keep local-mode behavior filesystem-first and avoid graph or notification
165
+ 3. Treat graph and publish steps as best-effort unless that workflow explicitly
166
+ says they are required.
167
+ 4. For every external notification, follow
168
+ \`.claude/context/notification-consent.md\`: plan without sending, then show
169
+ a separate exact Send / Edit / Cancel checkpoint. Never infer notification
170
+ consent from the workflow request or a batch approval.
171
+ 5. Keep local-mode behavior filesystem-first and avoid graph or notification
168
172
  calls when \`egregore.json\` declares \`"mode": "local"\`.
169
- 5. Never call the deprecated \`egregore-handoff\` CLI for Egregore project
173
+ 6. Never call the deprecated \`egregore-handoff\` CLI for Egregore project
170
174
  handoffs.
171
175
  EOF
172
176
  }
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  # Fetches personal dashboard data: single API call + parallel git ops.
3
3
  # Usage: bash bin/dashboard-data.sh [username] [time_range]
4
4
  # Returns a single JSON object with all query results.
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
 
4
4
  # Execute multiple Cypher queries in a single HTTP call.
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
  # Named graph operations — clean interface over raw Cypher.
4
4
  # Keeps implementation details out of the TUI.
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  # Graph Write-Ahead Log — resilient graph writes with local buffer.
3
3
  # Mirrors bin/telemetry.sh architecture.
4
4
  #
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
 
4
4
  SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  # handoff-pr-backfill.sh — fill in PR numbers in a handoff file's ## Repo State
3
3
  # table, then re-commit + push the memory repo. Detached fire-and-forget from
4
4
  # /handoff's hot path so user-visible latency doesn't include N × `gh pr list`.
@@ -1,4 +1,4 @@
1
- #!/bin/bash
1
+ #!/usr/bin/env bash
2
2
  set -euo pipefail
3
3
  # handoff-run.sh — atomic orchestrator for /handoff.
4
4
  #
@@ -25,7 +25,7 @@ set -euo pipefail
25
25
  # and returns a subgraph snapshot in the result JSON
26
26
  # 6. Commits + pushes memory repo (with orphan-stash dance if needed)
27
27
  # 7. Publishes HTML artifact via bin/publish-artifact.sh
28
- # 8. Sends Telegram notification via bin/notify.sh (if recipient)
28
+ # 8. Creates an exact notification proposal via bin/notify.sh (never sends)
29
29
  # 9. Emits ONE status line and ONE JSON blob on stdout
30
30
  #
31
31
  # Exit codes:
@@ -122,88 +122,63 @@ if [ ! -s "$ABS_FILE" ]; then
122
122
  exit 1
123
123
  fi
124
124
 
125
- # --- Canonical capture contract -----------------------------------------
126
- # /handoff is the addressed door into the shared capture engine. Persist the
127
- # same schema/mode fields used by /wrap and SessionEnd so filesystem and graph
128
- # retrieval can distinguish captures without inferring from directory names.
129
- if ! grep -qiE '^(capture_schema:|\*\*[Cc]apture [Ss]chema\*\*:)' "$ABS_FILE"; then
130
- CAPTURE_KIND=""
131
- if ! grep -qiE '^(kind:|\*\*[Kk]ind\*\*:)' "$ABS_FILE"; then
132
- CAPTURE_KIND="addressed"
133
- fi
134
- if [ "$(head -1 "$ABS_FILE")" = "---" ]; then
135
- awk -v kind="$CAPTURE_KIND" '
136
- NR == 1 {
137
- print
138
- print "capture_schema: egregore-capture/v1"
139
- print "capture_mode: addressed"
140
- if (kind != "") print "kind: " kind
141
- next
142
- }
143
- { print }
144
- ' "$ABS_FILE" > "$ABS_FILE.new" && mv "$ABS_FILE.new" "$ABS_FILE"
145
- else
146
- awk -v kind="$CAPTURE_KIND" '
147
- !injected && /^\*\*[Aa]uthor\*\*:/ {
148
- print
149
- print "**Capture Schema**: egregore-capture/v1"
150
- print "**Capture Mode**: addressed"
151
- if (kind != "") print "**Kind**: " kind
152
- injected=1
153
- next
154
- }
155
- { print }
156
- END {
157
- if (!injected) {
158
- print "**Capture Schema**: egregore-capture/v1"
159
- print "**Capture Mode**: addressed"
160
- if (kind != "") print "**Kind**: " kind
161
- }
162
- }
163
- ' "$ABS_FILE" > "$ABS_FILE.new" && mv "$ABS_FILE.new" "$ABS_FILE"
164
- fi
165
- fi
125
+ # --- Canonical metadata boundary ----------------------------------------
126
+ # Callers are allowed to send prose-only markdown, but persisted handoffs are
127
+ # not. Normalize every input to the same frontmatter contract before indexing
128
+ # or rendering so title/author/recipient cannot disappear at the adapter seam.
129
+ HAS_FRONTMATTER=0
130
+ [ "$(head -1 "$ABS_FILE")" = "---" ] && HAS_FRONTMATTER=1
166
131
 
167
- # --- Inject **To**: line if --recipient given and body omits it -----
168
- # index-handoff.sh parses recipients from the file body. Skills
169
- # normally write the To line themselves, but callers that invoke
170
- # handoff-run.sh directly often skip it. Inject after the Author
171
- # line so the graph gets the HANDED_TO edge.
172
- if [ -n "$RECIPIENT" ] && ! grep -qi "^\*\*[Tt]o\*\*:" "$ABS_FILE"; then
173
- awk -v r="$RECIPIENT" '
174
- !injected && /^\*\*[Aa]uthor\*\*:/ {
175
- print
176
- print "**To**: " r
177
- injected=1
178
- next
179
- }
180
- { print }
181
- ' "$ABS_FILE" > "$ABS_FILE.new" && mv "$ABS_FILE.new" "$ABS_FILE"
182
- fi
132
+ _has_frontmatter_key() {
133
+ [ "$HAS_FRONTMATTER" = "1" ] && sed -n '2,/^---$/p' "$ABS_FILE" | grep -qiE "^${1}:"
134
+ }
183
135
 
184
- # --- Persist lifecycle intent in the canonical handoff file -------------
185
- if ! grep -qiE '^(intent:|\*\*[Ii]ntent\*\*:)' "$ABS_FILE"; then
186
- if [ "$(head -1 "$ABS_FILE")" = "---" ]; then
187
- awk -v intent="$INTENT" '
188
- NR == 1 { print; print "intent: " intent; next }
189
- { print }
190
- ' "$ABS_FILE" > "$ABS_FILE.new" && mv "$ABS_FILE.new" "$ABS_FILE"
191
- else
192
- awk -v intent="$INTENT" '
193
- !injected && /^\*\*[Aa]uthor\*\*:/ {
194
- print
195
- print "**Intent**: " intent
196
- injected=1
197
- next
198
- }
199
- { print }
200
- END {
201
- if (!injected) print "**Intent**: " intent
202
- }
203
- ' "$ABS_FILE" > "$ABS_FILE.new" && mv "$ABS_FILE.new" "$ABS_FILE"
204
- fi
136
+ MISSING_SCHEMA=0; _has_frontmatter_key capture_schema || MISSING_SCHEMA=1
137
+ MISSING_MODE=0; _has_frontmatter_key capture_mode || MISSING_MODE=1
138
+ MISSING_KIND=0; _has_frontmatter_key kind || MISSING_KIND=1
139
+ MISSING_FROM=0; _has_frontmatter_key from || _has_frontmatter_key author || MISSING_FROM=1
140
+ MISSING_DATE=0; _has_frontmatter_key date || MISSING_DATE=1
141
+ MISSING_TOPIC=0; _has_frontmatter_key topic || MISSING_TOPIC=1
142
+ MISSING_INTENT=0; _has_frontmatter_key intent || MISSING_INTENT=1
143
+ MISSING_RECIPIENT=0
144
+ if [ -n "$RECIPIENT" ]; then
145
+ _has_frontmatter_key addressed_to || _has_frontmatter_key to || MISSING_RECIPIENT=1
205
146
  fi
206
147
 
148
+ awk \
149
+ -v has_frontmatter="$HAS_FRONTMATTER" \
150
+ -v schema="$MISSING_SCHEMA" -v mode="$MISSING_MODE" -v kind="$MISSING_KIND" \
151
+ -v from="$MISSING_FROM" -v date_missing="$MISSING_DATE" \
152
+ -v topic_missing="$MISSING_TOPIC" -v intent_missing="$MISSING_INTENT" \
153
+ -v recipient_missing="$MISSING_RECIPIENT" \
154
+ -v author="$AUTHOR" -v date="$TODAY" -v topic="$TOPIC" \
155
+ -v intent="$INTENT" -v recipient="$RECIPIENT" '
156
+ function metadata() {
157
+ if (schema) print "capture_schema: egregore-capture/v1"
158
+ if (mode) print "capture_mode: addressed"
159
+ if (kind) print "kind: addressed"
160
+ if (from) print "from: " author
161
+ if (recipient_missing) print "addressed_to: " recipient
162
+ if (date_missing) print "date: " date
163
+ if (topic_missing) print "topic: " topic
164
+ if (intent_missing) print "intent: " intent
165
+ }
166
+ BEGIN {
167
+ if (!has_frontmatter) {
168
+ print "---"
169
+ metadata()
170
+ print "---"
171
+ print ""
172
+ }
173
+ }
174
+ has_frontmatter && NR == 1 {
175
+ print
176
+ metadata()
177
+ next
178
+ }
179
+ { print }
180
+ ' "$ABS_FILE" > "$ABS_FILE.new" && mv "$ABS_FILE.new" "$ABS_FILE"
181
+
207
182
  # --- Append repo state ---------------------------------------------------
208
183
  # --no-pr skips `gh pr list` (~400–600ms per repo). A detached PR backfill
209
184
  # after the parallel phase rewrites `—` → `#N` and re-pushes memory.
@@ -231,14 +206,14 @@ awk -v line="$IDX_LINE" '
231
206
  END { if (!inserted) print line }
232
207
  ' "$INDEX" > "$INDEX.new" && mv "$INDEX.new" "$INDEX"
233
208
 
234
- # --- Parallel stage: graph + memory + (publish → notify) ----------------
209
+ # --- Parallel stage: graph + memory + (publish → notification proposal) -
235
210
  #
236
211
  # Three independent branches fork here and join before we emit the result:
237
212
  # A. Graph index — reads ABS_FILE, writes Session node to Neo4j, and
238
213
  # returns the handoff's neighborhood as subgraph JSON.
239
214
  # B. Memory push — commits + pushes memory repo (orphan-stash dance).
240
- # C. Publish+notify — publishes HTML artifact, then (if recipient is set)
241
- # sends Telegram with the artifact URL embedded.
215
+ # C. Publish+plan — publishes HTML artifact, then creates an immutable
216
+ # notification proposal with the artifact URL embedded.
242
217
  #
243
218
  # Each branch writes its result to a tmpfile. Wall-clock is max(A,B,C).
244
219
  #
@@ -251,7 +226,7 @@ MEMORY_DIR="$SCRIPT_DIR/memory"
251
226
  TMPD=$(mktemp -d -t handoff-run-XXXXXX)
252
227
  trap 'rm -rf "$TMPD"' EXIT
253
228
 
254
- # Extract briefing text once (used by publish and notify) so we don't
229
+ # Extract briefing text once (used by publish and the proposal) so we don't
255
230
  # re-awk the same file inside multiple workers.
256
231
  BRIEFING_LEAD=$(awk '/^## Briefing/{found=1; next} found && /^##/{exit} found && NF{print}' "$ABS_FILE" 2>/dev/null \
257
232
  | head -2 | tr '\n' ' ' | cut -c1-200 || true)
@@ -390,19 +365,27 @@ PID_MEMORY=$!
390
365
  fi
391
366
  EMISSARY_API_URL="${EMISSARY_API_URL:-https://egregore-production-55f2.up.railway.app/api/v1/emissary}"
392
367
 
393
- if [ -n "$EMISSARY_TOKEN" ]; then
368
+ # /handoff is an internal team primitive, not an implicit public-emissary
369
+ # composer. Use the emissary route only for an explicit recipient, and make
370
+ # that artifact directed-private. Recipient-less handoffs fall through to
371
+ # the org-scoped publisher (connected) or opt-in relay (local).
372
+ if [ -n "$EMISSARY_TOKEN" ] && [ -n "$RECIPIENT" ]; then
394
373
  # Step 1: render the handoff to HTML locally using egregore-artifacts.
395
374
  # Same renderer + template publish-artifact.sh uses today — handoffs
396
375
  # keep their familiar look.
397
376
  RENDERED_HTML="$TMPD/handoff.html"
398
377
  RENDER_OK=0
399
378
  LOCAL_CLI="$SCRIPT_DIR/packages/egregore-artifacts/bin/cli.js"
379
+ FIDELITY_ARGS=(--verify-fidelity)
380
+ if [ "$RENDER_TYPE" = "composed" ]; then
381
+ FIDELITY_ARGS+=(--source "$ABS_FILE")
382
+ fi
400
383
  if [ "${EGREGORE_USE_PUBLISHED:-0}" != "1" ] && [ -f "$LOCAL_CLI" ] && [ -d "$SCRIPT_DIR/packages/egregore-artifacts/node_modules/react" ]; then
401
- if node "$LOCAL_CLI" "$RENDER_TYPE" "${RENDER_SRC:-$ABS_FILE}" --output "$RENDERED_HTML" >/dev/null 2>&1; then
384
+ if node "$LOCAL_CLI" "$RENDER_TYPE" "${RENDER_SRC:-$ABS_FILE}" "${FIDELITY_ARGS[@]}" --output "$RENDERED_HTML" >/dev/null 2>"$TMPD/render-error"; then
402
385
  RENDER_OK=1
403
386
  fi
404
387
  else
405
- if npx egregore-artifacts "$RENDER_TYPE" "${RENDER_SRC:-$ABS_FILE}" --output "$RENDERED_HTML" >/dev/null 2>&1; then
388
+ if npx -y egregore-artifacts@latest "$RENDER_TYPE" "${RENDER_SRC:-$ABS_FILE}" "${FIDELITY_ARGS[@]}" --output "$RENDERED_HTML" >/dev/null 2>"$TMPD/render-error"; then
406
389
  RENDER_OK=1
407
390
  fi
408
391
  fi
@@ -422,12 +405,8 @@ PID_MEMORY=$!
422
405
  DISPLAY_NAME=$(head -1 "$PERSON_FILE" | sed 's/^# //')
423
406
  fi
424
407
 
425
- # addressed_to: only set if there's a recipient
426
- ADDRESSED_TO="[]"
427
- if [ -n "$RECIPIENT" ]; then
428
- RECIP_HANDLE=$(echo "$RECIPIENT" | tr '[:upper:]' '[:lower:]' | awk '{print $1}')
429
- ADDRESSED_TO=$(jq -nc --arg h "$RECIP_HANDLE" --arg d "$RECIPIENT" '[{"handle":$h,"display":$d}]')
430
- fi
408
+ RECIP_HANDLE=$(echo "$RECIPIENT" | tr '[:upper:]' '[:lower:]' | awk '{print $1}')
409
+ ADDRESSED_TO=$(jq -nc --arg h "$RECIP_HANDLE" --arg d "$RECIPIENT" '[{"handle":$h,"display":$d}]')
431
410
 
432
411
  CLAIM=$(echo "$BRIEFING_LEAD" | cut -c1-200)
433
412
 
@@ -456,8 +435,8 @@ PID_MEMORY=$!
456
435
  body: { prose: $prose },
457
436
  audience: {
458
437
  addressed_to: $addressed,
459
- visible_to: "public",
460
- extendable_by: "anyone"
438
+ visible_to: $addressed,
439
+ extendable_by: $addressed
461
440
  },
462
441
  parents: [],
463
442
  render_mode: "custom",
@@ -475,16 +454,35 @@ PID_MEMORY=$!
475
454
  fi
476
455
  fi
477
456
 
478
- # Fallback: if the emissary publish didn't produce a URL (no token, no
479
- # network, size cap, render failure), fire the legacy publish-artifact.sh
480
- # so handoffs still get a Telegram-able URL.
457
+ # Fallback: if a directed emissary publish didn't produce a URL—or this is a
458
+ # recipient-less team handoff—use publish-artifact.sh. Connected mode is
459
+ # authenticated and org-scoped; local mode's public relay is opt-in.
460
+ PUBLISH_RC=0
481
461
  if [ -z "$V1URL" ] && [ "$NO_PUBLISH" = "0" ] && [ -x "$SCRIPT_DIR/bin/publish-artifact.sh" ]; then
482
462
  AURL=$(bash "$SCRIPT_DIR/bin/publish-artifact.sh" "$RENDER_TYPE" "${RENDER_SRC:-$ABS_FILE}" \
463
+ --verify-fidelity \
464
+ --source "$ABS_FILE" \
483
465
  --title "$TOPIC" \
484
466
  --author "$AUTHOR" \
485
- --description "$BRIEFING_LEAD" 2>/dev/null || echo "")
467
+ --description "$BRIEFING_LEAD" 2>"$TMPD/publish-error") || PUBLISH_RC=$?
486
468
  fi
487
469
 
470
+ PS="published"
471
+ if [ "$NO_PUBLISH" = "1" ]; then
472
+ PS="disabled"
473
+ elif [ -n "$V1URL" ] || [ -n "$AURL" ]; then
474
+ PS="published"
475
+ elif [ "$PUBLISH_RC" = "4" ]; then
476
+ PS="relay-off"
477
+ elif [ "$PUBLISH_RC" = "3" ]; then
478
+ PS="hosting-off"
479
+ elif grep -q 'Handoff fidelity check failed' "$TMPD/render-error" "$TMPD/publish-error" 2>/dev/null; then
480
+ PS="fidelity-failed"
481
+ else
482
+ PS="failed"
483
+ fi
484
+ echo "$PS" > "$TMPD/publish"
485
+
488
486
  # Prefer v1 (emissary-rendered) URL when available; fall back to the
489
487
  # legacy egregore-artifacts URL only if the v1 publish failed.
490
488
  NOTIFY_URL=""
@@ -497,6 +495,7 @@ PID_MEMORY=$!
497
495
  fi
498
496
 
499
497
  NS="skipped"
498
+ echo '{}' > "$TMPD/notify-plan"
500
499
  if [ "$NO_NOTIFY" = "0" ]; then
501
500
  if [ -n "$NOTIFY_URL" ]; then
502
501
  MSG_NOTIFY="Handoff from ${AUTHOR}: ${TOPIC}
@@ -510,21 +509,19 @@ View: ${NOTIFY_URL}"
510
509
  \"${BRIEFING_SHORT}\""
511
510
  fi
512
511
 
513
- # Always notify. With a recipient (connected mode) → DM. Otherwise → group.
514
- # Self-handoffs still post to the group so they're visible on /activity
515
- # and in the Telegram feed — a handoff without a Telegram beat is invisible.
516
- if [ -n "$RECIPIENT" ] && [ "$MODE" = "connected" ]; then
517
- NR=$(bash "$SCRIPT_DIR/bin/notify.sh" send "$RECIPIENT" "$MSG_NOTIFY" 2>/dev/null || echo "Failed")
512
+ # Resolve the exact destination, but never approve or dispatch here. The
513
+ # interactive harness must show this proposal in a separate checkpoint.
514
+ if [ -n "$RECIPIENT" ]; then
515
+ NR=$(bash "$SCRIPT_DIR/bin/notify.sh" plan send "$RECIPIENT" "$MSG_NOTIFY" 2>/dev/null || echo '{}')
518
516
  else
519
- NR=$(bash "$SCRIPT_DIR/bin/notify.sh" group "$MSG_NOTIFY" 2>/dev/null || echo "Failed")
517
+ NR=$(bash "$SCRIPT_DIR/bin/notify.sh" plan group "$MSG_NOTIFY" 2>/dev/null || echo '{}')
520
518
  fi
521
519
 
522
- if echo "$NR" | grep -qi "^Sent"; then
523
- NS="sent"
524
- elif echo "$NR" | grep -qi "^Failed"; then
525
- NS="failed"
520
+ if printf '%s' "$NR" | jq -e '.status == "approval_required"' >/dev/null 2>&1; then
521
+ NS="approval_required"
522
+ printf '%s\n' "$NR" > "$TMPD/notify-plan"
526
523
  else
527
- NS="unknown"
524
+ NS="unavailable"
528
525
  fi
529
526
  fi
530
527
  echo "$NS" > "$TMPD/notify"
@@ -574,6 +571,9 @@ fi
574
571
  MEMORY_STATUS=$(cat "$TMPD/memory" 2>/dev/null || echo "skipped")
575
572
  ARTIFACT_URL=$(cat "$TMPD/artifact" 2>/dev/null || echo "")
576
573
  NOTIFY_STATUS=$(cat "$TMPD/notify" 2>/dev/null || echo "skipped")
574
+ NOTIFY_PLAN=$(cat "$TMPD/notify-plan" 2>/dev/null || echo "{}")
575
+ PUBLISH_STATUS=$(cat "$TMPD/publish" 2>/dev/null || echo "skipped")
576
+ [ -z "$PUBLISH_STATUS" ] && PUBLISH_STATUS="skipped"
577
577
  ARTIFACTS_ARR=$(cat "$TMPD/artifacts" 2>/dev/null || echo "[]")
578
578
  [ -z "$ARTIFACTS_ARR" ] && ARTIFACTS_ARR="[]"
579
579
 
@@ -594,16 +594,10 @@ fi
594
594
  STATUS_BITS=("saved")
595
595
  [ "$GRAPH_STATUS" = "ok" ] && STATUS_BITS+=("graphed")
596
596
  [ "$MEMORY_STATUS" = "ok" ] && STATUS_BITS+=("pushed")
597
- if [ "$NOTIFY_STATUS" = "sent" ]; then
598
- if [ -n "$RECIPIENT" ]; then
599
- STATUS_BITS+=("${RECIPIENT} notified")
600
- else
601
- STATUS_BITS+=("group notified")
602
- fi
603
- elif [ "$NOTIFY_STATUS" = "unknown" ] && [ -n "$RECIPIENT" ]; then
604
- STATUS_BITS+=("${RECIPIENT} relayed to group")
605
- fi
597
+ [ "$NOTIFY_STATUS" = "approval_required" ] && STATUS_BITS+=("notify approval pending")
606
598
  [ -n "$ARTIFACT_URL" ] && STATUS_BITS+=("published")
599
+ [ "$PUBLISH_STATUS" = "relay-off" ] && STATUS_BITS+=("not published")
600
+ [ "$PUBLISH_STATUS" = "fidelity-failed" ] && STATUS_BITS+=("artifact fidelity failed")
607
601
 
608
602
  STATUS_LINE=""
609
603
  for bit in "${STATUS_BITS[@]}"; do
@@ -625,7 +619,9 @@ jq -cn \
625
619
  --arg graphStatus "$GRAPH_STATUS" \
626
620
  --arg memoryStatus "$MEMORY_STATUS" \
627
621
  --arg notifyStatus "$NOTIFY_STATUS" \
622
+ --argjson notifyPlan "$NOTIFY_PLAN" \
628
623
  --arg artifactUrl "$ARTIFACT_URL" \
624
+ --arg publishStatus "$PUBLISH_STATUS" \
629
625
  --arg recipient "$RECIPIENT" \
630
626
  --arg topic "$TOPIC" \
631
627
  --arg author "$AUTHOR" \
@@ -640,7 +636,9 @@ jq -cn \
640
636
  graphStatus:$graphStatus,
641
637
  memoryStatus:$memoryStatus,
642
638
  notifyStatus:$notifyStatus,
639
+ notifyPlan:$notifyPlan,
643
640
  artifactUrl:$artifactUrl,
641
+ publishStatus:$publishStatus,
644
642
  recipient:$recipient,
645
643
  topic:$topic,
646
644
  author:$author,