create-egregore 0.21.6 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (719) hide show
  1. package/assets/egregore-launcher.js +58 -6
  2. package/assets/egregore-launcher.sh +15 -2
  3. package/lib/claude-runtime.js +2 -0
  4. package/lib/codex-runtime.js +2 -0
  5. package/lib/setup.js +20 -3
  6. package/package.json +2 -2
  7. package/runtime/claude/.claude/context/commit-format.md +7 -4
  8. package/runtime/claude/.claude/context/handoff-claiming.md +32 -0
  9. package/runtime/claude/.claude/context/notification-consent.md +12 -9
  10. package/runtime/claude/.claude/hooks/boundary-check.sh +14 -331
  11. package/runtime/claude/.claude/hooks/memory-read-guard.sh +9 -1
  12. package/runtime/claude/.claude/rules/voice-bedrock.md +6 -2
  13. package/runtime/claude/.claude/settings.json +1 -1
  14. package/runtime/claude/.claude/skills/commit/SKILL.md +5 -3
  15. package/runtime/claude/.claude/skills/dark-mode/SKILL.md +48 -369
  16. package/runtime/claude/.claude/skills/records/SKILL.md +158 -0
  17. package/runtime/claude/.claude/skills/reflect/SKILL.md +50 -21
  18. package/runtime/claude/.claude/skills/review-pr/SKILL.md +4 -2
  19. package/runtime/claude/.claude/skills/save/SKILL.md +9 -3
  20. package/runtime/claude/.claude/skills/summon/SKILL.md +138 -207
  21. package/runtime/claude/.claude/skills/tui-design/SKILL.md +1 -1
  22. package/runtime/claude/.claude/skills/update/SKILL.md +1 -1
  23. package/runtime/claude/.claude/skills/view/SKILL.md +52 -16
  24. package/runtime/claude/.claude/skills/view/compose-scaffold.html +19 -13
  25. package/runtime/claude/CLAUDE.md +59 -95
  26. package/runtime/claude/bin/agent.sh +231 -7
  27. package/runtime/claude/bin/api-call.sh +44 -23
  28. package/runtime/claude/bin/artifact-register.sh +7 -1
  29. package/runtime/claude/bin/artifact-writeback.sh +1 -1
  30. package/runtime/claude/bin/artifacts.sh +66 -265
  31. package/runtime/claude/bin/attendant.sh +4 -1
  32. package/runtime/claude/bin/boundary-guard.cjs +1848 -0
  33. package/runtime/claude/bin/boundary-hook.sh +41 -0
  34. package/runtime/claude/bin/boundary.sh +15 -155
  35. package/runtime/claude/bin/capture-run.sh +32 -2
  36. package/runtime/claude/bin/codex-render-spec.mjs +24 -46
  37. package/runtime/claude/bin/codex-session-start.sh +19 -0
  38. package/runtime/claude/bin/codex-skill-render.mjs +18 -0
  39. package/runtime/claude/bin/config-get.sh +10 -1
  40. package/runtime/claude/bin/connect-refresh.sh +16 -0
  41. package/runtime/claude/bin/corpus_map.py +5 -0
  42. package/runtime/claude/bin/data/capabilities/claude.json +1480 -0
  43. package/runtime/claude/bin/genui.sh +19 -0
  44. package/runtime/claude/bin/graph-batch.sh +1 -1
  45. package/runtime/claude/bin/graph-op.sh +14 -0
  46. package/runtime/claude/bin/graph.sh +1 -1
  47. package/runtime/claude/bin/handoff-pr-backfill.sh +1 -1
  48. package/runtime/claude/bin/handoff-run.sh +11 -6
  49. package/runtime/claude/bin/ingest-item.sh +1 -1
  50. package/runtime/claude/bin/ingest-surface.html +22 -4
  51. package/runtime/claude/bin/issue.sh +1 -1
  52. package/runtime/claude/bin/knowledge.sh +1 -1
  53. package/runtime/claude/bin/lib/card-delivery.sh +329 -0
  54. package/runtime/claude/bin/lib/config.sh +148 -3
  55. package/runtime/claude/bin/lib/context.sh +38 -67
  56. package/runtime/claude/bin/lib/genui-entry.py +36 -0
  57. package/runtime/claude/bin/lib/git-message.sh +25 -6
  58. package/runtime/claude/bin/lib/git-sync.sh +12 -4
  59. package/runtime/claude/bin/lib/greeting.sh +255 -28
  60. package/runtime/claude/bin/lib/handoff_meta.py +294 -0
  61. package/runtime/claude/bin/lib/health-footer.sh +83 -2
  62. package/runtime/claude/bin/lib/identity.sh +31 -10
  63. package/runtime/claude/bin/lib/instance-registry.sh +71 -0
  64. package/runtime/claude/bin/lib/local_ci_receipt.py +249 -0
  65. package/runtime/claude/bin/lib/metrics.sh +121 -8
  66. package/runtime/claude/bin/lib/notices.sh +36 -0
  67. package/runtime/claude/bin/lib/record_outcomes.py +729 -0
  68. package/runtime/claude/bin/lib/reflexes.py +267 -0
  69. package/runtime/claude/bin/lib/retrieval_scorecard.py +624 -0
  70. package/runtime/claude/bin/lib/session-record-prompt.txt +18 -0
  71. package/runtime/claude/bin/lib/session_record.py +3747 -0
  72. package/runtime/claude/bin/lib/session_trail.py +1983 -0
  73. package/runtime/claude/bin/lib/settings-drift.sh +8 -5
  74. package/runtime/claude/bin/lib/startup-restart.sh +41 -0
  75. package/runtime/claude/bin/lib/worktree-links.sh +92 -0
  76. package/runtime/claude/bin/memory-push.sh +6 -0
  77. package/runtime/claude/bin/merge-gate.sh +498 -0
  78. package/runtime/claude/bin/notify.sh +5 -2
  79. package/runtime/claude/bin/page-access.sh +103 -0
  80. package/runtime/claude/bin/person.sh +13 -2
  81. package/runtime/claude/bin/pi-render-spec.mjs +0 -1
  82. package/runtime/claude/bin/pi-spirit-discovery.mjs +34 -0
  83. package/runtime/claude/bin/post-update.sh +181 -0
  84. package/runtime/claude/bin/prime-render-spec.mjs +0 -1
  85. package/runtime/claude/bin/publish-artifact.sh +89 -42
  86. package/runtime/claude/bin/qa-inventory.sh +2 -2
  87. package/runtime/claude/bin/quest.sh +1 -1
  88. package/runtime/claude/bin/records.sh +11 -0
  89. package/runtime/claude/bin/reflexes/05-vitals.sh +9 -0
  90. package/runtime/claude/bin/reflexes/10-open-items.sh +12 -0
  91. package/runtime/claude/bin/reflexes/15-retrieval.sh +8 -0
  92. package/runtime/claude/bin/reflexes/20-nightly.sh +100 -0
  93. package/runtime/claude/bin/reflexes/20-sandbox.sh +85 -0
  94. package/runtime/claude/bin/reflexes/30-cost.py +116 -0
  95. package/runtime/claude/bin/reflexes/40-shells.py +51 -0
  96. package/runtime/claude/bin/reflexes/README.md +61 -0
  97. package/runtime/claude/bin/reflexes.sh +7 -0
  98. package/runtime/claude/bin/runtime-identity.sh +140 -42
  99. package/runtime/claude/bin/screenshot.sh +77 -0
  100. package/runtime/claude/bin/scroll.sh +1 -1
  101. package/runtime/claude/bin/search.sh +31 -5
  102. package/runtime/claude/bin/session-autosave.sh +6 -3
  103. package/runtime/claude/bin/session-id.sh +147 -0
  104. package/runtime/claude/bin/session-log.sh +19 -0
  105. package/runtime/claude/bin/session-record.sh +26 -0
  106. package/runtime/claude/bin/session-start.sh +121 -151
  107. package/runtime/claude/bin/settings.sh +13 -8
  108. package/runtime/claude/bin/spirit-discovery-claude.sh +4 -0
  109. package/runtime/claude/bin/spirit-discovery-codex.sh +4 -0
  110. package/runtime/claude/bin/spirit-discovery-pi.sh +4 -0
  111. package/runtime/claude/bin/spirit-discovery-prime.sh +4 -0
  112. package/runtime/claude/bin/spirit-discovery.sh +4 -0
  113. package/runtime/claude/bin/startup-check.sh +1 -1
  114. package/runtime/claude/bin/telemetry.sh +11 -4
  115. package/runtime/claude/bin/test-baseline.sh +33 -5
  116. package/runtime/claude/bin/todo.sh +1 -1
  117. package/runtime/claude/bin/worktree-create.sh +15 -45
  118. package/runtime/claude/bin/worktree.sh +6 -0
  119. package/runtime/claude/docs/spirit-discovery.md +96 -0
  120. package/runtime/claude/egregore_runtime/__init__.py +18 -12
  121. package/runtime/claude/egregore_runtime/access.py +608 -0
  122. package/runtime/claude/egregore_runtime/access_cli.py +190 -0
  123. package/runtime/claude/egregore_runtime/adapters/invitation.py +5 -3
  124. package/runtime/claude/egregore_runtime/adapters/qmd.py +521 -47
  125. package/runtime/claude/egregore_runtime/admin_entry.py +56 -0
  126. package/runtime/claude/egregore_runtime/artifacts.py +222 -16
  127. package/runtime/claude/egregore_runtime/contracts.py +27 -0
  128. package/runtime/claude/egregore_runtime/eligibility.py +5 -12
  129. package/runtime/claude/egregore_runtime/episode_binding.py +16 -5
  130. package/runtime/claude/egregore_runtime/github_issues.py +2 -2
  131. package/runtime/claude/egregore_runtime/handoff_lookup.py +9 -20
  132. package/runtime/claude/egregore_runtime/harness_cli.py +674 -149
  133. package/runtime/claude/egregore_runtime/held.py +2436 -0
  134. package/runtime/claude/egregore_runtime/hosted_api.py +137 -0
  135. package/runtime/claude/egregore_runtime/identity.py +196 -65
  136. package/runtime/claude/egregore_runtime/identity_transfer.py +6 -2
  137. package/runtime/claude/egregore_runtime/ingest_cli.py +2 -2
  138. package/runtime/claude/egregore_runtime/ingest_index_cli.py +4 -16
  139. package/runtime/claude/egregore_runtime/installation.py +119 -0
  140. package/runtime/claude/egregore_runtime/investigation.py +64 -41
  141. package/runtime/claude/egregore_runtime/investigation_guidance.py +16 -11
  142. package/runtime/claude/egregore_runtime/issue_cli.py +51 -32
  143. package/runtime/claude/egregore_runtime/issue_reporting.py +4 -3
  144. package/runtime/claude/egregore_runtime/issue_triage_service.py +2 -2
  145. package/runtime/claude/egregore_runtime/issues.py +12 -6
  146. package/runtime/claude/egregore_runtime/knowledge.py +331 -5
  147. package/runtime/claude/egregore_runtime/knowledge_cli.py +57 -17
  148. package/runtime/claude/egregore_runtime/lifecycle.py +88 -22
  149. package/runtime/claude/egregore_runtime/lifecycle_cli.py +21 -13
  150. package/runtime/claude/egregore_runtime/line_ids.py +10 -0
  151. package/runtime/claude/egregore_runtime/memory_push.py +349 -0
  152. package/runtime/claude/egregore_runtime/observe.py +64 -25
  153. package/runtime/claude/egregore_runtime/observers.py +19 -0
  154. package/runtime/claude/egregore_runtime/optional_modules.py +13 -0
  155. package/runtime/claude/egregore_runtime/outputs_cli.py +321 -0
  156. package/runtime/claude/egregore_runtime/policy.py +651 -24
  157. package/runtime/claude/egregore_runtime/private_result.py +2 -1
  158. package/runtime/claude/egregore_runtime/projection.py +946 -0
  159. package/runtime/claude/egregore_runtime/quest_cli.py +20 -23
  160. package/runtime/claude/egregore_runtime/question_cli.py +15 -11
  161. package/runtime/claude/egregore_runtime/questions.py +10 -10
  162. package/runtime/claude/egregore_runtime/quests.py +10 -10
  163. package/runtime/claude/egregore_runtime/record_publish.py +548 -0
  164. package/runtime/claude/egregore_runtime/record_subject.py +564 -0
  165. package/runtime/claude/egregore_runtime/research_ingest.py +2 -4
  166. package/runtime/claude/egregore_runtime/runtime.py +169 -60
  167. package/runtime/claude/egregore_runtime/sandbox.py +194 -0
  168. package/runtime/claude/egregore_runtime/scroll_cli.py +22 -32
  169. package/runtime/claude/egregore_runtime/scrolls.py +23 -15
  170. package/runtime/claude/egregore_runtime/shadow.py +262 -0
  171. package/runtime/claude/egregore_runtime/spirit_discovery.py +487 -0
  172. package/runtime/claude/egregore_runtime/spirit_discovery_cli.py +25 -0
  173. package/runtime/claude/egregore_runtime/spirit_discovery_transport.py +18 -0
  174. package/runtime/claude/egregore_runtime/status.py +101 -44
  175. package/runtime/claude/egregore_runtime/status_cli.py +13 -5
  176. package/runtime/claude/egregore_runtime/sync.py +39 -21
  177. package/runtime/claude/egregore_runtime/taste.py +934 -0
  178. package/runtime/claude/egregore_runtime/taste_cli.py +242 -0
  179. package/runtime/claude/egregore_runtime/taste_rules.py +91 -0
  180. package/runtime/claude/egregore_runtime/telemetry.py +26 -3
  181. package/runtime/claude/egregore_runtime/todo_cli.py +15 -12
  182. package/runtime/claude/egregore_runtime/todos.py +3 -2
  183. package/runtime/claude/egregore_runtime/upgrade.py +85 -58
  184. package/runtime/claude/egregore_runtime/writeback.py +330 -24
  185. package/runtime/claude/manifest.json +65 -5
  186. package/runtime/codex/.claude/context/handoff-claiming.md +32 -0
  187. package/runtime/codex/.claude/context/notification-consent.md +12 -9
  188. package/runtime/codex/.claude/skills/view/SKILL.md +438 -0
  189. package/runtime/codex/.codex/hooks.json +11 -0
  190. package/runtime/codex/.codex/skills/dark-mode/SKILL.md +1 -1
  191. package/runtime/codex/.codex/skills/records/SKILL.md +29 -0
  192. package/runtime/codex/.codex/skills/summon/SKILL.md +1 -1
  193. package/runtime/codex/.codex/skills/view/assets/compose-scaffold.html +19 -13
  194. package/runtime/codex/.codex/spec-manifest.json +13 -19
  195. package/runtime/codex/AGENTS.md +54 -105
  196. package/runtime/codex/bin/agent.sh +231 -7
  197. package/runtime/codex/bin/api-call.sh +44 -23
  198. package/runtime/codex/bin/artifact-register.sh +7 -1
  199. package/runtime/codex/bin/artifact-writeback.sh +1 -1
  200. package/runtime/codex/bin/artifacts.sh +66 -265
  201. package/runtime/codex/bin/attendant.sh +4 -1
  202. package/runtime/codex/bin/boundary-guard.cjs +1848 -0
  203. package/runtime/codex/bin/boundary-hook.sh +41 -0
  204. package/runtime/codex/bin/capture-run.sh +32 -2
  205. package/runtime/codex/bin/codex-render-spec.mjs +24 -46
  206. package/runtime/codex/bin/codex-session-start.sh +19 -0
  207. package/runtime/codex/bin/codex-skill-render.mjs +18 -0
  208. package/runtime/codex/bin/config-get.sh +10 -1
  209. package/runtime/codex/bin/connect-refresh.sh +16 -0
  210. package/runtime/codex/bin/corpus_map.py +5 -0
  211. package/runtime/codex/bin/data/capabilities/codex.json +1458 -0
  212. package/runtime/codex/bin/genui.sh +19 -0
  213. package/runtime/codex/bin/graph-batch.sh +1 -1
  214. package/runtime/codex/bin/graph-op.sh +14 -0
  215. package/runtime/codex/bin/graph.sh +1 -1
  216. package/runtime/codex/bin/handoff-pr-backfill.sh +1 -1
  217. package/runtime/codex/bin/handoff-run.sh +11 -6
  218. package/runtime/codex/bin/ingest-item.sh +1 -1
  219. package/runtime/codex/bin/ingest-surface.html +22 -4
  220. package/runtime/codex/bin/issue.sh +1 -1
  221. package/runtime/codex/bin/knowledge.sh +1 -1
  222. package/runtime/codex/bin/lib/card-delivery.sh +329 -0
  223. package/runtime/codex/bin/lib/config.sh +148 -3
  224. package/runtime/codex/bin/lib/context.sh +38 -67
  225. package/runtime/codex/bin/lib/genui-entry.py +36 -0
  226. package/runtime/codex/bin/lib/git-message.sh +25 -6
  227. package/runtime/codex/bin/lib/git-sync.sh +12 -4
  228. package/runtime/codex/bin/lib/greeting.sh +255 -28
  229. package/runtime/codex/bin/lib/handoff_meta.py +294 -0
  230. package/runtime/codex/bin/lib/health-footer.sh +83 -2
  231. package/runtime/codex/bin/lib/identity.sh +31 -10
  232. package/runtime/codex/bin/lib/instance-registry.sh +71 -0
  233. package/runtime/codex/bin/lib/local_ci_receipt.py +249 -0
  234. package/runtime/codex/bin/lib/metrics.sh +121 -8
  235. package/runtime/codex/bin/lib/notices.sh +36 -0
  236. package/runtime/codex/bin/lib/record_outcomes.py +729 -0
  237. package/runtime/codex/bin/lib/reflexes.py +267 -0
  238. package/runtime/codex/bin/lib/retrieval_scorecard.py +624 -0
  239. package/runtime/codex/bin/lib/session-record-prompt.txt +18 -0
  240. package/runtime/codex/bin/lib/session_record.py +3747 -0
  241. package/runtime/codex/bin/lib/session_trail.py +1983 -0
  242. package/runtime/codex/bin/lib/settings-drift.sh +8 -5
  243. package/runtime/codex/bin/lib/startup-restart.sh +41 -0
  244. package/runtime/codex/bin/lib/worktree-links.sh +92 -0
  245. package/runtime/codex/bin/memory-push.sh +6 -0
  246. package/runtime/codex/bin/merge-gate.sh +498 -0
  247. package/runtime/codex/bin/notify.sh +5 -2
  248. package/runtime/codex/bin/page-access.sh +103 -0
  249. package/runtime/codex/bin/person.sh +13 -2
  250. package/runtime/codex/bin/pi-render-spec.mjs +0 -1
  251. package/runtime/codex/bin/pi-spirit-discovery.mjs +34 -0
  252. package/runtime/codex/bin/post-update.sh +181 -0
  253. package/runtime/codex/bin/prime-render-spec.mjs +0 -1
  254. package/runtime/codex/bin/publish-artifact.sh +89 -42
  255. package/runtime/codex/bin/qa-inventory.sh +2 -2
  256. package/runtime/codex/bin/quest.sh +1 -1
  257. package/runtime/codex/bin/records.sh +11 -0
  258. package/runtime/codex/bin/reflexes/05-vitals.sh +9 -0
  259. package/runtime/codex/bin/reflexes/10-open-items.sh +12 -0
  260. package/runtime/codex/bin/reflexes/15-retrieval.sh +8 -0
  261. package/runtime/codex/bin/reflexes/20-nightly.sh +100 -0
  262. package/runtime/codex/bin/reflexes/20-sandbox.sh +85 -0
  263. package/runtime/codex/bin/reflexes/30-cost.py +116 -0
  264. package/runtime/codex/bin/reflexes/40-shells.py +51 -0
  265. package/runtime/codex/bin/reflexes/README.md +61 -0
  266. package/runtime/codex/bin/reflexes.sh +7 -0
  267. package/runtime/codex/bin/runtime-identity.sh +140 -42
  268. package/runtime/codex/bin/screenshot.sh +77 -0
  269. package/runtime/codex/bin/scroll.sh +1 -1
  270. package/runtime/codex/bin/search.sh +31 -5
  271. package/runtime/codex/bin/session-autosave.sh +6 -3
  272. package/runtime/codex/bin/session-id.sh +147 -0
  273. package/runtime/codex/bin/session-log.sh +19 -0
  274. package/runtime/codex/bin/session-record.sh +26 -0
  275. package/runtime/codex/bin/settings.sh +13 -8
  276. package/runtime/codex/bin/spirit-discovery-claude.sh +4 -0
  277. package/runtime/codex/bin/spirit-discovery-codex.sh +4 -0
  278. package/runtime/codex/bin/spirit-discovery-pi.sh +4 -0
  279. package/runtime/codex/bin/spirit-discovery-prime.sh +4 -0
  280. package/runtime/codex/bin/spirit-discovery.sh +4 -0
  281. package/runtime/codex/bin/startup-check.sh +1 -1
  282. package/runtime/codex/bin/telemetry.sh +11 -4
  283. package/runtime/codex/bin/test-baseline.sh +33 -5
  284. package/runtime/codex/bin/todo.sh +1 -1
  285. package/runtime/codex/bin/worktree-create.sh +15 -45
  286. package/runtime/codex/bin/worktree.sh +6 -0
  287. package/runtime/codex/docs/spirit-discovery.md +96 -0
  288. package/runtime/codex/egregore_runtime/__init__.py +18 -12
  289. package/runtime/codex/egregore_runtime/access.py +608 -0
  290. package/runtime/codex/egregore_runtime/access_cli.py +190 -0
  291. package/runtime/codex/egregore_runtime/adapters/invitation.py +5 -3
  292. package/runtime/codex/egregore_runtime/adapters/qmd.py +521 -47
  293. package/runtime/codex/egregore_runtime/admin_entry.py +56 -0
  294. package/runtime/codex/egregore_runtime/artifacts.py +222 -16
  295. package/runtime/codex/egregore_runtime/contracts.py +27 -0
  296. package/runtime/codex/egregore_runtime/eligibility.py +5 -12
  297. package/runtime/codex/egregore_runtime/episode_binding.py +16 -5
  298. package/runtime/codex/egregore_runtime/github_issues.py +2 -2
  299. package/runtime/codex/egregore_runtime/handoff_lookup.py +9 -20
  300. package/runtime/codex/egregore_runtime/harness_cli.py +674 -149
  301. package/runtime/codex/egregore_runtime/held.py +2436 -0
  302. package/runtime/codex/egregore_runtime/hosted_api.py +137 -0
  303. package/runtime/codex/egregore_runtime/identity.py +196 -65
  304. package/runtime/codex/egregore_runtime/identity_transfer.py +6 -2
  305. package/runtime/codex/egregore_runtime/ingest_cli.py +2 -2
  306. package/runtime/codex/egregore_runtime/ingest_index_cli.py +4 -16
  307. package/runtime/codex/egregore_runtime/installation.py +119 -0
  308. package/runtime/codex/egregore_runtime/investigation.py +64 -41
  309. package/runtime/codex/egregore_runtime/investigation_guidance.py +16 -11
  310. package/runtime/codex/egregore_runtime/issue_cli.py +51 -32
  311. package/runtime/codex/egregore_runtime/issue_reporting.py +4 -3
  312. package/runtime/codex/egregore_runtime/issue_triage_service.py +2 -2
  313. package/runtime/codex/egregore_runtime/issues.py +12 -6
  314. package/runtime/codex/egregore_runtime/knowledge.py +331 -5
  315. package/runtime/codex/egregore_runtime/knowledge_cli.py +57 -17
  316. package/runtime/codex/egregore_runtime/lifecycle.py +88 -22
  317. package/runtime/codex/egregore_runtime/lifecycle_cli.py +21 -13
  318. package/runtime/codex/egregore_runtime/line_ids.py +10 -0
  319. package/runtime/codex/egregore_runtime/memory_push.py +349 -0
  320. package/runtime/codex/egregore_runtime/observe.py +64 -25
  321. package/runtime/codex/egregore_runtime/observers.py +19 -0
  322. package/runtime/codex/egregore_runtime/optional_modules.py +13 -0
  323. package/runtime/codex/egregore_runtime/outputs_cli.py +321 -0
  324. package/runtime/codex/egregore_runtime/policy.py +651 -24
  325. package/runtime/codex/egregore_runtime/private_result.py +2 -1
  326. package/runtime/codex/egregore_runtime/projection.py +946 -0
  327. package/runtime/codex/egregore_runtime/quest_cli.py +20 -23
  328. package/runtime/codex/egregore_runtime/question_cli.py +15 -11
  329. package/runtime/codex/egregore_runtime/questions.py +10 -10
  330. package/runtime/codex/egregore_runtime/quests.py +10 -10
  331. package/runtime/codex/egregore_runtime/record_publish.py +548 -0
  332. package/runtime/codex/egregore_runtime/record_subject.py +564 -0
  333. package/runtime/codex/egregore_runtime/research_ingest.py +2 -4
  334. package/runtime/codex/egregore_runtime/runtime.py +169 -60
  335. package/runtime/codex/egregore_runtime/sandbox.py +194 -0
  336. package/runtime/codex/egregore_runtime/scroll_cli.py +22 -32
  337. package/runtime/codex/egregore_runtime/scrolls.py +23 -15
  338. package/runtime/codex/egregore_runtime/shadow.py +262 -0
  339. package/runtime/codex/egregore_runtime/spirit_discovery.py +487 -0
  340. package/runtime/codex/egregore_runtime/spirit_discovery_cli.py +25 -0
  341. package/runtime/codex/egregore_runtime/spirit_discovery_transport.py +18 -0
  342. package/runtime/codex/egregore_runtime/status.py +101 -44
  343. package/runtime/codex/egregore_runtime/status_cli.py +13 -5
  344. package/runtime/codex/egregore_runtime/sync.py +39 -21
  345. package/runtime/codex/egregore_runtime/taste.py +934 -0
  346. package/runtime/codex/egregore_runtime/taste_cli.py +242 -0
  347. package/runtime/codex/egregore_runtime/taste_rules.py +91 -0
  348. package/runtime/codex/egregore_runtime/telemetry.py +26 -3
  349. package/runtime/codex/egregore_runtime/todo_cli.py +15 -12
  350. package/runtime/codex/egregore_runtime/todos.py +3 -2
  351. package/runtime/codex/egregore_runtime/upgrade.py +85 -58
  352. package/runtime/codex/egregore_runtime/writeback.py +330 -24
  353. package/runtime/codex/manifest.json +66 -5
  354. package/runtime/pi/.claude/context/handoff-claiming.md +32 -0
  355. package/runtime/pi/.claude/context/notification-consent.md +12 -9
  356. package/runtime/pi/.claude/skills/view/SKILL.md +438 -0
  357. package/runtime/pi/.codex/hooks.json +11 -0
  358. package/runtime/pi/.codex/skills/dark-mode/SKILL.md +1 -1
  359. package/runtime/pi/.codex/skills/records/SKILL.md +29 -0
  360. package/runtime/pi/.codex/skills/summon/SKILL.md +1 -1
  361. package/runtime/pi/.codex/skills/view/assets/compose-scaffold.html +19 -13
  362. package/runtime/pi/.codex/spec-manifest.json +13 -19
  363. package/runtime/pi/.pi/APPEND_SYSTEM.md +53 -99
  364. package/runtime/pi/.pi/extensions/egregore.ts +13 -1
  365. package/runtime/pi/.pi/spec-manifest.json +2 -2
  366. package/runtime/pi/AGENTS.md +54 -105
  367. package/runtime/pi/bin/agent.sh +231 -7
  368. package/runtime/pi/bin/api-call.sh +44 -23
  369. package/runtime/pi/bin/artifact-register.sh +7 -1
  370. package/runtime/pi/bin/artifact-writeback.sh +1 -1
  371. package/runtime/pi/bin/artifacts.sh +66 -265
  372. package/runtime/pi/bin/attendant.sh +4 -1
  373. package/runtime/pi/bin/boundary-guard.cjs +1848 -0
  374. package/runtime/pi/bin/boundary-hook.sh +41 -0
  375. package/runtime/pi/bin/capture-run.sh +32 -2
  376. package/runtime/pi/bin/codex-render-spec.mjs +24 -46
  377. package/runtime/pi/bin/codex-session-start.sh +19 -0
  378. package/runtime/pi/bin/codex-skill-render.mjs +18 -0
  379. package/runtime/pi/bin/config-get.sh +10 -1
  380. package/runtime/pi/bin/connect-refresh.sh +16 -0
  381. package/runtime/pi/bin/corpus_map.py +5 -0
  382. package/runtime/pi/bin/data/capabilities/pi.json +1458 -0
  383. package/runtime/pi/bin/genui.sh +19 -0
  384. package/runtime/pi/bin/graph-batch.sh +1 -1
  385. package/runtime/pi/bin/graph-op.sh +14 -0
  386. package/runtime/pi/bin/graph.sh +1 -1
  387. package/runtime/pi/bin/handoff-pr-backfill.sh +1 -1
  388. package/runtime/pi/bin/handoff-run.sh +11 -6
  389. package/runtime/pi/bin/ingest-item.sh +1 -1
  390. package/runtime/pi/bin/ingest-surface.html +22 -4
  391. package/runtime/pi/bin/issue.sh +1 -1
  392. package/runtime/pi/bin/knowledge.sh +1 -1
  393. package/runtime/pi/bin/lib/card-delivery.sh +329 -0
  394. package/runtime/pi/bin/lib/config.sh +148 -3
  395. package/runtime/pi/bin/lib/context.sh +38 -67
  396. package/runtime/pi/bin/lib/genui-entry.py +36 -0
  397. package/runtime/pi/bin/lib/git-message.sh +25 -6
  398. package/runtime/pi/bin/lib/git-sync.sh +12 -4
  399. package/runtime/pi/bin/lib/greeting.sh +255 -28
  400. package/runtime/pi/bin/lib/handoff_meta.py +294 -0
  401. package/runtime/pi/bin/lib/health-footer.sh +83 -2
  402. package/runtime/pi/bin/lib/identity.sh +31 -10
  403. package/runtime/pi/bin/lib/instance-registry.sh +71 -0
  404. package/runtime/pi/bin/lib/local_ci_receipt.py +249 -0
  405. package/runtime/pi/bin/lib/metrics.sh +121 -8
  406. package/runtime/pi/bin/lib/notices.sh +36 -0
  407. package/runtime/pi/bin/lib/record_outcomes.py +729 -0
  408. package/runtime/pi/bin/lib/reflexes.py +267 -0
  409. package/runtime/pi/bin/lib/retrieval_scorecard.py +624 -0
  410. package/runtime/pi/bin/lib/session-record-prompt.txt +18 -0
  411. package/runtime/pi/bin/lib/session_record.py +3747 -0
  412. package/runtime/pi/bin/lib/session_trail.py +1983 -0
  413. package/runtime/pi/bin/lib/settings-drift.sh +8 -5
  414. package/runtime/pi/bin/lib/startup-restart.sh +41 -0
  415. package/runtime/pi/bin/lib/worktree-links.sh +92 -0
  416. package/runtime/pi/bin/memory-push.sh +6 -0
  417. package/runtime/pi/bin/merge-gate.sh +498 -0
  418. package/runtime/pi/bin/notify.sh +5 -2
  419. package/runtime/pi/bin/page-access.sh +103 -0
  420. package/runtime/pi/bin/person.sh +13 -2
  421. package/runtime/pi/bin/pi-branch-policy.mjs +37 -0
  422. package/runtime/pi/bin/pi-observe-context.mjs +97 -4
  423. package/runtime/pi/bin/pi-render-spec.mjs +0 -1
  424. package/runtime/pi/bin/pi-session-start.sh +4 -1
  425. package/runtime/pi/bin/pi-spirit-discovery.mjs +34 -0
  426. package/runtime/pi/bin/post-update.sh +181 -0
  427. package/runtime/pi/bin/prime-render-spec.mjs +0 -1
  428. package/runtime/pi/bin/publish-artifact.sh +89 -42
  429. package/runtime/pi/bin/qa-inventory.sh +2 -2
  430. package/runtime/pi/bin/quest.sh +1 -1
  431. package/runtime/pi/bin/records.sh +11 -0
  432. package/runtime/pi/bin/reflexes/05-vitals.sh +9 -0
  433. package/runtime/pi/bin/reflexes/10-open-items.sh +12 -0
  434. package/runtime/pi/bin/reflexes/15-retrieval.sh +8 -0
  435. package/runtime/pi/bin/reflexes/20-nightly.sh +100 -0
  436. package/runtime/pi/bin/reflexes/20-sandbox.sh +85 -0
  437. package/runtime/pi/bin/reflexes/30-cost.py +116 -0
  438. package/runtime/pi/bin/reflexes/40-shells.py +51 -0
  439. package/runtime/pi/bin/reflexes/README.md +61 -0
  440. package/runtime/pi/bin/reflexes.sh +7 -0
  441. package/runtime/pi/bin/runtime-identity.sh +140 -42
  442. package/runtime/pi/bin/screenshot.sh +77 -0
  443. package/runtime/pi/bin/scroll.sh +1 -1
  444. package/runtime/pi/bin/search.sh +31 -5
  445. package/runtime/pi/bin/session-autosave.sh +6 -3
  446. package/runtime/pi/bin/session-id.sh +147 -0
  447. package/runtime/pi/bin/session-log.sh +19 -0
  448. package/runtime/pi/bin/session-record.sh +26 -0
  449. package/runtime/pi/bin/settings.sh +13 -8
  450. package/runtime/pi/bin/spirit-discovery-claude.sh +4 -0
  451. package/runtime/pi/bin/spirit-discovery-codex.sh +4 -0
  452. package/runtime/pi/bin/spirit-discovery-pi.sh +4 -0
  453. package/runtime/pi/bin/spirit-discovery-prime.sh +4 -0
  454. package/runtime/pi/bin/spirit-discovery.sh +4 -0
  455. package/runtime/pi/bin/startup-check.sh +1 -1
  456. package/runtime/pi/bin/telemetry.sh +11 -4
  457. package/runtime/pi/bin/test-baseline.sh +33 -5
  458. package/runtime/pi/bin/todo.sh +1 -1
  459. package/runtime/pi/bin/worktree-create.sh +15 -45
  460. package/runtime/pi/bin/worktree.sh +6 -0
  461. package/runtime/pi/docs/spirit-discovery.md +96 -0
  462. package/runtime/pi/egregore_runtime/__init__.py +18 -12
  463. package/runtime/pi/egregore_runtime/access.py +608 -0
  464. package/runtime/pi/egregore_runtime/access_cli.py +190 -0
  465. package/runtime/pi/egregore_runtime/adapters/invitation.py +5 -3
  466. package/runtime/pi/egregore_runtime/adapters/qmd.py +521 -47
  467. package/runtime/pi/egregore_runtime/admin_entry.py +56 -0
  468. package/runtime/pi/egregore_runtime/artifacts.py +222 -16
  469. package/runtime/pi/egregore_runtime/contracts.py +27 -0
  470. package/runtime/pi/egregore_runtime/eligibility.py +5 -12
  471. package/runtime/pi/egregore_runtime/episode_binding.py +16 -5
  472. package/runtime/pi/egregore_runtime/github_issues.py +2 -2
  473. package/runtime/pi/egregore_runtime/handoff_lookup.py +9 -20
  474. package/runtime/pi/egregore_runtime/harness_cli.py +674 -149
  475. package/runtime/pi/egregore_runtime/held.py +2436 -0
  476. package/runtime/pi/egregore_runtime/hosted_api.py +137 -0
  477. package/runtime/pi/egregore_runtime/identity.py +196 -65
  478. package/runtime/pi/egregore_runtime/identity_transfer.py +6 -2
  479. package/runtime/pi/egregore_runtime/ingest_cli.py +2 -2
  480. package/runtime/pi/egregore_runtime/ingest_index_cli.py +4 -16
  481. package/runtime/pi/egregore_runtime/installation.py +119 -0
  482. package/runtime/pi/egregore_runtime/investigation.py +64 -41
  483. package/runtime/pi/egregore_runtime/investigation_guidance.py +16 -11
  484. package/runtime/pi/egregore_runtime/issue_cli.py +51 -32
  485. package/runtime/pi/egregore_runtime/issue_reporting.py +4 -3
  486. package/runtime/pi/egregore_runtime/issue_triage_service.py +2 -2
  487. package/runtime/pi/egregore_runtime/issues.py +12 -6
  488. package/runtime/pi/egregore_runtime/knowledge.py +331 -5
  489. package/runtime/pi/egregore_runtime/knowledge_cli.py +57 -17
  490. package/runtime/pi/egregore_runtime/lifecycle.py +88 -22
  491. package/runtime/pi/egregore_runtime/lifecycle_cli.py +21 -13
  492. package/runtime/pi/egregore_runtime/line_ids.py +10 -0
  493. package/runtime/pi/egregore_runtime/memory_push.py +349 -0
  494. package/runtime/pi/egregore_runtime/observe.py +64 -25
  495. package/runtime/pi/egregore_runtime/observers.py +19 -0
  496. package/runtime/pi/egregore_runtime/optional_modules.py +13 -0
  497. package/runtime/pi/egregore_runtime/outputs_cli.py +321 -0
  498. package/runtime/pi/egregore_runtime/policy.py +651 -24
  499. package/runtime/pi/egregore_runtime/private_result.py +2 -1
  500. package/runtime/pi/egregore_runtime/projection.py +946 -0
  501. package/runtime/pi/egregore_runtime/quest_cli.py +20 -23
  502. package/runtime/pi/egregore_runtime/question_cli.py +15 -11
  503. package/runtime/pi/egregore_runtime/questions.py +10 -10
  504. package/runtime/pi/egregore_runtime/quests.py +10 -10
  505. package/runtime/pi/egregore_runtime/record_publish.py +548 -0
  506. package/runtime/pi/egregore_runtime/record_subject.py +564 -0
  507. package/runtime/pi/egregore_runtime/research_ingest.py +2 -4
  508. package/runtime/pi/egregore_runtime/runtime.py +169 -60
  509. package/runtime/pi/egregore_runtime/sandbox.py +194 -0
  510. package/runtime/pi/egregore_runtime/scroll_cli.py +22 -32
  511. package/runtime/pi/egregore_runtime/scrolls.py +23 -15
  512. package/runtime/pi/egregore_runtime/shadow.py +262 -0
  513. package/runtime/pi/egregore_runtime/spirit_discovery.py +487 -0
  514. package/runtime/pi/egregore_runtime/spirit_discovery_cli.py +25 -0
  515. package/runtime/pi/egregore_runtime/spirit_discovery_transport.py +18 -0
  516. package/runtime/pi/egregore_runtime/status.py +101 -44
  517. package/runtime/pi/egregore_runtime/status_cli.py +13 -5
  518. package/runtime/pi/egregore_runtime/sync.py +39 -21
  519. package/runtime/pi/egregore_runtime/taste.py +934 -0
  520. package/runtime/pi/egregore_runtime/taste_cli.py +242 -0
  521. package/runtime/pi/egregore_runtime/taste_rules.py +91 -0
  522. package/runtime/pi/egregore_runtime/telemetry.py +26 -3
  523. package/runtime/pi/egregore_runtime/todo_cli.py +15 -12
  524. package/runtime/pi/egregore_runtime/todos.py +3 -2
  525. package/runtime/pi/egregore_runtime/upgrade.py +85 -58
  526. package/runtime/pi/egregore_runtime/writeback.py +330 -24
  527. package/runtime/pi/manifest.json +66 -5
  528. package/runtime/prime/.claude/context/handoff-claiming.md +32 -0
  529. package/runtime/prime/.claude/context/notification-consent.md +12 -9
  530. package/runtime/prime/.claude/skills/view/SKILL.md +438 -0
  531. package/runtime/prime/.codex/hooks.json +11 -0
  532. package/runtime/prime/.codex/skills/dark-mode/SKILL.md +1 -1
  533. package/runtime/prime/.codex/skills/records/SKILL.md +29 -0
  534. package/runtime/prime/.codex/skills/summon/SKILL.md +1 -1
  535. package/runtime/prime/.codex/skills/view/assets/compose-scaffold.html +19 -13
  536. package/runtime/prime/.codex/spec-manifest.json +13 -19
  537. package/runtime/prime/.prime/agent/APPEND_SYSTEM.md +53 -99
  538. package/runtime/prime/.prime/agent/extensions/egregore.ts +14 -1
  539. package/runtime/prime/.prime/agent/skills/egregore/SKILL.md +14 -6
  540. package/runtime/prime/.prime/agent/skills/egregore/src/egregore/__init__.py +66 -1
  541. package/runtime/prime/.prime/agent/spec-manifest.json +2 -2
  542. package/runtime/prime/AGENTS.md +54 -105
  543. package/runtime/prime/bin/agent.sh +231 -7
  544. package/runtime/prime/bin/api-call.sh +44 -23
  545. package/runtime/prime/bin/artifact-register.sh +7 -1
  546. package/runtime/prime/bin/artifact-writeback.sh +1 -1
  547. package/runtime/prime/bin/artifacts.sh +66 -265
  548. package/runtime/prime/bin/attendant.sh +4 -1
  549. package/runtime/prime/bin/boundary-guard.cjs +1848 -0
  550. package/runtime/prime/bin/boundary-hook.sh +41 -0
  551. package/runtime/prime/bin/capture-run.sh +32 -2
  552. package/runtime/prime/bin/codex-render-spec.mjs +24 -46
  553. package/runtime/prime/bin/codex-session-start.sh +19 -0
  554. package/runtime/prime/bin/codex-skill-render.mjs +18 -0
  555. package/runtime/prime/bin/config-get.sh +10 -1
  556. package/runtime/prime/bin/connect-refresh.sh +16 -0
  557. package/runtime/prime/bin/corpus_map.py +5 -0
  558. package/runtime/prime/bin/data/capabilities/prime.json +1458 -0
  559. package/runtime/prime/bin/genui.sh +19 -0
  560. package/runtime/prime/bin/graph-batch.sh +1 -1
  561. package/runtime/prime/bin/graph-op.sh +14 -0
  562. package/runtime/prime/bin/graph.sh +1 -1
  563. package/runtime/prime/bin/handoff-pr-backfill.sh +1 -1
  564. package/runtime/prime/bin/handoff-run.sh +11 -6
  565. package/runtime/prime/bin/ingest-item.sh +1 -1
  566. package/runtime/prime/bin/ingest-surface.html +22 -4
  567. package/runtime/prime/bin/issue.sh +1 -1
  568. package/runtime/prime/bin/knowledge.sh +1 -1
  569. package/runtime/prime/bin/lib/card-delivery.sh +329 -0
  570. package/runtime/prime/bin/lib/config.sh +148 -3
  571. package/runtime/prime/bin/lib/context.sh +38 -67
  572. package/runtime/prime/bin/lib/genui-entry.py +36 -0
  573. package/runtime/prime/bin/lib/git-message.sh +25 -6
  574. package/runtime/prime/bin/lib/git-sync.sh +12 -4
  575. package/runtime/prime/bin/lib/greeting.sh +255 -28
  576. package/runtime/prime/bin/lib/handoff_meta.py +294 -0
  577. package/runtime/prime/bin/lib/health-footer.sh +83 -2
  578. package/runtime/prime/bin/lib/identity.sh +31 -10
  579. package/runtime/prime/bin/lib/instance-registry.sh +71 -0
  580. package/runtime/prime/bin/lib/local_ci_receipt.py +249 -0
  581. package/runtime/prime/bin/lib/metrics.sh +121 -8
  582. package/runtime/prime/bin/lib/notices.sh +36 -0
  583. package/runtime/prime/bin/lib/record_outcomes.py +729 -0
  584. package/runtime/prime/bin/lib/reflexes.py +267 -0
  585. package/runtime/prime/bin/lib/retrieval_scorecard.py +624 -0
  586. package/runtime/prime/bin/lib/session-record-prompt.txt +18 -0
  587. package/runtime/prime/bin/lib/session_record.py +3747 -0
  588. package/runtime/prime/bin/lib/session_trail.py +1983 -0
  589. package/runtime/prime/bin/lib/settings-drift.sh +8 -5
  590. package/runtime/prime/bin/lib/startup-restart.sh +41 -0
  591. package/runtime/prime/bin/lib/worktree-links.sh +92 -0
  592. package/runtime/prime/bin/memory-push.sh +6 -0
  593. package/runtime/prime/bin/merge-gate.sh +498 -0
  594. package/runtime/prime/bin/notify.sh +5 -2
  595. package/runtime/prime/bin/page-access.sh +103 -0
  596. package/runtime/prime/bin/person.sh +13 -2
  597. package/runtime/prime/bin/pi-branch-policy.mjs +37 -0
  598. package/runtime/prime/bin/pi-observe-context.mjs +97 -4
  599. package/runtime/prime/bin/pi-render-spec.mjs +0 -1
  600. package/runtime/prime/bin/pi-spirit-discovery.mjs +34 -0
  601. package/runtime/prime/bin/post-update.sh +181 -0
  602. package/runtime/prime/bin/prime-render-spec.mjs +0 -1
  603. package/runtime/prime/bin/prime-session-start.sh +3 -1
  604. package/runtime/prime/bin/publish-artifact.sh +89 -42
  605. package/runtime/prime/bin/qa-inventory.sh +2 -2
  606. package/runtime/prime/bin/quest.sh +1 -1
  607. package/runtime/prime/bin/records.sh +11 -0
  608. package/runtime/prime/bin/reflexes/05-vitals.sh +9 -0
  609. package/runtime/prime/bin/reflexes/10-open-items.sh +12 -0
  610. package/runtime/prime/bin/reflexes/15-retrieval.sh +8 -0
  611. package/runtime/prime/bin/reflexes/20-nightly.sh +100 -0
  612. package/runtime/prime/bin/reflexes/20-sandbox.sh +85 -0
  613. package/runtime/prime/bin/reflexes/30-cost.py +116 -0
  614. package/runtime/prime/bin/reflexes/40-shells.py +51 -0
  615. package/runtime/prime/bin/reflexes/README.md +61 -0
  616. package/runtime/prime/bin/reflexes.sh +7 -0
  617. package/runtime/prime/bin/runtime-identity.sh +140 -42
  618. package/runtime/prime/bin/screenshot.sh +77 -0
  619. package/runtime/prime/bin/scroll.sh +1 -1
  620. package/runtime/prime/bin/search.sh +31 -5
  621. package/runtime/prime/bin/session-autosave.sh +6 -3
  622. package/runtime/prime/bin/session-id.sh +147 -0
  623. package/runtime/prime/bin/session-log.sh +19 -0
  624. package/runtime/prime/bin/session-record.sh +26 -0
  625. package/runtime/prime/bin/settings.sh +13 -8
  626. package/runtime/prime/bin/spirit-discovery-claude.sh +4 -0
  627. package/runtime/prime/bin/spirit-discovery-codex.sh +4 -0
  628. package/runtime/prime/bin/spirit-discovery-pi.sh +4 -0
  629. package/runtime/prime/bin/spirit-discovery-prime.sh +4 -0
  630. package/runtime/prime/bin/spirit-discovery.sh +4 -0
  631. package/runtime/prime/bin/startup-check.sh +1 -1
  632. package/runtime/prime/bin/telemetry.sh +11 -4
  633. package/runtime/prime/bin/test-baseline.sh +33 -5
  634. package/runtime/prime/bin/todo.sh +1 -1
  635. package/runtime/prime/bin/worktree-create.sh +15 -45
  636. package/runtime/prime/bin/worktree.sh +6 -0
  637. package/runtime/prime/docs/spirit-discovery.md +96 -0
  638. package/runtime/prime/egregore_runtime/__init__.py +18 -12
  639. package/runtime/prime/egregore_runtime/access.py +608 -0
  640. package/runtime/prime/egregore_runtime/access_cli.py +190 -0
  641. package/runtime/prime/egregore_runtime/adapters/invitation.py +5 -3
  642. package/runtime/prime/egregore_runtime/adapters/qmd.py +521 -47
  643. package/runtime/prime/egregore_runtime/admin_entry.py +56 -0
  644. package/runtime/prime/egregore_runtime/artifacts.py +222 -16
  645. package/runtime/prime/egregore_runtime/contracts.py +27 -0
  646. package/runtime/prime/egregore_runtime/eligibility.py +5 -12
  647. package/runtime/prime/egregore_runtime/episode_binding.py +16 -5
  648. package/runtime/prime/egregore_runtime/github_issues.py +2 -2
  649. package/runtime/prime/egregore_runtime/handoff_lookup.py +9 -20
  650. package/runtime/prime/egregore_runtime/harness_cli.py +674 -149
  651. package/runtime/prime/egregore_runtime/held.py +2436 -0
  652. package/runtime/prime/egregore_runtime/hosted_api.py +137 -0
  653. package/runtime/prime/egregore_runtime/identity.py +196 -65
  654. package/runtime/prime/egregore_runtime/identity_transfer.py +6 -2
  655. package/runtime/prime/egregore_runtime/ingest_cli.py +2 -2
  656. package/runtime/prime/egregore_runtime/ingest_index_cli.py +4 -16
  657. package/runtime/prime/egregore_runtime/installation.py +119 -0
  658. package/runtime/prime/egregore_runtime/investigation.py +64 -41
  659. package/runtime/prime/egregore_runtime/investigation_guidance.py +16 -11
  660. package/runtime/prime/egregore_runtime/issue_cli.py +51 -32
  661. package/runtime/prime/egregore_runtime/issue_reporting.py +4 -3
  662. package/runtime/prime/egregore_runtime/issue_triage_service.py +2 -2
  663. package/runtime/prime/egregore_runtime/issues.py +12 -6
  664. package/runtime/prime/egregore_runtime/knowledge.py +331 -5
  665. package/runtime/prime/egregore_runtime/knowledge_cli.py +57 -17
  666. package/runtime/prime/egregore_runtime/lifecycle.py +88 -22
  667. package/runtime/prime/egregore_runtime/lifecycle_cli.py +21 -13
  668. package/runtime/prime/egregore_runtime/line_ids.py +10 -0
  669. package/runtime/prime/egregore_runtime/memory_push.py +349 -0
  670. package/runtime/prime/egregore_runtime/observe.py +64 -25
  671. package/runtime/prime/egregore_runtime/observers.py +19 -0
  672. package/runtime/prime/egregore_runtime/optional_modules.py +13 -0
  673. package/runtime/prime/egregore_runtime/outputs_cli.py +321 -0
  674. package/runtime/prime/egregore_runtime/policy.py +651 -24
  675. package/runtime/prime/egregore_runtime/private_result.py +2 -1
  676. package/runtime/prime/egregore_runtime/projection.py +946 -0
  677. package/runtime/prime/egregore_runtime/quest_cli.py +20 -23
  678. package/runtime/prime/egregore_runtime/question_cli.py +15 -11
  679. package/runtime/prime/egregore_runtime/questions.py +10 -10
  680. package/runtime/prime/egregore_runtime/quests.py +10 -10
  681. package/runtime/prime/egregore_runtime/record_publish.py +548 -0
  682. package/runtime/prime/egregore_runtime/record_subject.py +564 -0
  683. package/runtime/prime/egregore_runtime/research_ingest.py +2 -4
  684. package/runtime/prime/egregore_runtime/runtime.py +169 -60
  685. package/runtime/prime/egregore_runtime/sandbox.py +194 -0
  686. package/runtime/prime/egregore_runtime/scroll_cli.py +22 -32
  687. package/runtime/prime/egregore_runtime/scrolls.py +23 -15
  688. package/runtime/prime/egregore_runtime/shadow.py +262 -0
  689. package/runtime/prime/egregore_runtime/spirit_discovery.py +487 -0
  690. package/runtime/prime/egregore_runtime/spirit_discovery_cli.py +25 -0
  691. package/runtime/prime/egregore_runtime/spirit_discovery_transport.py +18 -0
  692. package/runtime/prime/egregore_runtime/status.py +101 -44
  693. package/runtime/prime/egregore_runtime/status_cli.py +13 -5
  694. package/runtime/prime/egregore_runtime/sync.py +39 -21
  695. package/runtime/prime/egregore_runtime/taste.py +934 -0
  696. package/runtime/prime/egregore_runtime/taste_cli.py +242 -0
  697. package/runtime/prime/egregore_runtime/taste_rules.py +91 -0
  698. package/runtime/prime/egregore_runtime/telemetry.py +26 -3
  699. package/runtime/prime/egregore_runtime/todo_cli.py +15 -12
  700. package/runtime/prime/egregore_runtime/todos.py +3 -2
  701. package/runtime/prime/egregore_runtime/upgrade.py +85 -58
  702. package/runtime/prime/egregore_runtime/writeback.py +330 -24
  703. package/runtime/prime/manifest.json +66 -5
  704. package/runtime/claude/bin/thread.sh +0 -9
  705. package/runtime/claude/egregore_runtime/admin_gate.py +0 -102
  706. package/runtime/claude/egregore_runtime/thread_cli.py +0 -173
  707. package/runtime/claude/egregore_runtime/threads.py +0 -521
  708. package/runtime/codex/bin/thread.sh +0 -9
  709. package/runtime/codex/egregore_runtime/admin_gate.py +0 -102
  710. package/runtime/codex/egregore_runtime/thread_cli.py +0 -173
  711. package/runtime/codex/egregore_runtime/threads.py +0 -521
  712. package/runtime/pi/bin/thread.sh +0 -9
  713. package/runtime/pi/egregore_runtime/admin_gate.py +0 -102
  714. package/runtime/pi/egregore_runtime/thread_cli.py +0 -173
  715. package/runtime/pi/egregore_runtime/threads.py +0 -521
  716. package/runtime/prime/bin/thread.sh +0 -9
  717. package/runtime/prime/egregore_runtime/admin_gate.py +0 -102
  718. package/runtime/prime/egregore_runtime/thread_cli.py +0 -173
  719. package/runtime/prime/egregore_runtime/threads.py +0 -521
@@ -0,0 +1,119 @@
1
+ """Which Egregore installation a checkout belongs to.
2
+
3
+ Standard library only, no package imports: the upgrade engine, the map
4
+ hand-over and the memory map notice writer import it, and the map's server
5
+ (serve.py) loads this file by path from a checkout that may run another Runtime
6
+ version.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ import os
14
+ import stat
15
+ from pathlib import Path
16
+
17
+ _SMALL = 4096 # a .git file or a git dir's back-link is one short path
18
+ _UNSET = object()
19
+
20
+
21
+ def _read_small(path: str) -> str:
22
+ """A short regular file's text; a link, folder, pipe or device raises OSError."""
23
+ descriptor = os.open(path, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK)
24
+ try:
25
+ if not stat.S_ISREG(os.fstat(descriptor).st_mode):
26
+ raise OSError(f"not a regular file: {path}")
27
+ return os.read(descriptor, _SMALL).decode("utf-8")
28
+ finally:
29
+ os.close(descriptor)
30
+
31
+
32
+ def installation_root(repository_root) -> Path:
33
+ """The main installation directory a checkout belongs to.
34
+
35
+ A linked git worktree (``.git`` is a file) belongs to its main checkout;
36
+ upgrade state is per installation, so every worktree of one install
37
+ shares it. A standalone clone is its own installation.
38
+
39
+ The ``.git`` file sits in the checkout and anyone working there can rewrite
40
+ it, so its claim counts only when the git dir links back to this checkout,
41
+ as git's own ``<gitdir>/gitdir`` file does for a real linked worktree (the
42
+ check bin/boundary-guard.cjs makes). A forged or broken ``.git`` file, a git
43
+ dir outside ``<main>/.git/worktrees/<name>``, or any read error makes the
44
+ checkout its own installation.
45
+
46
+ So does a worktree moved with plain ``mv``: its back-link still names the
47
+ old place until ``git worktree repair`` is run in it. The shell copies of
48
+ this climb (bin/search.sh, bin/settings.sh, bin/graph.sh, bin/lib/greeting.sh,
49
+ bin/lib/runtime-owned.sh) skip the back-link and key such a checkout by its
50
+ main checkout. Every genuine layout gets the same answer from both.
51
+ """
52
+ root = Path(repository_root).resolve()
53
+ marker = root / ".git"
54
+ try:
55
+ if not stat.S_ISREG(os.lstat(marker).st_mode):
56
+ return root
57
+ for line in _read_small(str(marker)).splitlines():
58
+ if line.startswith("gitdir:"):
59
+ git_dir = Path(line.split(":", 1)[1].strip())
60
+ break
61
+ else:
62
+ return root
63
+ if not git_dir.is_absolute():
64
+ git_dir = (root / git_dir).resolve()
65
+ # <main>/.git/worktrees/<name> → <main>
66
+ if git_dir.parent.name != "worktrees" or git_dir.parent.parent.name != ".git":
67
+ return root
68
+ back = _read_small(str(git_dir / "gitdir")).strip()
69
+ # ``root`` is resolved and ``.git`` was read as a regular file, so ``marker`` is already its
70
+ # real path; resolving it again would follow a ``.git`` swapped for a link after the read.
71
+ if not back or os.path.realpath(os.path.join(git_dir, back)) != str(marker):
72
+ return root
73
+ main = git_dir.parent.parent.parent
74
+ return main.resolve() if main.is_dir() else root
75
+ except (OSError, ValueError):
76
+ return root
77
+
78
+
79
+ class InstallationIdentityError(ValueError):
80
+ """The checkout has no stable organization identity, so per-installation state fails closed."""
81
+
82
+
83
+ def installation_key(repository_root, *, existing_org_id=_UNSET) -> str:
84
+ """Durable per-installation key: stable org identity × installation identity.
85
+
86
+ It keys upgrade state and the map hand-over slot. Identity is never inferred
87
+ from a path alone: the stable organization ID from egregore.json is required
88
+ and leads the key, so two organizations that share, symlink, or otherwise
89
+ resolve to the same memory repository never share state. The installation
90
+ path is composed in so two installs of one organization stay independent,
91
+ while worktrees of one install share it. A checkout without a stable org_id
92
+ fails closed.
93
+
94
+ ``existing_org_id`` is an optional host-owned value already read and
95
+ validated by a caller. It avoids a second config read; it does not change
96
+ installation_root's existing path/backlink semantics or authenticate an org.
97
+ """
98
+ root = Path(repository_root).resolve()
99
+ if existing_org_id is _UNSET:
100
+ try:
101
+ org_id = str(json.loads((root / "egregore.json").read_text(encoding="utf-8")).get("org_id") or "").strip()
102
+ except (OSError, ValueError, AttributeError) as exc:
103
+ raise InstallationIdentityError(f"cannot read egregore.json for instance identity: {exc}") from exc
104
+ else:
105
+ org_id = existing_org_id
106
+ try:
107
+ valid = (isinstance(org_id, str) and bool(org_id) and org_id == org_id.strip()
108
+ and len(org_id.encode("utf-8")) <= 2000
109
+ and not any(ord(character) < 33 or ord(character) == 127 for character in org_id))
110
+ except UnicodeError:
111
+ valid = False
112
+ if not valid:
113
+ raise InstallationIdentityError("a canonical existing organization identity is required")
114
+ if not org_id:
115
+ raise InstallationIdentityError(
116
+ "this instance has no stable org_id; per-installation state fails closed "
117
+ "without a stable organization identity"
118
+ )
119
+ return hashlib.sha256(f"{org_id}|{installation_root(root)}".encode("utf-8")).hexdigest()[:16]
@@ -21,9 +21,10 @@ from .contracts import RetrievalHit, RetrievalMode, RetrievalRequest, RetrievalR
21
21
  from .errors import AuthorizationDenied, EgregoreRuntimeError
22
22
  from .eligibility import is_internal_event
23
23
  from .excerpts import select_excerpt
24
+ from .held import identity, package, redact
24
25
  from .identity import actor_lexical_formulations, resolve_actor_query
25
26
  from .investigation_contracts import InvestigationRequest
26
- from .policy import scope_allows_path
27
+ from .policy import allows, check, within
27
28
 
28
29
  KINDS = {'hybrid':RetrievalMode.HYBRID, 'semantic':RetrievalMode.VEC, 'keyword':RetrievalMode.LEX}
29
30
  STATE_VERSION = 'egregore-investigation/v1'
@@ -34,6 +35,17 @@ MAX_STATE_BYTES = 16_000_000
34
35
  MAX_OPEN_BATCH_BYTES = 16_000
35
36
 
36
37
 
38
+ def new_cursor():
39
+ """Mint a continuation cursor an agent can pass back as `--cursor TOKEN`.
40
+
41
+ Lowercase hex never starts with '-', so argparse cannot mistake the token
42
+ for an option. The length matches the 24-character size estimate used
43
+ when fitting a page into the output budget. Cursors minted earlier as
44
+ URL-safe base64 stay valid: lookup is by exact key.
45
+ """
46
+ return secrets.token_hex(12)
47
+
48
+
37
49
  def state_path(root, episode_id):
38
50
  key = hashlib.sha256(str(episode_id).encode()).hexdigest()
39
51
  return Path(root) / '.egregore/runtime/investigations' / (key + '.json')
@@ -108,9 +120,9 @@ def _save_state(path, value):
108
120
 
109
121
  class LookupAdapter:
110
122
  """Deterministic canonical lookup and filters, behind Runtime authorization."""
111
- def __init__(self, original, kind, params, actor, admin_gate, *, question=''):
123
+ def __init__(self, original, kind, params, actor, *, question=''):
112
124
  self.original, self.kind, self.params = original, kind, params
113
- self.actor, self.admin_gate = actor, admin_gate
125
+ self.actor = actor
114
126
  self.question = question or params.get('query', '')
115
127
  self.last_result = None
116
128
  self.scanned = 0
@@ -151,7 +163,7 @@ class LookupAdapter:
151
163
  if p.get('before') and (day is None or day > date.fromisoformat(p['before'])):
152
164
  return False
153
165
  prefix = p.get('prefix')
154
- if prefix and not scope_allows_path(path, (prefix,)):
166
+ if prefix and not within(path, (prefix,)):
155
167
  return False
156
168
  if p.get('artifact_type') and metadata.artifact_type != p['artifact_type']:
157
169
  return False
@@ -160,12 +172,12 @@ class LookupAdapter:
160
172
  return True
161
173
 
162
174
  def retrieve(self, request):
163
- return self._retrieve(request)
175
+ raise AuthorizationDenied("lookup requires an authorized decision")
164
176
 
165
- def retrieve_authorized(self, request, *, actor, admin_gate=None, lifecycle=None):
166
- return self._retrieve(request, lifecycle=lifecycle)
177
+ def retrieve_authorized(self, request, *, actor, decision, lifecycle=None):
178
+ return self._retrieve(request, decision=decision, lifecycle=lifecycle)
167
179
 
168
- def _retrieve(self, request, *, lifecycle=None):
180
+ def _retrieve(self, request, *, decision, lifecycle=None):
169
181
  started = time.monotonic()
170
182
  if self.kind in KINDS:
171
183
  lexical = actor_lexical_formulations(self.actor, request.task, request.lex)
@@ -174,8 +186,8 @@ class LookupAdapter:
174
186
  vec=tuple(resolve_actor_query(self.actor, value) for value in request.vec),
175
187
  artifact_types=(self.params['artifact_type'],) if self.params.get('artifact_type') else request.artifact_types)
176
188
  scoped = getattr(self.original, 'retrieve_authorized', None)
177
- raw = (scoped(ranked_request, actor=self.actor, admin_gate=self.admin_gate, lifecycle=lifecycle,
178
- path_filter=lambda path: not self.params.get('prefix') or scope_allows_path(path, (self.params['prefix'],)),
189
+ raw = (scoped(ranked_request, actor=self.actor, decision=decision, lifecycle=lifecycle,
190
+ path_filter=lambda path: not self.params.get('prefix') or within(path, (self.params['prefix'],)),
179
191
  metadata_filter=self._matches) if callable(scoped) else self.original.retrieve(ranked_request))
180
192
  candidates = raw.hits
181
193
  self.last_result = raw
@@ -185,15 +197,12 @@ class LookupAdapter:
185
197
  for path in sorted(root.rglob('*.md')):
186
198
  canonical = 'memory/' + path.relative_to(root).as_posix()
187
199
  # No metadata/content read outside the authorized canonical scope.
188
- if not scope_allows_path(canonical, request.authorized_scopes):
189
- continue
190
- resolved = path.resolve()
191
- if not resolved.is_relative_to(root.resolve()):
192
- continue
193
- if not scope_allows_path('memory/' + resolved.relative_to(root.resolve()).as_posix(), request.authorized_scopes):
200
+ verdict = check(decision, canonical, "read", root=root)
201
+ if not verdict.allowed:
194
202
  continue
203
+ resolved = verdict.resolved
195
204
  # Path lookup and explicit scope do not need to inspect every document.
196
- if self.params.get('prefix') and not scope_allows_path(canonical, (self.params['prefix'],)):
205
+ if self.params.get('prefix') and not within(canonical, (self.params['prefix'],)):
197
206
  continue
198
207
  if self.kind == 'filename' and self.params['query'].casefold() not in canonical.casefold():
199
208
  continue
@@ -204,8 +213,6 @@ class LookupAdapter:
204
213
  continue
205
214
  if request.allowed_artifact_ids and metadata.artifact_id not in request.allowed_artifact_ids:
206
215
  continue
207
- if self.admin_gate and not self.admin_gate.actor_is_admin(self.actor) and self.admin_gate.path_is_admin(canonical):
208
- continue
209
216
  self.scanned += 1
210
217
  if not self._matches(canonical, metadata):
211
218
  continue
@@ -227,14 +234,14 @@ class LookupAdapter:
227
234
  candidates.sort(key=lambda hit: (-(hit.observed_at.timestamp() if hit.observed_at else 0), hit.canonical_path))
228
235
  filtered = []
229
236
  for hit in candidates:
230
- if not scope_allows_path(hit.canonical_path, request.authorized_scopes):
237
+ if not allows(decision, hit.canonical_path, "read", root=self.original.memory_root):
231
238
  continue
232
239
  metadata = self.original.describe_source(hit.canonical_path)
233
240
  if metadata.observed_at is None and hit.observed_at is not None:
234
241
  metadata = replace(metadata, observed_at=hit.observed_at, date_provenance='lifecycle.created_at')
235
242
  if not self._matches(hit.canonical_path, metadata):
236
243
  continue
237
- # Stable, compact metadata plus a passage; no full-source dump.
244
+ # Stable, compact metadata plus a passage; no full-source dump. Observe redacts it field by field.
238
245
  passage = hit.passage if self.params.get('_context_projection') else json.dumps({
239
246
  'title':metadata.title, 'document_date':str(self._day(metadata.observed_at)) if metadata.observed_at else None,
240
247
  'date_provenance':getattr(metadata, 'date_provenance', None),
@@ -309,13 +316,34 @@ class Investigation:
309
316
  if path and identifier and self._can_deliver(path,identifier):
310
317
  self.ledger[path] = evidence.get('revision','unknown')
311
318
 
319
+ def _package(self, row):
320
+ """A cached row as it may be handed over now: its path and id decided again, every text redacted under
321
+ the held set in effect, not the one it was cached under. None when it is refused."""
322
+ from .contracts import Permission
323
+ decision = self.runtime.authorize(self.actor, Permission.READ, (row['artifact_id'],))
324
+ text = {key: value for key, value in row.items() if key not in ('path', 'artifact_id')}
325
+ kept = package(decision, text, root=self.runtime.canonical_root, paths=(row['path'],))
326
+ if kept is None:
327
+ return None
328
+ return {**row, **kept, 'artifact_id': identity(decision, row['artifact_id'], row['path'],
329
+ root=self.runtime.canonical_root)}
330
+
331
+ def _redacted(self, value):
332
+ """A delivery kept from an earlier call (a replayed response, a reused context), redacted again."""
333
+ from .contracts import Permission
334
+ return redact(self.runtime.authorize(self.actor, Permission.READ), value, root=self.runtime.canonical_root)
335
+
312
336
  def _can_deliver(self, path, artifact_id):
313
337
  from .contracts import Permission
314
338
  decision = self.runtime.authorize(self.actor, Permission.READ, (artifact_id,))
315
- if not decision.allowed or not scope_allows_path(path,decision.scopes):
339
+ return allows(decision, path, "read", root=self.runtime.canonical_root)
340
+
341
+ def _deliverable(self, path):
342
+ """Decide the path before reading it for its id, then decide the id."""
343
+ from .contracts import Permission
344
+ if not allows(self.runtime.authorize(self.actor, Permission.READ), path, "read", root=self.runtime.canonical_root):
316
345
  return False
317
- gate = self.runtime.admin_gate
318
- return not gate or gate.actor_is_admin(self.actor) or not gate.path_is_admin(path)
346
+ return self._can_deliver(path, self.runtime.retriever.describe_source(path).artifact_id)
319
347
 
320
348
  def _authorize(self):
321
349
  started=time.monotonic()
@@ -331,7 +359,6 @@ class Investigation:
331
359
  raise AuthorizationDenied('investigation requires current discover/read permission')
332
360
  signature = decision.to_dict()
333
361
  signature['profile_revision'] = self.actor.profile.revision
334
- signature['admin'] = self.runtime.admin_gate.actor_is_admin(self.actor) if self.runtime.admin_gate else False
335
362
  digest = hashlib.sha256(json.dumps(signature,sort_keys=True).encode()).hexdigest()
336
363
  if self.episode_signature is not None and self.episode_signature != digest:
337
364
  raise AuthorizationDenied('authorization changed; start a new investigation')
@@ -385,7 +412,7 @@ class Investigation:
385
412
  key = key_for(self._revision(), self._index_revision())
386
413
  cached = self.context_cache.get(key)
387
414
  if cached and (not request.open_sources or cached['open_sources']):
388
- context = cached['context']
415
+ context = self._redacted(cached['context'])
389
416
  self._check_context(context)
390
417
  return {'projection':'context', 'context':context, 'source_revision':context['source_revision'],
391
418
  'reused':True, 'searches_remaining':self.search_budget-self.searches}
@@ -403,7 +430,7 @@ class Investigation:
403
430
  adapter = LookupAdapter(self.runtime.retriever,
404
431
  {RetrievalMode.LEX:'keyword',RetrievalMode.VEC:'semantic',RetrievalMode.HYBRID:'hybrid'}[request.mode],
405
432
  {**self.bounds, '_context_projection':True, '_candidate_limit':request.top_k},
406
- self.actor,self.runtime.admin_gate)
433
+ self.actor)
407
434
  target = replace(self.runtime,retriever=adapter)
408
435
  try:
409
436
  context = target.observe(self.actor,request,token_budget=options.token_budget).to_dict()
@@ -446,20 +473,17 @@ class Investigation:
446
473
  if result['context'].get('freshness',{}).get('index_revision') != self._index_revision():
447
474
  raise ValueError('index changed before delivery; retry with a new request_id')
448
475
  elif result.get('path'):
449
- metadata=self.runtime.retriever.describe_source(result['path'])
450
- if not self._can_deliver(result['path'],metadata.artifact_id):
476
+ if not self._deliverable(result['path']):
451
477
  raise AuthorizationDenied('evidence authorization changed')
452
478
  elif result.get('sources'):
453
479
  for source in result['sources']:
454
- metadata = self.runtime.retriever.describe_source(source['path'])
455
- if not self._can_deliver(source['path'], metadata.artifact_id):
480
+ if not self._deliverable(source['path']):
456
481
  raise AuthorizationDenied('evidence authorization changed')
457
482
  elif any(not self._can_deliver(row['path'],row['artifact_id']) for row in result.get('results',[])):
458
483
  raise AuthorizationDenied('evidence authorization changed')
459
484
  for key in ['seen_sources','opened_sources']:
460
485
  for path in result.get(key,{}):
461
- metadata=self.runtime.retriever.describe_source(path)
462
- if not self._can_deliver(path,metadata.artifact_id):
486
+ if not self._deliverable(path):
463
487
  raise AuthorizationDenied('retained evidence authorization changed')
464
488
 
465
489
  def _request(self, text, mode, limit):
@@ -494,7 +518,7 @@ class Investigation:
494
518
  if params.get(key): date.fromisoformat(params[key])
495
519
  if params.get('after') and params.get('before') and params['after']>params['before']:
496
520
  raise ValueError('after must not exceed before')
497
- if params.get('prefix') and (not params['prefix'].startswith('memory') or '\\' in params['prefix'] or not scope_allows_path(params['prefix'],('memory',))):
521
+ if params.get('prefix') and (not params['prefix'].startswith('memory') or '\\' in params['prefix'] or not within(params['prefix'],('memory',))):
498
522
  raise ValueError('prefix must be a canonical memory path')
499
523
  return kind,limit
500
524
 
@@ -542,7 +566,7 @@ class Investigation:
542
566
  raise ValueError('investigation search budget exhausted; report remaining gaps')
543
567
  self.searches+=1
544
568
  self._checkpoint()
545
- adapter=LookupAdapter(self.runtime.retriever,kind,params,self.actor,self.runtime.admin_gate,
569
+ adapter=LookupAdapter(self.runtime.retriever,kind,params,self.actor,
546
570
  question=self.question)
547
571
  facade=replace(self.runtime,retriever=adapter)
548
572
  request=self._request(str(params.get('query') or 'Documents within the requested date interval'),KINDS.get(kind,RetrievalMode.LEX).value,10000)
@@ -568,8 +592,8 @@ class Investigation:
568
592
  'degraded':adapter.last_result.degraded,'warnings':list(adapter.last_result.warnings),'source_revision':context.source_revision,
569
593
  'retrieval_seconds':adapter.last_result.latency_ms/1000,'scanned_authorized':adapter.scanned}
570
594
  cached=self.cache[fingerprint]
571
- rows=cached['rows'][offset:offset+limit]
572
- if any(not self._can_deliver(row['path'],row['artifact_id']) for row in rows):
595
+ rows=[self._package(row) for row in cached['rows'][offset:offset+limit]]
596
+ if any(row is None for row in rows):
573
597
  raise AuthorizationDenied('evidence authorization changed; start a new investigation')
574
598
  next_cursor=None
575
599
  def result_for(selected):
@@ -583,7 +607,7 @@ class Investigation:
583
607
  if not rows and offset<len(cached['rows']):
584
608
  raise ValueError('evidence output budget exhausted; report the remaining gap')
585
609
  if offset+len(rows)<len(cached['rows']):
586
- next_cursor=secrets.token_urlsafe(18)
610
+ next_cursor=new_cursor()
587
611
  self.cursors[next_cursor]=(fingerprint,offset+len(rows),limit,signature,revision)
588
612
  for row in rows:self.ledger[row['path']]=row['revision']
589
613
  result=result_for(rows);result['next_cursor']=next_cursor;result['previous_evidence_retained']=len(self.ledger)
@@ -675,8 +699,7 @@ class Investigation:
675
699
  visible = {}
676
700
  for path, revision in sources.items():
677
701
  try:
678
- metadata = self.runtime.retriever.describe_source(path)
679
- if self._can_deliver(path, metadata.artifact_id):
702
+ if self._deliverable(path):
680
703
  visible[path] = revision
681
704
  except FileNotFoundError:
682
705
  continue
@@ -723,7 +746,7 @@ class Investigation:
723
746
  self._authorize()
724
747
  if cached.get('source_revision') and cached['source_revision'] != self._revision():
725
748
  raise ValueError('sources changed since this response; retry with a new request_id')
726
- response=copy.deepcopy(cached['response'])
749
+ response=self._redacted(copy.deepcopy(cached['response']))
727
750
  if not response['ok']:
728
751
  result=None
729
752
  else:
@@ -7,7 +7,7 @@ Use find for discovery (query is compatibility-only). Use search.sh open for sou
7
7
  reads; never use raw file tools or shell reads on memory. Answer from sufficient
8
8
  excerpts without opening again."""
9
9
 
10
- INVESTIGATION_GUIDANCE = RECALL_WORKFLOW_GUIDANCE + "\n" + """Search organizational memory through Runtime; reuse evidence already in context.
10
+ INVESTIGATION_GUIDANCE = RECALL_WORKFLOW_GUIDANCE + "\n" + """Reuse evidence already in context; never bypass Runtime with raw memory reads or direct QMD access.
11
11
  For exact handoff status/order, use `bash bin/search.sh handoffs --mine --status open --order newest --limit 1 --open`; adjust filters to the question.
12
12
  Choose a lookup and call `bash bin/search.sh find "<query>" --kind <kind>`:
13
13
  filename for known path fragments; literal for exact wording; dates for dated
@@ -30,17 +30,11 @@ Up to 10 sources per call; --offset N is a nonnegative character offset and
30
30
  result budget, so windows may be shorter. Follow the printed per-source
31
31
  continuation only when that source needs more context; do not assume a partial
32
32
  window is the complete document. Keep each source batch in its own tool result.
33
- In Codex, set the outer functions.exec output budget with
34
- `// @exec: {"max_output_tokens": 20000}` and exec_command.max_output_tokens to
35
- 20000 for source reads; a larger inner limit alone cannot prevent outer truncation.
36
33
  Known paths may be opened directly. Use find --cursor TOKEN only when another
37
34
  page is needed. Do not fetch or reread this contract when it is already attached.
38
35
  Runtime retains date bounds and resolves the native session automatically.
39
36
  Do not supply episode IDs, request IDs, or gap explanations in normal calls.
40
- If native binding is unavailable, use this prompt's supplied --episode reference;
41
- never borrow another prompt's reference. A new prompt resets retrieval limits.
42
- Use a normal completion wait (at least 10 seconds for yield_time_ms); do not
43
- create polling turns with one-second waits. Batch independent work in the harness.
37
+ A new prompt resets retrieval limits. Batch independent work in the harness.
44
38
  Stop when the question is supported. Ranked matches are not exhaustive; verify
45
39
  coverage before claiming something is newest or absent. Document dates need not
46
40
  be event dates. Distinguish proposals/conditions from completed work and cite sources.
@@ -52,7 +46,18 @@ failure or index-coverage warning into the final answer. Say what could not be
52
46
  verified and how the gap limits that conclusion; do not turn a search gap into a fact.
53
47
  Authorization, source checks, retained evidence and budgets remain inside Runtime:
54
48
  8 discoveries, 20 source windows, 50 calls and 120,000 result characters per prompt.
55
- Never bypass Runtime with raw memory filesystem or direct QMD access. Code search
56
- and tests use ordinary tools. Emit the memory retrieval beat once per question.
57
- On Claude append --context-packet; never reproduce internal JSON or ranking traces.
49
+ Never reproduce internal JSON or ranking traces.
58
50
  """
51
+
52
+ # Codex-only tool budgets; other harnesses never see these names.
53
+ CODEX_GUIDANCE = """In Codex, set the outer functions.exec output budget with
54
+ `// @exec: {"max_output_tokens": 20000}` and exec_command.max_output_tokens to
55
+ 20000 for source reads; a larger inner limit alone cannot prevent outer truncation.
56
+ Use a normal completion wait (at least 10 seconds for yield_time_ms); do not
57
+ create polling turns with one-second waits."""
58
+
59
+
60
+ def investigation_guidance(harness: str) -> str:
61
+ """The shared contract plus the lines only this harness can act on."""
62
+ base = INVESTIGATION_GUIDANCE.rstrip("\n")
63
+ return base + "\n" + CODEX_GUIDANCE if harness == "codex" else base