create-egregore 0.20.2 → 0.21.0-runtime-mvp.1

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 (706) hide show
  1. package/assets/egregore-launcher.js +1011 -16
  2. package/bin/cli.js +11 -0
  3. package/lib/claude-runtime.js +192 -0
  4. package/lib/local.js +38 -31
  5. package/lib/pi-runtime.js +1 -0
  6. package/lib/prime-runtime.js +1 -0
  7. package/lib/runtime-identity.js +146 -0
  8. package/lib/setup.js +116 -17
  9. package/package.json +10 -6
  10. package/runtime/claude/.claude/context/commit-format.md +110 -0
  11. package/runtime/claude/.claude/context/git-language.md +46 -0
  12. package/runtime/claude/.claude/context/notification-consent.md +66 -0
  13. package/runtime/claude/.claude/context/pr-format.md +67 -0
  14. package/runtime/claude/.claude/context/telemetry.md +133 -0
  15. package/runtime/claude/.claude/hooks/boundary-check.sh +333 -0
  16. package/runtime/claude/.claude/hooks/branch-guard.sh +231 -0
  17. package/runtime/claude/.claude/hooks/card-context.sh +38 -0
  18. package/runtime/claude/.claude/hooks/emissary-detect.sh +53 -0
  19. package/runtime/claude/.claude/hooks/memory-refresh.sh +67 -0
  20. package/runtime/claude/.claude/hooks/onboarding-guard.sh +86 -0
  21. package/runtime/claude/.claude/hooks/retrieval-context.sh +43 -0
  22. package/runtime/claude/.claude/rules/voice-bedrock.md +73 -0
  23. package/runtime/claude/.claude/settings.json +131 -0
  24. package/runtime/claude/.claude/skills/activity/SKILL.md +68 -0
  25. package/runtime/claude/.claude/skills/announce/SKILL.md +54 -0
  26. package/runtime/claude/.claude/skills/archive/SKILL.md +71 -0
  27. package/runtime/claude/.claude/skills/branch/SKILL.md +147 -0
  28. package/runtime/claude/.claude/skills/checkup/SKILL.md +159 -0
  29. package/runtime/claude/.claude/skills/commit/SKILL.md +103 -0
  30. package/runtime/claude/.claude/skills/contribute/SKILL.md +343 -0
  31. package/runtime/claude/.claude/skills/create-skill/SKILL.md +135 -0
  32. package/runtime/claude/.claude/skills/dark-mode/SKILL.md +410 -0
  33. package/runtime/claude/.claude/skills/dashboard/SKILL.md +43 -0
  34. package/runtime/claude/.claude/skills/deep-reflect/REPORT.md +140 -0
  35. package/runtime/claude/.claude/skills/deep-reflect/RESEARCH.md +132 -0
  36. package/runtime/claude/.claude/skills/deep-reflect/ROLES.md +104 -0
  37. package/runtime/claude/.claude/skills/deep-reflect/SKILL.md +170 -0
  38. package/runtime/claude/.claude/skills/delete-user/SKILL.md +150 -0
  39. package/runtime/claude/.claude/skills/emissary/SKILL.md +220 -0
  40. package/runtime/claude/.claude/skills/handoff/SKILL.md +124 -0
  41. package/runtime/claude/.claude/skills/harvest/AUDIT.md +546 -0
  42. package/runtime/claude/.claude/skills/harvest/FORMAT.md +436 -0
  43. package/runtime/claude/.claude/skills/harvest/PROCESS.md +395 -0
  44. package/runtime/claude/.claude/skills/harvest/QUESTION_PALETTE.md +76 -0
  45. package/runtime/claude/.claude/skills/harvest/SKILL.md +100 -0
  46. package/runtime/claude/.claude/skills/ingest/SKILL.md +112 -0
  47. package/runtime/claude/.claude/skills/ingest-corpus/SKILL.md +187 -0
  48. package/runtime/claude/.claude/skills/ingest-notion/SKILL.md +214 -0
  49. package/runtime/claude/.claude/skills/ingest-user-interview/SKILL.md +65 -0
  50. package/runtime/claude/.claude/skills/ingest-user-interview/references/analysis-contract.md +125 -0
  51. package/runtime/claude/.claude/skills/invite/SKILL.md +111 -0
  52. package/runtime/claude/.claude/skills/issue/SKILL.md +104 -0
  53. package/runtime/claude/.claude/skills/me/SKILL.md +81 -0
  54. package/runtime/claude/.claude/skills/meeting/SKILL.md +76 -0
  55. package/runtime/claude/.claude/skills/meeting/references/analysis-contract.md +102 -0
  56. package/runtime/claude/.claude/skills/note/SKILL.md +71 -0
  57. package/runtime/claude/.claude/skills/notion-connect/SKILL.md +124 -0
  58. package/runtime/claude/.claude/skills/onboarding/SKILL.md +159 -0
  59. package/runtime/claude/.claude/skills/pr/SKILL.md +85 -0
  60. package/runtime/claude/.claude/skills/pull/SKILL.md +79 -0
  61. package/runtime/claude/.claude/skills/push/SKILL.md +47 -0
  62. package/runtime/claude/.claude/skills/quest/SKILL.md +121 -0
  63. package/runtime/claude/.claude/skills/reflect/SKILL.md +69 -0
  64. package/runtime/claude/.claude/skills/review-pr/SKILL.md +276 -0
  65. package/runtime/claude/.claude/skills/save/SKILL.md +92 -0
  66. package/runtime/claude/.claude/skills/slack-connect/SKILL.md +148 -0
  67. package/runtime/claude/.claude/skills/summon/SKILL.md +240 -0
  68. package/runtime/claude/.claude/skills/sync-repos/SKILL.md +82 -0
  69. package/runtime/claude/.claude/skills/teams-connect/SKILL.md +216 -0
  70. package/runtime/claude/.claude/skills/telegram-connect/SKILL.md +110 -0
  71. package/runtime/claude/.claude/skills/telemetry/SKILL.md +117 -0
  72. package/runtime/claude/.claude/skills/test/SKILL.md +87 -0
  73. package/runtime/claude/.claude/skills/the-spiral/SKILL.md +492 -0
  74. package/runtime/claude/.claude/skills/tui-design/SKILL.md +188 -0
  75. package/runtime/claude/.claude/skills/tutorial/SKILL.md +100 -0
  76. package/runtime/claude/.claude/skills/update/SKILL.md +265 -0
  77. package/runtime/claude/.claude/skills/view/SKILL.md +393 -0
  78. package/runtime/claude/.claude/skills/view/compose-scaffold.html +221 -0
  79. package/runtime/claude/.claude/skills/visual-explain/SKILL.md +132 -0
  80. package/runtime/claude/.claude/skills/wrap/SKILL.md +98 -0
  81. package/runtime/claude/CLAUDE.md +447 -0
  82. package/runtime/claude/bin/activity-action.sh +92 -0
  83. package/runtime/claude/bin/activity-data.sh +17 -0
  84. package/runtime/claude/bin/agent.sh +783 -0
  85. package/runtime/claude/bin/artifact-register.sh +164 -0
  86. package/runtime/claude/bin/artifact-writeback.sh +53 -0
  87. package/runtime/claude/bin/artifacts.sh +288 -0
  88. package/runtime/claude/bin/attendant.sh +707 -0
  89. package/runtime/claude/bin/autosave.sh +112 -0
  90. package/runtime/claude/bin/boundary.sh +253 -0
  91. package/runtime/claude/bin/build-sealed-dataroom.mjs +722 -0
  92. package/runtime/claude/bin/capture-reconcile.sh +69 -0
  93. package/runtime/claude/bin/capture-run.sh +357 -0
  94. package/runtime/claude/bin/codex-install-skills.sh +78 -0
  95. package/runtime/claude/bin/codex-render-spec.mjs +462 -0
  96. package/runtime/claude/bin/codex-session-start.sh +275 -0
  97. package/runtime/claude/bin/codex-skill-render.mjs +349 -0
  98. package/runtime/claude/bin/codex-sync-skills.sh +237 -0
  99. package/runtime/claude/bin/connect-refresh.sh +33 -0
  100. package/runtime/claude/bin/contribute-guard.sh +79 -0
  101. package/runtime/claude/bin/corpus_map.py +806 -0
  102. package/runtime/claude/bin/corpus_survey.py +304 -0
  103. package/runtime/claude/bin/dashboard-data.sh +18 -0
  104. package/runtime/claude/bin/github-auth.sh +121 -0
  105. package/runtime/claude/bin/graph-batch.sh +86 -0
  106. package/runtime/claude/bin/graph-op.sh +1106 -0
  107. package/runtime/claude/bin/graph-projection.sh +54 -0
  108. package/runtime/claude/bin/graph-wal.sh +242 -0
  109. package/runtime/claude/bin/graph.sh +267 -0
  110. package/runtime/claude/bin/handoff-lifecycle-job.sh +146 -0
  111. package/runtime/claude/bin/handoff-lifecycle.sh +280 -0
  112. package/runtime/claude/bin/handoff-pr-backfill.sh +86 -0
  113. package/runtime/claude/bin/handoff-preview.sh +169 -0
  114. package/runtime/claude/bin/handoff-run.sh +692 -0
  115. package/runtime/claude/bin/handoff-save-egregore.sh +224 -0
  116. package/runtime/claude/bin/index-handoff.sh +322 -0
  117. package/runtime/claude/bin/ingest-graph.sh +86 -0
  118. package/runtime/claude/bin/ingest-item.sh +10 -0
  119. package/runtime/claude/bin/ingest-surface.html +495 -0
  120. package/runtime/claude/bin/ingest.py +1011 -0
  121. package/runtime/claude/bin/ingest.sh +308 -0
  122. package/runtime/claude/bin/ingest_graph.py +856 -0
  123. package/runtime/claude/bin/ingest_surface.py +544 -0
  124. package/runtime/claude/bin/invite.sh +6 -0
  125. package/runtime/claude/bin/issue.sh +10 -0
  126. package/runtime/claude/bin/knowledge.sh +10 -0
  127. package/runtime/claude/bin/lib/artifact-id.sh +46 -0
  128. package/runtime/claude/bin/lib/config.sh +136 -0
  129. package/runtime/claude/bin/lib/context.sh +642 -0
  130. package/runtime/claude/bin/lib/dashboard-artifact.sh +242 -0
  131. package/runtime/claude/bin/lib/ensure-develop.sh +183 -0
  132. package/runtime/claude/bin/lib/git-message.sh +37 -0
  133. package/runtime/claude/bin/lib/git-sync.sh +494 -0
  134. package/runtime/claude/bin/lib/greeting.sh +548 -0
  135. package/runtime/claude/bin/lib/handoff-meta.sh +97 -0
  136. package/runtime/claude/bin/lib/hash.sh +13 -0
  137. package/runtime/claude/bin/lib/identity.sh +213 -0
  138. package/runtime/claude/bin/lib/metrics.sh +374 -0
  139. package/runtime/claude/bin/lib/noncode.sh +31 -0
  140. package/runtime/claude/bin/lib/permissions.sh +106 -0
  141. package/runtime/claude/bin/lib/time.sh +56 -0
  142. package/runtime/claude/bin/lib/worktree-links.sh +85 -0
  143. package/runtime/claude/bin/node-run.sh +42 -0
  144. package/runtime/claude/bin/notification.sh +6 -0
  145. package/runtime/claude/bin/notify.sh +636 -0
  146. package/runtime/claude/bin/observe-context.sh +14 -0
  147. package/runtime/claude/bin/onboarding.sh +6 -0
  148. package/runtime/claude/bin/person.py +634 -0
  149. package/runtime/claude/bin/person.sh +481 -0
  150. package/runtime/claude/bin/pi-render-spec.mjs +140 -0
  151. package/runtime/claude/bin/post-update.sh +37 -0
  152. package/runtime/claude/bin/prime-render-spec.mjs +147 -0
  153. package/runtime/claude/bin/publish-artifact.sh +324 -0
  154. package/runtime/claude/bin/publish-references.sh +144 -0
  155. package/runtime/claude/bin/quest.sh +9 -0
  156. package/runtime/claude/bin/question.sh +8 -0
  157. package/runtime/claude/bin/repo-state.sh +96 -0
  158. package/runtime/claude/bin/research-ingest.sh +7 -0
  159. package/runtime/claude/bin/restore-owned-skills.sh +67 -0
  160. package/runtime/claude/bin/retrieval_eval.py +385 -0
  161. package/runtime/claude/bin/runtime-identity.sh +70 -0
  162. package/runtime/claude/bin/runtime-upgrade.sh +43 -0
  163. package/runtime/claude/bin/scroll.sh +9 -0
  164. package/runtime/claude/bin/search.sh +318 -0
  165. package/runtime/claude/bin/session-autosave.sh +220 -0
  166. package/runtime/claude/bin/session-log.sh +199 -0
  167. package/runtime/claude/bin/session-start.sh +696 -0
  168. package/runtime/claude/bin/settings.sh +532 -0
  169. package/runtime/claude/bin/startup-check.sh +136 -0
  170. package/runtime/claude/bin/statusline.sh +41 -0
  171. package/runtime/claude/bin/telemetry.sh +666 -0
  172. package/runtime/claude/bin/test-changes.sh +344 -0
  173. package/runtime/claude/bin/thread.sh +9 -0
  174. package/runtime/claude/bin/todo.sh +9 -0
  175. package/runtime/claude/bin/view-render.sh +126 -0
  176. package/runtime/claude/bin/worktree-create.sh +145 -0
  177. package/runtime/claude/bin/worktree-remove.sh +50 -0
  178. package/runtime/claude/bin/worktree.sh +198 -0
  179. package/runtime/claude/egregore_runtime/__init__.py +228 -0
  180. package/runtime/claude/egregore_runtime/adapters/__init__.py +5 -0
  181. package/runtime/claude/egregore_runtime/adapters/invitation.py +237 -0
  182. package/runtime/claude/egregore_runtime/adapters/notification.py +59 -0
  183. package/runtime/claude/egregore_runtime/adapters/qmd.py +1701 -0
  184. package/runtime/claude/egregore_runtime/adapters/qmd_cli.py +210 -0
  185. package/runtime/claude/egregore_runtime/adapters/qmd_embed_worker.py +59 -0
  186. package/runtime/claude/egregore_runtime/admin_gate.py +102 -0
  187. package/runtime/claude/egregore_runtime/artifacts.py +523 -0
  188. package/runtime/claude/egregore_runtime/contracts.py +499 -0
  189. package/runtime/claude/egregore_runtime/entitlements.py +85 -0
  190. package/runtime/claude/egregore_runtime/errors.py +10 -0
  191. package/runtime/claude/egregore_runtime/graph.py +356 -0
  192. package/runtime/claude/egregore_runtime/handoff_lookup.py +196 -0
  193. package/runtime/claude/egregore_runtime/harness_cli.py +1221 -0
  194. package/runtime/claude/egregore_runtime/identity.py +734 -0
  195. package/runtime/claude/egregore_runtime/identity_cli.py +91 -0
  196. package/runtime/claude/egregore_runtime/ingest.py +575 -0
  197. package/runtime/claude/egregore_runtime/ingest_cli.py +254 -0
  198. package/runtime/claude/egregore_runtime/ingest_index_cli.py +147 -0
  199. package/runtime/claude/egregore_runtime/invitation_cli.py +51 -0
  200. package/runtime/claude/egregore_runtime/invitations.py +116 -0
  201. package/runtime/claude/egregore_runtime/issue_cli.py +305 -0
  202. package/runtime/claude/egregore_runtime/issues.py +359 -0
  203. package/runtime/claude/egregore_runtime/knowledge.py +376 -0
  204. package/runtime/claude/egregore_runtime/knowledge_cli.py +173 -0
  205. package/runtime/claude/egregore_runtime/lifecycle.py +888 -0
  206. package/runtime/claude/egregore_runtime/lifecycle_cli.py +269 -0
  207. package/runtime/claude/egregore_runtime/notification_cli.py +125 -0
  208. package/runtime/claude/egregore_runtime/notifications.py +230 -0
  209. package/runtime/claude/egregore_runtime/observe.py +342 -0
  210. package/runtime/claude/egregore_runtime/onboarding.py +290 -0
  211. package/runtime/claude/egregore_runtime/onboarding_cli.py +110 -0
  212. package/runtime/claude/egregore_runtime/policy.py +144 -0
  213. package/runtime/claude/egregore_runtime/profile.py +193 -0
  214. package/runtime/claude/egregore_runtime/quest_cli.py +216 -0
  215. package/runtime/claude/egregore_runtime/question_cli.py +180 -0
  216. package/runtime/claude/egregore_runtime/questions.py +304 -0
  217. package/runtime/claude/egregore_runtime/quests.py +419 -0
  218. package/runtime/claude/egregore_runtime/readiness.py +379 -0
  219. package/runtime/claude/egregore_runtime/research_ingest.py +256 -0
  220. package/runtime/claude/egregore_runtime/research_ingest_cli.py +44 -0
  221. package/runtime/claude/egregore_runtime/runtime.py +464 -0
  222. package/runtime/claude/egregore_runtime/scroll_cli.py +185 -0
  223. package/runtime/claude/egregore_runtime/scrolls.py +726 -0
  224. package/runtime/claude/egregore_runtime/status.py +412 -0
  225. package/runtime/claude/egregore_runtime/status_cli.py +174 -0
  226. package/runtime/claude/egregore_runtime/sync.py +218 -0
  227. package/runtime/claude/egregore_runtime/teamsync.py +139 -0
  228. package/runtime/claude/egregore_runtime/telemetry.py +640 -0
  229. package/runtime/claude/egregore_runtime/thread_cli.py +173 -0
  230. package/runtime/claude/egregore_runtime/threads.py +517 -0
  231. package/runtime/claude/egregore_runtime/todo_cli.py +142 -0
  232. package/runtime/claude/egregore_runtime/todos.py +244 -0
  233. package/runtime/claude/egregore_runtime/upgrade.py +770 -0
  234. package/runtime/claude/egregore_runtime/upgrade_worker.py +53 -0
  235. package/runtime/claude/egregore_runtime/writeback.py +391 -0
  236. package/runtime/claude/egregore_runtime/writeback_cli.py +114 -0
  237. package/runtime/claude/manifest.json +284 -0
  238. package/runtime/codex/.codex/hooks/search-hint.js +21 -52
  239. package/runtime/codex/.codex/hooks.json +3 -3
  240. package/runtime/codex/.codex/skills/activity/SKILL.md +23 -66
  241. package/runtime/codex/.codex/skills/announce/SKILL.md +27 -50
  242. package/runtime/codex/.codex/skills/archive/SKILL.md +21 -36
  243. package/runtime/codex/.codex/skills/checkup/SKILL.md +77 -36
  244. package/runtime/codex/.codex/skills/dark-mode/SKILL.md +1 -1
  245. package/runtime/codex/.codex/skills/dashboard/SKILL.md +17 -47
  246. package/runtime/codex/.codex/skills/handoff/SKILL.md +84 -133
  247. package/runtime/codex/.codex/skills/harvest/SKILL.md +32 -117
  248. package/runtime/codex/.codex/skills/ingest/SKILL.md +47 -25
  249. package/runtime/codex/.codex/skills/ingest-user-interview/SKILL.md +18 -36
  250. package/runtime/codex/.codex/skills/ingest-user-interview/references/analysis-contract.md +42 -0
  251. package/runtime/codex/.codex/skills/invite/SKILL.md +21 -35
  252. package/runtime/codex/.codex/skills/issue/SKILL.md +60 -41
  253. package/runtime/codex/.codex/skills/me/SKILL.md +1 -1
  254. package/runtime/codex/.codex/skills/meeting/SKILL.md +16 -36
  255. package/runtime/codex/.codex/skills/meeting/references/analysis-contract.md +48 -0
  256. package/runtime/codex/.codex/skills/note/SKILL.md +30 -25
  257. package/runtime/codex/.codex/skills/onboarding/SKILL.md +36 -41
  258. package/runtime/codex/.codex/skills/pull/SKILL.md +1 -1
  259. package/runtime/codex/.codex/skills/quest/SKILL.md +27 -66
  260. package/runtime/codex/.codex/skills/reflect/SKILL.md +22 -36
  261. package/runtime/codex/.codex/skills/save/SKILL.md +2 -2
  262. package/runtime/codex/.codex/skills/telemetry/SKILL.md +1 -1
  263. package/runtime/codex/.codex/skills/test/SKILL.md +1 -1
  264. package/runtime/codex/.codex/skills/tutorial/SKILL.md +40 -41
  265. package/runtime/codex/.codex/skills/view/SKILL.md +115 -111
  266. package/runtime/codex/.codex/skills/wrap/SKILL.md +45 -41
  267. package/runtime/codex/.codex/spec-manifest.json +9 -9
  268. package/runtime/codex/AGENTS.md +62 -58
  269. package/runtime/codex/bin/activity-action.sh +92 -0
  270. package/runtime/codex/bin/activity-data.sh +12 -233
  271. package/runtime/codex/bin/agent.sh +84 -100
  272. package/runtime/codex/bin/artifact-register.sh +164 -0
  273. package/runtime/codex/bin/artifact-writeback.sh +53 -0
  274. package/runtime/codex/bin/artifacts.sh +288 -0
  275. package/runtime/codex/bin/build-sealed-dataroom.mjs +722 -0
  276. package/runtime/codex/bin/capture-run.sh +18 -2
  277. package/runtime/codex/bin/codex-render-spec.mjs +41 -16
  278. package/runtime/codex/bin/codex-session-start.sh +14 -4
  279. package/runtime/codex/bin/codex-skill-render.mjs +9 -7
  280. package/runtime/codex/bin/corpus_map.py +806 -0
  281. package/runtime/codex/bin/corpus_survey.py +304 -0
  282. package/runtime/codex/bin/dashboard-data.sh +11 -171
  283. package/runtime/codex/bin/github-auth.sh +121 -0
  284. package/runtime/codex/bin/graph-batch.sh +7 -0
  285. package/runtime/codex/bin/graph-op.sh +4 -0
  286. package/runtime/codex/bin/graph-projection.sh +54 -0
  287. package/runtime/codex/bin/graph-wal.sh +13 -0
  288. package/runtime/codex/bin/graph.sh +44 -0
  289. package/runtime/codex/bin/handoff-lifecycle-job.sh +146 -0
  290. package/runtime/codex/bin/handoff-lifecycle.sh +280 -0
  291. package/runtime/codex/bin/handoff-preview.sh +169 -0
  292. package/runtime/codex/bin/handoff-run.sh +42 -26
  293. package/runtime/codex/bin/ingest-graph.sh +6 -0
  294. package/runtime/codex/bin/ingest-item.sh +10 -0
  295. package/runtime/codex/bin/ingest.sh +59 -30
  296. package/runtime/codex/bin/invite.sh +6 -0
  297. package/runtime/codex/bin/issue.sh +10 -0
  298. package/runtime/codex/bin/knowledge.sh +10 -0
  299. package/runtime/codex/bin/lib/config.sh +20 -0
  300. package/runtime/codex/bin/lib/context.sh +46 -25
  301. package/runtime/codex/bin/lib/git-sync.sh +70 -6
  302. package/runtime/codex/bin/lib/greeting.sh +34 -5
  303. package/runtime/codex/bin/lib/handoff-meta.sh +97 -0
  304. package/runtime/codex/bin/lib/worktree-links.sh +6 -0
  305. package/runtime/codex/bin/node-run.sh +42 -0
  306. package/runtime/codex/bin/notification.sh +6 -0
  307. package/runtime/codex/bin/observe-context.sh +14 -0
  308. package/runtime/codex/bin/onboarding.sh +6 -0
  309. package/runtime/codex/bin/person.py +4 -0
  310. package/runtime/codex/bin/person.sh +43 -10
  311. package/runtime/codex/bin/pi-render-spec.mjs +140 -0
  312. package/runtime/codex/bin/post-update.sh +37 -0
  313. package/runtime/codex/bin/prime-render-spec.mjs +147 -0
  314. package/runtime/codex/bin/publish-artifact.sh +55 -2
  315. package/runtime/codex/bin/quest.sh +9 -0
  316. package/runtime/codex/bin/question.sh +8 -0
  317. package/runtime/codex/bin/research-ingest.sh +7 -0
  318. package/runtime/codex/bin/restore-owned-skills.sh +67 -0
  319. package/runtime/codex/bin/retrieval_eval.py +385 -0
  320. package/runtime/codex/bin/runtime-identity.sh +70 -0
  321. package/runtime/codex/bin/runtime-upgrade.sh +43 -0
  322. package/runtime/codex/bin/scroll.sh +9 -0
  323. package/runtime/codex/bin/search.sh +231 -195
  324. package/runtime/codex/bin/settings.sh +174 -5
  325. package/runtime/codex/bin/startup-check.sh +136 -0
  326. package/runtime/codex/bin/telemetry.sh +522 -247
  327. package/runtime/codex/bin/test-changes.sh +344 -0
  328. package/runtime/codex/bin/thread.sh +9 -0
  329. package/runtime/codex/bin/todo.sh +9 -0
  330. package/runtime/codex/bin/view-render.sh +126 -0
  331. package/runtime/codex/bin/worktree-create.sh +19 -5
  332. package/runtime/codex/egregore_runtime/__init__.py +228 -0
  333. package/runtime/codex/egregore_runtime/adapters/__init__.py +5 -0
  334. package/runtime/codex/egregore_runtime/adapters/invitation.py +237 -0
  335. package/runtime/codex/egregore_runtime/adapters/notification.py +59 -0
  336. package/runtime/codex/egregore_runtime/adapters/qmd.py +1701 -0
  337. package/runtime/codex/egregore_runtime/adapters/qmd_cli.py +210 -0
  338. package/runtime/codex/egregore_runtime/adapters/qmd_embed_worker.py +59 -0
  339. package/runtime/codex/egregore_runtime/admin_gate.py +102 -0
  340. package/runtime/codex/egregore_runtime/artifacts.py +523 -0
  341. package/runtime/codex/egregore_runtime/contracts.py +499 -0
  342. package/runtime/codex/egregore_runtime/entitlements.py +85 -0
  343. package/runtime/codex/egregore_runtime/errors.py +10 -0
  344. package/runtime/codex/egregore_runtime/graph.py +356 -0
  345. package/runtime/codex/egregore_runtime/handoff_lookup.py +196 -0
  346. package/runtime/codex/egregore_runtime/harness_cli.py +1221 -0
  347. package/runtime/codex/egregore_runtime/identity.py +734 -0
  348. package/runtime/codex/egregore_runtime/identity_cli.py +91 -0
  349. package/runtime/codex/egregore_runtime/ingest.py +575 -0
  350. package/runtime/codex/egregore_runtime/ingest_cli.py +254 -0
  351. package/runtime/codex/egregore_runtime/ingest_index_cli.py +147 -0
  352. package/runtime/codex/egregore_runtime/invitation_cli.py +51 -0
  353. package/runtime/codex/egregore_runtime/invitations.py +116 -0
  354. package/runtime/codex/egregore_runtime/issue_cli.py +305 -0
  355. package/runtime/codex/egregore_runtime/issues.py +359 -0
  356. package/runtime/codex/egregore_runtime/knowledge.py +376 -0
  357. package/runtime/codex/egregore_runtime/knowledge_cli.py +173 -0
  358. package/runtime/codex/egregore_runtime/lifecycle.py +888 -0
  359. package/runtime/codex/egregore_runtime/lifecycle_cli.py +269 -0
  360. package/runtime/codex/egregore_runtime/notification_cli.py +125 -0
  361. package/runtime/codex/egregore_runtime/notifications.py +230 -0
  362. package/runtime/codex/egregore_runtime/observe.py +342 -0
  363. package/runtime/codex/egregore_runtime/onboarding.py +290 -0
  364. package/runtime/codex/egregore_runtime/onboarding_cli.py +110 -0
  365. package/runtime/codex/egregore_runtime/policy.py +144 -0
  366. package/runtime/codex/egregore_runtime/profile.py +193 -0
  367. package/runtime/codex/egregore_runtime/quest_cli.py +216 -0
  368. package/runtime/codex/egregore_runtime/question_cli.py +180 -0
  369. package/runtime/codex/egregore_runtime/questions.py +304 -0
  370. package/runtime/codex/egregore_runtime/quests.py +419 -0
  371. package/runtime/codex/egregore_runtime/readiness.py +379 -0
  372. package/runtime/codex/egregore_runtime/research_ingest.py +256 -0
  373. package/runtime/codex/egregore_runtime/research_ingest_cli.py +44 -0
  374. package/runtime/codex/egregore_runtime/runtime.py +464 -0
  375. package/runtime/codex/egregore_runtime/scroll_cli.py +185 -0
  376. package/runtime/codex/egregore_runtime/scrolls.py +726 -0
  377. package/runtime/codex/egregore_runtime/status.py +412 -0
  378. package/runtime/codex/egregore_runtime/status_cli.py +174 -0
  379. package/runtime/codex/egregore_runtime/sync.py +218 -0
  380. package/runtime/codex/egregore_runtime/teamsync.py +139 -0
  381. package/runtime/codex/egregore_runtime/telemetry.py +640 -0
  382. package/runtime/codex/egregore_runtime/thread_cli.py +173 -0
  383. package/runtime/codex/egregore_runtime/threads.py +517 -0
  384. package/runtime/codex/egregore_runtime/todo_cli.py +142 -0
  385. package/runtime/codex/egregore_runtime/todos.py +244 -0
  386. package/runtime/codex/egregore_runtime/upgrade.py +770 -0
  387. package/runtime/codex/egregore_runtime/upgrade_worker.py +53 -0
  388. package/runtime/codex/egregore_runtime/writeback.py +391 -0
  389. package/runtime/codex/egregore_runtime/writeback_cli.py +114 -0
  390. package/runtime/codex/manifest.json +98 -1
  391. package/runtime/pi/.codex/hooks/search-hint.js +21 -52
  392. package/runtime/pi/.codex/hooks.json +3 -3
  393. package/runtime/pi/.codex/skills/activity/SKILL.md +23 -66
  394. package/runtime/pi/.codex/skills/announce/SKILL.md +27 -50
  395. package/runtime/pi/.codex/skills/archive/SKILL.md +21 -36
  396. package/runtime/pi/.codex/skills/checkup/SKILL.md +77 -36
  397. package/runtime/pi/.codex/skills/dark-mode/SKILL.md +1 -1
  398. package/runtime/pi/.codex/skills/dashboard/SKILL.md +17 -47
  399. package/runtime/pi/.codex/skills/handoff/SKILL.md +84 -133
  400. package/runtime/pi/.codex/skills/harvest/SKILL.md +32 -117
  401. package/runtime/pi/.codex/skills/ingest/SKILL.md +47 -25
  402. package/runtime/pi/.codex/skills/ingest-user-interview/SKILL.md +18 -36
  403. package/runtime/pi/.codex/skills/ingest-user-interview/references/analysis-contract.md +42 -0
  404. package/runtime/pi/.codex/skills/invite/SKILL.md +21 -35
  405. package/runtime/pi/.codex/skills/issue/SKILL.md +60 -41
  406. package/runtime/pi/.codex/skills/me/SKILL.md +1 -1
  407. package/runtime/pi/.codex/skills/meeting/SKILL.md +16 -36
  408. package/runtime/pi/.codex/skills/meeting/references/analysis-contract.md +48 -0
  409. package/runtime/pi/.codex/skills/note/SKILL.md +30 -25
  410. package/runtime/pi/.codex/skills/onboarding/SKILL.md +36 -41
  411. package/runtime/pi/.codex/skills/pull/SKILL.md +1 -1
  412. package/runtime/pi/.codex/skills/quest/SKILL.md +27 -66
  413. package/runtime/pi/.codex/skills/reflect/SKILL.md +22 -36
  414. package/runtime/pi/.codex/skills/save/SKILL.md +2 -2
  415. package/runtime/pi/.codex/skills/telemetry/SKILL.md +1 -1
  416. package/runtime/pi/.codex/skills/test/SKILL.md +1 -1
  417. package/runtime/pi/.codex/skills/tutorial/SKILL.md +40 -41
  418. package/runtime/pi/.codex/skills/view/SKILL.md +115 -111
  419. package/runtime/pi/.codex/skills/wrap/SKILL.md +45 -41
  420. package/runtime/pi/.codex/spec-manifest.json +9 -9
  421. package/runtime/pi/.pi/APPEND_SYSTEM.md +57 -48
  422. package/runtime/pi/.pi/extensions/egregore.ts +7 -0
  423. package/runtime/pi/.pi/spec-manifest.json +2 -2
  424. package/runtime/pi/AGENTS.md +62 -58
  425. package/runtime/pi/bin/activity-action.sh +92 -0
  426. package/runtime/pi/bin/activity-data.sh +12 -233
  427. package/runtime/pi/bin/agent.sh +84 -100
  428. package/runtime/pi/bin/artifact-register.sh +164 -0
  429. package/runtime/pi/bin/artifact-writeback.sh +53 -0
  430. package/runtime/pi/bin/artifacts.sh +288 -0
  431. package/runtime/pi/bin/build-sealed-dataroom.mjs +722 -0
  432. package/runtime/pi/bin/capture-run.sh +18 -2
  433. package/runtime/pi/bin/codex-render-spec.mjs +41 -16
  434. package/runtime/pi/bin/codex-session-start.sh +14 -4
  435. package/runtime/pi/bin/codex-skill-render.mjs +9 -7
  436. package/runtime/pi/bin/corpus_map.py +806 -0
  437. package/runtime/pi/bin/corpus_survey.py +304 -0
  438. package/runtime/pi/bin/dashboard-data.sh +11 -171
  439. package/runtime/pi/bin/github-auth.sh +121 -0
  440. package/runtime/pi/bin/graph-batch.sh +7 -0
  441. package/runtime/pi/bin/graph-op.sh +4 -0
  442. package/runtime/pi/bin/graph-projection.sh +54 -0
  443. package/runtime/pi/bin/graph-wal.sh +13 -0
  444. package/runtime/pi/bin/graph.sh +44 -0
  445. package/runtime/pi/bin/handoff-lifecycle-job.sh +146 -0
  446. package/runtime/pi/bin/handoff-lifecycle.sh +280 -0
  447. package/runtime/pi/bin/handoff-preview.sh +169 -0
  448. package/runtime/pi/bin/handoff-run.sh +42 -26
  449. package/runtime/pi/bin/ingest-graph.sh +6 -0
  450. package/runtime/pi/bin/ingest-item.sh +10 -0
  451. package/runtime/pi/bin/ingest.sh +59 -30
  452. package/runtime/pi/bin/invite.sh +6 -0
  453. package/runtime/pi/bin/issue.sh +10 -0
  454. package/runtime/pi/bin/knowledge.sh +10 -0
  455. package/runtime/pi/bin/lib/config.sh +20 -0
  456. package/runtime/pi/bin/lib/context.sh +46 -25
  457. package/runtime/pi/bin/lib/git-sync.sh +70 -6
  458. package/runtime/pi/bin/lib/greeting.sh +34 -5
  459. package/runtime/pi/bin/lib/handoff-meta.sh +97 -0
  460. package/runtime/pi/bin/lib/worktree-links.sh +6 -0
  461. package/runtime/pi/bin/node-run.sh +42 -0
  462. package/runtime/pi/bin/notification.sh +6 -0
  463. package/runtime/pi/bin/observe-context.sh +14 -0
  464. package/runtime/pi/bin/onboarding.sh +6 -0
  465. package/runtime/pi/bin/person.py +4 -0
  466. package/runtime/pi/bin/person.sh +43 -10
  467. package/runtime/pi/bin/pi-observe-context.mjs +93 -0
  468. package/runtime/pi/bin/pi-product-workflows.mjs +1 -1
  469. package/runtime/pi/bin/pi-render-spec.mjs +1 -1
  470. package/runtime/pi/bin/post-update.sh +37 -0
  471. package/runtime/pi/bin/prime-render-spec.mjs +147 -0
  472. package/runtime/pi/bin/publish-artifact.sh +55 -2
  473. package/runtime/pi/bin/quest.sh +9 -0
  474. package/runtime/pi/bin/question.sh +8 -0
  475. package/runtime/pi/bin/research-ingest.sh +7 -0
  476. package/runtime/pi/bin/restore-owned-skills.sh +67 -0
  477. package/runtime/pi/bin/retrieval_eval.py +385 -0
  478. package/runtime/pi/bin/runtime-identity.sh +70 -0
  479. package/runtime/pi/bin/runtime-upgrade.sh +43 -0
  480. package/runtime/pi/bin/scroll.sh +9 -0
  481. package/runtime/pi/bin/search.sh +231 -195
  482. package/runtime/pi/bin/settings.sh +174 -5
  483. package/runtime/pi/bin/startup-check.sh +136 -0
  484. package/runtime/pi/bin/telemetry.sh +522 -247
  485. package/runtime/pi/bin/test-changes.sh +344 -0
  486. package/runtime/pi/bin/thread.sh +9 -0
  487. package/runtime/pi/bin/todo.sh +9 -0
  488. package/runtime/pi/bin/view-render.sh +126 -0
  489. package/runtime/pi/bin/worktree-create.sh +19 -5
  490. package/runtime/pi/egregore_runtime/__init__.py +228 -0
  491. package/runtime/pi/egregore_runtime/adapters/__init__.py +5 -0
  492. package/runtime/pi/egregore_runtime/adapters/invitation.py +237 -0
  493. package/runtime/pi/egregore_runtime/adapters/notification.py +59 -0
  494. package/runtime/pi/egregore_runtime/adapters/qmd.py +1701 -0
  495. package/runtime/pi/egregore_runtime/adapters/qmd_cli.py +210 -0
  496. package/runtime/pi/egregore_runtime/adapters/qmd_embed_worker.py +59 -0
  497. package/runtime/pi/egregore_runtime/admin_gate.py +102 -0
  498. package/runtime/pi/egregore_runtime/artifacts.py +523 -0
  499. package/runtime/pi/egregore_runtime/contracts.py +499 -0
  500. package/runtime/pi/egregore_runtime/entitlements.py +85 -0
  501. package/runtime/pi/egregore_runtime/errors.py +10 -0
  502. package/runtime/pi/egregore_runtime/graph.py +356 -0
  503. package/runtime/pi/egregore_runtime/handoff_lookup.py +196 -0
  504. package/runtime/pi/egregore_runtime/harness_cli.py +1221 -0
  505. package/runtime/pi/egregore_runtime/identity.py +734 -0
  506. package/runtime/pi/egregore_runtime/identity_cli.py +91 -0
  507. package/runtime/pi/egregore_runtime/ingest.py +575 -0
  508. package/runtime/pi/egregore_runtime/ingest_cli.py +254 -0
  509. package/runtime/pi/egregore_runtime/ingest_index_cli.py +147 -0
  510. package/runtime/pi/egregore_runtime/invitation_cli.py +51 -0
  511. package/runtime/pi/egregore_runtime/invitations.py +116 -0
  512. package/runtime/pi/egregore_runtime/issue_cli.py +305 -0
  513. package/runtime/pi/egregore_runtime/issues.py +359 -0
  514. package/runtime/pi/egregore_runtime/knowledge.py +376 -0
  515. package/runtime/pi/egregore_runtime/knowledge_cli.py +173 -0
  516. package/runtime/pi/egregore_runtime/lifecycle.py +888 -0
  517. package/runtime/pi/egregore_runtime/lifecycle_cli.py +269 -0
  518. package/runtime/pi/egregore_runtime/notification_cli.py +125 -0
  519. package/runtime/pi/egregore_runtime/notifications.py +230 -0
  520. package/runtime/pi/egregore_runtime/observe.py +342 -0
  521. package/runtime/pi/egregore_runtime/onboarding.py +290 -0
  522. package/runtime/pi/egregore_runtime/onboarding_cli.py +110 -0
  523. package/runtime/pi/egregore_runtime/policy.py +144 -0
  524. package/runtime/pi/egregore_runtime/profile.py +193 -0
  525. package/runtime/pi/egregore_runtime/quest_cli.py +216 -0
  526. package/runtime/pi/egregore_runtime/question_cli.py +180 -0
  527. package/runtime/pi/egregore_runtime/questions.py +304 -0
  528. package/runtime/pi/egregore_runtime/quests.py +419 -0
  529. package/runtime/pi/egregore_runtime/readiness.py +379 -0
  530. package/runtime/pi/egregore_runtime/research_ingest.py +256 -0
  531. package/runtime/pi/egregore_runtime/research_ingest_cli.py +44 -0
  532. package/runtime/pi/egregore_runtime/runtime.py +464 -0
  533. package/runtime/pi/egregore_runtime/scroll_cli.py +185 -0
  534. package/runtime/pi/egregore_runtime/scrolls.py +726 -0
  535. package/runtime/pi/egregore_runtime/status.py +412 -0
  536. package/runtime/pi/egregore_runtime/status_cli.py +174 -0
  537. package/runtime/pi/egregore_runtime/sync.py +218 -0
  538. package/runtime/pi/egregore_runtime/teamsync.py +139 -0
  539. package/runtime/pi/egregore_runtime/telemetry.py +640 -0
  540. package/runtime/pi/egregore_runtime/thread_cli.py +173 -0
  541. package/runtime/pi/egregore_runtime/threads.py +517 -0
  542. package/runtime/pi/egregore_runtime/todo_cli.py +142 -0
  543. package/runtime/pi/egregore_runtime/todos.py +244 -0
  544. package/runtime/pi/egregore_runtime/upgrade.py +770 -0
  545. package/runtime/pi/egregore_runtime/upgrade_worker.py +53 -0
  546. package/runtime/pi/egregore_runtime/writeback.py +391 -0
  547. package/runtime/pi/egregore_runtime/writeback_cli.py +114 -0
  548. package/runtime/pi/manifest.json +98 -1
  549. package/runtime/prime/.codex/hooks/search-hint.js +21 -52
  550. package/runtime/prime/.codex/hooks.json +3 -3
  551. package/runtime/prime/.codex/skills/activity/SKILL.md +23 -66
  552. package/runtime/prime/.codex/skills/announce/SKILL.md +27 -50
  553. package/runtime/prime/.codex/skills/archive/SKILL.md +21 -36
  554. package/runtime/prime/.codex/skills/checkup/SKILL.md +77 -36
  555. package/runtime/prime/.codex/skills/dark-mode/SKILL.md +1 -1
  556. package/runtime/prime/.codex/skills/dashboard/SKILL.md +17 -47
  557. package/runtime/prime/.codex/skills/handoff/SKILL.md +84 -133
  558. package/runtime/prime/.codex/skills/harvest/SKILL.md +32 -117
  559. package/runtime/prime/.codex/skills/ingest/SKILL.md +47 -25
  560. package/runtime/prime/.codex/skills/ingest-user-interview/SKILL.md +18 -36
  561. package/runtime/prime/.codex/skills/ingest-user-interview/references/analysis-contract.md +42 -0
  562. package/runtime/prime/.codex/skills/invite/SKILL.md +21 -35
  563. package/runtime/prime/.codex/skills/issue/SKILL.md +60 -41
  564. package/runtime/prime/.codex/skills/me/SKILL.md +1 -1
  565. package/runtime/prime/.codex/skills/meeting/SKILL.md +16 -36
  566. package/runtime/prime/.codex/skills/meeting/references/analysis-contract.md +48 -0
  567. package/runtime/prime/.codex/skills/note/SKILL.md +30 -25
  568. package/runtime/prime/.codex/skills/onboarding/SKILL.md +36 -41
  569. package/runtime/prime/.codex/skills/pull/SKILL.md +1 -1
  570. package/runtime/prime/.codex/skills/quest/SKILL.md +27 -66
  571. package/runtime/prime/.codex/skills/reflect/SKILL.md +22 -36
  572. package/runtime/prime/.codex/skills/save/SKILL.md +2 -2
  573. package/runtime/prime/.codex/skills/telemetry/SKILL.md +1 -1
  574. package/runtime/prime/.codex/skills/test/SKILL.md +1 -1
  575. package/runtime/prime/.codex/skills/tutorial/SKILL.md +40 -41
  576. package/runtime/prime/.codex/skills/view/SKILL.md +115 -111
  577. package/runtime/prime/.codex/skills/wrap/SKILL.md +45 -41
  578. package/runtime/prime/.codex/spec-manifest.json +9 -9
  579. package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +57 -48
  580. package/runtime/prime/.prime/agent/extensions/egregore.ts +7 -0
  581. package/runtime/prime/.prime/agent/spec-manifest.json +2 -2
  582. package/runtime/prime/AGENTS.md +62 -58
  583. package/runtime/prime/bin/activity-action.sh +92 -0
  584. package/runtime/prime/bin/activity-data.sh +12 -233
  585. package/runtime/prime/bin/agent.sh +84 -100
  586. package/runtime/prime/bin/artifact-register.sh +164 -0
  587. package/runtime/prime/bin/artifact-writeback.sh +53 -0
  588. package/runtime/prime/bin/artifacts.sh +288 -0
  589. package/runtime/prime/bin/build-sealed-dataroom.mjs +722 -0
  590. package/runtime/prime/bin/capture-run.sh +18 -2
  591. package/runtime/prime/bin/codex-render-spec.mjs +41 -16
  592. package/runtime/prime/bin/codex-session-start.sh +14 -4
  593. package/runtime/prime/bin/codex-skill-render.mjs +9 -7
  594. package/runtime/prime/bin/corpus_map.py +806 -0
  595. package/runtime/prime/bin/corpus_survey.py +304 -0
  596. package/runtime/prime/bin/dashboard-data.sh +11 -171
  597. package/runtime/prime/bin/github-auth.sh +121 -0
  598. package/runtime/prime/bin/graph-batch.sh +7 -0
  599. package/runtime/prime/bin/graph-op.sh +4 -0
  600. package/runtime/prime/bin/graph-projection.sh +54 -0
  601. package/runtime/prime/bin/graph-wal.sh +13 -0
  602. package/runtime/prime/bin/graph.sh +44 -0
  603. package/runtime/prime/bin/handoff-lifecycle-job.sh +146 -0
  604. package/runtime/prime/bin/handoff-lifecycle.sh +280 -0
  605. package/runtime/prime/bin/handoff-preview.sh +169 -0
  606. package/runtime/prime/bin/handoff-run.sh +42 -26
  607. package/runtime/prime/bin/ingest-graph.sh +6 -0
  608. package/runtime/prime/bin/ingest-item.sh +10 -0
  609. package/runtime/prime/bin/ingest.sh +59 -30
  610. package/runtime/prime/bin/invite.sh +6 -0
  611. package/runtime/prime/bin/issue.sh +10 -0
  612. package/runtime/prime/bin/knowledge.sh +10 -0
  613. package/runtime/prime/bin/lib/config.sh +20 -0
  614. package/runtime/prime/bin/lib/context.sh +46 -25
  615. package/runtime/prime/bin/lib/git-sync.sh +70 -6
  616. package/runtime/prime/bin/lib/greeting.sh +34 -5
  617. package/runtime/prime/bin/lib/handoff-meta.sh +97 -0
  618. package/runtime/prime/bin/lib/worktree-links.sh +6 -0
  619. package/runtime/prime/bin/node-run.sh +42 -0
  620. package/runtime/prime/bin/notification.sh +6 -0
  621. package/runtime/prime/bin/observe-context.sh +14 -0
  622. package/runtime/prime/bin/onboarding.sh +6 -0
  623. package/runtime/prime/bin/person.py +4 -0
  624. package/runtime/prime/bin/person.sh +43 -10
  625. package/runtime/prime/bin/pi-observe-context.mjs +93 -0
  626. package/runtime/prime/bin/pi-product-workflows.mjs +1 -1
  627. package/runtime/prime/bin/pi-render-spec.mjs +140 -0
  628. package/runtime/prime/bin/post-update.sh +37 -0
  629. package/runtime/prime/bin/prime-render-spec.mjs +1 -1
  630. package/runtime/prime/bin/publish-artifact.sh +55 -2
  631. package/runtime/prime/bin/quest.sh +9 -0
  632. package/runtime/prime/bin/question.sh +8 -0
  633. package/runtime/prime/bin/research-ingest.sh +7 -0
  634. package/runtime/prime/bin/restore-owned-skills.sh +67 -0
  635. package/runtime/prime/bin/retrieval_eval.py +385 -0
  636. package/runtime/prime/bin/runtime-identity.sh +70 -0
  637. package/runtime/prime/bin/runtime-upgrade.sh +43 -0
  638. package/runtime/prime/bin/scroll.sh +9 -0
  639. package/runtime/prime/bin/search.sh +231 -195
  640. package/runtime/prime/bin/settings.sh +174 -5
  641. package/runtime/prime/bin/startup-check.sh +136 -0
  642. package/runtime/prime/bin/telemetry.sh +522 -247
  643. package/runtime/prime/bin/test-changes.sh +344 -0
  644. package/runtime/prime/bin/thread.sh +9 -0
  645. package/runtime/prime/bin/todo.sh +9 -0
  646. package/runtime/prime/bin/view-render.sh +126 -0
  647. package/runtime/prime/bin/worktree-create.sh +19 -5
  648. package/runtime/prime/egregore_runtime/__init__.py +228 -0
  649. package/runtime/prime/egregore_runtime/adapters/__init__.py +5 -0
  650. package/runtime/prime/egregore_runtime/adapters/invitation.py +237 -0
  651. package/runtime/prime/egregore_runtime/adapters/notification.py +59 -0
  652. package/runtime/prime/egregore_runtime/adapters/qmd.py +1701 -0
  653. package/runtime/prime/egregore_runtime/adapters/qmd_cli.py +210 -0
  654. package/runtime/prime/egregore_runtime/adapters/qmd_embed_worker.py +59 -0
  655. package/runtime/prime/egregore_runtime/admin_gate.py +102 -0
  656. package/runtime/prime/egregore_runtime/artifacts.py +523 -0
  657. package/runtime/prime/egregore_runtime/contracts.py +499 -0
  658. package/runtime/prime/egregore_runtime/entitlements.py +85 -0
  659. package/runtime/prime/egregore_runtime/errors.py +10 -0
  660. package/runtime/prime/egregore_runtime/graph.py +356 -0
  661. package/runtime/prime/egregore_runtime/handoff_lookup.py +196 -0
  662. package/runtime/prime/egregore_runtime/harness_cli.py +1221 -0
  663. package/runtime/prime/egregore_runtime/identity.py +734 -0
  664. package/runtime/prime/egregore_runtime/identity_cli.py +91 -0
  665. package/runtime/prime/egregore_runtime/ingest.py +575 -0
  666. package/runtime/prime/egregore_runtime/ingest_cli.py +254 -0
  667. package/runtime/prime/egregore_runtime/ingest_index_cli.py +147 -0
  668. package/runtime/prime/egregore_runtime/invitation_cli.py +51 -0
  669. package/runtime/prime/egregore_runtime/invitations.py +116 -0
  670. package/runtime/prime/egregore_runtime/issue_cli.py +305 -0
  671. package/runtime/prime/egregore_runtime/issues.py +359 -0
  672. package/runtime/prime/egregore_runtime/knowledge.py +376 -0
  673. package/runtime/prime/egregore_runtime/knowledge_cli.py +173 -0
  674. package/runtime/prime/egregore_runtime/lifecycle.py +888 -0
  675. package/runtime/prime/egregore_runtime/lifecycle_cli.py +269 -0
  676. package/runtime/prime/egregore_runtime/notification_cli.py +125 -0
  677. package/runtime/prime/egregore_runtime/notifications.py +230 -0
  678. package/runtime/prime/egregore_runtime/observe.py +342 -0
  679. package/runtime/prime/egregore_runtime/onboarding.py +290 -0
  680. package/runtime/prime/egregore_runtime/onboarding_cli.py +110 -0
  681. package/runtime/prime/egregore_runtime/policy.py +144 -0
  682. package/runtime/prime/egregore_runtime/profile.py +193 -0
  683. package/runtime/prime/egregore_runtime/quest_cli.py +216 -0
  684. package/runtime/prime/egregore_runtime/question_cli.py +180 -0
  685. package/runtime/prime/egregore_runtime/questions.py +304 -0
  686. package/runtime/prime/egregore_runtime/quests.py +419 -0
  687. package/runtime/prime/egregore_runtime/readiness.py +379 -0
  688. package/runtime/prime/egregore_runtime/research_ingest.py +256 -0
  689. package/runtime/prime/egregore_runtime/research_ingest_cli.py +44 -0
  690. package/runtime/prime/egregore_runtime/runtime.py +464 -0
  691. package/runtime/prime/egregore_runtime/scroll_cli.py +185 -0
  692. package/runtime/prime/egregore_runtime/scrolls.py +726 -0
  693. package/runtime/prime/egregore_runtime/status.py +412 -0
  694. package/runtime/prime/egregore_runtime/status_cli.py +174 -0
  695. package/runtime/prime/egregore_runtime/sync.py +218 -0
  696. package/runtime/prime/egregore_runtime/teamsync.py +139 -0
  697. package/runtime/prime/egregore_runtime/telemetry.py +640 -0
  698. package/runtime/prime/egregore_runtime/thread_cli.py +173 -0
  699. package/runtime/prime/egregore_runtime/threads.py +517 -0
  700. package/runtime/prime/egregore_runtime/todo_cli.py +142 -0
  701. package/runtime/prime/egregore_runtime/todos.py +244 -0
  702. package/runtime/prime/egregore_runtime/upgrade.py +770 -0
  703. package/runtime/prime/egregore_runtime/upgrade_worker.py +53 -0
  704. package/runtime/prime/egregore_runtime/writeback.py +391 -0
  705. package/runtime/prime/egregore_runtime/writeback_cli.py +114 -0
  706. package/runtime/prime/manifest.json +98 -1
@@ -0,0 +1,269 @@
1
+ """Thin shell compatibility adapter for canonical Runtime lifecycle operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from dataclasses import replace
7
+ import json
8
+ import os
9
+ from pathlib import Path
10
+ import sys
11
+
12
+ from .lifecycle import (
13
+ AttentionState,
14
+ LifecycleAction,
15
+ LifecycleError,
16
+ LifecyclePlan,
17
+ LifecyclePolicy,
18
+ LifecycleRecord,
19
+ ObligationState,
20
+ )
21
+ from .identity import actor_presentation_name
22
+ from .runtime import local_runtime
23
+
24
+
25
+ def _root() -> Path:
26
+ return Path(os.environ.get("EGREGORE_ROOT") or Path.cwd()).resolve()
27
+
28
+
29
+ def _session_id(root: Path) -> str:
30
+ configured = os.environ.get("EGREGORE_SESSION_ID", "").strip()
31
+ if configured:
32
+ return configured
33
+ try:
34
+ return (root / ".egregore-session-id").read_text(encoding="utf-8").strip() or "lifecycle-shell"
35
+ except OSError:
36
+ return "lifecycle-shell"
37
+
38
+
39
+ def _runtime(args: argparse.Namespace):
40
+ root = _root()
41
+ runtime = local_runtime(
42
+ root,
43
+ push_remote=os.environ.get("EGREGORE_LIFECYCLE_PUSH", "1") != "0",
44
+ )
45
+ if args.days is not None and runtime.lifecycle is not None:
46
+ runtime.lifecycle.policy = replace(
47
+ runtime.lifecycle.policy,
48
+ handoff_ttl_days=args.days,
49
+ fyi_expiry_days=args.days,
50
+ )
51
+ actor = runtime.resolve_actor(session_id=_session_id(root), harness="lifecycle-shell")
52
+ return runtime, actor
53
+
54
+
55
+ def _activity_status(record: LifecycleRecord) -> str:
56
+ if record.obligation_state is ObligationState.COMPLETED:
57
+ return "done"
58
+ if record.obligation_state is ObligationState.CLAIMED:
59
+ return "claimed"
60
+ if record.obligation_state is ObligationState.READ:
61
+ return "read"
62
+ if record.obligation_state is ObligationState.REVIEW_REQUIRED:
63
+ return "review_due"
64
+ if record.attention_state is AttentionState.EXPIRED and record.intent == "fyi":
65
+ return "expired"
66
+ return "pending"
67
+
68
+
69
+ def _item(actor, record: LifecycleRecord) -> dict[str, object]:
70
+ recipient = record.recipients[0] if len(record.recipients) == 1 else None
71
+ author = actor_presentation_name(actor, record.created_by, record.created_by_alias)
72
+ return {
73
+ "id": record.artifact_id,
74
+ "sessionId": record.artifact_id,
75
+ "topic": record.title,
76
+ "author": author,
77
+ "from": author,
78
+ "authorActorId": record.created_by,
79
+ "recipient": actor_presentation_name(actor, recipient) if recipient else None,
80
+ "to": actor_presentation_name(actor, recipient) if recipient else None,
81
+ "date": record.created_at.date().isoformat(),
82
+ "filePath": record.canonical_path.removeprefix("memory/"),
83
+ "status": _activity_status(record),
84
+ "intent": record.intent or "unclassified",
85
+ "ageDays": record.age_days,
86
+ "authority": record.authority_state.value,
87
+ "attention": record.attention_state.value,
88
+ "obligation": record.obligation_state.value,
89
+ "lifecycleRevision": record.lifecycle_revision,
90
+ "lifecycleReason": record.terminal_reason,
91
+ "recommendation": record.recommendation,
92
+ "automaticTransitionSafe": record.automatic_transition_safe,
93
+ "supersededBy": list(record.superseded_by),
94
+ }
95
+
96
+
97
+ def _plan_json(actor, plan: LifecyclePlan, *, managed_only: bool = False) -> dict[str, object]:
98
+ records = [record for record in plan.records if record.artifact_type == "handoff"]
99
+ if managed_only:
100
+ records = [record for record in records if record.intent in {"action", "feedback", "fyi"}]
101
+ items = [_item(actor, record) for record in records]
102
+ safe = [item for item in items if item["automaticTransitionSafe"]]
103
+ review = [item for item in items if item["recommendation"] == "review"]
104
+ return {
105
+ "schema": plan.schema_version,
106
+ "index_spec_version": plan.index_spec_version,
107
+ "snapshot_id": plan.snapshot_id,
108
+ "source_revision": plan.source_revision,
109
+ "generated_at": plan.generated_at.isoformat(),
110
+ "authority": "canonical_markdown",
111
+ "graph_dependency": False,
112
+ "managed_only": managed_only,
113
+ "counts": {
114
+ "handoffs": len(items),
115
+ "safe_candidates": len(safe),
116
+ "review_candidates": len(review),
117
+ },
118
+ "safe_candidates": safe,
119
+ "review_candidates": review,
120
+ "handoffs_to_me": items,
121
+ "items": items,
122
+ "warnings": list(plan.warnings),
123
+ "apply_contract": {
124
+ "requires_snapshot": True,
125
+ "confirmation": "APPLY_SAFE_HANDOFF_LIFECYCLE",
126
+ "age_alone_never_marks_done": True,
127
+ "attention_expiry_never_completes_obligation": True,
128
+ },
129
+ }
130
+
131
+
132
+ def _scan(args: argparse.Namespace) -> int:
133
+ runtime, actor = _runtime(args)
134
+ plan = runtime.lifecycle_plan(actor, artifact_types=("handoff",), user=args.user)
135
+ print(json.dumps(_plan_json(actor, plan, managed_only=args.managed_only), separators=(",", ":")))
136
+ return 0
137
+
138
+
139
+ def _action(args: argparse.Namespace) -> int:
140
+ runtime, actor = _runtime(args)
141
+ action = {
142
+ "read": LifecycleAction.ACKNOWLEDGE,
143
+ "acknowledge": LifecycleAction.ACKNOWLEDGE,
144
+ "claim": LifecycleAction.CLAIM,
145
+ "done": LifecycleAction.COMPLETE,
146
+ "complete": LifecycleAction.COMPLETE,
147
+ "expire": LifecycleAction.EXPIRE_ATTENTION,
148
+ "expire_attention": LifecycleAction.EXPIRE_ATTENTION,
149
+ "reopen": LifecycleAction.REOPEN,
150
+ "review": LifecycleAction.REQUEST_REVIEW,
151
+ "request_review": LifecycleAction.REQUEST_REVIEW,
152
+ }[args.action]
153
+ receipt = runtime.transition_lifecycle(
154
+ actor,
155
+ target_artifact_id=args.target,
156
+ action=action,
157
+ reason=args.reason,
158
+ evidence_ids=tuple(args.evidence),
159
+ automatic=args.automatic,
160
+ expected_lifecycle_revision=args.expected_revision,
161
+ user=args.user,
162
+ )
163
+ resulting_status = {
164
+ LifecycleAction.ACKNOWLEDGE: "read",
165
+ LifecycleAction.CLAIM: "claimed",
166
+ LifecycleAction.COMPLETE: "done",
167
+ LifecycleAction.EXPIRE_ATTENTION: "expired",
168
+ LifecycleAction.REOPEN: "pending",
169
+ LifecycleAction.REQUEST_REVIEW: "review_due",
170
+ }[action]
171
+ print(
172
+ json.dumps(
173
+ {
174
+ "applied": receipt.status.value != "rejected",
175
+ "action": action.value,
176
+ "id": args.target,
177
+ "event_id": receipt.artifact.artifact_id,
178
+ "status": resulting_status,
179
+ "writeback_status": receipt.status.value,
180
+ "git_revision": receipt.git_revision,
181
+ "warnings": list(receipt.warnings),
182
+ },
183
+ separators=(",", ":"),
184
+ )
185
+ )
186
+ return 0 if receipt.status.value != "rejected" else 3
187
+
188
+
189
+ def _apply(args: argparse.Namespace) -> int:
190
+ runtime, actor = _runtime(args)
191
+ plan = runtime.lifecycle_plan(actor, artifact_types=("handoff",), user=args.user)
192
+ if args.snapshot != plan.snapshot_id:
193
+ raise LifecycleError("snapshot changed; scan again before applying")
194
+ if args.confirm != "APPLY_SAFE_HANDOFF_LIFECYCLE":
195
+ raise LifecycleError("explicit lifecycle confirmation is required")
196
+ receipts = []
197
+ for record in plan.records:
198
+ if not record.automatic_transition_safe:
199
+ continue
200
+ receipt = runtime.transition_lifecycle(
201
+ actor,
202
+ target_artifact_id=record.artifact_id,
203
+ action=LifecycleAction.EXPIRE_ATTENTION,
204
+ reason="typed_attention_ttl_elapsed",
205
+ automatic=True,
206
+ expected_lifecycle_revision=record.lifecycle_revision,
207
+ user=args.user,
208
+ )
209
+ receipts.append(receipt)
210
+ print(
211
+ json.dumps(
212
+ {
213
+ **_plan_json(actor, plan, managed_only=args.managed_only),
214
+ "applied": True,
215
+ "transitions": {
216
+ "attention_expired": len(receipts),
217
+ "completed": 0,
218
+ },
219
+ },
220
+ separators=(",", ":"),
221
+ )
222
+ )
223
+ return 0
224
+
225
+
226
+ def _parser() -> argparse.ArgumentParser:
227
+ parser = argparse.ArgumentParser(prog="egregore-lifecycle")
228
+ commands = parser.add_subparsers(dest="command", required=True)
229
+ for name in ("scan", "apply"):
230
+ command = commands.add_parser(name)
231
+ command.add_argument("--days", type=int)
232
+ command.add_argument("--user")
233
+ command.add_argument("--managed-only", action="store_true")
234
+ if name == "apply":
235
+ command.add_argument("--snapshot", required=True)
236
+ command.add_argument("--confirm", required=True)
237
+ command.set_defaults(handler=_scan if name == "scan" else _apply)
238
+ action = commands.add_parser("action")
239
+ action.add_argument(
240
+ "action",
241
+ choices=(
242
+ "read", "acknowledge", "claim", "done", "complete", "expire",
243
+ "expire_attention", "reopen", "review", "request_review",
244
+ ),
245
+ )
246
+ action.add_argument("target")
247
+ action.add_argument("--reason", default="explicit_user_action")
248
+ action.add_argument("--evidence", action="append", default=[])
249
+ action.add_argument("--automatic", action="store_true")
250
+ action.add_argument("--expected-revision")
251
+ action.add_argument("--user")
252
+ action.add_argument("--days", type=int)
253
+ action.set_defaults(handler=_action)
254
+ return parser
255
+
256
+
257
+ def main() -> int:
258
+ args = _parser().parse_args()
259
+ if args.days is not None and not 1 <= args.days <= 365:
260
+ raise LifecycleError("days must be between 1 and 365")
261
+ return args.handler(args)
262
+
263
+
264
+ if __name__ == "__main__":
265
+ try:
266
+ raise SystemExit(main())
267
+ except (LifecycleError, RuntimeError, ValueError) as exc:
268
+ print(f"egregore lifecycle: {exc}", file=sys.stderr)
269
+ raise SystemExit(1) from exc
@@ -0,0 +1,125 @@
1
+ """Runtime-neutral command adapter for notification consent and delivery."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import json
7
+ import os
8
+ from pathlib import Path
9
+ import sys
10
+ from uuid import uuid4
11
+
12
+ from .adapters.notification import ShellNotificationTransport
13
+ from .errors import AuthorizationDenied
14
+ from .notifications import NotificationError, NotificationService
15
+ from .runtime import local_runtime
16
+
17
+
18
+ def _root() -> Path:
19
+ return Path(os.environ.get("EGREGORE_ROOT") or Path.cwd()).resolve()
20
+
21
+
22
+ def _context():
23
+ root = _root()
24
+ runtime = local_runtime(root, push_remote=False)
25
+ session_path = root / ".egregore-session-id"
26
+ session_id = os.environ.get("EGREGORE_SESSION_ID")
27
+ if not session_id and session_path.is_file():
28
+ session_id = session_path.read_text(encoding="utf-8").splitlines()[0].strip()
29
+ actor = runtime.resolve_actor(
30
+ session_id=session_id or f"session_{uuid4().hex}",
31
+ harness=os.environ.get("EGREGORE_RUNTIME", "shell"),
32
+ )
33
+ service = NotificationService(
34
+ runtime,
35
+ ShellNotificationTransport(root),
36
+ root / ".egregore" / "runtime" / "notifications",
37
+ )
38
+ return actor, service
39
+
40
+
41
+ def _plan(args: argparse.Namespace) -> int:
42
+ actor, service = _context()
43
+ message = Path(args.message_file).read_text(encoding="utf-8")
44
+ result = service.plan(
45
+ actor,
46
+ kind=args.kind,
47
+ recipient=args.recipient,
48
+ message=message,
49
+ )
50
+ print(json.dumps(result, ensure_ascii=False))
51
+ return 0
52
+
53
+
54
+ def _status(args: argparse.Namespace) -> int:
55
+ del args
56
+ actor, service = _context()
57
+ print(json.dumps(service.status(actor), ensure_ascii=False))
58
+ return 0
59
+
60
+
61
+ def _approve(args: argparse.Namespace) -> int:
62
+ actor, service = _context()
63
+ result = service.approve(
64
+ actor,
65
+ plan_id=args.plan_id,
66
+ digest=args.digest,
67
+ confirmation=args.confirmation,
68
+ )
69
+ print(json.dumps(result, ensure_ascii=False))
70
+ return 0
71
+
72
+
73
+ def _dispatch(args: argparse.Namespace) -> int:
74
+ actor, service = _context()
75
+ result = service.dispatch(
76
+ actor,
77
+ plan_id=args.plan_id,
78
+ approval_token=args.approval_token,
79
+ )
80
+ print(json.dumps(result, ensure_ascii=False))
81
+ return 0
82
+
83
+
84
+ def _cancel(args: argparse.Namespace) -> int:
85
+ actor, service = _context()
86
+ print(json.dumps(service.cancel(actor, plan_id=args.plan_id), ensure_ascii=False))
87
+ return 0
88
+
89
+
90
+ def _parser() -> argparse.ArgumentParser:
91
+ parser = argparse.ArgumentParser(prog="egregore-notification")
92
+ commands = parser.add_subparsers(dest="command", required=True)
93
+ status = commands.add_parser("status")
94
+ status.set_defaults(handler=_status)
95
+ plan = commands.add_parser("plan")
96
+ plan.add_argument("--kind", choices=("group", "send"), required=True)
97
+ plan.add_argument("--recipient")
98
+ plan.add_argument("--message-file", required=True)
99
+ plan.set_defaults(handler=_plan)
100
+ approve = commands.add_parser("approve")
101
+ approve.add_argument("plan_id")
102
+ approve.add_argument("digest")
103
+ approve.add_argument("confirmation")
104
+ approve.set_defaults(handler=_approve)
105
+ dispatch = commands.add_parser("dispatch")
106
+ dispatch.add_argument("plan_id")
107
+ dispatch.add_argument("approval_token")
108
+ dispatch.set_defaults(handler=_dispatch)
109
+ cancel = commands.add_parser("cancel")
110
+ cancel.add_argument("plan_id")
111
+ cancel.set_defaults(handler=_cancel)
112
+ return parser
113
+
114
+
115
+ def main() -> int:
116
+ args = _parser().parse_args()
117
+ return args.handler(args)
118
+
119
+
120
+ if __name__ == "__main__":
121
+ try:
122
+ raise SystemExit(main())
123
+ except (AuthorizationDenied, NotificationError, OSError, ValueError) as exc:
124
+ print(f"notification: {exc}", file=sys.stderr)
125
+ raise SystemExit(1) from exc
@@ -0,0 +1,230 @@
1
+ """Actor-bound notification planning and exact-consent dispatch."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from datetime import UTC, datetime
7
+ import json
8
+ import os
9
+ from pathlib import Path
10
+ from typing import Callable, Mapping, Protocol
11
+ from uuid import uuid4
12
+
13
+ from .contracts import ActorContext, Permission, TelemetryEvent
14
+ from .errors import AuthorizationDenied
15
+ from .runtime import EgregoreRuntime
16
+ from .telemetry import TELEMETRY_SCHEMA_VERSION
17
+
18
+
19
+ EXACT_NOTIFICATION_CONFIRMATION = "APPROVE_EXACT_NOTIFICATION"
20
+ NOTIFICATION_BINDING_SCHEMA = "egregore-notification-binding/v1"
21
+
22
+
23
+ class NotificationError(RuntimeError):
24
+ """A notification plan or dispatch failed closed."""
25
+
26
+
27
+ class NotificationTransport(Protocol):
28
+ def status(self) -> Mapping[str, object]: ...
29
+
30
+ def plan(self, *, kind: str, recipient: str | None, message: str) -> Mapping[str, object]: ...
31
+
32
+ def approve(self, *, plan_id: str, digest: str, confirmation: str) -> Mapping[str, object]: ...
33
+
34
+ def dispatch(self, *, plan_id: str, approval_token: str) -> Mapping[str, object]: ...
35
+
36
+ def cancel(self, *, plan_id: str) -> Mapping[str, object]: ...
37
+
38
+
39
+ @dataclass(frozen=True, slots=True)
40
+ class NotificationBinding:
41
+ plan_id: str
42
+ digest: str
43
+ org_id: str
44
+ actor_id: str
45
+ session_id: str
46
+ kind: str
47
+ recipient: str | None
48
+
49
+
50
+ class NotificationService:
51
+ """Authorize and bind one immutable notification plan to one actor session."""
52
+
53
+ def __init__(
54
+ self,
55
+ runtime: EgregoreRuntime,
56
+ transport: NotificationTransport,
57
+ state_root: Path,
58
+ *,
59
+ clock: Callable[[], datetime] | None = None,
60
+ ) -> None:
61
+ self.runtime = runtime
62
+ self.transport = transport
63
+ self.state_root = state_root.resolve()
64
+ self.clock = clock or (lambda: datetime.now(UTC))
65
+
66
+ def _authorize(
67
+ self,
68
+ actor: ActorContext,
69
+ permission: Permission,
70
+ resource: str,
71
+ ) -> None:
72
+ decision = self.runtime.authorize(actor, permission, (resource,))
73
+ if not decision.allowed:
74
+ raise AuthorizationDenied(
75
+ "; ".join(decision.reasons) or f"notification {permission.value} denied"
76
+ )
77
+
78
+ def status(self, actor: ActorContext) -> Mapping[str, object]:
79
+ """Return sanitized transport readiness through the Runtime boundary."""
80
+
81
+ self._authorize(actor, Permission.READ, "notification:configuration")
82
+ receipt = self.transport.status()
83
+ return {
84
+ "status": str(receipt.get("status") or "unknown"),
85
+ "configured": bool(receipt.get("configured", False)),
86
+ "channels": tuple(str(value) for value in receipt.get("channels", ()) if value),
87
+ }
88
+
89
+ def _binding_path(self, plan_id: str) -> Path:
90
+ if not plan_id or any(character not in "0123456789abcdef" for character in plan_id):
91
+ raise NotificationError("notification plan id is invalid")
92
+ return self.state_root / f"{plan_id}.json"
93
+
94
+ def _write_binding(self, actor: ActorContext, plan: Mapping[str, object], *, kind: str, recipient: str | None) -> None:
95
+ plan_id = str(plan.get("plan_id") or "")
96
+ digest = str(plan.get("digest") or "")
97
+ if plan.get("status") != "approval_required" or not plan_id or not digest:
98
+ raise NotificationError("notification transport returned an invalid plan")
99
+ self.state_root.mkdir(parents=True, exist_ok=True)
100
+ os.chmod(self.state_root, 0o700)
101
+ target = self._binding_path(plan_id)
102
+ temporary = target.with_name(f".{target.name}.tmp")
103
+ payload = {
104
+ "schema_version": NOTIFICATION_BINDING_SCHEMA,
105
+ "plan_id": plan_id,
106
+ "digest": digest,
107
+ "org_id": actor.profile.org_id,
108
+ "actor_id": actor.actor.actor_id,
109
+ "session_id": actor.session_id,
110
+ "kind": kind,
111
+ "recipient": recipient,
112
+ "created_at": self.clock().astimezone(UTC).isoformat(),
113
+ }
114
+ temporary.write_text(json.dumps(payload, sort_keys=True) + "\n", encoding="utf-8")
115
+ os.chmod(temporary, 0o600)
116
+ temporary.replace(target)
117
+
118
+ def _binding(self, actor: ActorContext, *, plan_id: str, digest: str | None = None) -> NotificationBinding:
119
+ path = self._binding_path(plan_id)
120
+ try:
121
+ payload = json.loads(path.read_text(encoding="utf-8"))
122
+ except (OSError, ValueError) as exc:
123
+ raise NotificationError("notification plan binding is unavailable") from exc
124
+ if payload.get("schema_version") != NOTIFICATION_BINDING_SCHEMA:
125
+ raise NotificationError("notification plan binding is invalid")
126
+ if (
127
+ payload.get("org_id") != actor.profile.org_id
128
+ or payload.get("actor_id") != actor.actor.actor_id
129
+ or payload.get("session_id") != actor.session_id
130
+ ):
131
+ raise AuthorizationDenied("notification plan belongs to another actor session")
132
+ if digest is not None and payload.get("digest") != digest:
133
+ raise NotificationError("notification plan digest changed; prepare it again")
134
+ return NotificationBinding(
135
+ plan_id=plan_id,
136
+ digest=str(payload["digest"]),
137
+ org_id=str(payload["org_id"]),
138
+ actor_id=str(payload["actor_id"]),
139
+ session_id=str(payload["session_id"]),
140
+ kind=str(payload["kind"]),
141
+ recipient=str(payload["recipient"]) if payload.get("recipient") else None,
142
+ )
143
+
144
+ def plan(
145
+ self,
146
+ actor: ActorContext,
147
+ *,
148
+ kind: str,
149
+ message: str,
150
+ recipient: str | None = None,
151
+ ) -> Mapping[str, object]:
152
+ clean_kind = kind.strip().casefold()
153
+ if clean_kind not in {"group", "send"}:
154
+ raise NotificationError("notification kind must be group or send")
155
+ clean_message = message.strip()
156
+ if not clean_message:
157
+ raise NotificationError("notification message is required")
158
+ clean_recipient = recipient.strip() if recipient and recipient.strip() else None
159
+ if clean_kind == "send" and clean_recipient is None:
160
+ raise NotificationError("direct notification recipient is required")
161
+ resource = f"notification:{clean_kind}:{clean_recipient or 'organization'}"
162
+ self._authorize(actor, Permission.SHARE, resource)
163
+ plan = self.transport.plan(
164
+ kind=clean_kind,
165
+ recipient=clean_recipient,
166
+ message=clean_message,
167
+ )
168
+ self._write_binding(actor, plan, kind=clean_kind, recipient=clean_recipient)
169
+ return plan
170
+
171
+ def approve(
172
+ self,
173
+ actor: ActorContext,
174
+ *,
175
+ plan_id: str,
176
+ digest: str,
177
+ confirmation: str,
178
+ ) -> Mapping[str, object]:
179
+ if confirmation != EXACT_NOTIFICATION_CONFIRMATION:
180
+ raise NotificationError("exact notification confirmation is required")
181
+ binding = self._binding(actor, plan_id=plan_id, digest=digest)
182
+ resource = f"notification:{binding.kind}:{binding.recipient or 'organization'}"
183
+ self._authorize(actor, Permission.SHARE, resource)
184
+ approval = self.transport.approve(
185
+ plan_id=plan_id,
186
+ digest=digest,
187
+ confirmation=confirmation,
188
+ )
189
+ if approval.get("status") != "approved" or not approval.get("approval_token"):
190
+ raise NotificationError("notification transport did not approve the exact plan")
191
+ return approval
192
+
193
+ def dispatch(
194
+ self,
195
+ actor: ActorContext,
196
+ *,
197
+ plan_id: str,
198
+ approval_token: str,
199
+ ) -> Mapping[str, object]:
200
+ binding = self._binding(actor, plan_id=plan_id)
201
+ resource = f"notification:{binding.kind}:{binding.recipient or 'organization'}"
202
+ self._authorize(actor, Permission.SHARE, resource)
203
+ self._authorize(actor, Permission.EXECUTE, resource)
204
+ receipt = self.transport.dispatch(plan_id=plan_id, approval_token=approval_token)
205
+ if receipt.get("status") not in {"sent", "delivered", "partial"}:
206
+ raise NotificationError("notification dispatch did not return a delivery receipt")
207
+ self._binding_path(plan_id).unlink(missing_ok=True)
208
+ try:
209
+ self.runtime.telemetry.emit(
210
+ TelemetryEvent(
211
+ schema_version=TELEMETRY_SCHEMA_VERSION,
212
+ event_id=f"evt_{uuid4().hex}",
213
+ event_type="notification.dispatched",
214
+ occurred_at=self.clock().astimezone(UTC),
215
+ org_id=actor.profile.org_id,
216
+ actor_id=actor.actor.actor_id,
217
+ session_id=actor.session_id,
218
+ org_revision=actor.profile.revision,
219
+ metrics={"success": True, "action": binding.kind},
220
+ )
221
+ )
222
+ except Exception:
223
+ pass
224
+ return receipt
225
+
226
+ def cancel(self, actor: ActorContext, *, plan_id: str) -> Mapping[str, object]:
227
+ self._binding(actor, plan_id=plan_id)
228
+ receipt = self.transport.cancel(plan_id=plan_id)
229
+ self._binding_path(plan_id).unlink(missing_ok=True)
230
+ return receipt