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,61 @@
1
+ # Reflexes
2
+
3
+ A reflex is a probe with a tier. The probe states a fact about yesterday; the
4
+ tier says how far the egregore may go on its own: say it (show), end the line
5
+ with the command to run (propose), or do it and leave a receipt (act). The
6
+ startup card is where the probes speak, on every harness. The act tier never
7
+ prints from here; it lives in the path it governs, such as the merge gate in
8
+ the save path.
9
+
10
+ ## A probe
11
+
12
+ One file in this directory: a `.sh` or `.py` file, or any executable. The
13
+ runner (`bin/reflexes.sh`, `bin/lib/reflexes.py`) runs them in name order,
14
+ one at a time, and prints each line a probe writes to stdout with the card's
15
+ sigil in front. A probe prints nothing when there is nothing to say, one line
16
+ for a fact, two at most. Lines are cut at 160 characters.
17
+
18
+ The runner never fails the card. A probe that exits non-zero, prints nothing,
19
+ or runs past one second is silent; the runner stops launching probes once
20
+ three seconds have passed in total. `bash bin/reflexes.sh --debug` names
21
+ every silent probe and the reason.
22
+
23
+ Sessions started minutes apart print the same card, so the runner keeps the
24
+ last card for each harness in `.egregore/runtime/reflexes/` and prints it
25
+ again, for up to ten minutes, while what the probes read is unchanged: the
26
+ probe and `bin/lib` files, everything under `memory/sessions` (records and
27
+ ledgers), the features in `egregore.json`, the person's names and records
28
+ switch in the state file, the local date and nightly's cache (`cache_key` in
29
+ `bin/lib/reflexes.py`). Anything else, such as the memory lookups the
30
+ retrieval line counts, can be up to ten minutes old on the card. `--debug`, a
31
+ sandbox marker, or a run in which a probe ran past its budget or never
32
+ started skips the cache.
33
+
34
+ Every probe gets, on top of the caller's environment:
35
+
36
+ - `EGREGORE_ROOT` the project root
37
+ - `EGREGORE_MEMORY` the memory directory, which may not exist
38
+ - `EGREGORE_STATE` the per-instance state file (`.egregore-state.json`)
39
+ - `EGREGORE_AUTHOR` the person's GitHub username, when known
40
+ - `EGREGORE_HARNESS` `claude`, `codex`, `pi` or `prime`
41
+
42
+ A probe reads records, state and local files; it never reaches the network
43
+ without a cache and a budget, never writes outside `tmp/` (beyond one file
44
+ created and removed to test a directory, as `20-sandbox.sh` does), and never
45
+ prints anything a record would withhold.
46
+
47
+ ## Adding one
48
+
49
+ Add a file here with a two-digit prefix for order (`20-nightly.sh`), make it
50
+ print its line only when its predicate holds, and give it a case in
51
+ `tests/test-reflexes.sh` or a test of its own. A probe that reads a file the
52
+ cache key does not cover shows its change up to ten minutes late; add the
53
+ file to `cache_key` when that matters. The runtime bundle ships this
54
+ directory whole (`BIN_DIRS` in the bundle builder), so a tracked probe needs
55
+ no allowlist entry. An organisation adds its own probes the same way.
56
+
57
+ ## Wording
58
+
59
+ A show line states the fact: `3 open items are older than three days and
60
+ have no owner`. A propose line ends with the command: `... · /records file
61
+ a1b2c3`. No exclamation marks, no advice, no explanation of the mechanism.
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ # The reflexes: one runner, a directory of probes. See bin/reflexes/README.md.
3
+ # Prints the probes' lines for the startup card; never fails the card.
4
+ set -uo pipefail
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)" || exit 0
6
+ command -v python3 >/dev/null 2>&1 || exit 0
7
+ exec python3 "$SCRIPT_DIR/bin/lib/reflexes.py" --root "$SCRIPT_DIR" "$@"
@@ -14,6 +14,8 @@ ROOT="${EGREGORE_INSTANCE_ROOT:-$RUNTIME_ROOT}"
14
14
  ROOT="$(cd "$ROOT" && pwd)"
15
15
  CONFIG="$ROOT/egregore.json"
16
16
  STATE="$ROOT/.egregore-state.json"
17
+ # shellcheck source=bin/lib/config.sh
18
+ source "$RUNTIME_ROOT/bin/lib/config.sh"
17
19
 
18
20
  resolved() {
19
21
  [ -f "$CONFIG" ] && [ -f "$STATE" ] || return 1
@@ -26,6 +28,114 @@ resolved() {
26
28
  ' "$STATE" >/dev/null 2>&1
27
29
  }
28
30
 
31
+ # The saved address is resolved: an egregore.json saved before the October
32
+ # 2026 move still names the retired origin, which never receives a token.
33
+ connected_config() {
34
+ api_url="$(_config_api_url)" || api_url=""
35
+ slug="$(jq -r '.slug // empty' "$CONFIG" 2>/dev/null)"
36
+ api_key="$(grep '^EGREGORE_API_KEY=' "$ROOT/.env" 2>/dev/null | cut -d= -f2- || true)"
37
+ [ -n "$api_url" ] && [ -n "$slug" ]
38
+ }
39
+
40
+ # The greeting's one note about the organization key (bin/lib/health-footer.sh
41
+ # renders it): "renewed" shows once; "needs_sign_in" shows until renewal works.
42
+ key_notice_state() {
43
+ jq -r '.hosted_key_notice.state // empty' "$STATE" 2>/dev/null || true
44
+ }
45
+
46
+ key_notice() {
47
+ local file tmp
48
+ [ -f "$STATE" ] || return 0
49
+ # A worktree links the checkout's state file: rename onto its target.
50
+ file="$(realpath "$STATE" 2>/dev/null)" || file="$STATE"
51
+ tmp="$(mktemp "$file.XXXXXX" 2>/dev/null)" || return 0
52
+ if [ "$1" = clear ]; then
53
+ jq 'if .hosted_key_notice.state == "needs_sign_in" then del(.hosted_key_notice) else . end' \
54
+ "$file" >"$tmp" 2>/dev/null
55
+ else
56
+ jq --arg state "$1" --arg at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
57
+ '.hosted_key_notice = {state: $state, at: $at}' "$file" >"$tmp" 2>/dev/null
58
+ fi && [ -s "$tmp" ] && mv "$tmp" "$file" || rm -f "$tmp"
59
+ }
60
+
61
+ # One authenticated status read; sets status_code and status_body.
62
+ probe_status() {
63
+ local response=""
64
+ status_code=""
65
+ status_body=""
66
+ [ -n "$api_key" ] || return 0
67
+ response="$(curl -s "$api_url/api/org/status" \
68
+ -H "Authorization: Bearer $api_key" --connect-timeout 2 --max-time 4 \
69
+ -w '\n%{http_code}' 2>/dev/null || true)"
70
+ status_code="${response##*$'\n'}"
71
+ status_body="${response%$'\n'*}"
72
+ }
73
+
74
+ status_ok() {
75
+ [ "$status_code" = 200 ] && printf '%s' "$status_body" | jq -e --arg slug "$slug" '
76
+ (.org_id | type == "string" and length > 0) and .slug == $slug
77
+ ' >/dev/null 2>&1
78
+ }
79
+
80
+ rejection_code() {
81
+ [ "$status_code" = 401 ] || return 0
82
+ printf '%s' "$status_body" | jq -r '.code // empty' 2>/dev/null || true
83
+ }
84
+
85
+ # Recover the configured org's key only through the membership-verifying
86
+ # endpoint, which renews a key retired in the October 2026 security reset.
87
+ # A historic path/namespace collision could also leave this checkout with
88
+ # another Egregore's key. Install it atomically, then verify it. No
89
+ # credential bytes are printed. $1 is the API's code for the rejected key.
90
+ recover_key() {
91
+ local rejected="${1:-}" github_token encoded_slug response code recovered renewed previous_key
92
+ github_token="$(grep '^GITHUB_TOKEN=' "$ROOT/.env" 2>/dev/null | cut -d= -f2- || true)"
93
+ if [ -z "$github_token" ]; then
94
+ [ "$rejected" != key_retired ] || key_notice needs_sign_in
95
+ return 1
96
+ fi
97
+ encoded_slug="$(printf '%s' "$slug" | jq -sRr @uri)"
98
+ response="$(curl -s "$api_url/api/org/$encoded_slug/key" \
99
+ -H "Authorization: Bearer $github_token" --connect-timeout 2 --max-time 12 \
100
+ -w '\n%{http_code}' 2>/dev/null || true)"
101
+ code="${response##*$'\n'}"
102
+ recovered="${response%$'\n'*}"
103
+ if [ "$code" = 401 ]; then
104
+ # The GitHub sign-in was rejected; a fresh one renews the key.
105
+ [ "$rejected" != key_retired ] || key_notice needs_sign_in
106
+ return 1
107
+ fi
108
+ [ "$code" = 200 ] || return 1
109
+ # The key itself must name this org (ek_<slug>_<secret>), not just the reply.
110
+ printf '%s' "$recovered" | jq -e --arg slug "$slug" '
111
+ (.api_key | type == "string" and startswith("ek_" + $slug + "_")
112
+ and length > ($slug | length) + 4)
113
+ and .org_slug == $slug
114
+ ' >/dev/null 2>&1 || return 1
115
+ renewed="$(printf '%s' "$recovered" | jq -r '.renewed == true' 2>/dev/null || echo false)"
116
+ # Prove the candidate works before it replaces the saved key.
117
+ previous_key="$api_key"
118
+ api_key="$(printf '%s' "$recovered" | jq -r '.api_key')"
119
+ probe_status
120
+ if ! status_ok; then
121
+ api_key="$previous_key"
122
+ return 1
123
+ fi
124
+ if ! printf '%s' "$recovered" | \
125
+ EGREGORE_ROOT="$ROOT" \
126
+ PYTHONSAFEPATH=1 PYTHONPATH="$RUNTIME_ROOT${PYTHONPATH:+:$PYTHONPATH}" \
127
+ python3 -m egregore_runtime.identity_cli install-connected-key >/dev/null; then
128
+ api_key="$previous_key"
129
+ return 1
130
+ fi
131
+ api_key="$(grep '^EGREGORE_API_KEY=' "$ROOT/.env" 2>/dev/null | cut -d= -f2- || true)"
132
+ if [ "$rejected" = key_retired ] || [ "$renewed" = true ]; then
133
+ key_notice renewed
134
+ else
135
+ key_notice clear
136
+ fi
137
+ }
138
+
29
139
  case "${1:-ensure}" in
30
140
  status)
31
141
  if resolved; then
@@ -35,56 +145,44 @@ case "${1:-ensure}" in
35
145
  printf '{"status":"unresolved"}\n'
36
146
  exit 1
37
147
  ;;
148
+ recover)
149
+ # A hosted request just rejected the organization key ($2 is the API's
150
+ # code). Once a fresh sign-in is known to be needed, only session start
151
+ # retries, so the notice and the retry stay one per session.
152
+ [ "$(key_notice_state)" != needs_sign_in ] || exit 1
153
+ connected_config || exit 1
154
+ recover_key "${2:-}"
155
+ ;;
38
156
  ensure)
39
- resolved && exit 0
157
+ if resolved; then
158
+ # Healthy starts stop here, with no network call. After a recorded
159
+ # need for a fresh sign-in, retry so the greeting shows the outcome.
160
+ [ "$(key_notice_state)" = needs_sign_in ] || exit 0
161
+ connected_config || exit 0
162
+ probe_status
163
+ if status_ok; then
164
+ key_notice clear
165
+ else
166
+ recover_key "$(rejection_code)" || true
167
+ fi
168
+ exit 0
169
+ fi
40
170
  mode="$(jq -r 'if (.mode // "local") == "connected" or (.api_url // "") != "" then "connected" else "local" end' "$CONFIG" 2>/dev/null || echo local)"
41
171
  if [ "$mode" = "local" ]; then
42
172
  EGREGORE_ROOT="$ROOT" \
43
173
  PYTHONSAFEPATH=1 PYTHONPATH="$RUNTIME_ROOT${PYTHONPATH:+:$PYTHONPATH}" \
44
174
  python3 -m egregore_runtime.identity_cli initialize-local >/dev/null
45
175
  else
46
- api_url="$(jq -r '.api_url // empty' "$CONFIG" 2>/dev/null)"
47
- slug="$(jq -r '.slug // empty' "$CONFIG" 2>/dev/null)"
48
- api_key="$(grep '^EGREGORE_API_KEY=' "$ROOT/.env" 2>/dev/null | cut -d= -f2-)"
49
- [ -n "$api_url" ] && [ -n "$slug" ] || exit 1
176
+ connected_config || exit 1
50
177
  # Identity repair selects already-existing account and membership
51
- # records, then adopts their opaque IDs locally. If a stale credential
52
- # belongs to another org, recover only the configured org's existing key
53
- # through verified GitHub membership. No control-plane records are made.
54
- control_plane=""
55
- if [ -n "$api_key" ]; then
56
- control_plane="$(curl -sf "$api_url/api/org/status" \
57
- -H "Authorization: Bearer $api_key" --connect-timeout 2 --max-time 4 \
58
- 2>/dev/null || true)"
59
- fi
60
- if ! printf '%s' "$control_plane" | jq -e --arg slug "$slug" '
61
- (.org_id | type == "string" and length > 0) and .slug == $slug
62
- ' >/dev/null 2>&1; then
63
- # A historic path/namespace collision could leave this checkout with
64
- # another Egregore's API key. Recover the configured org's existing key
65
- # only through the membership-verifying endpoint, install it atomically,
66
- # and retry. No credential bytes are printed.
67
- github_token="$(grep '^GITHUB_TOKEN=' "$ROOT/.env" 2>/dev/null | cut -d= -f2-)"
68
- [ -n "$github_token" ] || exit 1
69
- encoded_slug="$(printf '%s' "$slug" | jq -sRr @uri)"
70
- recovered="$(curl -sf "$api_url/api/org/$encoded_slug/key" \
71
- -H "Authorization: Bearer $github_token" --connect-timeout 2 --max-time 12 \
72
- 2>/dev/null || true)"
73
- printf '%s' "$recovered" | jq -e --arg slug "$slug" '
74
- (.api_key | type == "string" and length > 0) and .org_slug == $slug
75
- ' >/dev/null 2>&1 || exit 1
76
- printf '%s' "$recovered" | \
77
- EGREGORE_ROOT="$ROOT" \
78
- PYTHONSAFEPATH=1 PYTHONPATH="$RUNTIME_ROOT${PYTHONPATH:+:$PYTHONPATH}" \
79
- python3 -m egregore_runtime.identity_cli install-connected-key >/dev/null
80
- api_key="$(grep '^EGREGORE_API_KEY=' "$ROOT/.env" 2>/dev/null | cut -d= -f2-)"
81
- control_plane="$(curl -sf "$api_url/api/org/status" \
82
- -H "Authorization: Bearer $api_key" --connect-timeout 2 --max-time 4 \
83
- 2>/dev/null || true)"
84
- printf '%s' "$control_plane" | jq -e --arg slug "$slug" '
85
- (.org_id | type == "string" and length > 0) and .slug == $slug
86
- ' >/dev/null 2>&1 || exit 1
178
+ # records, then adopts their opaque IDs locally. A rejected key is
179
+ # recovered for the configured org only, through verified GitHub
180
+ # membership. No control-plane records are made.
181
+ probe_status
182
+ if ! status_ok; then
183
+ recover_key "$(rejection_code)" || exit 1
87
184
  fi
185
+ control_plane="$status_body"
88
186
  roster="$(curl -sf "$api_url/api/org/$slug/members?include_removed=true" \
89
187
  -H "Authorization: Bearer $api_key" --connect-timeout 2 --max-time 4 \
90
188
  2>/dev/null || true)"
@@ -102,7 +200,7 @@ case "${1:-ensure}" in
102
200
  resolved
103
201
  ;;
104
202
  *)
105
- echo 'usage: bash bin/runtime-identity.sh {ensure|status}' >&2
203
+ echo 'usage: bash bin/runtime-identity.sh {ensure|status|recover [code]}' >&2
106
204
  exit 2
107
205
  ;;
108
206
  esac
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env bash
2
+ # Render an HTML file or a URL to a PNG with headless Chrome.
3
+ # bin/screenshot.sh <file.html|url> <out.png> [width] [height] (1440 x 2400)
4
+ # Chrome: $EGREGORE_CHROME when set, with no fallback when it is wrong; else
5
+ # the macOS Google Chrome app; else google-chrome or chromium on PATH. An
6
+ # aborted render (no file, or zero bytes) is retried once; each try is capped
7
+ # at 30 s. Prints "<out>: <bytes> bytes"; a failure prints one line naming the
8
+ # cause and exits non-zero.
9
+ # Headless Chrome enforces a minimum window width near 500 px, so phone checks
10
+ # use 600. Heights above about 5400 px yield no file. Run one headless Chrome
11
+ # at a time. Chrome dies at launch under the Codex sandbox, so in a minion run
12
+ # the driver renders (.claude/skills/minion/SKILL.md, LAND).
13
+ set -u
14
+
15
+ die() { printf 'screenshot: %s\n' "$1" >&2; exit "${2:-1}"; }
16
+ whole() { for n in "$@"; do case $n in '' | 0* | *[!0-9]*) return 1 ;; esac; done; }
17
+
18
+ [ $# -ge 2 ] && [ $# -le 4 ] || die "usage: bin/screenshot.sh <file.html|url> <out.png> [width] [height]" 2
19
+ input=$1 out=$2 width=${3:-1440} height=${4:-2400}
20
+ whole "$width" "$height" || die "width and height must be whole pixels, got $width x $height" 2
21
+
22
+ if [[ $input =~ ^[A-Za-z][A-Za-z0-9+.-]*:// ]] || [[ $input == data:* ]] || [[ $input == about:* ]]; then
23
+ url=$input
24
+ else
25
+ [ -f "$input" ] && [ -r "$input" ] || die "input file missing: $input"
26
+ case $input in */*) dir=${input%/*} ;; *) dir=. ;; esac
27
+ dir=$(cd -- "${dir:-/}" && pwd -P) || die "input file missing: $input"
28
+ url=file://
29
+ # Percent-encode every byte outside the unreserved set, so a space, "#", "?",
30
+ # "%", a control character or a non-UTF-8 name reaches Chrome intact.
31
+ # shellcheck disable=SC2046 # the words are od's hex pairs; splitting them is the point
32
+ for byte in $(printf '%s' "${dir%/}/${input##*/}" | od -An -v -tx1); do
33
+ case $byte in
34
+ 2[d-f] | 3[0-9] | 4[1-9a-f] | 5[0-9a] | 5f | 6[1-9a-f] | 7[0-9a] | 7e)
35
+ printf -v char '%b' "\\x$byte"; url+=$char ;;
36
+ *) url+=%$byte ;;
37
+ esac
38
+ done
39
+ fi
40
+
41
+ case $out in */*) outdir=${out%/*} ;; *) outdir=. ;; esac
42
+ [ -d "${outdir:-/}" ] && [ -w "${outdir:-/}" ] || die "output directory missing or not writable: ${outdir:-/}"
43
+ [ ! -d "$out" ] || die "output path is a directory: $out"
44
+
45
+ if [ -n "${EGREGORE_CHROME:-}" ]; then
46
+ chrome=$EGREGORE_CHROME
47
+ [ -f "$chrome" ] && [ -x "$chrome" ] || die "no Chrome found: EGREGORE_CHROME=$chrome is not an executable file"
48
+ else
49
+ chrome="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
50
+ [ -x "$chrome" ] || chrome=$(command -v google-chrome || command -v chromium) \
51
+ || die "no Chrome found: set EGREGORE_CHROME, or install Google Chrome or Chromium"
52
+ fi
53
+
54
+ pid=
55
+ trap '[ -z "$pid" ] || kill "$pid" 2>/dev/null' EXIT
56
+ trap 'exit 130' INT TERM HUP
57
+
58
+ render() { # one try; true when Chrome left a non-empty file at $out
59
+ rm -f -- "$out"; timed_out=0 ticks=0
60
+ "$chrome" --headless=new --disable-gpu --hide-scrollbars --window-size="$width,$height" \
61
+ --virtual-time-budget=4000 --screenshot="$out" "$url" >/dev/null 2>&1 &
62
+ pid=$!
63
+ while kill -0 "$pid" 2>/dev/null; do
64
+ [ "$ticks" -lt 150 ] || { kill -9 "$pid" 2>/dev/null; timed_out=1; break; }
65
+ sleep 0.2; ticks=$((ticks + 1))
66
+ done
67
+ wait "$pid" 2>/dev/null; pid=
68
+ [ -f "$out" ] && [ -s "$out" ]
69
+ }
70
+
71
+ if ! render && ! render; then
72
+ cause="no file at $out"
73
+ [ "$timed_out" = 0 ] || cause="the last try timed out after 30 s"
74
+ [ "$height" -le 5400 ] || cause="$cause; heights above about 5400 px yield no file"
75
+ die "render aborted twice ($cause)"
76
+ fi
77
+ printf '%s: %s bytes\n' "$out" "$(wc -c < "$out" | tr -d ' ')"
@@ -3,7 +3,7 @@ set -euo pipefail
3
3
 
4
4
  ROOT="$(cd "$(dirname "$0")/.." && pwd)"
5
5
  export EGREGORE_ROOT="$ROOT"
6
- export EGREGORE_SESSION_ID="${EGREGORE_SESSION_ID:-$(cat "$ROOT/.egregore-session-id" 2>/dev/null || true)}"
6
+ 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)}"
7
7
  export PYTHONSAFEPATH=1 PYTHONPATH="$ROOT${PYTHONPATH:+:$PYTHONPATH}"
8
8
 
9
9
  exec python3 -m egregore_runtime.scroll_cli "$@"
@@ -10,6 +10,7 @@
10
10
  # bash bin/search.sh start
11
11
  # bash bin/search.sh stop
12
12
  # bash bin/search.sh open memory/path/to/source.md
13
+ # bash bin/search.sh mind publish
13
14
  #
14
15
  # The shell owns the established user-facing output. Retrieval infrastructure
15
16
  # is isolated behind the Egregore Retriever adapter.
@@ -47,6 +48,28 @@ _elapsed_s() {
47
48
  awk -v ms="$(( $(_now_ms) - $1 ))" 'BEGIN { printf "%.1f", ms / 1000 }'
48
49
  }
49
50
 
51
+ # Run a Runtime operation as an OpenTelemetry span when the harness traces
52
+ # this process (it exports TRACEPARENT). Untraced calls take the plain path.
53
+ # Usage: _traced <span-name> <original-args-array-name> <command...>
54
+ _traced() {
55
+ local name="$1" argv_ref="$2[@]"; shift 2
56
+ if [ -z "${TRACEPARENT:-}" ]; then "$@"; return $?; fi
57
+ local start out rc results degraded stale
58
+ start=$(_now_ms)
59
+ out=$(mktemp "${TMPDIR:-/tmp}/egregore-span.XXXXXX")
60
+ "$@" | tee "$out"
61
+ rc=${PIPESTATUS[0]}
62
+ results=$(grep -cE '^[0-9]+\. ' "$out" 2>/dev/null)
63
+ degraded=false; grep -q 'Search degraded' "$out" 2>/dev/null && degraded=true
64
+ stale=$(sed -nE 's/^Note: ([0-9]+) eligible document.*/\1/p' "$out" 2>/dev/null | head -1)
65
+ rm -f "$out"
66
+ ( python3 "$SCRIPT_DIR/bin/lib/otel_span.py" --name "$name" --start-ms "$start" \
67
+ --end-ms "$(_now_ms)" --rc "$rc" --attr "egregore.search.results=${results:-0}" \
68
+ --attr "egregore.search.degraded=$degraded" --attr "egregore.search.stale_documents=${stale:-}" \
69
+ --argv -- ${!argv_ref+"${!argv_ref}"} >/dev/null 2>&1 & ) 2>/dev/null
70
+ return "$rc"
71
+ }
72
+
50
73
  _result_paths() {
51
74
  local line path canonical_prefix
52
75
  canonical_prefix="**file:** \`memory/"
@@ -71,7 +94,7 @@ _result_paths() {
71
94
  # calls there. The dormant graph configuration is preserved untouched for
72
95
  # rollback only.
73
96
  _upgrade_instance_key() {
74
- # Mirrors egregore_runtime.upgrade.instance_key: stable org identity
97
+ # Mirrors egregore_runtime.installation.installation_key: stable org identity
75
98
  # composed with the main installation path. No org_id → fail closed.
76
99
  local org main gitdir
77
100
  org=$(jq -r '.org_id // empty' "$SCRIPT_DIR/egregore.json" 2>/dev/null)
@@ -371,11 +394,12 @@ case "${1:-}" in
371
394
  for arg in "$@"; do
372
395
  if [ "$arg" = --context-packet ]; then FIND_ARGS+=(--private-result); else FIND_ARGS+=("$arg"); fi
373
396
  done
374
- _runtime find "${FIND_ARGS[@]}"
397
+ _traced egregore.search.find FIND_ARGS _runtime find "${FIND_ARGS[@]}"
375
398
  ;;
376
399
  investigate) shift; cmd_investigate "$@" ;;
377
400
  start) shift; _runtime start "$@" ;;
378
401
  stop) shift; _runtime stop "$@" ;;
402
+ mind) shift; _runtime mind "$@" ;;
379
403
  open)
380
404
  shift
381
405
  OPEN_PACKET=0; OPEN_PATHS=()
@@ -393,19 +417,21 @@ case "${1:-}" in
393
417
  [ "$OPEN_PACKET" = 1 ] && OPEN_BINDING+=(--private-result)
394
418
  # Older Bash treats an empty array as unset under nounset. Optional flags
395
419
  # must expand to zero arguments without requiring an explicit episode ID.
396
- _runtime open ${OPEN_PATHS[@]+"${OPEN_PATHS[@]}"} ${OPEN_BINDING[@]+"${OPEN_BINDING[@]}"}
420
+ OPEN_ARGS=(${OPEN_PATHS[@]+"${OPEN_PATHS[@]}"} ${OPEN_BINDING[@]+"${OPEN_BINDING[@]}"})
421
+ _traced egregore.search.open OPEN_ARGS _runtime open ${OPEN_ARGS[@]+"${OPEN_ARGS[@]}"}
397
422
  ;;
398
423
  help|-h|--help)
399
424
  cat <<'USAGE'
400
- usage: bash bin/search.sh {find|investigate|query|handoffs|reindex|install|start|stop|status|readiness|open}
425
+ usage: bash bin/search.sh {find|investigate|query|handoffs|reindex|install|start|stop|status|readiness|open|mind}
401
426
  find "terms" [--kind keyword|semantic|hybrid|filename|literal|dates] [--recent-days N]
402
427
  open memory/path.md [memory/other.md ...] [--offset N] [--length N]
403
428
  handoffs --mine --status open --order newest --limit 1 --open
404
429
  handoffs [--addressed-to NAME|--sent|--sent-by NAME] [--status STATUS] [--order newest|oldest] [--limit N] [--json]
430
+ mind publish
405
431
  USAGE
406
432
  ;;
407
433
  *)
408
- echo "usage: bash bin/search.sh {find|investigate|query|handoffs|reindex|install|start|stop|status|readiness|open}" >&2
434
+ echo "usage: bash bin/search.sh {find|investigate|query|handoffs|reindex|install|start|stop|status|readiness|open|mind}" >&2
409
435
  exit 1
410
436
  ;;
411
437
  esac
@@ -133,9 +133,12 @@ if git -C "$DIR/memory" rev-parse --git-dir >/dev/null 2>&1; then
133
133
  fi
134
134
  if [ -n "$(git -C "$DIR/memory" log origin/main..HEAD --oneline 2>/dev/null)" ]; then
135
135
  for _try in 1 2 3; do
136
- if git -C "$DIR/memory" pull --rebase origin main --quiet 2>/dev/null \
137
- && git -C "$DIR/memory" push origin main --quiet 2>/dev/null; then
138
- break
136
+ if git -C "$DIR/memory" pull --rebase origin main --quiet 2>/dev/null; then
137
+ if bash "$SCRIPT_ROOT/bin/memory-push.sh" --repository "$DIR/memory" --branch main >/dev/null 2>&1; then
138
+ break
139
+ else
140
+ case "$?" in 75) ;; *) break ;; esac
141
+ fi
139
142
  fi
140
143
  sleep 1
141
144
  done
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env bash
2
+ # session-id.sh — the calling harness session's own Egregore session id.
3
+ #
4
+ # Every session start mints an Egregore session id and writes it to the
5
+ # checkout's .egregore-session-id, which each worktree links to. With several
6
+ # sessions open on one machine, the latest start owns that file, so a commit
7
+ # that reads it can carry another session's Egregore-Session trailer. This
8
+ # script keeps one small map file per harness session and resolves the
9
+ # caller's own id from the native session id its harness exports.
10
+ #
11
+ # session-id.sh [--root DIR]
12
+ # Print the caller's Egregore session id; print nothing and exit 1
13
+ # when there is none. A native id in the environment whose map was
14
+ # recorded for DIR's repository wins; otherwise DIR/.egregore-session-id.
15
+ # session-id.sh record <harness> <native-id> <egregore-id> [--root DIR]
16
+ # Map a starting session (bin/lib/identity.sh), replacing an old map.
17
+ # session-id.sh bind <harness> <native-id> [--root DIR]
18
+ # Map a session first seen after its start (a Codex thread, at its
19
+ # first prompt) to the id it resolves to now. A map this repository
20
+ # can use is kept; one recorded for a moved checkout is replaced.
21
+ #
22
+ # Native ids, in order: EGREGORE_NATIVE_SESSION_ID under
23
+ # EGREGORE_NATIVE_HARNESS (Claude, Pi and Prime tool commands), then
24
+ # CLAUDE_CODE_SESSION_ID, then CODEX_THREAD_ID. A Codex worker started from a
25
+ # Claude or Pi shell inherits that shell's ids and so resolves to the session
26
+ # that started it.
27
+ #
28
+ # Map files: ~/.egregore/sessions/<harness>-<native-id>.id, two lines: the
29
+ # Egregore id and the repository's physical git common dir, so a map never
30
+ # applies to another repository (a test fixture, another instance). Names are
31
+ # checked, never rewritten. Each record prunes maps unused for 30 days; every
32
+ # resolve and bind that uses a map marks it used.
33
+ set -u
34
+ export LC_ALL=C
35
+
36
+ ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
37
+ MAP_DIR=""
38
+ [ -z "${HOME:-}" ] || MAP_DIR="$HOME/.egregore/sessions"
39
+ SCOPE=""
40
+
41
+ usage() {
42
+ awk 'NR == 1 { next } /^#/ { sub(/^# ?/, ""); print; next } { exit }' "$0"
43
+ }
44
+
45
+ valid_harness() {
46
+ case "$1" in ''|*[!a-z0-9]*) return 1 ;; esac
47
+ [ "${#1}" -le 16 ]
48
+ }
49
+
50
+ valid_native() {
51
+ case "$1" in ''|.*|*[!A-Za-z0-9._-]*) return 1 ;; esac
52
+ [ "${#1}" -le 128 ]
53
+ }
54
+
55
+ valid_session() {
56
+ case "$1" in ''|*[[:cntrl:]]*) return 1 ;; esac
57
+ [ "${#1}" -le 200 ]
58
+ }
59
+
60
+ # The repository's git common dir, physical, so worktrees and every spelling
61
+ # of one checkout agree.
62
+ scope_of() {
63
+ local dir
64
+ dir="$(git -C "$1" rev-parse --git-common-dir 2>/dev/null)" || return 1
65
+ case "$dir" in /*) ;; *) dir="$1/$dir" ;; esac
66
+ (cd "$dir" 2>/dev/null && pwd -P)
67
+ }
68
+
69
+ # Print a map's Egregore id when the map belongs to this repository, and mark
70
+ # it used so the age prune spares a session that is still working.
71
+ lookup() {
72
+ local harness="$1" native="$2" file id="" scope=""
73
+ [ -n "$MAP_DIR" ] && valid_harness "$harness" && valid_native "$native" || return 1
74
+ file="$MAP_DIR/$harness-$native.id"
75
+ [ -f "$file" ] || return 1
76
+ { IFS= read -r id; IFS= read -r scope; } < "$file" 2>/dev/null
77
+ valid_session "$id" && [ -n "$scope" ] || return 1
78
+ [ -n "$SCOPE" ] || SCOPE="$(scope_of "$ROOT_DIR")" || return 1
79
+ [ "$scope" = "$SCOPE" ] || return 1
80
+ touch -c "$file" 2>/dev/null # -c: a map pruned meanwhile stays gone, never empty
81
+ printf '%s\n' "$id"
82
+ }
83
+
84
+ resolve() {
85
+ local id=""
86
+ if [ -n "${EGREGORE_NATIVE_SESSION_ID:-}" ] && [ -n "${EGREGORE_NATIVE_HARNESS:-}" ]; then
87
+ if lookup "$EGREGORE_NATIVE_HARNESS" "$EGREGORE_NATIVE_SESSION_ID"; then return 0; fi
88
+ fi
89
+ if [ -n "${CLAUDE_CODE_SESSION_ID:-}" ]; then
90
+ if lookup claude "$CLAUDE_CODE_SESSION_ID"; then return 0; fi
91
+ fi
92
+ if [ -n "${CODEX_THREAD_ID:-}" ]; then
93
+ if lookup codex "$CODEX_THREAD_ID"; then return 0; fi
94
+ fi
95
+ [ -f "$ROOT_DIR/.egregore-session-id" ] || return 1
96
+ IFS= read -r id < "$ROOT_DIR/.egregore-session-id" 2>/dev/null
97
+ valid_session "$id" || return 1
98
+ printf '%s\n' "$id"
99
+ }
100
+
101
+ record() {
102
+ local harness="$1" native="$2" id="$3" scope tmp
103
+ [ -n "$MAP_DIR" ] && valid_harness "$harness" && valid_native "$native" && valid_session "$id" || return 1
104
+ scope="$(scope_of "$ROOT_DIR")" && [ -n "$scope" ] || return 1
105
+ mkdir -p "$MAP_DIR" 2>/dev/null || return 1
106
+ tmp="$MAP_DIR/.$harness-$native.$$"
107
+ printf '%s\n%s\n' "$id" "$scope" > "$tmp" 2>/dev/null \
108
+ && mv -f "$tmp" "$MAP_DIR/$harness-$native.id" 2>/dev/null || { rm -f "$tmp"; return 1; }
109
+ find "$MAP_DIR" -maxdepth 1 -type f \( -name '*.id' -o -name '.*' \) -mtime +30 \
110
+ -exec rm -f {} + 2>/dev/null
111
+ return 0
112
+ }
113
+
114
+ bind() {
115
+ local harness="$1" native="$2" id
116
+ [ -n "$MAP_DIR" ] && valid_harness "$harness" && valid_native "$native" || return 1
117
+ # A map this repository can use is kept; one recorded for a checkout that
118
+ # has since moved is replaced rather than left unusable.
119
+ lookup "$harness" "$native" >/dev/null && return 0
120
+ id="$(resolve)" || return 1
121
+ record "$harness" "$native" "$id"
122
+ }
123
+
124
+ ARGS=()
125
+ while [ $# -gt 0 ]; do
126
+ case "$1" in
127
+ --root)
128
+ [ -n "${2:-}" ] || { echo "session-id.sh: --root needs a directory" >&2; exit 2; }
129
+ ROOT_DIR="$2"; shift 2 ;;
130
+ -h|--help) usage; exit 0 ;;
131
+ *) ARGS+=("$1"); shift ;;
132
+ esac
133
+ done
134
+ set -- ${ARGS[@]+"${ARGS[@]}"}
135
+
136
+ case "${1:-resolve}" in
137
+ resolve)
138
+ [ $# -le 1 ] || { usage >&2; exit 2; }
139
+ resolve ;;
140
+ record)
141
+ [ $# -eq 4 ] || { usage >&2; exit 2; }
142
+ record "$2" "$3" "$4" ;;
143
+ bind)
144
+ [ $# -eq 3 ] || { usage >&2; exit 2; }
145
+ bind "$2" "$3" ;;
146
+ *) usage >&2; exit 2 ;;
147
+ esac
@@ -21,6 +21,25 @@ INPUT=$(cat /dev/stdin 2>/dev/null || echo "{}")
21
21
  SESSION_ID=$(echo "$INPUT" | jq -r '.session_id // empty' 2>/dev/null || true)
22
22
  TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null || true)
23
23
 
24
+ # Route known native transcript locations before reading their contents.
25
+ RUNTIME=$(printf '%s' "$INPUT" | jq -r '.runtime // empty' 2>/dev/null || true)
26
+ RECORD_TRANSCRIPT=false
27
+ if [ -n "${HOME:-}" ]; then
28
+ if [[ "$TRANSCRIPT_PATH" == "$HOME/.claude/projects/"* ]] && \
29
+ printf '%s' "$INPUT" | jq -e 'has("hook_event_name")' >/dev/null 2>&1; then
30
+ RECORD_TRANSCRIPT=true
31
+ elif { [ "$RUNTIME" = pi ] && [[ "$TRANSCRIPT_PATH" == "$HOME/.pi/agent/sessions/"* ]]; } || \
32
+ { [ "$RUNTIME" = prime ] && [[ "$TRANSCRIPT_PATH" == "$HOME/.prime/agent/sessions/"* ]]; }; then
33
+ RECORD_TRANSCRIPT=true
34
+ fi
35
+ fi
36
+ if [ "$RECORD_TRANSCRIPT" = true ]; then
37
+ source "$SCRIPT_DIR/bin/lib/config.sh"
38
+ if _session_records_enabled; then
39
+ exec bash "$SCRIPT_DIR/bin/session-record.sh" --mode end <<< "$INPUT"
40
+ fi
41
+ fi
42
+
24
43
  if [ -z "$SESSION_ID" ]; then
25
44
  exit 0
26
45
  fi