mirror-mind 0.0.1 → 0.33.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 (474) hide show
  1. package/.claude/hooks/log-assistant-reply.sh +85 -0
  2. package/.claude/hooks/log-session-end.sh +85 -0
  3. package/.claude/hooks/log-user-prompt.sh +85 -0
  4. package/.claude/hooks/mirror-inject.sh +85 -0
  5. package/.claude/hooks/session-start.sh +85 -0
  6. package/.gemini/hooks/log-assistant.sh +85 -0
  7. package/.gemini/hooks/log-user.sh +85 -0
  8. package/.gemini/hooks/session-end.sh +85 -0
  9. package/.gemini/hooks/session-start.sh +85 -0
  10. package/.pi/extensions/mirror-logger.ts +646 -0
  11. package/.pi/skills/mm-backup/SKILL.md +21 -0
  12. package/.pi/skills/mm-build/SKILL.md +1206 -0
  13. package/.pi/skills/mm-consolidate/SKILL.md +112 -0
  14. package/.pi/skills/mm-consult/SKILL.md +70 -0
  15. package/.pi/skills/mm-conversations/SKILL.md +16 -0
  16. package/.pi/skills/mm-discard/SKILL.md +39 -0
  17. package/.pi/skills/mm-explore/SKILL.md +255 -0
  18. package/.pi/skills/mm-help/SKILL.md +74 -0
  19. package/.pi/skills/mm-identity/SKILL.md +96 -0
  20. package/.pi/skills/mm-journal/SKILL.md +16 -0
  21. package/.pi/skills/mm-journey/SKILL.md +23 -0
  22. package/.pi/skills/mm-journeys/SKILL.md +15 -0
  23. package/.pi/skills/mm-memories/SKILL.md +17 -0
  24. package/.pi/skills/mm-mirror/SKILL.md +98 -0
  25. package/.pi/skills/mm-mute/SKILL.md +18 -0
  26. package/.pi/skills/mm-new/SKILL.md +18 -0
  27. package/.pi/skills/mm-recall/SKILL.md +17 -0
  28. package/.pi/skills/mm-release-notes/SKILL.md +52 -0
  29. package/.pi/skills/mm-seed/SKILL.md +19 -0
  30. package/.pi/skills/mm-shadow/SKILL.md +117 -0
  31. package/.pi/skills/mm-soul/SKILL.md +502 -0
  32. package/.pi/skills/mm-tasks/SKILL.md +24 -0
  33. package/.pi/skills/mm-update/SKILL.md +32 -0
  34. package/.pi/skills/mm-week/SKILL.md +28 -0
  35. package/.pi/skills/mm-welcome/SKILL.md +24 -0
  36. package/AGENTS.md +188 -0
  37. package/README.md +126 -9
  38. package/bin/loader.js +67 -0
  39. package/bin/mirror-hook.js +7 -0
  40. package/bin/mirror.js +7 -0
  41. package/docs/releases/index.md +100 -0
  42. package/docs/releases/pending-cutoffs.md +510 -0
  43. package/docs/releases/v0.10.0.md +123 -0
  44. package/docs/releases/v0.10.1.md +66 -0
  45. package/docs/releases/v0.10.10.md +51 -0
  46. package/docs/releases/v0.10.11.md +39 -0
  47. package/docs/releases/v0.10.12.md +57 -0
  48. package/docs/releases/v0.10.13.md +35 -0
  49. package/docs/releases/v0.10.14.md +42 -0
  50. package/docs/releases/v0.10.15.md +53 -0
  51. package/docs/releases/v0.10.16.md +35 -0
  52. package/docs/releases/v0.10.17.md +43 -0
  53. package/docs/releases/v0.10.2.md +64 -0
  54. package/docs/releases/v0.10.3.md +78 -0
  55. package/docs/releases/v0.10.4.md +42 -0
  56. package/docs/releases/v0.10.5.md +57 -0
  57. package/docs/releases/v0.10.6.md +47 -0
  58. package/docs/releases/v0.10.7.md +53 -0
  59. package/docs/releases/v0.10.8.md +49 -0
  60. package/docs/releases/v0.10.9.md +37 -0
  61. package/docs/releases/v0.11.0.md +86 -0
  62. package/docs/releases/v0.12.0.md +67 -0
  63. package/docs/releases/v0.13.0.md +64 -0
  64. package/docs/releases/v0.14.0.md +68 -0
  65. package/docs/releases/v0.15.0.md +48 -0
  66. package/docs/releases/v0.16.0.md +50 -0
  67. package/docs/releases/v0.16.1.md +55 -0
  68. package/docs/releases/v0.16.2.md +36 -0
  69. package/docs/releases/v0.17.0.md +50 -0
  70. package/docs/releases/v0.17.1.md +58 -0
  71. package/docs/releases/v0.17.2.md +42 -0
  72. package/docs/releases/v0.17.3.md +58 -0
  73. package/docs/releases/v0.18.0.md +84 -0
  74. package/docs/releases/v0.18.1.md +51 -0
  75. package/docs/releases/v0.18.2.md +69 -0
  76. package/docs/releases/v0.19.0.md +85 -0
  77. package/docs/releases/v0.19.1.md +46 -0
  78. package/docs/releases/v0.20.0.md +85 -0
  79. package/docs/releases/v0.21.0.md +61 -0
  80. package/docs/releases/v0.21.1.md +47 -0
  81. package/docs/releases/v0.22.0.md +77 -0
  82. package/docs/releases/v0.22.1.md +42 -0
  83. package/docs/releases/v0.23.0.md +105 -0
  84. package/docs/releases/v0.24.0.md +125 -0
  85. package/docs/releases/v0.25.0.md +107 -0
  86. package/docs/releases/v0.26.0.md +139 -0
  87. package/docs/releases/v0.26.1.md +65 -0
  88. package/docs/releases/v0.26.2.md +43 -0
  89. package/docs/releases/v0.27.0.md +63 -0
  90. package/docs/releases/v0.28.0.md +59 -0
  91. package/docs/releases/v0.29.0.md +61 -0
  92. package/docs/releases/v0.29.1.md +59 -0
  93. package/docs/releases/v0.29.2.md +59 -0
  94. package/docs/releases/v0.29.3.md +93 -0
  95. package/docs/releases/v0.30.0.md +75 -0
  96. package/docs/releases/v0.30.1.md +93 -0
  97. package/docs/releases/v0.30.2.md +66 -0
  98. package/docs/releases/v0.31.0.md +122 -0
  99. package/docs/releases/v0.31.1.md +142 -0
  100. package/docs/releases/v0.31.10.md +118 -0
  101. package/docs/releases/v0.31.11.md +88 -0
  102. package/docs/releases/v0.31.12.md +105 -0
  103. package/docs/releases/v0.31.13.md +99 -0
  104. package/docs/releases/v0.31.14.md +97 -0
  105. package/docs/releases/v0.31.2.md +115 -0
  106. package/docs/releases/v0.31.3.md +142 -0
  107. package/docs/releases/v0.31.4.md +117 -0
  108. package/docs/releases/v0.31.5.md +155 -0
  109. package/docs/releases/v0.31.6.md +132 -0
  110. package/docs/releases/v0.31.7.md +132 -0
  111. package/docs/releases/v0.31.8.md +120 -0
  112. package/docs/releases/v0.31.9.md +120 -0
  113. package/docs/releases/v0.32.0.md +261 -0
  114. package/docs/releases/v0.32.1.md +59 -0
  115. package/docs/releases/v0.33.0.md +164 -0
  116. package/docs/releases/v0.8.0.md +118 -0
  117. package/docs/releases/v0.9.0.md +98 -0
  118. package/docs/releases/v0.9.1.md +83 -0
  119. package/package.json +102 -6
  120. package/plugins/mirror-mind/.claude-plugin/plugin.json +17 -0
  121. package/plugins/mirror-mind/hooks/hooks.json +62 -0
  122. package/plugins/mirror-mind/hooks/log-assistant-reply.sh +98 -0
  123. package/plugins/mirror-mind/hooks/log-session-end.sh +98 -0
  124. package/plugins/mirror-mind/hooks/log-user-prompt.sh +98 -0
  125. package/plugins/mirror-mind/hooks/mirror-inject.sh +98 -0
  126. package/plugins/mirror-mind/hooks/session-start.sh +98 -0
  127. package/plugins/mirror-mind/skills/mm-backup/SKILL.md +27 -0
  128. package/plugins/mirror-mind/skills/mm-build/SKILL.md +1206 -0
  129. package/plugins/mirror-mind/skills/mm-consolidate/SKILL.md +112 -0
  130. package/plugins/mirror-mind/skills/mm-consult/SKILL.md +83 -0
  131. package/plugins/mirror-mind/skills/mm-conversations/SKILL.md +17 -0
  132. package/plugins/mirror-mind/skills/mm-discard/SKILL.md +40 -0
  133. package/plugins/mirror-mind/skills/mm-explore/SKILL.md +241 -0
  134. package/plugins/mirror-mind/skills/mm-help/SKILL.md +104 -0
  135. package/plugins/mirror-mind/skills/mm-identity/SKILL.md +96 -0
  136. package/plugins/mirror-mind/skills/mm-journal/SKILL.md +21 -0
  137. package/plugins/mirror-mind/skills/mm-journey/SKILL.md +37 -0
  138. package/plugins/mirror-mind/skills/mm-journeys/SKILL.md +15 -0
  139. package/plugins/mirror-mind/skills/mm-memories/SKILL.md +20 -0
  140. package/plugins/mirror-mind/skills/mm-mirror/SKILL.md +67 -0
  141. package/plugins/mirror-mind/skills/mm-mute/SKILL.md +18 -0
  142. package/plugins/mirror-mind/skills/mm-new/SKILL.md +18 -0
  143. package/plugins/mirror-mind/skills/mm-recall/SKILL.md +17 -0
  144. package/plugins/mirror-mind/skills/mm-release-notes/SKILL.md +31 -0
  145. package/plugins/mirror-mind/skills/mm-seed/SKILL.md +15 -0
  146. package/plugins/mirror-mind/skills/mm-shadow/SKILL.md +117 -0
  147. package/plugins/mirror-mind/skills/mm-soul/SKILL.md +488 -0
  148. package/plugins/mirror-mind/skills/mm-tasks/SKILL.md +36 -0
  149. package/plugins/mirror-mind/skills/mm-update/SKILL.md +30 -0
  150. package/plugins/mirror-mind/skills/mm-week/SKILL.md +46 -0
  151. package/plugins/mirror-mind/skills/mm-welcome/SKILL.md +22 -0
  152. package/scripts/codex-hooks/session-end.sh +85 -0
  153. package/scripts/codex-hooks/session-start.sh +85 -0
  154. package/scripts/codex-mirror.sh +48 -0
  155. package/templates/identity/README.md +119 -0
  156. package/templates/identity/ego/behavior.yaml +52 -0
  157. package/templates/identity/ego/constraints.yaml +15 -0
  158. package/templates/identity/ego/identity.yaml +43 -0
  159. package/templates/identity/journeys/personal-growth.yaml +39 -0
  160. package/templates/identity/organization/identity.yaml +24 -0
  161. package/templates/identity/organization/principles.yaml +17 -0
  162. package/templates/identity/personas/coach.yaml +94 -0
  163. package/templates/identity/personas/designer.yaml +93 -0
  164. package/templates/identity/personas/doctor.yaml +96 -0
  165. package/templates/identity/personas/engineer.yaml +77 -0
  166. package/templates/identity/personas/financial.yaml +97 -0
  167. package/templates/identity/personas/prompt-engineer.yaml +122 -0
  168. package/templates/identity/personas/researcher.yaml +88 -0
  169. package/templates/identity/personas/strategist.yaml +91 -0
  170. package/templates/identity/personas/teacher.yaml +95 -0
  171. package/templates/identity/personas/therapist.yaml +91 -0
  172. package/templates/identity/personas/thinker.yaml +74 -0
  173. package/templates/identity/personas/writer.yaml +76 -0
  174. package/templates/identity/self/config.yaml +16 -0
  175. package/templates/identity/self/soul.yaml +105 -0
  176. package/templates/identity/user/identity.yaml +30 -0
  177. package/ts/src/backup/staging.ts +62 -0
  178. package/ts/src/backup/zipBackup.ts +267 -0
  179. package/ts/src/backup/zipReader.ts +109 -0
  180. package/ts/src/backup/zipWriter.ts +148 -0
  181. package/ts/src/builder/activeCheckpoint.ts +134 -0
  182. package/ts/src/builder/aggregateStatus.ts +34 -0
  183. package/ts/src/builder/approve.ts +149 -0
  184. package/ts/src/builder/argv.ts +292 -0
  185. package/ts/src/builder/ariadMethod.ts +536 -0
  186. package/ts/src/builder/artifacts/artifactSurfaces.ts +106 -0
  187. package/ts/src/builder/artifacts/artifactWriter.ts +113 -0
  188. package/ts/src/builder/artifacts/closureArtifacts.ts +199 -0
  189. package/ts/src/builder/artifacts/deliveryStoryArtifacts.ts +316 -0
  190. package/ts/src/builder/artifacts/planArtifacts.ts +242 -0
  191. package/ts/src/builder/artifacts/scaffoldSections.ts +273 -0
  192. package/ts/src/builder/artifacts/scaffoldState.ts +227 -0
  193. package/ts/src/builder/artifacts/storyFiles.ts +61 -0
  194. package/ts/src/builder/artifacts/storyIndex.ts +166 -0
  195. package/ts/src/builder/cadence.ts +59 -0
  196. package/ts/src/builder/card.ts +192 -0
  197. package/ts/src/builder/checkpointRefused.ts +66 -0
  198. package/ts/src/builder/closure.ts +964 -0
  199. package/ts/src/builder/commands.ts +2053 -0
  200. package/ts/src/builder/cursorPosition.ts +176 -0
  201. package/ts/src/builder/cursorTransitions.ts +77 -0
  202. package/ts/src/builder/deliveryCursor.ts +577 -0
  203. package/ts/src/builder/deliveryStoryClosure.ts +521 -0
  204. package/ts/src/builder/deliveryStoryPlan.ts +536 -0
  205. package/ts/src/builder/deliveryStoryReady.ts +160 -0
  206. package/ts/src/builder/deliveryStoryRoadmapClosure.ts +151 -0
  207. package/ts/src/builder/expand.ts +336 -0
  208. package/ts/src/builder/flowUnit.ts +339 -0
  209. package/ts/src/builder/homeSurface.ts +122 -0
  210. package/ts/src/builder/implementationGuard.ts +125 -0
  211. package/ts/src/builder/index.ts +11 -0
  212. package/ts/src/builder/lifecycleRefusal.ts +92 -0
  213. package/ts/src/builder/lifecycleRibbon.ts +159 -0
  214. package/ts/src/builder/load.ts +313 -0
  215. package/ts/src/builder/methodAdoption.ts +113 -0
  216. package/ts/src/builder/methodDefinition.ts +429 -0
  217. package/ts/src/builder/methodInspection.ts +371 -0
  218. package/ts/src/builder/plan.ts +408 -0
  219. package/ts/src/builder/planPreauthorization.ts +265 -0
  220. package/ts/src/builder/prepare.ts +225 -0
  221. package/ts/src/builder/projectPaths.ts +64 -0
  222. package/ts/src/builder/pull.ts +356 -0
  223. package/ts/src/builder/pullCandidates.ts +463 -0
  224. package/ts/src/builder/pullCandidatesRender.ts +238 -0
  225. package/ts/src/builder/refinementField.ts +93 -0
  226. package/ts/src/builder/releaseIntent.ts +173 -0
  227. package/ts/src/builder/resumeState.ts +84 -0
  228. package/ts/src/builder/resumeSurface.ts +149 -0
  229. package/ts/src/builder/roadmapGrammar.ts +300 -0
  230. package/ts/src/builder/roadmapScan.ts +97 -0
  231. package/ts/src/builder/roadmapScope.ts +210 -0
  232. package/ts/src/builder/scopePhrases.ts +146 -0
  233. package/ts/src/builder/storyPaths.ts +196 -0
  234. package/ts/src/builder/storyPlanPreauthorization.ts +287 -0
  235. package/ts/src/builder/surfaceProtocol.ts +42 -0
  236. package/ts/src/builder/templateGeneration.ts +148 -0
  237. package/ts/src/builder/transition.ts +178 -0
  238. package/ts/src/consult/args.ts +99 -0
  239. package/ts/src/consult/core.ts +122 -0
  240. package/ts/src/consult/modelCatalog.ts +55 -0
  241. package/ts/src/consult/render.ts +47 -0
  242. package/ts/src/conversation/append.ts +414 -0
  243. package/ts/src/conversation/backfill.ts +387 -0
  244. package/ts/src/conversation/closeTail.ts +467 -0
  245. package/ts/src/conversation/extraction.ts +333 -0
  246. package/ts/src/conversation/extractionDriver.ts +130 -0
  247. package/ts/src/conversation/extractionRun.ts +70 -0
  248. package/ts/src/conversation/hookPayload.ts +51 -0
  249. package/ts/src/conversation/journeyInference.ts +165 -0
  250. package/ts/src/conversation/journeyRepair.ts +114 -0
  251. package/ts/src/conversation/lifecycleFaces.ts +197 -0
  252. package/ts/src/conversation/lifecycleWrites.ts +313 -0
  253. package/ts/src/conversation/listing.ts +77 -0
  254. package/ts/src/conversation/logger.ts +851 -0
  255. package/ts/src/conversation/loggerCli.ts +321 -0
  256. package/ts/src/conversation/loggerRuntime.ts +259 -0
  257. package/ts/src/conversation/metadataLifecycle.ts +443 -0
  258. package/ts/src/conversation/recall.ts +66 -0
  259. package/ts/src/conversation/sessionComposites.ts +258 -0
  260. package/ts/src/conversation/sessionImport.ts +90 -0
  261. package/ts/src/conversation/transcriptBackfill.ts +141 -0
  262. package/ts/src/cultivation/applyActions.ts +241 -0
  263. package/ts/src/cultivation/cluster.ts +86 -0
  264. package/ts/src/cultivation/consolidationStore.ts +281 -0
  265. package/ts/src/cultivation/promptContext.ts +62 -0
  266. package/ts/src/cultivation/propose.ts +305 -0
  267. package/ts/src/cultivation/scan.ts +155 -0
  268. package/ts/src/db/backupGate.ts +47 -0
  269. package/ts/src/db/bootstrap.ts +108 -0
  270. package/ts/src/db/bootstrapLock.ts +223 -0
  271. package/ts/src/db/copyGuard.ts +60 -0
  272. package/ts/src/db/database.ts +397 -0
  273. package/ts/src/db/decode.ts +66 -0
  274. package/ts/src/db/ftsIntegrity.ts +41 -0
  275. package/ts/src/db/migrateOnOpen.ts +214 -0
  276. package/ts/src/db/migrations.ts +576 -0
  277. package/ts/src/db/readyOnOpen.ts +35 -0
  278. package/ts/src/db/rowDecode.ts +42 -0
  279. package/ts/src/db/schema.ts +432 -0
  280. package/ts/src/db/schemaInventory.ts +225 -0
  281. package/ts/src/db/schemaInventorySnapshot.ts +2107 -0
  282. package/ts/src/db/schemaState.ts +91 -0
  283. package/ts/src/db/schemaTsDivergence.ts +114 -0
  284. package/ts/src/descriptor/descriptorRead.ts +49 -0
  285. package/ts/src/docs/docsLint.ts +265 -0
  286. package/ts/src/explorer/handoff.ts +522 -0
  287. package/ts/src/explorer/render.ts +335 -0
  288. package/ts/src/explorer/story.ts +769 -0
  289. package/ts/src/explorer/transition.ts +72 -0
  290. package/ts/src/extensions/bindings.ts +170 -0
  291. package/ts/src/extensions/catalog.ts +249 -0
  292. package/ts/src/extensions/catalogCommands.ts +513 -0
  293. package/ts/src/extensions/catalogWrites.ts +652 -0
  294. package/ts/src/extensions/contextRuntime.ts +325 -0
  295. package/ts/src/extensions/dispatch.ts +374 -0
  296. package/ts/src/extensions/errors.ts +24 -0
  297. package/ts/src/extensions/manifest.ts +356 -0
  298. package/ts/src/extensions/migrations.ts +350 -0
  299. package/ts/src/extraction/conversation.ts +304 -0
  300. package/ts/src/extraction/conversationMetadata.ts +206 -0
  301. package/ts/src/extraction/fencing.ts +106 -0
  302. package/ts/src/extraction/json.ts +17 -0
  303. package/ts/src/extraction/prompts.ts +470 -0
  304. package/ts/src/frontDoor/args.ts +30 -0
  305. package/ts/src/frontDoor/argvShape.ts +106 -0
  306. package/ts/src/frontDoor/buildLoadRuntime.ts +139 -0
  307. package/ts/src/frontDoor/buildRoute.ts +398 -0
  308. package/ts/src/frontDoor/cli.ts +1872 -0
  309. package/ts/src/frontDoor/cloneRoleGuard.ts +98 -0
  310. package/ts/src/frontDoor/consultRoute.ts +50 -0
  311. package/ts/src/frontDoor/contentTailRoute.ts +239 -0
  312. package/ts/src/frontDoor/conversationLoggerRoute.ts +83 -0
  313. package/ts/src/frontDoor/cultivationRoute.ts +210 -0
  314. package/ts/src/frontDoor/dbPath.ts +131 -0
  315. package/ts/src/frontDoor/dbSafetyToolsRoute.ts +240 -0
  316. package/ts/src/frontDoor/exploreRoute.ts +572 -0
  317. package/ts/src/frontDoor/extensionCatalogRoute.ts +252 -0
  318. package/ts/src/frontDoor/frontDoorLog.ts +57 -0
  319. package/ts/src/frontDoor/identityWrite.ts +36 -0
  320. package/ts/src/frontDoor/journeyWriteRoute.ts +26 -0
  321. package/ts/src/frontDoor/lifecycleWriteRoute.ts +110 -0
  322. package/ts/src/frontDoor/liveBackup.ts +100 -0
  323. package/ts/src/frontDoor/mirrorModeRoute.ts +163 -0
  324. package/ts/src/frontDoor/namedRefusal.ts +35 -0
  325. package/ts/src/frontDoor/nodeSupport.ts +24 -0
  326. package/ts/src/frontDoor/render/consolidate.ts +199 -0
  327. package/ts/src/frontDoor/render/conversations.ts +33 -0
  328. package/ts/src/frontDoor/render/cultivationShared.ts +21 -0
  329. package/ts/src/frontDoor/render/descriptor.ts +20 -0
  330. package/ts/src/frontDoor/render/detectPersona.ts +50 -0
  331. package/ts/src/frontDoor/render/icons.ts +13 -0
  332. package/ts/src/frontDoor/render/identity.ts +59 -0
  333. package/ts/src/frontDoor/render/identityRows.ts +17 -0
  334. package/ts/src/frontDoor/render/inspectPersona.ts +53 -0
  335. package/ts/src/frontDoor/render/journeyStatus.ts +78 -0
  336. package/ts/src/frontDoor/render/journeys.ts +79 -0
  337. package/ts/src/frontDoor/render/list.ts +41 -0
  338. package/ts/src/frontDoor/render/memories.ts +67 -0
  339. package/ts/src/frontDoor/render/recall.ts +49 -0
  340. package/ts/src/frontDoor/render/shadow.ts +155 -0
  341. package/ts/src/frontDoor/render/tasks.ts +99 -0
  342. package/ts/src/frontDoor/render/tasksImportSync.ts +63 -0
  343. package/ts/src/frontDoor/render/week.ts +113 -0
  344. package/ts/src/frontDoor/routing.ts +1001 -0
  345. package/ts/src/frontDoor/runtimeRoute.ts +623 -0
  346. package/ts/src/frontDoor/searchRoute.ts +166 -0
  347. package/ts/src/frontDoor/seedPaths.ts +98 -0
  348. package/ts/src/frontDoor/sessionStartWelcomeRoute.ts +166 -0
  349. package/ts/src/frontDoor/soulRoute.ts +433 -0
  350. package/ts/src/frontDoor/stdinSource.ts +37 -0
  351. package/ts/src/frontDoor/tasksImportSyncRoute.ts +110 -0
  352. package/ts/src/frontDoor/tasksWriteRoute.ts +101 -0
  353. package/ts/src/frontDoor/usage.ts +176 -0
  354. package/ts/src/guards/claudePlugin.ts +298 -0
  355. package/ts/src/guards/packContents.ts +306 -0
  356. package/ts/src/guards/piSourcedSkills.ts +70 -0
  357. package/ts/src/guards/retiredRouteShadows.ts +57 -0
  358. package/ts/src/guards/retiredSurfaces.ts +564 -0
  359. package/ts/src/hooks/claude.ts +214 -0
  360. package/ts/src/hooks/codex.ts +45 -0
  361. package/ts/src/hooks/gemini.ts +126 -0
  362. package/ts/src/hooks/main.ts +109 -0
  363. package/ts/src/hooks/mirrorState.ts +71 -0
  364. package/ts/src/hooks/payload.ts +73 -0
  365. package/ts/src/hooks/runtime.ts +179 -0
  366. package/ts/src/hooks/runtimeDetection.ts +34 -0
  367. package/ts/src/identity/applyConsolidationIdentityUpdate.ts +67 -0
  368. package/ts/src/identity/descriptorGenerate.ts +162 -0
  369. package/ts/src/identity/identityEdit.ts +143 -0
  370. package/ts/src/identity/identityKey.ts +77 -0
  371. package/ts/src/identity/identityRead.ts +69 -0
  372. package/ts/src/identity/identityStore.ts +80 -0
  373. package/ts/src/identity/journeyListing.ts +53 -0
  374. package/ts/src/identity/personaInspect.ts +44 -0
  375. package/ts/src/identity/personaListing.ts +37 -0
  376. package/ts/src/identity/setIdentity.ts +64 -0
  377. package/ts/src/index.ts +231 -0
  378. package/ts/src/init/init.ts +111 -0
  379. package/ts/src/journey/journeyOptions.ts +131 -0
  380. package/ts/src/journey/journeyRemoval.ts +158 -0
  381. package/ts/src/journey/journeyStatus.ts +149 -0
  382. package/ts/src/journey/journeySyncFile.ts +87 -0
  383. package/ts/src/journey/journeyWrite.ts +203 -0
  384. package/ts/src/journey/parentJourney.ts +41 -0
  385. package/ts/src/journey/validateParentJourney.ts +55 -0
  386. package/ts/src/mcp/boundary.ts +151 -0
  387. package/ts/src/mcp/guards.ts +244 -0
  388. package/ts/src/mcp/main.ts +121 -0
  389. package/ts/src/mcp/payload.ts +141 -0
  390. package/ts/src/mcp/protocol.ts +141 -0
  391. package/ts/src/mcp/readModels.ts +241 -0
  392. package/ts/src/mcp/registry.ts +201 -0
  393. package/ts/src/mcp/serve.ts +120 -0
  394. package/ts/src/mcp/tools/deterministic.ts +137 -0
  395. package/ts/src/mcp/tools/providerCrossing.ts +187 -0
  396. package/ts/src/mcp/wire.ts +8 -0
  397. package/ts/src/memory/journal.ts +180 -0
  398. package/ts/src/memory/listing.ts +107 -0
  399. package/ts/src/memory/memoryWrite.ts +88 -0
  400. package/ts/src/memory/reinforcement.ts +35 -0
  401. package/ts/src/mirror/context.ts +161 -0
  402. package/ts/src/mirror/defaultResolution.ts +199 -0
  403. package/ts/src/mirror/mirrorForm.ts +43 -0
  404. package/ts/src/mirror/orchestration.ts +364 -0
  405. package/ts/src/mirror/reception.ts +194 -0
  406. package/ts/src/mirror/render.ts +75 -0
  407. package/ts/src/mirror/runtimeSession.ts +205 -0
  408. package/ts/src/mode/operatingMode.ts +148 -0
  409. package/ts/src/observability/callOutcome.ts +115 -0
  410. package/ts/src/observability/inspectLedger.ts +329 -0
  411. package/ts/src/observability/ledgerHooks.ts +126 -0
  412. package/ts/src/observability/llmCalls.ts +154 -0
  413. package/ts/src/persona/detectPersona.ts +81 -0
  414. package/ts/src/planning/promptAssembly.ts +111 -0
  415. package/ts/src/planning/weekPending.ts +81 -0
  416. package/ts/src/planning/weekPlan.ts +183 -0
  417. package/ts/src/planning/weekSave.ts +117 -0
  418. package/ts/src/providers/config.ts +189 -0
  419. package/ts/src/providers/cost.ts +64 -0
  420. package/ts/src/providers/credits.ts +204 -0
  421. package/ts/src/providers/embedding.ts +321 -0
  422. package/ts/src/providers/familyProviders.ts +147 -0
  423. package/ts/src/providers/llm.ts +334 -0
  424. package/ts/src/providers/openrouter.ts +244 -0
  425. package/ts/src/providers/redaction.ts +110 -0
  426. package/ts/src/providers/replay.ts +15 -0
  427. package/ts/src/providers/transport.ts +410 -0
  428. package/ts/src/repair/encodingRepair.ts +253 -0
  429. package/ts/src/runtime/backup.ts +151 -0
  430. package/ts/src/runtime/channel.ts +146 -0
  431. package/ts/src/runtime/config.ts +168 -0
  432. package/ts/src/runtime/diagnose.ts +686 -0
  433. package/ts/src/runtime/git.ts +510 -0
  434. package/ts/src/runtime/installKind.ts +220 -0
  435. package/ts/src/runtime/migrate.ts +154 -0
  436. package/ts/src/runtime/packageIdentity.ts +102 -0
  437. package/ts/src/runtime/releaseNotes.ts +244 -0
  438. package/ts/src/runtime/status.ts +557 -0
  439. package/ts/src/runtime/strategies/clone.ts +200 -0
  440. package/ts/src/runtime/strategies/package.ts +328 -0
  441. package/ts/src/runtime/treeRoot.ts +30 -0
  442. package/ts/src/runtime/update.ts +445 -0
  443. package/ts/src/runtime/updateGate.ts +40 -0
  444. package/ts/src/runtime/updatePipeline.ts +159 -0
  445. package/ts/src/runtime/version.ts +36 -0
  446. package/ts/src/runtime/wiring.ts +130 -0
  447. package/ts/src/search/memorySearch.ts +338 -0
  448. package/ts/src/search/ranker.ts +154 -0
  449. package/ts/src/seed/seed.ts +256 -0
  450. package/ts/src/seed/seedYaml.ts +133 -0
  451. package/ts/src/soul/apply.ts +218 -0
  452. package/ts/src/soul/harvest.ts +267 -0
  453. package/ts/src/soul/prompts/soul_beauty_voice.md +103 -0
  454. package/ts/src/soul/prompts/soul_self_voice.md +219 -0
  455. package/ts/src/soul/prompts/soul_wisdom_voice.md +121 -0
  456. package/ts/src/soul/prompts.ts +85 -0
  457. package/ts/src/soul/render.ts +358 -0
  458. package/ts/src/soul/state.ts +212 -0
  459. package/ts/src/soul/transition.ts +37 -0
  460. package/ts/src/tasks/journeyPathParse.ts +113 -0
  461. package/ts/src/tasks/taskImportSync.ts +142 -0
  462. package/ts/src/tasks/taskStore.ts +312 -0
  463. package/ts/src/tasks/weekView.ts +120 -0
  464. package/ts/src/util/clipCodePoints.ts +26 -0
  465. package/ts/src/util/paths.ts +63 -0
  466. package/ts/src/util/program.ts +9 -0
  467. package/ts/src/util/pyGenerators.ts +144 -0
  468. package/ts/src/util/pythonText.ts +317 -0
  469. package/ts/src/util/semver.ts +45 -0
  470. package/ts/src/util/shellWord.ts +25 -0
  471. package/ts/src/util/slug.ts +64 -0
  472. package/ts/src/welcome/card.ts +339 -0
  473. package/ts/src/welcome/statusLine.ts +101 -0
  474. package/ts/src/welcome/updateCache.ts +129 -0
@@ -0,0 +1,166 @@
1
+ import type { WritableDatabase } from "#db/database.ts";
2
+ import { requireString } from "#db/rowDecode.ts";
3
+ import type { EmbeddingProvider } from "#providers/embedding.ts";
4
+ import { resolveFamilyProviders } from "#providers/familyProviders.ts";
5
+ import { SEARCH_TRANSPORT } from "#providers/transport.ts";
6
+ import type { FreshSearchResult } from "#search/memorySearch.ts";
7
+ import { searchMemoriesWithStatus } from "#search/memorySearch.ts";
8
+ import { optionValue } from "./args.ts";
9
+ import { ICONS } from "./render/icons.ts";
10
+ import { tagsText } from "./render/memories.ts";
11
+
12
+ // Mirrors Python's cli/memories.py degraded_note wording exactly (AI-04),
13
+ // including under a degraded search with zero results.
14
+ const DEGRADED_NOTE =
15
+ "⚠ Degraded: lexical-only search (embedding unavailable — offline or no API key).";
16
+
17
+ export interface SearchMemoryRow {
18
+ id: string;
19
+ memory_type: string;
20
+ layer: string;
21
+ title: string;
22
+ content: string;
23
+ created_at: string;
24
+ journey: string | null;
25
+ tags: string | null;
26
+ }
27
+
28
+ /**
29
+ * Resolve the embedding provider by the same precedence the router used
30
+ * (CV22.DS8.US1), so the route can never disagree with the routing decision
31
+ * about which transport is in play.
32
+ */
33
+ export async function resolveSearchEmbeddingProvider(
34
+ env: NodeJS.ProcessEnv = process.env,
35
+ ): Promise<EmbeddingProvider> {
36
+ // The live provider resolves its config lazily, so a missing key surfaces
37
+ // inside searchMemoriesWithStatus and degrades to lexical-only rather than
38
+ // failing the command -- Python's behavior for an unconfigured install.
39
+ const family = await resolveFamilyProviders(env, SEARCH_TRANSPORT);
40
+ if (!family.embedding) {
41
+ // The search family declares an embedding fixture, so replay and live both
42
+ // build one; this is defense in depth, not a reachable state.
43
+ throw new Error("memories --search requires an embedding provider");
44
+ }
45
+ return family.embedding;
46
+ }
47
+
48
+ export interface MemorySearchRouteOptions {
49
+ /** Receives a content-free degraded category for the front-door log. */
50
+ onDegraded?: (detail: string) => void;
51
+ }
52
+
53
+ export async function runMemorySearchRoute(
54
+ db: WritableDatabase,
55
+ args: readonly string[],
56
+ options: MemorySearchRouteOptions = {},
57
+ ): Promise<string> {
58
+ const query = optionValue(args, "--search");
59
+ if (!query) throw new Error("memories --search requires a query");
60
+ const provider = await resolveSearchEmbeddingProvider();
61
+ const limit = Number(optionValue(args, "--limit") ?? 20);
62
+ const { results, degraded, degradedKind } = await searchMemoriesWithStatus(db, {
63
+ query,
64
+ limit,
65
+ memoryType: optionValue(args, "--type"),
66
+ layer: optionValue(args, "--layer"),
67
+ journey: optionValue(args, "--journey"),
68
+ provider,
69
+ // An exploratory CLI search is not a genuine context load, so it must not
70
+ // reinforce: `access_count` feeds `reinforcement_score` and the hybrid
71
+ // ranker, and a ranker fed by its own exhaust drifts toward whatever was
72
+ // searched for rather than whatever was used (AI-12). Python's
73
+ // `cli/memories.py` has passed `log_access=False` since 2026-07-16; this
74
+ // port did not, and reinforced on every `memories --search` from the flip
75
+ // until CV22.DS9.US2 measured it. Builder context load deliberately keeps
76
+ // the default and still reinforces -- that one IS a genuine load.
77
+ logAccess: false,
78
+ });
79
+ // A degraded live search is the one failure an operator has to diagnose
80
+ // without a re-run, so the taxonomy class reaches the front-door log rather
81
+ // than dying inside the degrade path. Category only -- never a message,
82
+ // never the query (RS005/CR026).
83
+ if (degraded && degradedKind) {
84
+ options.onDegraded?.(`embedding_degraded kind=${degradedKind}`);
85
+ }
86
+ const rows = memoriesById(
87
+ db,
88
+ results.map((result) => result.id),
89
+ );
90
+ return formatSearchResults(query, results, rows, degraded);
91
+ }
92
+
93
+ /**
94
+ * Pure rendering of a fresh-search outcome (AI-04). Split out from
95
+ * `runMemorySearchRoute` so the degraded/normal render branches are directly
96
+ * unit-testable without a database or a live-failing embedding provider (none
97
+ * exists yet -- see CR037 plan).
98
+ */
99
+ export function formatSearchResults(
100
+ query: string,
101
+ results: readonly FreshSearchResult[],
102
+ rows: ReadonlyMap<string, SearchMemoryRow>,
103
+ degraded: boolean,
104
+ ): string {
105
+ if (results.length === 0) {
106
+ return degraded ? `${DEGRADED_NOTE}\n` : "No memories found.\n";
107
+ }
108
+ const lines: string[] = [];
109
+ if (degraded) {
110
+ lines.push(`${DEGRADED_NOTE} Ranked by keyword match.`, "");
111
+ }
112
+ lines.push(`🔍 Search: "${query}" (${results.length} results)`, "");
113
+ for (const result of results) {
114
+ const memory = rows.get(result.id);
115
+ if (!memory) continue;
116
+ const icon = ICONS[memory.memory_type] ?? "•";
117
+ const date = memory.created_at ? memory.created_at.slice(0, 10) : "?";
118
+ const journey = memory.journey ? ` 🧭 ${memory.journey}` : "";
119
+ const tags = tagsText(memory.tags);
120
+ lines.push(`${icon} **${memory.title}** (score: ${result.score.toFixed(3)})`);
121
+ lines.push(
122
+ ` ${date} | \`${memory.id.slice(0, 8)}\` | ${memory.memory_type} [${memory.layer}]${journey}`,
123
+ );
124
+ lines.push(` ${memory.content.slice(0, 200)}`);
125
+ if (tags) lines.push(` 🏷 ${tags}`);
126
+ lines.push("");
127
+ }
128
+ return `${lines.join("\n")}\n`;
129
+ }
130
+
131
+ /**
132
+ * The row reader both search faces share.
133
+ *
134
+ * Exported for `build load` (CV22.DS7.US8 plateau 7), which renders the same
135
+ * memories from the same ranked ids: the ranker returns `{id, score}` only, so a
136
+ * second copy of this query is a second chance for the two blocks to disagree
137
+ * about what a memory says.
138
+ */
139
+ export function memoriesById(
140
+ db: WritableDatabase,
141
+ ids: readonly string[],
142
+ ): Map<string, SearchMemoryRow> {
143
+ if (ids.length === 0) return new Map();
144
+ const placeholders = ids.map(() => "?").join(", ");
145
+ const rows = db
146
+ .prepare(
147
+ `SELECT id, memory_type, layer, title, content, created_at, journey, tags FROM memories ` +
148
+ `WHERE id IN (${placeholders})`,
149
+ )
150
+ .all(...ids);
151
+ return new Map(
152
+ rows.map((row) => [
153
+ requireString(row, "id"),
154
+ {
155
+ id: requireString(row, "id"),
156
+ memory_type: requireString(row, "memory_type"),
157
+ layer: requireString(row, "layer"),
158
+ title: requireString(row, "title"),
159
+ content: requireString(row, "content"),
160
+ created_at: requireString(row, "created_at"),
161
+ journey: typeof row.journey === "string" ? row.journey : null,
162
+ tags: typeof row.tags === "string" ? row.tags : null,
163
+ },
164
+ ]),
165
+ );
166
+ }
@@ -0,0 +1,98 @@
1
+ // `seed` path resolution — the port of the bespoke resolution inside
2
+ // memory.cli.seed.seed(), which is NOT the same precedence chain
3
+ // `resolveDbPath` (dbPath.ts) uses for every other command. Verified against
4
+ // the live oracle (never assumed) because it diverges in a genuinely
5
+ // surprising way:
6
+ //
7
+ // - `identity_root`/`mirror_home` resolve via `--mirror-home` or the plain
8
+ // MIRROR_HOME/MIRROR_USER chain (`resolveMirrorHome`) -- completely
9
+ // independent of `--env`, `MEMORY_DIR`, or `DB_PATH`.
10
+ // - When `--mirror-home` IS given, the database path is ALWAYS
11
+ // `<mirror_home>/memory.db` -- `--env` is silently ignored for the
12
+ // filename (`default_db_path_for_home` hardcodes "memory.db"). Confirmed
13
+ // live: `seed --mirror-home X --env test` writes `X/memory.db`, not
14
+ // `X/memory_test.db`.
15
+ // - When `--mirror-home` is absent and `--env` differs from the ambient
16
+ // `MEMORY_ENV` (or ambient is unset, defaulting "production" like Python's
17
+ // module-level MEMORY_ENV constant), the database path follows
18
+ // `db_path_for_env`: MEMORY_PROD_DIR (production only) > MEMORY_DIR > the
19
+ // resolved mirror home, with the env-appropriate filename -- but WITHOUT
20
+ // checking `DB_PATH` (that env var is only wired to the *ambient*
21
+ // environment in Python, cached once at import time).
22
+ // - When `--mirror-home` is absent and `--env` matches the ambient
23
+ // `MEMORY_ENV` (or is omitted), the database path follows the SAME full
24
+ // generic chain every other command uses (`require_db_path()` ==
25
+ // `resolveDbPath`).
26
+ //
27
+ // `--db-path` is a TS-front-door-only convenience (Python's `seed` CLI has no
28
+ // such flag), kept here for consistency with every other ported command --
29
+ // it wins over everything, as documented in dbPath.ts.
30
+
31
+ import { join } from "node:path";
32
+ import { expandHome } from "#util/paths.ts";
33
+ import { optionValue } from "./args.ts";
34
+ import {
35
+ type DbPathEnv,
36
+ type DbPathIo,
37
+ dbNameForEnv,
38
+ MirrorHomeNotConfiguredError,
39
+ resolveDbPath,
40
+ resolveMirrorHome,
41
+ } from "./dbPath.ts";
42
+
43
+ export interface SeedPaths {
44
+ dbPath: string;
45
+ identityRoot: string;
46
+ mirrorHome: string;
47
+ env: string;
48
+ }
49
+
50
+ /**
51
+ * Resolve `seed`'s database path, identity root, mirror home, and effective
52
+ * env, mirroring the Python branches documented above exactly. Throws
53
+ * MirrorHomeNotConfiguredError when nothing resolves (mapped to exit 2 by the
54
+ * caller, matching every other command's unconfigured-home contract).
55
+ */
56
+ export function resolveSeedPaths(
57
+ args: readonly string[],
58
+ env: DbPathEnv = process.env,
59
+ io: DbPathIo = {},
60
+ ): SeedPaths {
61
+ const explicitDbPath = optionValue(args, "--db-path");
62
+ const explicitMirrorHome = optionValue(args, "--mirror-home");
63
+ const envFlag = optionValue(args, "--env");
64
+ const ambientEnv = env.MEMORY_ENV || "production";
65
+ const effectiveEnv = envFlag || ambientEnv;
66
+
67
+ const mirrorHome = explicitMirrorHome
68
+ ? expandHome(explicitMirrorHome)
69
+ : resolveMirrorHome(env, io);
70
+ const identityRoot = join(mirrorHome, "identity");
71
+
72
+ if (explicitDbPath) {
73
+ return { dbPath: expandHome(explicitDbPath), identityRoot, mirrorHome, env: effectiveEnv };
74
+ }
75
+ if (explicitMirrorHome) {
76
+ // default_db_path_for_home: ALWAYS "memory.db", --env is not consulted.
77
+ return { dbPath: join(mirrorHome, "memory.db"), identityRoot, mirrorHome, env: effectiveEnv };
78
+ }
79
+ if (envFlag && envFlag !== ambientEnv) {
80
+ const dbName = dbNameForEnv(envFlag);
81
+ let dir: string;
82
+ if (envFlag === "production" && env.MEMORY_PROD_DIR) {
83
+ dir = expandHome(env.MEMORY_PROD_DIR);
84
+ } else if (env.MEMORY_DIR) {
85
+ dir = expandHome(env.MEMORY_DIR);
86
+ } else {
87
+ dir = mirrorHome;
88
+ }
89
+ return { dbPath: join(dir, dbName), identityRoot, mirrorHome, env: effectiveEnv };
90
+ }
91
+ // require_db_path(): by construction neither --db-path nor --mirror-home is
92
+ // present here, so this is exactly resolveDbPath's own DB_PATH ->
93
+ // MEMORY_PROD_DIR -> MEMORY_DIR -> resolved-mirror-home chain -- the same
94
+ // one every other command uses. Reused directly rather than re-implemented.
95
+ return { dbPath: resolveDbPath(args, env, io), identityRoot, mirrorHome, env: effectiveEnv };
96
+ }
97
+
98
+ export { MirrorHomeNotConfiguredError };
@@ -0,0 +1,166 @@
1
+ // `conversation-logger session-start --fast --welcome --format json` (CV9.E2.S32).
2
+ //
3
+ // The Pi extension used to open a session with three awaited front-door
4
+ // processes in a row -- `session-start --fast`, `welcome`, and
5
+ // `welcome --status-line` -- paying the loader's fixed cost three times
6
+ // before the user could type. They cannot run in parallel: the first WRITES
7
+ // the orientation the other two READ. They can run in one process, as long as
8
+ // the write commits before the reads. This route is that sequencing and
9
+ // nothing else.
10
+ //
11
+ // What it deliberately does not do:
12
+ //
13
+ // * It does not teach `loggerCli.ts` to render a welcome card. That module
14
+ // is the conversation domain; composition across domains is this layer's
15
+ // job.
16
+ // * It does not touch `runWelcomeRoute`'s read-only contract. Both renders
17
+ // run through that route with captured io, AFTER the write handle has
18
+ // closed, so the card and the status line are byte-identical to the
19
+ // standalone commands and never share the live write lock with the
20
+ // card's bounded update check.
21
+ // * It has no text form. The card is free text; the only safe delimiter is
22
+ // a JSON envelope.
23
+ //
24
+ // The envelope is for the extension, not for a skill. A skill that called this
25
+ // would put card text in front of the model through a channel the Ariad
26
+ // surface rules do not cover; `checkSkillCommandParity.ts` refuses the flag in
27
+ // every SKILL.md.
28
+
29
+ import type { WritableDatabase } from "#db/database.ts";
30
+ import { runConversationLoggerRoute } from "./conversationLoggerRoute.ts";
31
+ import { runWelcomeRoute } from "./runtimeRoute.ts";
32
+
33
+ export const SESSION_START_WELCOME_SCHEMA_VERSION = "1.0.0";
34
+
35
+ export interface SessionStartWelcomeEnvelope {
36
+ schemaVersion: typeof SESSION_START_WELCOME_SCHEMA_VERSION;
37
+ /** The logger's stdout lines, joined with `\n`: what `session-start --fast` prints. */
38
+ sessionStart: string;
39
+ /** `mirror welcome`'s stdout minus the trailing newline; `""` when disabled. */
40
+ welcome: string;
41
+ /** `mirror welcome --status-line`'s stdout minus the trailing newline; `""` when empty. */
42
+ statusLine: string;
43
+ }
44
+
45
+ export interface SessionStartWelcomeOutcome {
46
+ exitCode: number;
47
+ /** Content-free category for the front-door log when a render failed after the write. */
48
+ detail?: string;
49
+ }
50
+
51
+ export interface SessionStartWelcomeDeps {
52
+ /** The real write path: opens the live write database, runs `write`, closes it. */
53
+ withMirrorWriteDb: (
54
+ argv: readonly string[],
55
+ write: (db: WritableDatabase, dbPath: string) => Promise<number> | number,
56
+ ) => Promise<number>;
57
+ /**
58
+ * The welcome renderer. Defaults to the real route; the render-failure test
59
+ * injects one that throws. The write path is never injected: it is the real
60
+ * one in every test.
61
+ */
62
+ renderWelcome?: typeof runWelcomeRoute;
63
+ stdout?: (text: string) => void;
64
+ stderr?: (text: string) => void;
65
+ }
66
+
67
+ /** Only the `--fast --welcome` composite answers here; everything else is the plain logger route. */
68
+ export function isSessionStartWelcome(argv: readonly string[]): boolean {
69
+ return (
70
+ argv[0] === "conversation-logger" &&
71
+ argv.includes("session-start") &&
72
+ argv.includes("--welcome")
73
+ );
74
+ }
75
+
76
+ function optionValue(args: readonly string[], name: string): string | null {
77
+ const index = args.indexOf(name);
78
+ if (index === -1) return null;
79
+ return args[index + 1] ?? null;
80
+ }
81
+
82
+ /** The logger's `--mirror-home` reaches the welcome renders too, so both read the same home. */
83
+ function welcomeArgv(argv: readonly string[], statusLine: boolean): string[] {
84
+ const out = ["welcome"];
85
+ if (statusLine) out.push("--status-line");
86
+ const home = optionValue(argv, "--mirror-home");
87
+ if (home !== null) out.push("--mirror-home", home);
88
+ const sessionId = optionValue(argv, "--session-id");
89
+ if (statusLine && sessionId !== null) out.push("--session-id", sessionId);
90
+ return out;
91
+ }
92
+
93
+ /** The logger's own argv: the composite flags removed, `--format`'s value with it. */
94
+ function withoutCompositeFlags(argv: readonly string[]): string[] {
95
+ const out: string[] = [];
96
+ for (let i = 0; i < argv.length; i += 1) {
97
+ const arg = argv[i] as string;
98
+ if (arg === "--welcome") continue;
99
+ if (arg === "--format") {
100
+ i += 1;
101
+ continue;
102
+ }
103
+ out.push(arg);
104
+ }
105
+ return out;
106
+ }
107
+
108
+ function stripTrailingNewline(text: string): string {
109
+ return text.endsWith("\n") ? text.slice(0, -1) : text;
110
+ }
111
+
112
+ export async function runSessionStartWelcomeRoute(
113
+ argv: readonly string[],
114
+ deps: SessionStartWelcomeDeps,
115
+ ): Promise<SessionStartWelcomeOutcome> {
116
+ const stdout = deps.stdout ?? ((text: string) => process.stdout.write(text));
117
+ const stderr = deps.stderr ?? ((text: string) => process.stderr.write(text));
118
+ const renderWelcome = deps.renderWelcome ?? runWelcomeRoute;
119
+
120
+ if (!argv.includes("--fast")) {
121
+ stderr("session-start: --welcome requires --fast (the full session-start runs maintenance)\n");
122
+ return { exitCode: 2 };
123
+ }
124
+ const format = optionValue(argv, "--format");
125
+ if (format !== "json") {
126
+ stderr(
127
+ "session-start: --welcome requires --format json (the card has no safe text delimiter)\n",
128
+ );
129
+ return { exitCode: 2 };
130
+ }
131
+
132
+ // 1. The write, through the real path. Its handle is closed when this returns.
133
+ const loggerArgv = withoutCompositeFlags(argv);
134
+ const sessionStartLines: string[] = [];
135
+ const exitCode = await deps.withMirrorWriteDb(loggerArgv, (db, dbPath) =>
136
+ runConversationLoggerRoute(db, dbPath, loggerArgv, {
137
+ stdout: (line) => sessionStartLines.push(line),
138
+ // The logger's refusals keep going to stderr, as they do standalone.
139
+ stderr: (line) => stderr(`${line}\n`),
140
+ }),
141
+ );
142
+ if (exitCode !== 0) return { exitCode };
143
+
144
+ // 2. The reads, after the write committed and its handle closed. A render
145
+ // failure must not lose the unmute: the envelope still goes out, with the
146
+ // failed field empty, and the category reaches the front-door log.
147
+ let detail: string | undefined;
148
+ const render = (statusLine: boolean): string => {
149
+ let captured = "";
150
+ try {
151
+ renderWelcome(welcomeArgv(argv, statusLine), { stdout: (text) => (captured += text) });
152
+ } catch (error) {
153
+ detail = `render-failed=${error instanceof Error ? error.name : "unknown"}`;
154
+ return "";
155
+ }
156
+ return stripTrailingNewline(captured);
157
+ };
158
+ const envelope: SessionStartWelcomeEnvelope = {
159
+ schemaVersion: SESSION_START_WELCOME_SCHEMA_VERSION,
160
+ sessionStart: sessionStartLines.join("\n"),
161
+ welcome: render(false),
162
+ statusLine: render(true),
163
+ };
164
+ stdout(`${JSON.stringify(envelope)}\n`);
165
+ return detail ? { exitCode: 0, detail } : { exitCode: 0 };
166
+ }