create-egregore 0.21.6 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (719) hide show
  1. package/assets/egregore-launcher.js +58 -6
  2. package/assets/egregore-launcher.sh +15 -2
  3. package/lib/claude-runtime.js +2 -0
  4. package/lib/codex-runtime.js +2 -0
  5. package/lib/setup.js +20 -3
  6. package/package.json +2 -2
  7. package/runtime/claude/.claude/context/commit-format.md +7 -4
  8. package/runtime/claude/.claude/context/handoff-claiming.md +32 -0
  9. package/runtime/claude/.claude/context/notification-consent.md +12 -9
  10. package/runtime/claude/.claude/hooks/boundary-check.sh +14 -331
  11. package/runtime/claude/.claude/hooks/memory-read-guard.sh +9 -1
  12. package/runtime/claude/.claude/rules/voice-bedrock.md +6 -2
  13. package/runtime/claude/.claude/settings.json +1 -1
  14. package/runtime/claude/.claude/skills/commit/SKILL.md +5 -3
  15. package/runtime/claude/.claude/skills/dark-mode/SKILL.md +48 -369
  16. package/runtime/claude/.claude/skills/records/SKILL.md +158 -0
  17. package/runtime/claude/.claude/skills/reflect/SKILL.md +50 -21
  18. package/runtime/claude/.claude/skills/review-pr/SKILL.md +4 -2
  19. package/runtime/claude/.claude/skills/save/SKILL.md +9 -3
  20. package/runtime/claude/.claude/skills/summon/SKILL.md +138 -207
  21. package/runtime/claude/.claude/skills/tui-design/SKILL.md +1 -1
  22. package/runtime/claude/.claude/skills/update/SKILL.md +1 -1
  23. package/runtime/claude/.claude/skills/view/SKILL.md +52 -16
  24. package/runtime/claude/.claude/skills/view/compose-scaffold.html +19 -13
  25. package/runtime/claude/CLAUDE.md +59 -95
  26. package/runtime/claude/bin/agent.sh +231 -7
  27. package/runtime/claude/bin/api-call.sh +44 -23
  28. package/runtime/claude/bin/artifact-register.sh +7 -1
  29. package/runtime/claude/bin/artifact-writeback.sh +1 -1
  30. package/runtime/claude/bin/artifacts.sh +66 -265
  31. package/runtime/claude/bin/attendant.sh +4 -1
  32. package/runtime/claude/bin/boundary-guard.cjs +1848 -0
  33. package/runtime/claude/bin/boundary-hook.sh +41 -0
  34. package/runtime/claude/bin/boundary.sh +15 -155
  35. package/runtime/claude/bin/capture-run.sh +32 -2
  36. package/runtime/claude/bin/codex-render-spec.mjs +24 -46
  37. package/runtime/claude/bin/codex-session-start.sh +19 -0
  38. package/runtime/claude/bin/codex-skill-render.mjs +18 -0
  39. package/runtime/claude/bin/config-get.sh +10 -1
  40. package/runtime/claude/bin/connect-refresh.sh +16 -0
  41. package/runtime/claude/bin/corpus_map.py +5 -0
  42. package/runtime/claude/bin/data/capabilities/claude.json +1480 -0
  43. package/runtime/claude/bin/genui.sh +19 -0
  44. package/runtime/claude/bin/graph-batch.sh +1 -1
  45. package/runtime/claude/bin/graph-op.sh +14 -0
  46. package/runtime/claude/bin/graph.sh +1 -1
  47. package/runtime/claude/bin/handoff-pr-backfill.sh +1 -1
  48. package/runtime/claude/bin/handoff-run.sh +11 -6
  49. package/runtime/claude/bin/ingest-item.sh +1 -1
  50. package/runtime/claude/bin/ingest-surface.html +22 -4
  51. package/runtime/claude/bin/issue.sh +1 -1
  52. package/runtime/claude/bin/knowledge.sh +1 -1
  53. package/runtime/claude/bin/lib/card-delivery.sh +329 -0
  54. package/runtime/claude/bin/lib/config.sh +148 -3
  55. package/runtime/claude/bin/lib/context.sh +38 -67
  56. package/runtime/claude/bin/lib/genui-entry.py +36 -0
  57. package/runtime/claude/bin/lib/git-message.sh +25 -6
  58. package/runtime/claude/bin/lib/git-sync.sh +12 -4
  59. package/runtime/claude/bin/lib/greeting.sh +255 -28
  60. package/runtime/claude/bin/lib/handoff_meta.py +294 -0
  61. package/runtime/claude/bin/lib/health-footer.sh +83 -2
  62. package/runtime/claude/bin/lib/identity.sh +31 -10
  63. package/runtime/claude/bin/lib/instance-registry.sh +71 -0
  64. package/runtime/claude/bin/lib/local_ci_receipt.py +249 -0
  65. package/runtime/claude/bin/lib/metrics.sh +121 -8
  66. package/runtime/claude/bin/lib/notices.sh +36 -0
  67. package/runtime/claude/bin/lib/record_outcomes.py +729 -0
  68. package/runtime/claude/bin/lib/reflexes.py +267 -0
  69. package/runtime/claude/bin/lib/retrieval_scorecard.py +624 -0
  70. package/runtime/claude/bin/lib/session-record-prompt.txt +18 -0
  71. package/runtime/claude/bin/lib/session_record.py +3747 -0
  72. package/runtime/claude/bin/lib/session_trail.py +1983 -0
  73. package/runtime/claude/bin/lib/settings-drift.sh +8 -5
  74. package/runtime/claude/bin/lib/startup-restart.sh +41 -0
  75. package/runtime/claude/bin/lib/worktree-links.sh +92 -0
  76. package/runtime/claude/bin/memory-push.sh +6 -0
  77. package/runtime/claude/bin/merge-gate.sh +498 -0
  78. package/runtime/claude/bin/notify.sh +5 -2
  79. package/runtime/claude/bin/page-access.sh +103 -0
  80. package/runtime/claude/bin/person.sh +13 -2
  81. package/runtime/claude/bin/pi-render-spec.mjs +0 -1
  82. package/runtime/claude/bin/pi-spirit-discovery.mjs +34 -0
  83. package/runtime/claude/bin/post-update.sh +181 -0
  84. package/runtime/claude/bin/prime-render-spec.mjs +0 -1
  85. package/runtime/claude/bin/publish-artifact.sh +89 -42
  86. package/runtime/claude/bin/qa-inventory.sh +2 -2
  87. package/runtime/claude/bin/quest.sh +1 -1
  88. package/runtime/claude/bin/records.sh +11 -0
  89. package/runtime/claude/bin/reflexes/05-vitals.sh +9 -0
  90. package/runtime/claude/bin/reflexes/10-open-items.sh +12 -0
  91. package/runtime/claude/bin/reflexes/15-retrieval.sh +8 -0
  92. package/runtime/claude/bin/reflexes/20-nightly.sh +100 -0
  93. package/runtime/claude/bin/reflexes/20-sandbox.sh +85 -0
  94. package/runtime/claude/bin/reflexes/30-cost.py +116 -0
  95. package/runtime/claude/bin/reflexes/40-shells.py +51 -0
  96. package/runtime/claude/bin/reflexes/README.md +61 -0
  97. package/runtime/claude/bin/reflexes.sh +7 -0
  98. package/runtime/claude/bin/runtime-identity.sh +140 -42
  99. package/runtime/claude/bin/screenshot.sh +77 -0
  100. package/runtime/claude/bin/scroll.sh +1 -1
  101. package/runtime/claude/bin/search.sh +31 -5
  102. package/runtime/claude/bin/session-autosave.sh +6 -3
  103. package/runtime/claude/bin/session-id.sh +147 -0
  104. package/runtime/claude/bin/session-log.sh +19 -0
  105. package/runtime/claude/bin/session-record.sh +26 -0
  106. package/runtime/claude/bin/session-start.sh +121 -151
  107. package/runtime/claude/bin/settings.sh +13 -8
  108. package/runtime/claude/bin/spirit-discovery-claude.sh +4 -0
  109. package/runtime/claude/bin/spirit-discovery-codex.sh +4 -0
  110. package/runtime/claude/bin/spirit-discovery-pi.sh +4 -0
  111. package/runtime/claude/bin/spirit-discovery-prime.sh +4 -0
  112. package/runtime/claude/bin/spirit-discovery.sh +4 -0
  113. package/runtime/claude/bin/startup-check.sh +1 -1
  114. package/runtime/claude/bin/telemetry.sh +11 -4
  115. package/runtime/claude/bin/test-baseline.sh +33 -5
  116. package/runtime/claude/bin/todo.sh +1 -1
  117. package/runtime/claude/bin/worktree-create.sh +15 -45
  118. package/runtime/claude/bin/worktree.sh +6 -0
  119. package/runtime/claude/docs/spirit-discovery.md +96 -0
  120. package/runtime/claude/egregore_runtime/__init__.py +18 -12
  121. package/runtime/claude/egregore_runtime/access.py +608 -0
  122. package/runtime/claude/egregore_runtime/access_cli.py +190 -0
  123. package/runtime/claude/egregore_runtime/adapters/invitation.py +5 -3
  124. package/runtime/claude/egregore_runtime/adapters/qmd.py +521 -47
  125. package/runtime/claude/egregore_runtime/admin_entry.py +56 -0
  126. package/runtime/claude/egregore_runtime/artifacts.py +222 -16
  127. package/runtime/claude/egregore_runtime/contracts.py +27 -0
  128. package/runtime/claude/egregore_runtime/eligibility.py +5 -12
  129. package/runtime/claude/egregore_runtime/episode_binding.py +16 -5
  130. package/runtime/claude/egregore_runtime/github_issues.py +2 -2
  131. package/runtime/claude/egregore_runtime/handoff_lookup.py +9 -20
  132. package/runtime/claude/egregore_runtime/harness_cli.py +674 -149
  133. package/runtime/claude/egregore_runtime/held.py +2436 -0
  134. package/runtime/claude/egregore_runtime/hosted_api.py +137 -0
  135. package/runtime/claude/egregore_runtime/identity.py +196 -65
  136. package/runtime/claude/egregore_runtime/identity_transfer.py +6 -2
  137. package/runtime/claude/egregore_runtime/ingest_cli.py +2 -2
  138. package/runtime/claude/egregore_runtime/ingest_index_cli.py +4 -16
  139. package/runtime/claude/egregore_runtime/installation.py +119 -0
  140. package/runtime/claude/egregore_runtime/investigation.py +64 -41
  141. package/runtime/claude/egregore_runtime/investigation_guidance.py +16 -11
  142. package/runtime/claude/egregore_runtime/issue_cli.py +51 -32
  143. package/runtime/claude/egregore_runtime/issue_reporting.py +4 -3
  144. package/runtime/claude/egregore_runtime/issue_triage_service.py +2 -2
  145. package/runtime/claude/egregore_runtime/issues.py +12 -6
  146. package/runtime/claude/egregore_runtime/knowledge.py +331 -5
  147. package/runtime/claude/egregore_runtime/knowledge_cli.py +57 -17
  148. package/runtime/claude/egregore_runtime/lifecycle.py +88 -22
  149. package/runtime/claude/egregore_runtime/lifecycle_cli.py +21 -13
  150. package/runtime/claude/egregore_runtime/line_ids.py +10 -0
  151. package/runtime/claude/egregore_runtime/memory_push.py +349 -0
  152. package/runtime/claude/egregore_runtime/observe.py +64 -25
  153. package/runtime/claude/egregore_runtime/observers.py +19 -0
  154. package/runtime/claude/egregore_runtime/optional_modules.py +13 -0
  155. package/runtime/claude/egregore_runtime/outputs_cli.py +321 -0
  156. package/runtime/claude/egregore_runtime/policy.py +651 -24
  157. package/runtime/claude/egregore_runtime/private_result.py +2 -1
  158. package/runtime/claude/egregore_runtime/projection.py +946 -0
  159. package/runtime/claude/egregore_runtime/quest_cli.py +20 -23
  160. package/runtime/claude/egregore_runtime/question_cli.py +15 -11
  161. package/runtime/claude/egregore_runtime/questions.py +10 -10
  162. package/runtime/claude/egregore_runtime/quests.py +10 -10
  163. package/runtime/claude/egregore_runtime/record_publish.py +548 -0
  164. package/runtime/claude/egregore_runtime/record_subject.py +564 -0
  165. package/runtime/claude/egregore_runtime/research_ingest.py +2 -4
  166. package/runtime/claude/egregore_runtime/runtime.py +169 -60
  167. package/runtime/claude/egregore_runtime/sandbox.py +194 -0
  168. package/runtime/claude/egregore_runtime/scroll_cli.py +22 -32
  169. package/runtime/claude/egregore_runtime/scrolls.py +23 -15
  170. package/runtime/claude/egregore_runtime/shadow.py +262 -0
  171. package/runtime/claude/egregore_runtime/spirit_discovery.py +487 -0
  172. package/runtime/claude/egregore_runtime/spirit_discovery_cli.py +25 -0
  173. package/runtime/claude/egregore_runtime/spirit_discovery_transport.py +18 -0
  174. package/runtime/claude/egregore_runtime/status.py +101 -44
  175. package/runtime/claude/egregore_runtime/status_cli.py +13 -5
  176. package/runtime/claude/egregore_runtime/sync.py +39 -21
  177. package/runtime/claude/egregore_runtime/taste.py +934 -0
  178. package/runtime/claude/egregore_runtime/taste_cli.py +242 -0
  179. package/runtime/claude/egregore_runtime/taste_rules.py +91 -0
  180. package/runtime/claude/egregore_runtime/telemetry.py +26 -3
  181. package/runtime/claude/egregore_runtime/todo_cli.py +15 -12
  182. package/runtime/claude/egregore_runtime/todos.py +3 -2
  183. package/runtime/claude/egregore_runtime/upgrade.py +85 -58
  184. package/runtime/claude/egregore_runtime/writeback.py +330 -24
  185. package/runtime/claude/manifest.json +65 -5
  186. package/runtime/codex/.claude/context/handoff-claiming.md +32 -0
  187. package/runtime/codex/.claude/context/notification-consent.md +12 -9
  188. package/runtime/codex/.claude/skills/view/SKILL.md +438 -0
  189. package/runtime/codex/.codex/hooks.json +11 -0
  190. package/runtime/codex/.codex/skills/dark-mode/SKILL.md +1 -1
  191. package/runtime/codex/.codex/skills/records/SKILL.md +29 -0
  192. package/runtime/codex/.codex/skills/summon/SKILL.md +1 -1
  193. package/runtime/codex/.codex/skills/view/assets/compose-scaffold.html +19 -13
  194. package/runtime/codex/.codex/spec-manifest.json +13 -19
  195. package/runtime/codex/AGENTS.md +54 -105
  196. package/runtime/codex/bin/agent.sh +231 -7
  197. package/runtime/codex/bin/api-call.sh +44 -23
  198. package/runtime/codex/bin/artifact-register.sh +7 -1
  199. package/runtime/codex/bin/artifact-writeback.sh +1 -1
  200. package/runtime/codex/bin/artifacts.sh +66 -265
  201. package/runtime/codex/bin/attendant.sh +4 -1
  202. package/runtime/codex/bin/boundary-guard.cjs +1848 -0
  203. package/runtime/codex/bin/boundary-hook.sh +41 -0
  204. package/runtime/codex/bin/capture-run.sh +32 -2
  205. package/runtime/codex/bin/codex-render-spec.mjs +24 -46
  206. package/runtime/codex/bin/codex-session-start.sh +19 -0
  207. package/runtime/codex/bin/codex-skill-render.mjs +18 -0
  208. package/runtime/codex/bin/config-get.sh +10 -1
  209. package/runtime/codex/bin/connect-refresh.sh +16 -0
  210. package/runtime/codex/bin/corpus_map.py +5 -0
  211. package/runtime/codex/bin/data/capabilities/codex.json +1458 -0
  212. package/runtime/codex/bin/genui.sh +19 -0
  213. package/runtime/codex/bin/graph-batch.sh +1 -1
  214. package/runtime/codex/bin/graph-op.sh +14 -0
  215. package/runtime/codex/bin/graph.sh +1 -1
  216. package/runtime/codex/bin/handoff-pr-backfill.sh +1 -1
  217. package/runtime/codex/bin/handoff-run.sh +11 -6
  218. package/runtime/codex/bin/ingest-item.sh +1 -1
  219. package/runtime/codex/bin/ingest-surface.html +22 -4
  220. package/runtime/codex/bin/issue.sh +1 -1
  221. package/runtime/codex/bin/knowledge.sh +1 -1
  222. package/runtime/codex/bin/lib/card-delivery.sh +329 -0
  223. package/runtime/codex/bin/lib/config.sh +148 -3
  224. package/runtime/codex/bin/lib/context.sh +38 -67
  225. package/runtime/codex/bin/lib/genui-entry.py +36 -0
  226. package/runtime/codex/bin/lib/git-message.sh +25 -6
  227. package/runtime/codex/bin/lib/git-sync.sh +12 -4
  228. package/runtime/codex/bin/lib/greeting.sh +255 -28
  229. package/runtime/codex/bin/lib/handoff_meta.py +294 -0
  230. package/runtime/codex/bin/lib/health-footer.sh +83 -2
  231. package/runtime/codex/bin/lib/identity.sh +31 -10
  232. package/runtime/codex/bin/lib/instance-registry.sh +71 -0
  233. package/runtime/codex/bin/lib/local_ci_receipt.py +249 -0
  234. package/runtime/codex/bin/lib/metrics.sh +121 -8
  235. package/runtime/codex/bin/lib/notices.sh +36 -0
  236. package/runtime/codex/bin/lib/record_outcomes.py +729 -0
  237. package/runtime/codex/bin/lib/reflexes.py +267 -0
  238. package/runtime/codex/bin/lib/retrieval_scorecard.py +624 -0
  239. package/runtime/codex/bin/lib/session-record-prompt.txt +18 -0
  240. package/runtime/codex/bin/lib/session_record.py +3747 -0
  241. package/runtime/codex/bin/lib/session_trail.py +1983 -0
  242. package/runtime/codex/bin/lib/settings-drift.sh +8 -5
  243. package/runtime/codex/bin/lib/startup-restart.sh +41 -0
  244. package/runtime/codex/bin/lib/worktree-links.sh +92 -0
  245. package/runtime/codex/bin/memory-push.sh +6 -0
  246. package/runtime/codex/bin/merge-gate.sh +498 -0
  247. package/runtime/codex/bin/notify.sh +5 -2
  248. package/runtime/codex/bin/page-access.sh +103 -0
  249. package/runtime/codex/bin/person.sh +13 -2
  250. package/runtime/codex/bin/pi-render-spec.mjs +0 -1
  251. package/runtime/codex/bin/pi-spirit-discovery.mjs +34 -0
  252. package/runtime/codex/bin/post-update.sh +181 -0
  253. package/runtime/codex/bin/prime-render-spec.mjs +0 -1
  254. package/runtime/codex/bin/publish-artifact.sh +89 -42
  255. package/runtime/codex/bin/qa-inventory.sh +2 -2
  256. package/runtime/codex/bin/quest.sh +1 -1
  257. package/runtime/codex/bin/records.sh +11 -0
  258. package/runtime/codex/bin/reflexes/05-vitals.sh +9 -0
  259. package/runtime/codex/bin/reflexes/10-open-items.sh +12 -0
  260. package/runtime/codex/bin/reflexes/15-retrieval.sh +8 -0
  261. package/runtime/codex/bin/reflexes/20-nightly.sh +100 -0
  262. package/runtime/codex/bin/reflexes/20-sandbox.sh +85 -0
  263. package/runtime/codex/bin/reflexes/30-cost.py +116 -0
  264. package/runtime/codex/bin/reflexes/40-shells.py +51 -0
  265. package/runtime/codex/bin/reflexes/README.md +61 -0
  266. package/runtime/codex/bin/reflexes.sh +7 -0
  267. package/runtime/codex/bin/runtime-identity.sh +140 -42
  268. package/runtime/codex/bin/screenshot.sh +77 -0
  269. package/runtime/codex/bin/scroll.sh +1 -1
  270. package/runtime/codex/bin/search.sh +31 -5
  271. package/runtime/codex/bin/session-autosave.sh +6 -3
  272. package/runtime/codex/bin/session-id.sh +147 -0
  273. package/runtime/codex/bin/session-log.sh +19 -0
  274. package/runtime/codex/bin/session-record.sh +26 -0
  275. package/runtime/codex/bin/settings.sh +13 -8
  276. package/runtime/codex/bin/spirit-discovery-claude.sh +4 -0
  277. package/runtime/codex/bin/spirit-discovery-codex.sh +4 -0
  278. package/runtime/codex/bin/spirit-discovery-pi.sh +4 -0
  279. package/runtime/codex/bin/spirit-discovery-prime.sh +4 -0
  280. package/runtime/codex/bin/spirit-discovery.sh +4 -0
  281. package/runtime/codex/bin/startup-check.sh +1 -1
  282. package/runtime/codex/bin/telemetry.sh +11 -4
  283. package/runtime/codex/bin/test-baseline.sh +33 -5
  284. package/runtime/codex/bin/todo.sh +1 -1
  285. package/runtime/codex/bin/worktree-create.sh +15 -45
  286. package/runtime/codex/bin/worktree.sh +6 -0
  287. package/runtime/codex/docs/spirit-discovery.md +96 -0
  288. package/runtime/codex/egregore_runtime/__init__.py +18 -12
  289. package/runtime/codex/egregore_runtime/access.py +608 -0
  290. package/runtime/codex/egregore_runtime/access_cli.py +190 -0
  291. package/runtime/codex/egregore_runtime/adapters/invitation.py +5 -3
  292. package/runtime/codex/egregore_runtime/adapters/qmd.py +521 -47
  293. package/runtime/codex/egregore_runtime/admin_entry.py +56 -0
  294. package/runtime/codex/egregore_runtime/artifacts.py +222 -16
  295. package/runtime/codex/egregore_runtime/contracts.py +27 -0
  296. package/runtime/codex/egregore_runtime/eligibility.py +5 -12
  297. package/runtime/codex/egregore_runtime/episode_binding.py +16 -5
  298. package/runtime/codex/egregore_runtime/github_issues.py +2 -2
  299. package/runtime/codex/egregore_runtime/handoff_lookup.py +9 -20
  300. package/runtime/codex/egregore_runtime/harness_cli.py +674 -149
  301. package/runtime/codex/egregore_runtime/held.py +2436 -0
  302. package/runtime/codex/egregore_runtime/hosted_api.py +137 -0
  303. package/runtime/codex/egregore_runtime/identity.py +196 -65
  304. package/runtime/codex/egregore_runtime/identity_transfer.py +6 -2
  305. package/runtime/codex/egregore_runtime/ingest_cli.py +2 -2
  306. package/runtime/codex/egregore_runtime/ingest_index_cli.py +4 -16
  307. package/runtime/codex/egregore_runtime/installation.py +119 -0
  308. package/runtime/codex/egregore_runtime/investigation.py +64 -41
  309. package/runtime/codex/egregore_runtime/investigation_guidance.py +16 -11
  310. package/runtime/codex/egregore_runtime/issue_cli.py +51 -32
  311. package/runtime/codex/egregore_runtime/issue_reporting.py +4 -3
  312. package/runtime/codex/egregore_runtime/issue_triage_service.py +2 -2
  313. package/runtime/codex/egregore_runtime/issues.py +12 -6
  314. package/runtime/codex/egregore_runtime/knowledge.py +331 -5
  315. package/runtime/codex/egregore_runtime/knowledge_cli.py +57 -17
  316. package/runtime/codex/egregore_runtime/lifecycle.py +88 -22
  317. package/runtime/codex/egregore_runtime/lifecycle_cli.py +21 -13
  318. package/runtime/codex/egregore_runtime/line_ids.py +10 -0
  319. package/runtime/codex/egregore_runtime/memory_push.py +349 -0
  320. package/runtime/codex/egregore_runtime/observe.py +64 -25
  321. package/runtime/codex/egregore_runtime/observers.py +19 -0
  322. package/runtime/codex/egregore_runtime/optional_modules.py +13 -0
  323. package/runtime/codex/egregore_runtime/outputs_cli.py +321 -0
  324. package/runtime/codex/egregore_runtime/policy.py +651 -24
  325. package/runtime/codex/egregore_runtime/private_result.py +2 -1
  326. package/runtime/codex/egregore_runtime/projection.py +946 -0
  327. package/runtime/codex/egregore_runtime/quest_cli.py +20 -23
  328. package/runtime/codex/egregore_runtime/question_cli.py +15 -11
  329. package/runtime/codex/egregore_runtime/questions.py +10 -10
  330. package/runtime/codex/egregore_runtime/quests.py +10 -10
  331. package/runtime/codex/egregore_runtime/record_publish.py +548 -0
  332. package/runtime/codex/egregore_runtime/record_subject.py +564 -0
  333. package/runtime/codex/egregore_runtime/research_ingest.py +2 -4
  334. package/runtime/codex/egregore_runtime/runtime.py +169 -60
  335. package/runtime/codex/egregore_runtime/sandbox.py +194 -0
  336. package/runtime/codex/egregore_runtime/scroll_cli.py +22 -32
  337. package/runtime/codex/egregore_runtime/scrolls.py +23 -15
  338. package/runtime/codex/egregore_runtime/shadow.py +262 -0
  339. package/runtime/codex/egregore_runtime/spirit_discovery.py +487 -0
  340. package/runtime/codex/egregore_runtime/spirit_discovery_cli.py +25 -0
  341. package/runtime/codex/egregore_runtime/spirit_discovery_transport.py +18 -0
  342. package/runtime/codex/egregore_runtime/status.py +101 -44
  343. package/runtime/codex/egregore_runtime/status_cli.py +13 -5
  344. package/runtime/codex/egregore_runtime/sync.py +39 -21
  345. package/runtime/codex/egregore_runtime/taste.py +934 -0
  346. package/runtime/codex/egregore_runtime/taste_cli.py +242 -0
  347. package/runtime/codex/egregore_runtime/taste_rules.py +91 -0
  348. package/runtime/codex/egregore_runtime/telemetry.py +26 -3
  349. package/runtime/codex/egregore_runtime/todo_cli.py +15 -12
  350. package/runtime/codex/egregore_runtime/todos.py +3 -2
  351. package/runtime/codex/egregore_runtime/upgrade.py +85 -58
  352. package/runtime/codex/egregore_runtime/writeback.py +330 -24
  353. package/runtime/codex/manifest.json +66 -5
  354. package/runtime/pi/.claude/context/handoff-claiming.md +32 -0
  355. package/runtime/pi/.claude/context/notification-consent.md +12 -9
  356. package/runtime/pi/.claude/skills/view/SKILL.md +438 -0
  357. package/runtime/pi/.codex/hooks.json +11 -0
  358. package/runtime/pi/.codex/skills/dark-mode/SKILL.md +1 -1
  359. package/runtime/pi/.codex/skills/records/SKILL.md +29 -0
  360. package/runtime/pi/.codex/skills/summon/SKILL.md +1 -1
  361. package/runtime/pi/.codex/skills/view/assets/compose-scaffold.html +19 -13
  362. package/runtime/pi/.codex/spec-manifest.json +13 -19
  363. package/runtime/pi/.pi/APPEND_SYSTEM.md +53 -99
  364. package/runtime/pi/.pi/extensions/egregore.ts +13 -1
  365. package/runtime/pi/.pi/spec-manifest.json +2 -2
  366. package/runtime/pi/AGENTS.md +54 -105
  367. package/runtime/pi/bin/agent.sh +231 -7
  368. package/runtime/pi/bin/api-call.sh +44 -23
  369. package/runtime/pi/bin/artifact-register.sh +7 -1
  370. package/runtime/pi/bin/artifact-writeback.sh +1 -1
  371. package/runtime/pi/bin/artifacts.sh +66 -265
  372. package/runtime/pi/bin/attendant.sh +4 -1
  373. package/runtime/pi/bin/boundary-guard.cjs +1848 -0
  374. package/runtime/pi/bin/boundary-hook.sh +41 -0
  375. package/runtime/pi/bin/capture-run.sh +32 -2
  376. package/runtime/pi/bin/codex-render-spec.mjs +24 -46
  377. package/runtime/pi/bin/codex-session-start.sh +19 -0
  378. package/runtime/pi/bin/codex-skill-render.mjs +18 -0
  379. package/runtime/pi/bin/config-get.sh +10 -1
  380. package/runtime/pi/bin/connect-refresh.sh +16 -0
  381. package/runtime/pi/bin/corpus_map.py +5 -0
  382. package/runtime/pi/bin/data/capabilities/pi.json +1458 -0
  383. package/runtime/pi/bin/genui.sh +19 -0
  384. package/runtime/pi/bin/graph-batch.sh +1 -1
  385. package/runtime/pi/bin/graph-op.sh +14 -0
  386. package/runtime/pi/bin/graph.sh +1 -1
  387. package/runtime/pi/bin/handoff-pr-backfill.sh +1 -1
  388. package/runtime/pi/bin/handoff-run.sh +11 -6
  389. package/runtime/pi/bin/ingest-item.sh +1 -1
  390. package/runtime/pi/bin/ingest-surface.html +22 -4
  391. package/runtime/pi/bin/issue.sh +1 -1
  392. package/runtime/pi/bin/knowledge.sh +1 -1
  393. package/runtime/pi/bin/lib/card-delivery.sh +329 -0
  394. package/runtime/pi/bin/lib/config.sh +148 -3
  395. package/runtime/pi/bin/lib/context.sh +38 -67
  396. package/runtime/pi/bin/lib/genui-entry.py +36 -0
  397. package/runtime/pi/bin/lib/git-message.sh +25 -6
  398. package/runtime/pi/bin/lib/git-sync.sh +12 -4
  399. package/runtime/pi/bin/lib/greeting.sh +255 -28
  400. package/runtime/pi/bin/lib/handoff_meta.py +294 -0
  401. package/runtime/pi/bin/lib/health-footer.sh +83 -2
  402. package/runtime/pi/bin/lib/identity.sh +31 -10
  403. package/runtime/pi/bin/lib/instance-registry.sh +71 -0
  404. package/runtime/pi/bin/lib/local_ci_receipt.py +249 -0
  405. package/runtime/pi/bin/lib/metrics.sh +121 -8
  406. package/runtime/pi/bin/lib/notices.sh +36 -0
  407. package/runtime/pi/bin/lib/record_outcomes.py +729 -0
  408. package/runtime/pi/bin/lib/reflexes.py +267 -0
  409. package/runtime/pi/bin/lib/retrieval_scorecard.py +624 -0
  410. package/runtime/pi/bin/lib/session-record-prompt.txt +18 -0
  411. package/runtime/pi/bin/lib/session_record.py +3747 -0
  412. package/runtime/pi/bin/lib/session_trail.py +1983 -0
  413. package/runtime/pi/bin/lib/settings-drift.sh +8 -5
  414. package/runtime/pi/bin/lib/startup-restart.sh +41 -0
  415. package/runtime/pi/bin/lib/worktree-links.sh +92 -0
  416. package/runtime/pi/bin/memory-push.sh +6 -0
  417. package/runtime/pi/bin/merge-gate.sh +498 -0
  418. package/runtime/pi/bin/notify.sh +5 -2
  419. package/runtime/pi/bin/page-access.sh +103 -0
  420. package/runtime/pi/bin/person.sh +13 -2
  421. package/runtime/pi/bin/pi-branch-policy.mjs +37 -0
  422. package/runtime/pi/bin/pi-observe-context.mjs +97 -4
  423. package/runtime/pi/bin/pi-render-spec.mjs +0 -1
  424. package/runtime/pi/bin/pi-session-start.sh +4 -1
  425. package/runtime/pi/bin/pi-spirit-discovery.mjs +34 -0
  426. package/runtime/pi/bin/post-update.sh +181 -0
  427. package/runtime/pi/bin/prime-render-spec.mjs +0 -1
  428. package/runtime/pi/bin/publish-artifact.sh +89 -42
  429. package/runtime/pi/bin/qa-inventory.sh +2 -2
  430. package/runtime/pi/bin/quest.sh +1 -1
  431. package/runtime/pi/bin/records.sh +11 -0
  432. package/runtime/pi/bin/reflexes/05-vitals.sh +9 -0
  433. package/runtime/pi/bin/reflexes/10-open-items.sh +12 -0
  434. package/runtime/pi/bin/reflexes/15-retrieval.sh +8 -0
  435. package/runtime/pi/bin/reflexes/20-nightly.sh +100 -0
  436. package/runtime/pi/bin/reflexes/20-sandbox.sh +85 -0
  437. package/runtime/pi/bin/reflexes/30-cost.py +116 -0
  438. package/runtime/pi/bin/reflexes/40-shells.py +51 -0
  439. package/runtime/pi/bin/reflexes/README.md +61 -0
  440. package/runtime/pi/bin/reflexes.sh +7 -0
  441. package/runtime/pi/bin/runtime-identity.sh +140 -42
  442. package/runtime/pi/bin/screenshot.sh +77 -0
  443. package/runtime/pi/bin/scroll.sh +1 -1
  444. package/runtime/pi/bin/search.sh +31 -5
  445. package/runtime/pi/bin/session-autosave.sh +6 -3
  446. package/runtime/pi/bin/session-id.sh +147 -0
  447. package/runtime/pi/bin/session-log.sh +19 -0
  448. package/runtime/pi/bin/session-record.sh +26 -0
  449. package/runtime/pi/bin/settings.sh +13 -8
  450. package/runtime/pi/bin/spirit-discovery-claude.sh +4 -0
  451. package/runtime/pi/bin/spirit-discovery-codex.sh +4 -0
  452. package/runtime/pi/bin/spirit-discovery-pi.sh +4 -0
  453. package/runtime/pi/bin/spirit-discovery-prime.sh +4 -0
  454. package/runtime/pi/bin/spirit-discovery.sh +4 -0
  455. package/runtime/pi/bin/startup-check.sh +1 -1
  456. package/runtime/pi/bin/telemetry.sh +11 -4
  457. package/runtime/pi/bin/test-baseline.sh +33 -5
  458. package/runtime/pi/bin/todo.sh +1 -1
  459. package/runtime/pi/bin/worktree-create.sh +15 -45
  460. package/runtime/pi/bin/worktree.sh +6 -0
  461. package/runtime/pi/docs/spirit-discovery.md +96 -0
  462. package/runtime/pi/egregore_runtime/__init__.py +18 -12
  463. package/runtime/pi/egregore_runtime/access.py +608 -0
  464. package/runtime/pi/egregore_runtime/access_cli.py +190 -0
  465. package/runtime/pi/egregore_runtime/adapters/invitation.py +5 -3
  466. package/runtime/pi/egregore_runtime/adapters/qmd.py +521 -47
  467. package/runtime/pi/egregore_runtime/admin_entry.py +56 -0
  468. package/runtime/pi/egregore_runtime/artifacts.py +222 -16
  469. package/runtime/pi/egregore_runtime/contracts.py +27 -0
  470. package/runtime/pi/egregore_runtime/eligibility.py +5 -12
  471. package/runtime/pi/egregore_runtime/episode_binding.py +16 -5
  472. package/runtime/pi/egregore_runtime/github_issues.py +2 -2
  473. package/runtime/pi/egregore_runtime/handoff_lookup.py +9 -20
  474. package/runtime/pi/egregore_runtime/harness_cli.py +674 -149
  475. package/runtime/pi/egregore_runtime/held.py +2436 -0
  476. package/runtime/pi/egregore_runtime/hosted_api.py +137 -0
  477. package/runtime/pi/egregore_runtime/identity.py +196 -65
  478. package/runtime/pi/egregore_runtime/identity_transfer.py +6 -2
  479. package/runtime/pi/egregore_runtime/ingest_cli.py +2 -2
  480. package/runtime/pi/egregore_runtime/ingest_index_cli.py +4 -16
  481. package/runtime/pi/egregore_runtime/installation.py +119 -0
  482. package/runtime/pi/egregore_runtime/investigation.py +64 -41
  483. package/runtime/pi/egregore_runtime/investigation_guidance.py +16 -11
  484. package/runtime/pi/egregore_runtime/issue_cli.py +51 -32
  485. package/runtime/pi/egregore_runtime/issue_reporting.py +4 -3
  486. package/runtime/pi/egregore_runtime/issue_triage_service.py +2 -2
  487. package/runtime/pi/egregore_runtime/issues.py +12 -6
  488. package/runtime/pi/egregore_runtime/knowledge.py +331 -5
  489. package/runtime/pi/egregore_runtime/knowledge_cli.py +57 -17
  490. package/runtime/pi/egregore_runtime/lifecycle.py +88 -22
  491. package/runtime/pi/egregore_runtime/lifecycle_cli.py +21 -13
  492. package/runtime/pi/egregore_runtime/line_ids.py +10 -0
  493. package/runtime/pi/egregore_runtime/memory_push.py +349 -0
  494. package/runtime/pi/egregore_runtime/observe.py +64 -25
  495. package/runtime/pi/egregore_runtime/observers.py +19 -0
  496. package/runtime/pi/egregore_runtime/optional_modules.py +13 -0
  497. package/runtime/pi/egregore_runtime/outputs_cli.py +321 -0
  498. package/runtime/pi/egregore_runtime/policy.py +651 -24
  499. package/runtime/pi/egregore_runtime/private_result.py +2 -1
  500. package/runtime/pi/egregore_runtime/projection.py +946 -0
  501. package/runtime/pi/egregore_runtime/quest_cli.py +20 -23
  502. package/runtime/pi/egregore_runtime/question_cli.py +15 -11
  503. package/runtime/pi/egregore_runtime/questions.py +10 -10
  504. package/runtime/pi/egregore_runtime/quests.py +10 -10
  505. package/runtime/pi/egregore_runtime/record_publish.py +548 -0
  506. package/runtime/pi/egregore_runtime/record_subject.py +564 -0
  507. package/runtime/pi/egregore_runtime/research_ingest.py +2 -4
  508. package/runtime/pi/egregore_runtime/runtime.py +169 -60
  509. package/runtime/pi/egregore_runtime/sandbox.py +194 -0
  510. package/runtime/pi/egregore_runtime/scroll_cli.py +22 -32
  511. package/runtime/pi/egregore_runtime/scrolls.py +23 -15
  512. package/runtime/pi/egregore_runtime/shadow.py +262 -0
  513. package/runtime/pi/egregore_runtime/spirit_discovery.py +487 -0
  514. package/runtime/pi/egregore_runtime/spirit_discovery_cli.py +25 -0
  515. package/runtime/pi/egregore_runtime/spirit_discovery_transport.py +18 -0
  516. package/runtime/pi/egregore_runtime/status.py +101 -44
  517. package/runtime/pi/egregore_runtime/status_cli.py +13 -5
  518. package/runtime/pi/egregore_runtime/sync.py +39 -21
  519. package/runtime/pi/egregore_runtime/taste.py +934 -0
  520. package/runtime/pi/egregore_runtime/taste_cli.py +242 -0
  521. package/runtime/pi/egregore_runtime/taste_rules.py +91 -0
  522. package/runtime/pi/egregore_runtime/telemetry.py +26 -3
  523. package/runtime/pi/egregore_runtime/todo_cli.py +15 -12
  524. package/runtime/pi/egregore_runtime/todos.py +3 -2
  525. package/runtime/pi/egregore_runtime/upgrade.py +85 -58
  526. package/runtime/pi/egregore_runtime/writeback.py +330 -24
  527. package/runtime/pi/manifest.json +66 -5
  528. package/runtime/prime/.claude/context/handoff-claiming.md +32 -0
  529. package/runtime/prime/.claude/context/notification-consent.md +12 -9
  530. package/runtime/prime/.claude/skills/view/SKILL.md +438 -0
  531. package/runtime/prime/.codex/hooks.json +11 -0
  532. package/runtime/prime/.codex/skills/dark-mode/SKILL.md +1 -1
  533. package/runtime/prime/.codex/skills/records/SKILL.md +29 -0
  534. package/runtime/prime/.codex/skills/summon/SKILL.md +1 -1
  535. package/runtime/prime/.codex/skills/view/assets/compose-scaffold.html +19 -13
  536. package/runtime/prime/.codex/spec-manifest.json +13 -19
  537. package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +53 -99
  538. package/runtime/prime/.prime/agent/extensions/egregore.ts +14 -1
  539. package/runtime/prime/.prime/agent/skills/egregore/SKILL.md +14 -6
  540. package/runtime/prime/.prime/agent/skills/egregore/src/egregore/__init__.py +66 -1
  541. package/runtime/prime/.prime/agent/spec-manifest.json +2 -2
  542. package/runtime/prime/AGENTS.md +54 -105
  543. package/runtime/prime/bin/agent.sh +231 -7
  544. package/runtime/prime/bin/api-call.sh +44 -23
  545. package/runtime/prime/bin/artifact-register.sh +7 -1
  546. package/runtime/prime/bin/artifact-writeback.sh +1 -1
  547. package/runtime/prime/bin/artifacts.sh +66 -265
  548. package/runtime/prime/bin/attendant.sh +4 -1
  549. package/runtime/prime/bin/boundary-guard.cjs +1848 -0
  550. package/runtime/prime/bin/boundary-hook.sh +41 -0
  551. package/runtime/prime/bin/capture-run.sh +32 -2
  552. package/runtime/prime/bin/codex-render-spec.mjs +24 -46
  553. package/runtime/prime/bin/codex-session-start.sh +19 -0
  554. package/runtime/prime/bin/codex-skill-render.mjs +18 -0
  555. package/runtime/prime/bin/config-get.sh +10 -1
  556. package/runtime/prime/bin/connect-refresh.sh +16 -0
  557. package/runtime/prime/bin/corpus_map.py +5 -0
  558. package/runtime/prime/bin/data/capabilities/prime.json +1458 -0
  559. package/runtime/prime/bin/genui.sh +19 -0
  560. package/runtime/prime/bin/graph-batch.sh +1 -1
  561. package/runtime/prime/bin/graph-op.sh +14 -0
  562. package/runtime/prime/bin/graph.sh +1 -1
  563. package/runtime/prime/bin/handoff-pr-backfill.sh +1 -1
  564. package/runtime/prime/bin/handoff-run.sh +11 -6
  565. package/runtime/prime/bin/ingest-item.sh +1 -1
  566. package/runtime/prime/bin/ingest-surface.html +22 -4
  567. package/runtime/prime/bin/issue.sh +1 -1
  568. package/runtime/prime/bin/knowledge.sh +1 -1
  569. package/runtime/prime/bin/lib/card-delivery.sh +329 -0
  570. package/runtime/prime/bin/lib/config.sh +148 -3
  571. package/runtime/prime/bin/lib/context.sh +38 -67
  572. package/runtime/prime/bin/lib/genui-entry.py +36 -0
  573. package/runtime/prime/bin/lib/git-message.sh +25 -6
  574. package/runtime/prime/bin/lib/git-sync.sh +12 -4
  575. package/runtime/prime/bin/lib/greeting.sh +255 -28
  576. package/runtime/prime/bin/lib/handoff_meta.py +294 -0
  577. package/runtime/prime/bin/lib/health-footer.sh +83 -2
  578. package/runtime/prime/bin/lib/identity.sh +31 -10
  579. package/runtime/prime/bin/lib/instance-registry.sh +71 -0
  580. package/runtime/prime/bin/lib/local_ci_receipt.py +249 -0
  581. package/runtime/prime/bin/lib/metrics.sh +121 -8
  582. package/runtime/prime/bin/lib/notices.sh +36 -0
  583. package/runtime/prime/bin/lib/record_outcomes.py +729 -0
  584. package/runtime/prime/bin/lib/reflexes.py +267 -0
  585. package/runtime/prime/bin/lib/retrieval_scorecard.py +624 -0
  586. package/runtime/prime/bin/lib/session-record-prompt.txt +18 -0
  587. package/runtime/prime/bin/lib/session_record.py +3747 -0
  588. package/runtime/prime/bin/lib/session_trail.py +1983 -0
  589. package/runtime/prime/bin/lib/settings-drift.sh +8 -5
  590. package/runtime/prime/bin/lib/startup-restart.sh +41 -0
  591. package/runtime/prime/bin/lib/worktree-links.sh +92 -0
  592. package/runtime/prime/bin/memory-push.sh +6 -0
  593. package/runtime/prime/bin/merge-gate.sh +498 -0
  594. package/runtime/prime/bin/notify.sh +5 -2
  595. package/runtime/prime/bin/page-access.sh +103 -0
  596. package/runtime/prime/bin/person.sh +13 -2
  597. package/runtime/prime/bin/pi-branch-policy.mjs +37 -0
  598. package/runtime/prime/bin/pi-observe-context.mjs +97 -4
  599. package/runtime/prime/bin/pi-render-spec.mjs +0 -1
  600. package/runtime/prime/bin/pi-spirit-discovery.mjs +34 -0
  601. package/runtime/prime/bin/post-update.sh +181 -0
  602. package/runtime/prime/bin/prime-render-spec.mjs +0 -1
  603. package/runtime/prime/bin/prime-session-start.sh +3 -1
  604. package/runtime/prime/bin/publish-artifact.sh +89 -42
  605. package/runtime/prime/bin/qa-inventory.sh +2 -2
  606. package/runtime/prime/bin/quest.sh +1 -1
  607. package/runtime/prime/bin/records.sh +11 -0
  608. package/runtime/prime/bin/reflexes/05-vitals.sh +9 -0
  609. package/runtime/prime/bin/reflexes/10-open-items.sh +12 -0
  610. package/runtime/prime/bin/reflexes/15-retrieval.sh +8 -0
  611. package/runtime/prime/bin/reflexes/20-nightly.sh +100 -0
  612. package/runtime/prime/bin/reflexes/20-sandbox.sh +85 -0
  613. package/runtime/prime/bin/reflexes/30-cost.py +116 -0
  614. package/runtime/prime/bin/reflexes/40-shells.py +51 -0
  615. package/runtime/prime/bin/reflexes/README.md +61 -0
  616. package/runtime/prime/bin/reflexes.sh +7 -0
  617. package/runtime/prime/bin/runtime-identity.sh +140 -42
  618. package/runtime/prime/bin/screenshot.sh +77 -0
  619. package/runtime/prime/bin/scroll.sh +1 -1
  620. package/runtime/prime/bin/search.sh +31 -5
  621. package/runtime/prime/bin/session-autosave.sh +6 -3
  622. package/runtime/prime/bin/session-id.sh +147 -0
  623. package/runtime/prime/bin/session-log.sh +19 -0
  624. package/runtime/prime/bin/session-record.sh +26 -0
  625. package/runtime/prime/bin/settings.sh +13 -8
  626. package/runtime/prime/bin/spirit-discovery-claude.sh +4 -0
  627. package/runtime/prime/bin/spirit-discovery-codex.sh +4 -0
  628. package/runtime/prime/bin/spirit-discovery-pi.sh +4 -0
  629. package/runtime/prime/bin/spirit-discovery-prime.sh +4 -0
  630. package/runtime/prime/bin/spirit-discovery.sh +4 -0
  631. package/runtime/prime/bin/startup-check.sh +1 -1
  632. package/runtime/prime/bin/telemetry.sh +11 -4
  633. package/runtime/prime/bin/test-baseline.sh +33 -5
  634. package/runtime/prime/bin/todo.sh +1 -1
  635. package/runtime/prime/bin/worktree-create.sh +15 -45
  636. package/runtime/prime/bin/worktree.sh +6 -0
  637. package/runtime/prime/docs/spirit-discovery.md +96 -0
  638. package/runtime/prime/egregore_runtime/__init__.py +18 -12
  639. package/runtime/prime/egregore_runtime/access.py +608 -0
  640. package/runtime/prime/egregore_runtime/access_cli.py +190 -0
  641. package/runtime/prime/egregore_runtime/adapters/invitation.py +5 -3
  642. package/runtime/prime/egregore_runtime/adapters/qmd.py +521 -47
  643. package/runtime/prime/egregore_runtime/admin_entry.py +56 -0
  644. package/runtime/prime/egregore_runtime/artifacts.py +222 -16
  645. package/runtime/prime/egregore_runtime/contracts.py +27 -0
  646. package/runtime/prime/egregore_runtime/eligibility.py +5 -12
  647. package/runtime/prime/egregore_runtime/episode_binding.py +16 -5
  648. package/runtime/prime/egregore_runtime/github_issues.py +2 -2
  649. package/runtime/prime/egregore_runtime/handoff_lookup.py +9 -20
  650. package/runtime/prime/egregore_runtime/harness_cli.py +674 -149
  651. package/runtime/prime/egregore_runtime/held.py +2436 -0
  652. package/runtime/prime/egregore_runtime/hosted_api.py +137 -0
  653. package/runtime/prime/egregore_runtime/identity.py +196 -65
  654. package/runtime/prime/egregore_runtime/identity_transfer.py +6 -2
  655. package/runtime/prime/egregore_runtime/ingest_cli.py +2 -2
  656. package/runtime/prime/egregore_runtime/ingest_index_cli.py +4 -16
  657. package/runtime/prime/egregore_runtime/installation.py +119 -0
  658. package/runtime/prime/egregore_runtime/investigation.py +64 -41
  659. package/runtime/prime/egregore_runtime/investigation_guidance.py +16 -11
  660. package/runtime/prime/egregore_runtime/issue_cli.py +51 -32
  661. package/runtime/prime/egregore_runtime/issue_reporting.py +4 -3
  662. package/runtime/prime/egregore_runtime/issue_triage_service.py +2 -2
  663. package/runtime/prime/egregore_runtime/issues.py +12 -6
  664. package/runtime/prime/egregore_runtime/knowledge.py +331 -5
  665. package/runtime/prime/egregore_runtime/knowledge_cli.py +57 -17
  666. package/runtime/prime/egregore_runtime/lifecycle.py +88 -22
  667. package/runtime/prime/egregore_runtime/lifecycle_cli.py +21 -13
  668. package/runtime/prime/egregore_runtime/line_ids.py +10 -0
  669. package/runtime/prime/egregore_runtime/memory_push.py +349 -0
  670. package/runtime/prime/egregore_runtime/observe.py +64 -25
  671. package/runtime/prime/egregore_runtime/observers.py +19 -0
  672. package/runtime/prime/egregore_runtime/optional_modules.py +13 -0
  673. package/runtime/prime/egregore_runtime/outputs_cli.py +321 -0
  674. package/runtime/prime/egregore_runtime/policy.py +651 -24
  675. package/runtime/prime/egregore_runtime/private_result.py +2 -1
  676. package/runtime/prime/egregore_runtime/projection.py +946 -0
  677. package/runtime/prime/egregore_runtime/quest_cli.py +20 -23
  678. package/runtime/prime/egregore_runtime/question_cli.py +15 -11
  679. package/runtime/prime/egregore_runtime/questions.py +10 -10
  680. package/runtime/prime/egregore_runtime/quests.py +10 -10
  681. package/runtime/prime/egregore_runtime/record_publish.py +548 -0
  682. package/runtime/prime/egregore_runtime/record_subject.py +564 -0
  683. package/runtime/prime/egregore_runtime/research_ingest.py +2 -4
  684. package/runtime/prime/egregore_runtime/runtime.py +169 -60
  685. package/runtime/prime/egregore_runtime/sandbox.py +194 -0
  686. package/runtime/prime/egregore_runtime/scroll_cli.py +22 -32
  687. package/runtime/prime/egregore_runtime/scrolls.py +23 -15
  688. package/runtime/prime/egregore_runtime/shadow.py +262 -0
  689. package/runtime/prime/egregore_runtime/spirit_discovery.py +487 -0
  690. package/runtime/prime/egregore_runtime/spirit_discovery_cli.py +25 -0
  691. package/runtime/prime/egregore_runtime/spirit_discovery_transport.py +18 -0
  692. package/runtime/prime/egregore_runtime/status.py +101 -44
  693. package/runtime/prime/egregore_runtime/status_cli.py +13 -5
  694. package/runtime/prime/egregore_runtime/sync.py +39 -21
  695. package/runtime/prime/egregore_runtime/taste.py +934 -0
  696. package/runtime/prime/egregore_runtime/taste_cli.py +242 -0
  697. package/runtime/prime/egregore_runtime/taste_rules.py +91 -0
  698. package/runtime/prime/egregore_runtime/telemetry.py +26 -3
  699. package/runtime/prime/egregore_runtime/todo_cli.py +15 -12
  700. package/runtime/prime/egregore_runtime/todos.py +3 -2
  701. package/runtime/prime/egregore_runtime/upgrade.py +85 -58
  702. package/runtime/prime/egregore_runtime/writeback.py +330 -24
  703. package/runtime/prime/manifest.json +66 -5
  704. package/runtime/claude/bin/thread.sh +0 -9
  705. package/runtime/claude/egregore_runtime/admin_gate.py +0 -102
  706. package/runtime/claude/egregore_runtime/thread_cli.py +0 -173
  707. package/runtime/claude/egregore_runtime/threads.py +0 -521
  708. package/runtime/codex/bin/thread.sh +0 -9
  709. package/runtime/codex/egregore_runtime/admin_gate.py +0 -102
  710. package/runtime/codex/egregore_runtime/thread_cli.py +0 -173
  711. package/runtime/codex/egregore_runtime/threads.py +0 -521
  712. package/runtime/pi/bin/thread.sh +0 -9
  713. package/runtime/pi/egregore_runtime/admin_gate.py +0 -102
  714. package/runtime/pi/egregore_runtime/thread_cli.py +0 -173
  715. package/runtime/pi/egregore_runtime/threads.py +0 -521
  716. package/runtime/prime/bin/thread.sh +0 -9
  717. package/runtime/prime/egregore_runtime/admin_gate.py +0 -102
  718. package/runtime/prime/egregore_runtime/thread_cli.py +0 -173
  719. package/runtime/prime/egregore_runtime/threads.py +0 -521
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env bash
2
+ # Stable harness adapter for generated-interface taste: record what people
3
+ # like or dislike in an interface an agent made, and read it back as words.
4
+ # Identity, authorization, the event files and Git stay behind the Runtime.
5
+ set -euo pipefail
6
+
7
+ ROOT="$(cd "$(dirname "$0")/.." && pwd)"
8
+ export EGREGORE_ROOT="${EGREGORE_ROOT:-$ROOT}"
9
+ export EGREGORE_SESSION_ID="${EGREGORE_SESSION_ID:-$(bash "$ROOT/bin/session-id.sh" --root "$ROOT" 2>/dev/null || cat "$ROOT/.egregore-session-id" 2>/dev/null || true)}"
10
+ # A reaction is one line the person just said: commit it locally and deliver
11
+ # it to the remote in the background so the conversation never waits on push.
12
+ export EGREGORE_ASYNC_REMOTE_PUSH="${EGREGORE_ASYNC_REMOTE_PUSH:-1}"
13
+ export PYTHONSAFEPATH=1 PYTHONPATH="$ROOT${PYTHONPATH:+:$PYTHONPATH}"
14
+
15
+ # Runtime code reaches an existing workspace through the launcher's Runtime
16
+ # update, never through /update, which carries bin/ but not the Runtime. The
17
+ # entry sits outside the Runtime package so a missing or older Runtime gets one
18
+ # line naming that update, not a Python traceback.
19
+ exec python3 "$ROOT/bin/lib/genui-entry.py" "$@"
@@ -45,7 +45,7 @@ if [ -n "$_ENV_FILE" ] && [ -f "$_ENV_FILE" ]; then
45
45
  EGREGORE_API_KEY="${EGREGORE_API_KEY:-$(grep '^EGREGORE_API_KEY=' "$_ENV_FILE" 2>/dev/null | cut -d'=' -f2- || true)}"
46
46
  fi
47
47
 
48
- API_URL="${EGREGORE_API_URL:-$(jq -r '.api_url // empty' "$CONFIG")}"
48
+ API_URL="$(_hosted_api_url "${EGREGORE_API_URL:-$(jq -r '.api_url // empty' "$CONFIG")}")" || API_URL=""
49
49
  API_KEY="${EGREGORE_API_KEY:-}"
50
50
 
51
51
  if [ -z "$API_URL" ]; then
@@ -226,6 +226,20 @@ if [ "$_MODE" = "local" ]; then
226
226
  exit 0
227
227
  fi
228
228
 
229
+ # Every read leaves through the Runtime's packaging: an object naming a memory
230
+ # file the reader may not open is dropped, held names are stripped.
231
+ case "$OP" in
232
+ people|open-quests|spirit-context|spirit-list|open-handoffs|pending-questions|lineage|meeting-history|check-implements|\
233
+ my-merged-prs|my-implemented-handoffs|claim-handoff|claim-handoff-nudge|mark-read|mark-done) # reads, and receipts of stored text
234
+ if [ "${EGREGORE_GRAPH_PACKAGED:-}" != "1" ]; then
235
+ READ_OUT="$(EGREGORE_GRAPH_PACKAGED=1 bash "$SCRIPT_DIR/bin/graph-op.sh" "$OP" "$@")" || exit $?
236
+ printf '%s\n' "$READ_OUT" | (cd "$SCRIPT_DIR" && EGREGORE_ROOT="$SCRIPT_DIR" PYTHONSAFEPATH=1 \
237
+ PYTHONPATH="$SCRIPT_DIR${PYTHONPATH:+:$PYTHONPATH}" python3 -m egregore_runtime.harness_cli package)
238
+ exit $?
239
+ fi
240
+ ;;
241
+ esac
242
+
229
243
  # Return a bounded set of exact canonical paths containing a literal query.
230
244
  # This is intentionally a coverage check around graph results, not a second
231
245
  # full-text answer corpus: agents still open only the relevant canonical files.
@@ -81,7 +81,7 @@ fi
81
81
 
82
82
  # api_url comes from egregore.json (committed, non-secret)
83
83
  # api_key comes from .env only (EGREGORE_API_KEY) — never from egregore.json
84
- API_URL="${EGREGORE_API_URL:-$(jq -r '.api_url // empty' "$CONFIG")}"
84
+ API_URL="$(_hosted_api_url "${EGREGORE_API_URL:-$(jq -r '.api_url // empty' "$CONFIG")}")" || API_URL=""
85
85
  API_KEY="${EGREGORE_API_KEY:-}"
86
86
 
87
87
  # --- Millisecond timer (macOS + Linux compatible) ---
@@ -79,7 +79,7 @@ if [ -d "$MEMORY_DIR" ]; then
79
79
  git add -A >/dev/null 2>&1
80
80
  git commit -m "chore(handoff): backfill PR numbers for $TOPIC" >/dev/null 2>&1 || exit 0
81
81
  git pull --rebase origin main --quiet >/dev/null 2>&1
82
- git push origin main --quiet >/dev/null 2>&1
82
+ bash "$SCRIPT_DIR/bin/memory-push.sh" --repository "$MEMORY_DIR" --branch main >/dev/null 2>&1
83
83
  ) || true
84
84
  fi
85
85
 
@@ -44,6 +44,8 @@ type egregore_commit >/dev/null 2>&1 || egregore_commit() {
44
44
  local gd="$1" m="$3"; shift 3; git -C "$gd" commit -m "$m" "$@"
45
45
  }
46
46
  CONFIG="$SCRIPT_DIR/egregore.json"
47
+ # shellcheck source=bin/lib/config.sh
48
+ source "$SCRIPT_DIR/bin/lib/config.sh"
47
49
 
48
50
  if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
49
51
  sed -n '2,30p' "$0"
@@ -359,10 +361,13 @@ PID_ARTIFACTS=$!
359
361
 
360
362
  MEM_OK=0
361
363
  for i in 1 2 3; do
362
- if git pull --rebase origin main --quiet >/dev/null 2>&1 \
363
- && git push origin main --quiet >/dev/null 2>&1; then
364
- MEM_OK=1
365
- break
364
+ if git pull --rebase origin main --quiet >/dev/null 2>&1; then
365
+ if bash "$SCRIPT_DIR/bin/memory-push.sh" --repository "$MEMORY_DIR" --branch main >/dev/null 2>&1; then
366
+ MEM_OK=1
367
+ break
368
+ else
369
+ case "$?" in 75) ;; *) break ;; esac
370
+ fi
366
371
  fi
367
372
  sleep 1
368
373
  done
@@ -402,13 +407,13 @@ PID_MEMORY=$!
402
407
  if [ -f "$EMISSARY_CONFIG" ]; then
403
408
  EMISSARY_TOKEN=$(jq -r '.auth_token // empty' "$EMISSARY_CONFIG" 2>/dev/null)
404
409
  fi
405
- EMISSARY_API_URL="${EMISSARY_API_URL:-https://api.egregore.xyz/api/v1/emissary}"
410
+ EMISSARY_API_URL="$(_hosted_api_url "${EMISSARY_API_URL:-$EGREGORE_HOSTED_API_ORIGIN/api/v1/emissary}")" || EMISSARY_API_URL=""
406
411
 
407
412
  # /handoff is an internal team primitive, not an implicit public-emissary
408
413
  # composer. Use the emissary route only for an explicit recipient, and make
409
414
  # that artifact directed-private. Recipient-less handoffs fall through to
410
415
  # the org-scoped publisher (connected) or opt-in relay (local).
411
- if [ -n "$EMISSARY_TOKEN" ] && [ -n "$RECIPIENT" ]; then
416
+ if [ -n "$EMISSARY_TOKEN" ] && [ -n "$RECIPIENT" ] && [ -n "$EMISSARY_API_URL" ]; then
412
417
  # Step 1: render the handoff to HTML locally using egregore-artifacts.
413
418
  # Same renderer + template publish-artifact.sh uses today — handoffs
414
419
  # keep their familiar look.
@@ -4,7 +4,7 @@ set -euo pipefail
4
4
 
5
5
  ROOT="$(cd "$(dirname "$0")/.." && pwd)"
6
6
  export EGREGORE_ROOT="${EGREGORE_ROOT:-$ROOT}"
7
- export EGREGORE_SESSION_ID="${EGREGORE_SESSION_ID:-$(cat "$ROOT/.egregore-session-id" 2>/dev/null || true)}"
7
+ export EGREGORE_SESSION_ID="${EGREGORE_SESSION_ID:-$(bash "$ROOT/bin/session-id.sh" --root "$ROOT" 2>/dev/null || cat "$ROOT/.egregore-session-id" 2>/dev/null || true)}"
8
8
  export PYTHONSAFEPATH=1 PYTHONPATH="$ROOT${PYTHONPATH:+:$PYTHONPATH}"
9
9
 
10
10
  exec python3 -m egregore_runtime.ingest_cli "$@"
@@ -151,9 +151,15 @@ __EGREGORE_DESIGN_CSS__
151
151
  .connector:hover { border-color: var(--terracotta); }
152
152
  .connector span { color: var(--muted); font-size: 12px; }
153
153
  .connector-note { margin-top: 10px; color: var(--muted); font-size: 12px; line-height: 1.5; }
154
- .status { border-left: 2px solid var(--terracotta); padding: 10px 12px; color: var(--muted); font-size: 12px; line-height: 1.5; }
155
- .status.error { border-color: var(--danger); color: var(--danger); }
156
- .status.done { border-color: var(--success); color: var(--success); }
154
+ /* Status: a quiet panel from the highlight recipe (tint, hairline all round).
155
+ Error and done add a status word whose shape carries the state too. */
156
+ .status { --tone: var(--neutral); display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; padding: 10px 14px; border-radius: 12px; background: color-mix(in oklab, var(--tone) 6%, var(--card)); border: 1px solid color-mix(in oklab, var(--tone) 30%, transparent); color: var(--muted); font-size: 12px; line-height: 1.5; }
157
+ .status.error { --tone: var(--critical); color: var(--black); }
158
+ .status.done { --tone: var(--ok); color: var(--black); }
159
+ .status-word { display: inline-flex; align-items: center; gap: 8px; color: var(--tone); font: 500 11px/1 var(--font-mono); letter-spacing: .12em; text-transform: uppercase; }
160
+ .status-word::before { content: ""; width: 8px; height: 8px; background: currentColor; flex: none; }
161
+ .status.error .status-word::before { border-radius: 1px; }
162
+ .status.done .status-word::before { border-radius: 50%; }
157
163
  .completion { position: fixed; inset: 0; z-index: 1000; display: grid; place-items: center; overflow: hidden; background: var(--paper); color: var(--ink); }
158
164
  .completion::before, .completion::after { content: ""; position: absolute; border: 1px solid var(--line); border-radius: 50%; pointer-events: none; }
159
165
  .completion::before { width: min(74vw, 920px); aspect-ratio: 1; left: -18vw; top: -42vw; }
@@ -275,8 +281,20 @@ __EGREGORE_DESIGN_CSS__
275
281
  if (ext === 'pdf') return ['agent/PDF reader needed', 'attention'];
276
282
  return ['unsupported until an adapter is available', 'attention'];
277
283
  }
284
+ // Error and done lead with a status word, so the state never rests on
285
+ // colour alone (a raw error message does not always say it failed).
286
+ var STATUS_WORDS = { error: 'Failed', done: 'Done' };
278
287
  function setStatus(message, kind) {
279
- statusBox.textContent = message;
288
+ statusBox.replaceChildren();
289
+ if (STATUS_WORDS[kind]) {
290
+ var word = document.createElement('span');
291
+ word.className = 'status-word';
292
+ word.textContent = STATUS_WORDS[kind];
293
+ statusBox.appendChild(word);
294
+ }
295
+ var text = document.createElement('span');
296
+ text.textContent = message;
297
+ statusBox.appendChild(text);
280
298
  statusBox.className = 'status' + (kind ? ' ' + kind : '');
281
299
  }
282
300
  function showCompletion(result) {
@@ -4,7 +4,7 @@ set -euo pipefail
4
4
 
5
5
  ROOT="$(cd "$(dirname "$0")/.." && pwd)"
6
6
  export EGREGORE_ROOT="${EGREGORE_ROOT:-$ROOT}"
7
- export EGREGORE_SESSION_ID="${EGREGORE_SESSION_ID:-$(cat "$ROOT/.egregore-session-id" 2>/dev/null || true)}"
7
+ export EGREGORE_SESSION_ID="${EGREGORE_SESSION_ID:-$(bash "$ROOT/bin/session-id.sh" --root "$ROOT" 2>/dev/null || cat "$ROOT/.egregore-session-id" 2>/dev/null || true)}"
8
8
  export PYTHONSAFEPATH=1 PYTHONPATH="$ROOT${PYTHONPATH:+:$PYTHONPATH}"
9
9
 
10
10
  exec python3 -m egregore_runtime.issue_cli "$@"
@@ -4,7 +4,7 @@ set -euo pipefail
4
4
 
5
5
  ROOT="$(cd "$(dirname "$0")/.." && pwd)"
6
6
  export EGREGORE_ROOT="${EGREGORE_ROOT:-$ROOT}"
7
- export EGREGORE_SESSION_ID="${EGREGORE_SESSION_ID:-$(cat "$ROOT/.egregore-session-id" 2>/dev/null || true)}"
7
+ export EGREGORE_SESSION_ID="${EGREGORE_SESSION_ID:-$(bash "$ROOT/bin/session-id.sh" --root "$ROOT" 2>/dev/null || cat "$ROOT/.egregore-session-id" 2>/dev/null || true)}"
8
8
  export PYTHONSAFEPATH=1 PYTHONPATH="$ROOT${PYTHONPATH:+:$PYTHONPATH}"
9
9
 
10
10
  exec python3 -m egregore_runtime.knowledge_cli "$@"
@@ -0,0 +1,329 @@
1
+ # shellcheck shell=bash
2
+ # card-delivery.sh — deliver the startup card by contract, not by inference.
3
+ #
4
+ # Claude Code shows a SessionStart hook's `systemMessage` to the user and gives
5
+ # `hookSpecificOutput.additionalContext` to the model only. Splitting the
6
+ # rendered greeting that way puts the scripted card on screen the moment the
7
+ # session opens, and the model never retypes it: echoing the box art used to
8
+ # cost ~15 s of output before the first reply. Codex and Pi already show a
9
+ # scripted card (bin/codex-session-start.sh); this gives Claude the same
10
+ # contract.
11
+ #
12
+ # Startup from the saved card: every full startup saves its envelope. The next
13
+ # launch on the same branch and identity within three days, the next morning
14
+ # included and under any framework version, shows that saved card at once
15
+ # (stamped with when it was saved) after a quick pass that does only the
16
+ # per-session work (session id, consent resets, onboarding check, boundary
17
+ # rules, local fast-forwards), then
18
+ # runs the full startup detached to refresh memory, state and the saved card
19
+ # for the launch after. The full startup used to sit in front of the first
20
+ # reply: p50 26 s over 30 days of launches.
21
+ #
22
+ # Usage (sourced by bin/session-start.sh):
23
+ # [ "$(egregore_card_delivery_mode)" = harness ] && egregore_card_outer_pass "$root" "$version"
24
+
25
+ # Above this many characters Claude Code moves hook context into a file the
26
+ # model has to read back, an extra round trip on every boot. Stay under it by
27
+ # dropping the model's copy of the card first; the hidden context stays whole.
28
+ EGREGORE_CARD_CONTEXT_MAX="${EGREGORE_CARD_CONTEXT_MAX:-9500}"
29
+
30
+ # Print "harness" inside a Claude Code SessionStart hook (Claude sets
31
+ # CLAUDE_ENV_FILE for those runs alone), "text" everywhere else. An explicit
32
+ # EGREGORE_CARD_DELIVERY=harness|text wins.
33
+ egregore_card_delivery_mode() {
34
+ case "${EGREGORE_CARD_DELIVERY:-}" in
35
+ harness|text) printf '%s\n' "$EGREGORE_CARD_DELIVERY"; return 0 ;;
36
+ esac
37
+ if [ -n "${CLAUDE_ENV_FILE:-}" ] && command -v jq >/dev/null 2>&1; then
38
+ printf 'harness\n'
39
+ else
40
+ printf 'text\n'
41
+ fi
42
+ }
43
+
44
+ # Print the hook JSON envelope for a rendered greeting file. The visible card
45
+ # is everything before the hidden `<!-- session-context` block; the model gets
46
+ # that card without its logo and rules, then the hidden context and the
47
+ # closing instruction. Prints nothing and returns 1 when the file has no
48
+ # hidden block or jq fails, so the caller can fall back to plain text.
49
+ egregore_emit_card_json() {
50
+ local greeting="$1" card hidden model_card context
51
+ [ -f "$greeting" ] || return 1
52
+ grep -q '^<!-- session-context' "$greeting" 2>/dev/null || return 1
53
+
54
+ # Leading blank lines would push the logo down the screen.
55
+ card=$(awk '/^<!-- session-context/{exit} {print}' "$greeting" | sed '/./,$!d')
56
+ hidden=$(awk '/^<!-- session-context/{found=1} found' "$greeting")
57
+ # Fixed-string matches: the logo and rule glyphs are multibyte, which BSD
58
+ # awk/sed bracket expressions do not handle.
59
+ model_card=$(printf '%s\n' "$card" | grep -v -F -e '██' -e '╚═' -e '┄┄┄┄' | sed '/./,$!d')
60
+
61
+ context=$(printf '<!-- startup-card: already on the user'"'"'s screen; never reprint it\n%s\n-->\n\n%s\n' \
62
+ "$model_card" "$hidden")
63
+ if [ "${#context}" -gt "$EGREGORE_CARD_CONTEXT_MAX" ]; then
64
+ context="$hidden"
65
+ fi
66
+
67
+ jq -n --arg card "$card" --arg context "$context" '{
68
+ systemMessage: $card,
69
+ hookSpecificOutput: {hookEventName: "SessionStart", additionalContext: $context}
70
+ }' 2>/dev/null
71
+ }
72
+
73
+ # --- Saved card -------------------------------------------------------------
74
+
75
+ # Print the saved-card path for a checkout, or nothing when saving does not
76
+ # apply: worktrees and transient clones (their branch would clobber the main
77
+ # checkout's card), or EGREGORE_STARTUP_CACHE=off. `force` also saves for a
78
+ # worktree; it exists for end-to-end tests.
79
+ egregore_card_cache_path() {
80
+ local root="$1" version="$2" key
81
+ case "${EGREGORE_STARTUP_CACHE:-on}" in
82
+ off) return 0 ;;
83
+ force) ;;
84
+ *)
85
+ [ -f "$root/.git" ] && return 0
86
+ [ "${EGREGORE_TRANSIENT_CHECKOUT:-0}" = "1" ] && return 0
87
+ ;;
88
+ esac
89
+ key=$(printf '%s' "$root" | cksum | cut -d' ' -f1)
90
+ printf '%s/startup-card-v%s-%s.json\n' "${EGREGORE_CARD_CACHE_DIR:-$HOME/.egregore}" "$version" "$key"
91
+ }
92
+
93
+ # Print the saved card to start from: this version's, else the newest card
94
+ # another framework version saved for the same checkout. A version bump moves
95
+ # the path, and the refresh that renders the new version's card can run from
96
+ # the old version's startup, so neither may cost a full startup.
97
+ egregore_card_cache_find() {
98
+ local cache="$1" key
99
+ [ -n "$cache" ] || return 0
100
+ if [ -f "$cache" ]; then
101
+ printf '%s\n' "$cache"
102
+ return 0
103
+ fi
104
+ key="${cache##*-}"
105
+ find "$(dirname "$cache")" -maxdepth 1 -name "startup-card-v*-$key" -exec ls -t {} + 2>/dev/null | head -1
106
+ }
107
+
108
+ # The identity a saved card belongs to: branch and GitHub login.
109
+ _egregore_card_branch() { git -C "$1" symbolic-ref --short -q HEAD 2>/dev/null || true; }
110
+ _egregore_card_author() { jq -r '.github_username // empty' "$1/.egregore-state.json" 2>/dev/null || true; }
111
+ # The configured base branch (bin/lib/config.sh _get_base_branch, top level).
112
+ _egregore_card_base() {
113
+ jq -r 'if has("base_branch") then .base_branch else "develop" end' "$1/egregore.json" 2>/dev/null || true
114
+ }
115
+
116
+ # Save an envelope with the identity it was rendered for, and the notice
117
+ # stage of the render that produced it in the same record (null for a
118
+ # foreground render, which recorded its notices directly), so the card and
119
+ # its notices are replaced together. Atomic; fail-soft.
120
+ egregore_card_cache_write() {
121
+ local cache="$1" envelope="$2" root="$3" stage="${4:-}" notices='null'
122
+ if [ -n "$stage" ] && jq -e 'type == "object"' "$stage" >/dev/null 2>&1; then
123
+ notices=$(jq -c . "$stage" 2>/dev/null) || notices='null'
124
+ fi
125
+ [ -z "$stage" ] || rm -f "$stage"
126
+ [ -n "$cache" ] || return 0
127
+ mkdir -p "$(dirname "$cache")" 2>/dev/null || return 0
128
+ printf '%s' "$envelope" | jq -c \
129
+ --argjson saved_at "$(date +%s)" \
130
+ --arg day "$(date +%Y-%m-%d)" \
131
+ --arg branch "$(_egregore_card_branch "$root")" \
132
+ --arg author "$(_egregore_card_author "$root")" \
133
+ --argjson notices "$notices" \
134
+ '{saved_at: $saved_at, day: $day, branch: $branch, author: $author, envelope: ., notices: $notices}' \
135
+ > "$cache.tmp.$$" 2>/dev/null \
136
+ && mv "$cache.tmp.$$" "$cache" 2>/dev/null \
137
+ || rm -f "$cache.tmp.$$" 2>/dev/null
138
+ return 0
139
+ }
140
+
141
+ # The saved card (a snapshot of it) is on screen now: record the notices it
142
+ # shows. The record keeps them, so a failed write is retried at the next
143
+ # showing of the same card.
144
+ _egregore_card_promote_notices() {
145
+ local snap="$1" root="$2" stage
146
+ jq -e '.notices | type == "object"' "$snap" >/dev/null 2>&1 || return 0
147
+ stage=$(mktemp "${TMPDIR:-/tmp}/egregore-card-notices.XXXXXX" 2>/dev/null) || return 0
148
+ if jq -c '.notices' "$snap" > "$stage" 2>/dev/null && . "$root/bin/lib/notices.sh" 2>/dev/null; then
149
+ _notice_promote "$stage" >/dev/null 2>&1
150
+ fi
151
+ rm -f "$stage"
152
+ return 0
153
+ }
154
+
155
+ # Succeed when a full startup may apply a framework update from upstream
156
+ # (bin/lib/git-sync.sh _apply_framework_update, same tests): a downstream
157
+ # instance with auto_update on whose framework the Runtime does not own. A
158
+ # refresh under a live session never applies one, so such an instance keeps
159
+ # the full startup on its first launch each day.
160
+ _egregore_card_daily_update() {
161
+ local root="$1"
162
+ [ "$(jq -r '.upstream_url // empty' "$root/egregore.json" 2>/dev/null)" != "none" ] || return 1
163
+ case "$(jq -r '.auto_update | tojson' "$root/egregore.json" 2>/dev/null)" in
164
+ null|true) ;;
165
+ *) return 1 ;;
166
+ esac
167
+ ! (
168
+ # shellcheck disable=SC2034 # runtime_owns_framework reads SCRIPT_DIR
169
+ SCRIPT_DIR="$root"
170
+ . "$root/bin/lib/runtime-owned.sh" >/dev/null 2>&1 && runtime_owns_framework
171
+ )
172
+ }
173
+
174
+ # Print the saved card's age in seconds when it may stand in for a full
175
+ # startup: younger than EGREGORE_CARD_CACHE_TTL (default 3 days, so the first
176
+ # launch of a day or after a weekend is quick too), rendered for the current
177
+ # branch and identity, and that branch is the base branch: any other branch
178
+ # needs the full startup's autosave, push and switch, which never run under a
179
+ # live session. Where the full startup applies framework updates
180
+ # (_egregore_card_daily_update) the card must also be from today and under
181
+ # 12 h old. Returns 1 otherwise.
182
+ egregore_card_cache_fresh() {
183
+ local cache="$1" root="$2" now age day="" ttl=259200
184
+ [ -n "$cache" ] && [ -f "$cache" ] || return 1
185
+ [ "$(_egregore_card_branch "$root")" = "$(_egregore_card_base "$root")" ] || return 1
186
+ if _egregore_card_daily_update "$root"; then
187
+ day=$(date +%Y-%m-%d)
188
+ ttl=43200
189
+ fi
190
+ now=$(date +%s)
191
+ age=$(jq -r \
192
+ --arg day "$day" \
193
+ --arg branch "$(_egregore_card_branch "$root")" \
194
+ --arg author "$(_egregore_card_author "$root")" \
195
+ --argjson now "$now" \
196
+ 'select(($day == "" or .day == $day) and .branch == $branch and .author == $author
197
+ and (.envelope.systemMessage | type) == "string")
198
+ | $now - .saved_at' "$cache" 2>/dev/null) || return 1
199
+ case "$age" in ''|*[!0-9]*) return 1 ;; esac
200
+ [ "$age" -lt "${EGREGORE_CARD_CACHE_TTL:-$ttl}" ] || return 1
201
+ printf '%s\n' "$age"
202
+ }
203
+
204
+ # Print the saved envelope for this launch: anything the quick pass printed
205
+ # goes on top of the card, an age line goes above the closing question, and
206
+ # the model is told how old its startup context is. A card from an earlier
207
+ # day names that day and time, so its own "today" and "yesterday" read as of
208
+ # then.
209
+ egregore_card_cache_show() {
210
+ local cache="$1" preamble="$2" age="$3" when day clock dated=""
211
+ if [ "$age" -lt 120 ]; then when="just now"
212
+ elif [ "$age" -lt 7200 ]; then when="$((age / 60)) min ago"
213
+ else when="$((age / 3600)) h ago"; fi
214
+ day=$(jq -r '.day // empty' "$cache" 2>/dev/null)
215
+ if [ -n "$day" ] && [ "$day" != "$(date +%Y-%m-%d)" ] \
216
+ && clock=$(jq -er '.saved_at | strflocaltime("%a %H:%M")' "$cache" 2>/dev/null); then
217
+ if [ "$day" = "$(date -v-1d +%Y-%m-%d 2>/dev/null || date -d yesterday +%Y-%m-%d 2>/dev/null)" ]; then
218
+ when="yesterday ${clock#* }"
219
+ else
220
+ when="$clock"
221
+ fi
222
+ dated="; its dates (today, yesterday, ago) are as of then"
223
+ fi
224
+ jq -c --arg pre "$preamble" --arg when "$when" --arg dated "$dated" '.envelope
225
+ | .systemMessage |= (
226
+ split("\n") as $l
227
+ | ([range(0; $l | length)] | map(select($l[.] | test("\\S"))) | last // ($l | length)) as $i
228
+ | ($l[:$i] + [" ◦ card from \($when) · updating in the background", ""] + $l[$i:])
229
+ | join("\n")
230
+ | if $pre == "" then . else $pre + "\n\n" + . end)
231
+ | .hookSpecificOutput.additionalContext |= (
232
+ "<!-- startup-context-age: saved \($when)\($dated); a background startup is refreshing memory and state now -->\n\n" + .)' \
233
+ "$cache" 2>/dev/null
234
+ }
235
+
236
+ # Run the full startup detached for a session the quick pass identified, and
237
+ # save its envelope for the next launch. Nothing inherits the hook's pipe.
238
+ egregore_card_refresh_detached() {
239
+ local root="$1" cache="$2" sid="$3"
240
+ ( (
241
+ # Its notices wait in a stage, saved with its card, until that card is
242
+ # shown (bin/lib/notices.sh). Without a capture file the refresh still
243
+ # runs; it just saves no card.
244
+ _refresh_stage="$cache.notices.tmp.$$"
245
+ _refresh_out=$(mktemp "${TMPDIR:-/tmp}/egregore-card-refresh.XXXXXX" 2>/dev/null) || _refresh_out=""
246
+ _EGREGORE_CARD_PASS=refresh _EGREGORE_REUSE_SESSION_ID="$sid" EGREGORE_NOTICE_STAGE="$_refresh_stage" \
247
+ bash "$root/bin/session-start.sh" > "${_refresh_out:-/dev/null}" 2>/dev/null < /dev/null
248
+ if [ -n "$_refresh_out" ] && _refresh_envelope=$(egregore_emit_card_json "$_refresh_out"); then
249
+ egregore_card_cache_write "$cache" "$_refresh_envelope" "$root" "$_refresh_stage"
250
+ fi
251
+ rm -f "$_refresh_stage" ${_refresh_out:+"$_refresh_out"}
252
+ ) > /dev/null 2>&1 < /dev/null & ) 2>/dev/null
253
+ }
254
+
255
+ # Print a finished startup's envelope and save it, then exit with the
256
+ # startup's status. When no envelope can be built the output goes out as plain
257
+ # text, so its closing instruction becomes the text-mode one: nothing is on
258
+ # the user's screen for the model to leave alone.
259
+ _egregore_card_finish() {
260
+ local out="$1" cache="$2" root="$3" rc="$4" envelope
261
+ if envelope=$(egregore_emit_card_json "$out"); then
262
+ printf '%s\n' "$envelope"
263
+ egregore_card_cache_write "$cache" "$envelope" "$root"
264
+ else
265
+ awk '
266
+ /^egregore-quick-ok / { next }
267
+ /^STARTUP CARD: .*\/onboarding/ {
268
+ print "IMPORTANT: Display the above greeting exactly as-is (ASCII art + ornamented status). Then ask the user if they'"'"'d like a quick onboarding tour (run /onboarding), or if they want to jump straight in."
269
+ next
270
+ }
271
+ /^STARTUP CARD: / {
272
+ print "IMPORTANT: Display the above greeting to the user exactly as-is (preserve the ASCII art formatting and ornamented status) on their first message. Then ask: What are you working on?"
273
+ next
274
+ }
275
+ { print }' "$out"
276
+ fi
277
+ rm -f "$out"
278
+ exit "$rc"
279
+ }
280
+
281
+ # The hook's outer pass. Exits the calling script with the startup's status
282
+ # once the envelope (or the plain fallback) is printed; returns 1 only when it
283
+ # could not set up a capture, so the caller continues as a plain run.
284
+ egregore_card_outer_pass() {
285
+ local root="$1" version="$2" out cache saved="" snap="" age rc sid envelope
286
+ out=$(mktemp "${TMPDIR:-/tmp}/egregore-card.XXXXXX" 2>/dev/null) || return 1
287
+ cache=$(egregore_card_cache_path "$root" "$version")
288
+
289
+ # Read the saved card once: a refresh can replace it at any moment, and the
290
+ # notices recorded must be the ones on the card shown. The refresh saves
291
+ # under this version's path whichever version's card was shown.
292
+ [ "${EGREGORE_STARTUP_FAST:-on}" = "off" ] || saved=$(egregore_card_cache_find "$cache")
293
+ if [ -n "$saved" ]; then
294
+ snap=$(mktemp "${TMPDIR:-/tmp}/egregore-card-snap.XXXXXX" 2>/dev/null) || snap=""
295
+ if [ -n "$snap" ] && ! cp "$saved" "$snap" 2>/dev/null; then rm -f "$snap"; snap=""; fi
296
+ fi
297
+
298
+ if [ -n "$snap" ] && age=$(egregore_card_cache_fresh "$snap" "$root"); then
299
+ # The quick pass inherits the hook's stdin so it maps this session's id.
300
+ _EGREGORE_CARD_PASS=quick bash "$root/bin/session-start.sh" > "$out"
301
+ rc=$?
302
+ sid=$(sed -n 's/^egregore-quick-ok //p' "$out" | tail -1)
303
+ if [ "$rc" -ne 0 ] || [ -z "$sid" ]; then
304
+ # The quick pass stopped early (onboarding_needed, an error): show what
305
+ # it said; nothing else runs for this session.
306
+ rm -f "$snap"
307
+ _egregore_card_finish "$out" "" "$root" "$rc"
308
+ fi
309
+ if envelope=$(egregore_card_cache_show "$snap" "$(grep -v '^egregore-quick-ok ' "$out")" "$age") \
310
+ && [ -n "$envelope" ]; then
311
+ printf '%s\n' "$envelope"
312
+ # Before the refresh renders the next card against the ledger.
313
+ _egregore_card_promote_notices "$snap" "$root"
314
+ egregore_card_refresh_detached "$root" "$cache" "$sid"
315
+ rm -f "$out" "$snap"
316
+ exit 0
317
+ fi
318
+ # The saved card could not be read after all: finish this session's
319
+ # startup in the foreground under the id the quick pass minted.
320
+ rm -f "$snap"
321
+ _EGREGORE_CARD_PASS=refresh _EGREGORE_REUSE_SESSION_ID="$sid" \
322
+ bash "$root/bin/session-start.sh" > "$out" < /dev/null
323
+ _egregore_card_finish "$out" "$cache" "$root" "$?"
324
+ fi
325
+ [ -z "$snap" ] || rm -f "$snap"
326
+
327
+ _EGREGORE_CARD_PASS=inner bash "$root/bin/session-start.sh" > "$out"
328
+ _egregore_card_finish "$out" "$cache" "$root" "$?"
329
+ }