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

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 +1013 -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,342 @@
1
+ """Organizational context compilation independent of harness/infrastructure."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import time
6
+ from dataclasses import dataclass, replace
7
+ from datetime import UTC, datetime
8
+ from uuid import uuid4
9
+
10
+ from .contracts import (
11
+ ActionAuthorizer,
12
+ ActorContext,
13
+ EvidenceItem,
14
+ OrgContext,
15
+ OrgContextCompiler,
16
+ Permission,
17
+ RetrievalHit,
18
+ RetrievalRequest,
19
+ Retriever,
20
+ TelemetryEvent,
21
+ TelemetrySink,
22
+ TemporalScope,
23
+ )
24
+ from .admin_gate import AdminGate
25
+ from .errors import AuthorizationDenied, ContextBudgetError
26
+ from .lifecycle import AuthorityState, CanonicalLifecycleService, LifecycleRecord
27
+ from .policy import scope_allows_path
28
+
29
+
30
+ def _token_count(content: str) -> int:
31
+ # Deterministic, dependency-free planning estimate. Harness adapters may
32
+ # supply a tokenizer later without weakening the authorization boundary.
33
+ return max(1, (len(content) + 3) // 4)
34
+
35
+
36
+ def _truncate_to_budget(content: str, budget: int) -> str:
37
+ return content[: max(0, budget * 4)]
38
+
39
+
40
+ @dataclass(slots=True)
41
+ class DefaultOrgContextCompiler(OrgContextCompiler):
42
+ authorizer: ActionAuthorizer
43
+ retriever: Retriever
44
+ telemetry: TelemetrySink
45
+ lifecycle: CanonicalLifecycleService | None = None
46
+ admin_gate: AdminGate | None = None
47
+
48
+ def observe(
49
+ self,
50
+ actor: ActorContext,
51
+ request: RetrievalRequest,
52
+ *,
53
+ token_budget: int,
54
+ ) -> OrgContext:
55
+ if token_budget <= 0:
56
+ raise ContextBudgetError("token budget must be positive")
57
+
58
+ started = time.monotonic()
59
+ decision = self.authorizer.authorize_observe(actor, request)
60
+ if not decision.allowed:
61
+ self._emit(
62
+ actor,
63
+ request,
64
+ "observe.denied",
65
+ metrics={"success": False, "failure_code": "authorization_denied"},
66
+ )
67
+ raise AuthorizationDenied("; ".join(decision.reasons))
68
+
69
+ scopes = tuple(
70
+ scope
71
+ for scope in (request.authorized_scopes or decision.scopes)
72
+ if not decision.scopes or scope_allows_path(scope, decision.scopes)
73
+ )
74
+ if not scopes:
75
+ raise AuthorizationDenied("policy produced no authorized retrieval scope")
76
+
77
+ allowed_ids = request.allowed_artifact_ids
78
+ if decision.resource_ids:
79
+ allowed_ids = tuple(
80
+ artifact_id
81
+ for artifact_id in (allowed_ids or decision.resource_ids)
82
+ if artifact_id in decision.resource_ids
83
+ )
84
+ if not allowed_ids:
85
+ raise AuthorizationDenied("policy produced no authorized artifact set")
86
+
87
+ authorized_request = replace(
88
+ request,
89
+ authorized_scopes=scopes,
90
+ allowed_artifact_ids=allowed_ids,
91
+ )
92
+ result = self.retriever.retrieve(authorized_request)
93
+
94
+ # Defense in depth: an adapter returning an out-of-scope candidate
95
+ # cannot place it in model context.
96
+ authorized_hits = tuple(
97
+ hit
98
+ for hit in result.hits
99
+ if scope_allows_path(hit.canonical_path, scopes)
100
+ and (not allowed_ids or hit.artifact_id in allowed_ids)
101
+ )
102
+
103
+ # Egregore-surface admin protection: QMD may match an admin-marked
104
+ # document internally, but for a non-admin actor it must contribute
105
+ # nothing to evidence — no title, path, snippet, count detail, or
106
+ # model context. Only an opaque withheld tally survives.
107
+ withheld_admin = 0
108
+ if self.admin_gate is not None and not self.admin_gate.actor_is_admin(actor):
109
+ visible_hits = []
110
+ for hit in authorized_hits:
111
+ if self.admin_gate.path_is_admin(hit.canonical_path):
112
+ withheld_admin += 1
113
+ else:
114
+ visible_hits.append(hit)
115
+ authorized_hits = tuple(visible_hits)
116
+
117
+ lifecycle_by_path: dict[str, LifecycleRecord] = {}
118
+ lifecycle_revision = "unavailable"
119
+ lifecycle_warning: str | None = None
120
+ if self.lifecycle is not None:
121
+ try:
122
+ resolved, lifecycle_revision = self.lifecycle.resolve_paths(
123
+ tuple(hit.canonical_path for hit in authorized_hits),
124
+ source_revision=result.source_revision,
125
+ authorized_scopes=scopes,
126
+ allowed_artifact_ids=allowed_ids,
127
+ )
128
+ lifecycle_by_path = dict(resolved)
129
+ except Exception as exc:
130
+ lifecycle_warning = f"lifecycle-unavailable:{type(exc).__name__}"
131
+
132
+ # Lifecycle events are organizational receipts, not normal answer
133
+ # evidence. Current authority is selected only after authorization and
134
+ # before any source is opened.
135
+ selected_hits: list[RetrievalHit] = []
136
+ for hit in authorized_hits:
137
+ record = lifecycle_by_path.get(hit.canonical_path)
138
+ if record is not None and record.artifact_type == "lifecycle-event":
139
+ if "lifecycle-event" not in request.artifact_types:
140
+ continue
141
+ if record is not None:
142
+ historical = record.authority_state in {
143
+ AuthorityState.SUPERSEDED,
144
+ AuthorityState.HISTORICAL,
145
+ }
146
+ if request.temporal_scope is TemporalScope.CURRENT and historical:
147
+ continue
148
+ if request.temporal_scope is TemporalScope.HISTORICAL and not historical:
149
+ continue
150
+ observed_at = hit.observed_at or (record.created_at if record is not None else None)
151
+ if request.not_before is not None:
152
+ if observed_at is None:
153
+ continue
154
+ if observed_at.tzinfo is None:
155
+ observed_at = observed_at.replace(tzinfo=UTC)
156
+ if observed_at.astimezone(UTC) < request.not_before.astimezone(UTC):
157
+ continue
158
+ selected_hits.append(hit)
159
+
160
+ selected_hits.sort(
161
+ key=lambda hit: (
162
+ 1
163
+ if lifecycle_by_path.get(hit.canonical_path)
164
+ and lifecycle_by_path[hit.canonical_path].authority_state
165
+ is AuthorityState.AMBIGUOUS
166
+ else 2
167
+ if lifecycle_by_path.get(hit.canonical_path)
168
+ and lifecycle_by_path[hit.canonical_path].authority_state
169
+ in {AuthorityState.SUPERSEDED, AuthorityState.HISTORICAL}
170
+ else 0,
171
+ hit.rank,
172
+ )
173
+ )
174
+
175
+ evidence, opened_ids, omissions, tokens_used = self._package(
176
+ tuple(selected_hits),
177
+ request,
178
+ token_budget,
179
+ lifecycle_by_path,
180
+ )
181
+ if lifecycle_warning:
182
+ omissions = (*omissions, lifecycle_warning)
183
+ if withheld_admin:
184
+ # Tag-not-hide: existence is visible, identity is not. No id,
185
+ # title, or path of the withheld documents may appear here.
186
+ omissions = (*omissions, f"[admin] {withheld_admin} admin-marked item(s) withheld")
187
+ permissions = frozenset(
188
+ permission
189
+ for permission in Permission
190
+ if self.authorizer.authorize_action(actor, permission).allowed
191
+ )
192
+ context = OrgContext(
193
+ schema_version="egregore-context/v1",
194
+ context_id=f"ctx_{uuid4().hex}",
195
+ org_id=actor.profile.org_id,
196
+ actor_id=actor.actor.actor_id,
197
+ task=request.task,
198
+ profile_revision=actor.profile.revision,
199
+ source_revision=result.source_revision,
200
+ policy_epoch=decision.policy_epoch,
201
+ evidence=evidence,
202
+ action_permissions=permissions,
203
+ token_budget=token_budget,
204
+ tokens_used=tokens_used,
205
+ omissions=omissions,
206
+ freshness={
207
+ "source_revision": result.source_revision,
208
+ "index_revision": result.index_revision,
209
+ "index_spec_version": result.index_spec_version,
210
+ "lifecycle_revision": lifecycle_revision,
211
+ "temporal_scope": request.temporal_scope.value,
212
+ "temporal_authority": "canonical-markdown",
213
+ },
214
+ )
215
+ elapsed_ms = int((time.monotonic() - started) * 1000)
216
+ self._emit(
217
+ actor,
218
+ request,
219
+ "observe.completed",
220
+ # Artifact ids retain retrieval order, so array position is the
221
+ # privacy-safe rank without creating a content-bearing map.
222
+ artifact_ids=tuple(hit.artifact_id for hit in selected_hits),
223
+ metrics={
224
+ "duration_ms": elapsed_ms,
225
+ "latency_ms": result.latency_ms,
226
+ "count": len(selected_hits),
227
+ "opened_count": len(opened_ids),
228
+ "result": "context_produced",
229
+ "token_count": tokens_used,
230
+ "retrieval_type": result.mode.value,
231
+ "success": True,
232
+ },
233
+ index_spec_version=result.index_spec_version,
234
+ )
235
+ if opened_ids:
236
+ self._emit(
237
+ actor,
238
+ request,
239
+ "source.opened",
240
+ artifact_ids=opened_ids,
241
+ metrics={"opened_count": len(opened_ids)},
242
+ index_spec_version=result.index_spec_version,
243
+ )
244
+ return context
245
+
246
+ def _package(
247
+ self,
248
+ hits: tuple[RetrievalHit, ...],
249
+ request: RetrievalRequest,
250
+ token_budget: int,
251
+ lifecycle_by_path: dict[str, LifecycleRecord] | None = None,
252
+ ) -> tuple[tuple[EvidenceItem, ...], tuple[str, ...], tuple[str, ...], int]:
253
+ evidence: list[EvidenceItem] = []
254
+ opened_ids: list[str] = []
255
+ omissions: list[str] = []
256
+ remaining = token_budget
257
+
258
+ for hit in hits:
259
+ if remaining <= 0:
260
+ omissions.append(f"budget:{hit.artifact_id}")
261
+ continue
262
+ if request.open_sources:
263
+ content = self.retriever.open_source(hit)
264
+ opened_ids.append(hit.artifact_id)
265
+ else:
266
+ content = hit.passage or ""
267
+ if not content:
268
+ omissions.append(f"empty:{hit.artifact_id}")
269
+ continue
270
+
271
+ count = _token_count(content)
272
+ if count > remaining:
273
+ content = _truncate_to_budget(content, remaining)
274
+ count = _token_count(content)
275
+ omissions.append(f"truncated:{hit.artifact_id}")
276
+ evidence.append(
277
+ EvidenceItem(
278
+ artifact_id=hit.artifact_id,
279
+ canonical_path=hit.canonical_path,
280
+ revision=hit.revision or "unknown",
281
+ reason=self._evidence_reason(
282
+ hit,
283
+ (lifecycle_by_path or {}).get(hit.canonical_path),
284
+ ),
285
+ content=content,
286
+ token_count=count,
287
+ )
288
+ )
289
+ remaining -= count
290
+
291
+ return (
292
+ tuple(evidence),
293
+ tuple(opened_ids),
294
+ tuple(omissions),
295
+ token_budget - remaining,
296
+ )
297
+
298
+ @staticmethod
299
+ def _evidence_reason(hit: RetrievalHit, lifecycle: LifecycleRecord | None) -> str:
300
+ observed_at = hit.observed_at or (lifecycle.created_at if lifecycle is not None else None)
301
+ observed = (
302
+ f"; observed={observed_at.date().isoformat()}" if observed_at is not None else ""
303
+ )
304
+ if lifecycle is None:
305
+ return f"retrieval rank {hit.rank}; temporal authority unknown{observed}"
306
+ return (
307
+ f"retrieval rank {hit.rank}; authority={lifecycle.authority_state.value}; "
308
+ f"attention={lifecycle.attention_state.value}; "
309
+ f"obligation={lifecycle.obligation_state.value}{observed}"
310
+ )
311
+
312
+ def _emit(
313
+ self,
314
+ actor: ActorContext,
315
+ request: RetrievalRequest,
316
+ event_type: str,
317
+ *,
318
+ artifact_ids: tuple[str, ...] = (),
319
+ metrics: dict[str, int | float | bool | str | None] | None = None,
320
+ index_spec_version: str | None = None,
321
+ ) -> None:
322
+ try:
323
+ self.telemetry.emit(
324
+ TelemetryEvent(
325
+ schema_version="egregore.telemetry/v1",
326
+ event_id=f"evt_{uuid4().hex}",
327
+ event_type=event_type,
328
+ occurred_at=datetime.now(UTC),
329
+ org_id=actor.profile.org_id,
330
+ actor_id=actor.actor.actor_id,
331
+ session_id=actor.session_id,
332
+ task_id=request.request_id,
333
+ org_revision=actor.profile.revision,
334
+ index_spec_version=index_spec_version,
335
+ metrics=metrics or {},
336
+ artifact_ids=artifact_ids,
337
+ )
338
+ )
339
+ except Exception:
340
+ # Telemetry is an observability projection. It cannot make a valid
341
+ # authorization/context result fail.
342
+ return
@@ -0,0 +1,290 @@
1
+ """Small resumable onboarding model and authorized state service."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+ from datetime import UTC, datetime
7
+ import json
8
+ import os
9
+ from pathlib import Path
10
+ import re
11
+ import tempfile
12
+ from typing import Any, Mapping
13
+
14
+ from .contracts import ActorContext, Permission, Serializable
15
+ from .errors import AuthorizationDenied
16
+
17
+
18
+ ONBOARDING_SCHEMA = "egregore-onboarding/v1"
19
+
20
+
21
+ @dataclass(frozen=True, slots=True)
22
+ class OnboardingStep:
23
+ step_id: str
24
+ required_fields: tuple[str, ...]
25
+ next_step: str | None = None
26
+ branches: Mapping[str, str] = field(default_factory=dict)
27
+
28
+
29
+ @dataclass(frozen=True, slots=True)
30
+ class OnboardingPlan:
31
+ schema_version: str
32
+ intent: str
33
+ org_type: str
34
+ start_step: str
35
+ steps: tuple[OnboardingStep, ...]
36
+
37
+ def step(self, step_id: str) -> OnboardingStep:
38
+ for item in self.steps:
39
+ if item.step_id == step_id:
40
+ return item
41
+ raise KeyError(step_id)
42
+
43
+ def advance(self, step_id: str, *, choice: str | None = None) -> str | None:
44
+ current = self.step(step_id)
45
+ if choice is not None and choice in current.branches:
46
+ return current.branches[choice]
47
+ return current.next_step
48
+
49
+
50
+ def onboarding_plan(*, intent: str = "collaborate", org_type: str = "team") -> OnboardingPlan:
51
+ """Return today's short flow represented as an evolvable decision tree."""
52
+
53
+ normalized_intent = intent.strip().lower() or "collaborate"
54
+ normalized_type = org_type.strip().lower() or "team"
55
+ return OnboardingPlan(
56
+ schema_version=ONBOARDING_SCHEMA,
57
+ intent=normalized_intent,
58
+ org_type=normalized_type,
59
+ start_step="identity",
60
+ steps=(
61
+ OnboardingStep("identity", ("display_name",), next_step="organization"),
62
+ OnboardingStep(
63
+ "organization",
64
+ ("org_name", "org_type", "intent"),
65
+ next_step="role",
66
+ ),
67
+ OnboardingStep("role", ("member_role",), next_step="workspace"),
68
+ OnboardingStep(
69
+ "workspace",
70
+ ("runtime",),
71
+ branches={"founder": "invite", "joiner": "complete"},
72
+ next_step="complete",
73
+ ),
74
+ OnboardingStep("invite", (), next_step="complete"),
75
+ OnboardingStep("complete", (), next_step=None),
76
+ ),
77
+ )
78
+
79
+
80
+ @dataclass(frozen=True, slots=True)
81
+ class OnboardingSnapshot(Serializable):
82
+ schema_version: str
83
+ phase: str
84
+ complete: bool
85
+ mode: str
86
+ usage_type: str
87
+ display_name: str | None
88
+ member_role: str | None
89
+ profile_fields_collected: tuple[str, ...]
90
+ invite_skipped: bool | None
91
+ installer_captured: bool
92
+ invite_handled_by: str | None
93
+ profile_witness: bool
94
+ ready: bool
95
+ blockers: tuple[str, ...]
96
+
97
+
98
+ class OnboardingService:
99
+ """Own resumable onboarding state behind ActorContext authorization."""
100
+
101
+ LEGACY_PHASES = frozenset(
102
+ {"welcome", "harvest_identity", "harvest_connection", "consent", "first_todo"}
103
+ )
104
+
105
+ def __init__(self, root: Path | str, runtime) -> None:
106
+ self.root = Path(root).resolve()
107
+ self.runtime = runtime
108
+ self.state_path = self.root / ".egregore-state.json"
109
+
110
+ def _authorize(self, actor: ActorContext, permission: Permission) -> None:
111
+ resource = f"identity:onboarding:{actor.actor.actor_id}"
112
+ decision = self.runtime.authorize(actor, permission, (resource,))
113
+ if not decision.allowed:
114
+ raise AuthorizationDenied("; ".join(decision.reasons))
115
+
116
+ def _load(self) -> dict[str, Any]:
117
+ try:
118
+ value = json.loads(self.state_path.read_text(encoding="utf-8"))
119
+ except FileNotFoundError:
120
+ value = {}
121
+ if not isinstance(value, dict):
122
+ raise ValueError("onboarding state must contain an object")
123
+ return value
124
+
125
+ def _write(self, state: Mapping[str, Any]) -> None:
126
+ target = self.state_path.resolve() if self.state_path.is_symlink() else self.state_path
127
+ target.parent.mkdir(parents=True, exist_ok=True)
128
+ descriptor, temporary = tempfile.mkstemp(prefix=f"{target.name}.", dir=target.parent)
129
+ try:
130
+ with os.fdopen(descriptor, "w", encoding="utf-8") as handle:
131
+ json.dump(dict(state), handle, ensure_ascii=False, indent=2)
132
+ handle.write("\n")
133
+ os.chmod(temporary, 0o600)
134
+ os.replace(temporary, target)
135
+ finally:
136
+ if os.path.exists(temporary):
137
+ os.unlink(temporary)
138
+
139
+ @staticmethod
140
+ def _fields(state: Mapping[str, Any]) -> list[str]:
141
+ values = state.get("profile_fields_collected") or []
142
+ return [str(value) for value in values if str(value)] if isinstance(values, list) else []
143
+
144
+ def _has_secret(self, name: str) -> bool:
145
+ if os.environ.get(name, "").strip():
146
+ return True
147
+ env_path = self.root / ".env"
148
+ if not env_path.is_file():
149
+ return False
150
+ prefix = f"{name}="
151
+ return any(
152
+ line.startswith(prefix) and bool(line[len(prefix) :].strip())
153
+ for line in env_path.read_text(encoding="utf-8").splitlines()
154
+ )
155
+
156
+ def _migrate(self, state: dict[str, Any]) -> tuple[dict[str, Any], bool]:
157
+ onboarding = dict(state.get("onboarding") or {})
158
+ phase = str(onboarding.get("phase") or "verify")
159
+ changed = False
160
+ if phase in self.LEGACY_PHASES:
161
+ onboarding["phase"] = "invite" if state.get("display_name") else "orient"
162
+ fields = self._fields(state)
163
+ if state.get("display_name") and "name" not in fields:
164
+ fields.append("name")
165
+ state["profile_fields_collected"] = fields
166
+ changed = True
167
+ if onboarding.get("schema_version") != ONBOARDING_SCHEMA:
168
+ onboarding["schema_version"] = ONBOARDING_SCHEMA
169
+ changed = True
170
+ state["onboarding"] = onboarding
171
+ return state, changed
172
+
173
+ def snapshot(self, actor: ActorContext) -> OnboardingSnapshot:
174
+ self._authorize(actor, Permission.READ)
175
+ # Reads may normalize legacy phases in the returned view, but only an
176
+ # ADMINISTER-authorized mutation is allowed to persist that migration.
177
+ state, _ = self._migrate(self._load())
178
+ config = json.loads((self.root / "egregore.json").read_text(encoding="utf-8"))
179
+ onboarding = dict(state.get("onboarding") or {})
180
+ username = str(state.get("github_username") or "")
181
+ profile = self.root / "memory" / "people" / f"{username}.md"
182
+ profile_lines = (
183
+ profile.read_text(encoding="utf-8").splitlines() if profile.is_file() else []
184
+ )
185
+ witness = bool(profile_lines) and (
186
+ profile_lines[0].startswith("# ")
187
+ or any(line.startswith("Onboarded:") for line in profile_lines)
188
+ )
189
+ connected = bool(config.get("api_url")) or config.get("mode") == "connected"
190
+ blockers: list[str] = []
191
+ if not (self.root / "memory").exists():
192
+ blockers.append("shared memory is unavailable; run the normal Egregore sync")
193
+ if not self._has_secret("GITHUB_TOKEN"):
194
+ blockers.append("GitHub authentication is missing; run bash bin/github-auth.sh")
195
+ if connected and not self._has_secret("EGREGORE_API_KEY"):
196
+ blockers.append("Connected authentication is missing")
197
+ return OnboardingSnapshot(
198
+ schema_version=ONBOARDING_SCHEMA,
199
+ phase=str(onboarding.get("phase") or "verify"),
200
+ complete=bool(state.get("onboarding_complete")),
201
+ mode=(
202
+ "connected"
203
+ if connected
204
+ else "local"
205
+ ),
206
+ usage_type=str(state.get("usage_type") or "joiner_group"),
207
+ display_name=str(state.get("display_name")) if state.get("display_name") else None,
208
+ member_role=str(state.get("member_role")) if state.get("member_role") else None,
209
+ profile_fields_collected=tuple(self._fields(state)),
210
+ invite_skipped=(
211
+ bool(onboarding["invite_skipped"])
212
+ if "invite_skipped" in onboarding else None
213
+ ),
214
+ installer_captured=bool(onboarding.get("installer_captured")),
215
+ invite_handled_by=(
216
+ str(onboarding["invite_handled_by"])
217
+ if onboarding.get("invite_handled_by") else None
218
+ ),
219
+ profile_witness=witness,
220
+ ready=not blockers,
221
+ blockers=tuple(blockers),
222
+ )
223
+
224
+ def set_name(self, actor: ActorContext, display_name: str) -> OnboardingSnapshot:
225
+ self._authorize(actor, Permission.ADMINISTER)
226
+ name = display_name.strip()
227
+ if not 1 <= len(name) <= 30 or not re.fullmatch(r"[\w -]+", name, re.UNICODE):
228
+ raise ValueError("display name must be 1-30 letters, numbers, spaces, or hyphens")
229
+ state, _ = self._migrate(self._load())
230
+ onboarding = dict(state.get("onboarding") or {})
231
+ onboarding.update(
232
+ {
233
+ "phase": "invite",
234
+ "started_at": onboarding.get("started_at")
235
+ or datetime.now(UTC).isoformat().replace("+00:00", "Z"),
236
+ }
237
+ )
238
+ fields = self._fields(state)
239
+ if "name" not in fields:
240
+ fields.append("name")
241
+ state.update(
242
+ {
243
+ "display_name": name,
244
+ "name": re.sub(r"-+", "-", re.sub(r"[^a-z0-9]+", "-", name.lower())).strip("-"),
245
+ "profile_fields_collected": fields,
246
+ "onboarding": onboarding,
247
+ }
248
+ )
249
+ self._write(state)
250
+ return self.snapshot(actor)
251
+
252
+ def set_role(self, actor: ActorContext, role: str) -> OnboardingSnapshot:
253
+ self._authorize(actor, Permission.ADMINISTER)
254
+ value = role.strip()
255
+ if not 1 <= len(value) <= 80:
256
+ raise ValueError("member role must be 1-80 characters")
257
+ state, _ = self._migrate(self._load())
258
+ fields = self._fields(state)
259
+ if "role" not in fields:
260
+ fields.append("role")
261
+ state["member_role"] = value
262
+ state["profile_fields_collected"] = fields
263
+ self._write(state)
264
+ return self.snapshot(actor)
265
+
266
+ def record_invite(self, actor: ActorContext, *, skipped: bool) -> OnboardingSnapshot:
267
+ self._authorize(actor, Permission.ADMINISTER)
268
+ state, _ = self._migrate(self._load())
269
+ onboarding = dict(state.get("onboarding") or {})
270
+ onboarding.update({"phase": "invite", "invite_skipped": skipped})
271
+ state["onboarding"] = onboarding
272
+ self._write(state)
273
+ return self.snapshot(actor)
274
+
275
+ def complete(self, actor: ActorContext, *, profile_witness: bool) -> OnboardingSnapshot:
276
+ self._authorize(actor, Permission.ADMINISTER)
277
+ if not profile_witness:
278
+ raise ValueError("canonical person profile witness is missing")
279
+ state, _ = self._migrate(self._load())
280
+ onboarding = dict(state.get("onboarding") or {})
281
+ onboarding.update(
282
+ {
283
+ "phase": "complete",
284
+ "completed_at": datetime.now(UTC).isoformat().replace("+00:00", "Z"),
285
+ }
286
+ )
287
+ state["onboarding"] = onboarding
288
+ state["onboarding_complete"] = True
289
+ self._write(state)
290
+ return self.snapshot(actor)