mirror-mind 0.0.1 → 0.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. package/.claude/hooks/log-session-end.sh +85 -0
  2. package/.claude/hooks/log-user-prompt.sh +85 -0
  3. package/.claude/hooks/mirror-inject.sh +85 -0
  4. package/.claude/hooks/session-start.sh +85 -0
  5. package/.gemini/hooks/log-assistant.sh +85 -0
  6. package/.gemini/hooks/log-user.sh +85 -0
  7. package/.gemini/hooks/session-end.sh +85 -0
  8. package/.gemini/hooks/session-start.sh +85 -0
  9. package/.pi/extensions/mirror-logger.ts +561 -0
  10. package/.pi/skills/mm-backup/SKILL.md +21 -0
  11. package/.pi/skills/mm-build/SKILL.md +1206 -0
  12. package/.pi/skills/mm-consolidate/SKILL.md +112 -0
  13. package/.pi/skills/mm-consult/SKILL.md +70 -0
  14. package/.pi/skills/mm-conversations/SKILL.md +16 -0
  15. package/.pi/skills/mm-discard/SKILL.md +39 -0
  16. package/.pi/skills/mm-explore/SKILL.md +255 -0
  17. package/.pi/skills/mm-help/SKILL.md +74 -0
  18. package/.pi/skills/mm-identity/SKILL.md +96 -0
  19. package/.pi/skills/mm-journal/SKILL.md +16 -0
  20. package/.pi/skills/mm-journey/SKILL.md +23 -0
  21. package/.pi/skills/mm-journeys/SKILL.md +15 -0
  22. package/.pi/skills/mm-memories/SKILL.md +17 -0
  23. package/.pi/skills/mm-mirror/SKILL.md +98 -0
  24. package/.pi/skills/mm-mute/SKILL.md +18 -0
  25. package/.pi/skills/mm-new/SKILL.md +18 -0
  26. package/.pi/skills/mm-recall/SKILL.md +17 -0
  27. package/.pi/skills/mm-release-notes/SKILL.md +52 -0
  28. package/.pi/skills/mm-seed/SKILL.md +19 -0
  29. package/.pi/skills/mm-shadow/SKILL.md +117 -0
  30. package/.pi/skills/mm-soul/SKILL.md +502 -0
  31. package/.pi/skills/mm-tasks/SKILL.md +24 -0
  32. package/.pi/skills/mm-update/SKILL.md +32 -0
  33. package/.pi/skills/mm-week/SKILL.md +28 -0
  34. package/.pi/skills/mm-welcome/SKILL.md +24 -0
  35. package/AGENTS.md +188 -0
  36. package/README.md +126 -9
  37. package/bin/loader.js +67 -0
  38. package/bin/mirror-hook.js +7 -0
  39. package/bin/mirror.js +7 -0
  40. package/docs/releases/index.md +99 -0
  41. package/docs/releases/pending-cutoffs.md +510 -0
  42. package/docs/releases/v0.10.0.md +123 -0
  43. package/docs/releases/v0.10.1.md +66 -0
  44. package/docs/releases/v0.10.10.md +51 -0
  45. package/docs/releases/v0.10.11.md +39 -0
  46. package/docs/releases/v0.10.12.md +57 -0
  47. package/docs/releases/v0.10.13.md +35 -0
  48. package/docs/releases/v0.10.14.md +42 -0
  49. package/docs/releases/v0.10.15.md +53 -0
  50. package/docs/releases/v0.10.16.md +35 -0
  51. package/docs/releases/v0.10.17.md +43 -0
  52. package/docs/releases/v0.10.2.md +64 -0
  53. package/docs/releases/v0.10.3.md +78 -0
  54. package/docs/releases/v0.10.4.md +42 -0
  55. package/docs/releases/v0.10.5.md +57 -0
  56. package/docs/releases/v0.10.6.md +47 -0
  57. package/docs/releases/v0.10.7.md +53 -0
  58. package/docs/releases/v0.10.8.md +49 -0
  59. package/docs/releases/v0.10.9.md +37 -0
  60. package/docs/releases/v0.11.0.md +86 -0
  61. package/docs/releases/v0.12.0.md +67 -0
  62. package/docs/releases/v0.13.0.md +64 -0
  63. package/docs/releases/v0.14.0.md +68 -0
  64. package/docs/releases/v0.15.0.md +48 -0
  65. package/docs/releases/v0.16.0.md +50 -0
  66. package/docs/releases/v0.16.1.md +55 -0
  67. package/docs/releases/v0.16.2.md +36 -0
  68. package/docs/releases/v0.17.0.md +50 -0
  69. package/docs/releases/v0.17.1.md +58 -0
  70. package/docs/releases/v0.17.2.md +42 -0
  71. package/docs/releases/v0.17.3.md +58 -0
  72. package/docs/releases/v0.18.0.md +84 -0
  73. package/docs/releases/v0.18.1.md +51 -0
  74. package/docs/releases/v0.18.2.md +69 -0
  75. package/docs/releases/v0.19.0.md +85 -0
  76. package/docs/releases/v0.19.1.md +46 -0
  77. package/docs/releases/v0.20.0.md +85 -0
  78. package/docs/releases/v0.21.0.md +61 -0
  79. package/docs/releases/v0.21.1.md +47 -0
  80. package/docs/releases/v0.22.0.md +77 -0
  81. package/docs/releases/v0.22.1.md +42 -0
  82. package/docs/releases/v0.23.0.md +105 -0
  83. package/docs/releases/v0.24.0.md +125 -0
  84. package/docs/releases/v0.25.0.md +107 -0
  85. package/docs/releases/v0.26.0.md +139 -0
  86. package/docs/releases/v0.26.1.md +65 -0
  87. package/docs/releases/v0.26.2.md +43 -0
  88. package/docs/releases/v0.27.0.md +63 -0
  89. package/docs/releases/v0.28.0.md +59 -0
  90. package/docs/releases/v0.29.0.md +61 -0
  91. package/docs/releases/v0.29.1.md +59 -0
  92. package/docs/releases/v0.29.2.md +59 -0
  93. package/docs/releases/v0.29.3.md +93 -0
  94. package/docs/releases/v0.30.0.md +75 -0
  95. package/docs/releases/v0.30.1.md +93 -0
  96. package/docs/releases/v0.30.2.md +66 -0
  97. package/docs/releases/v0.31.0.md +122 -0
  98. package/docs/releases/v0.31.1.md +142 -0
  99. package/docs/releases/v0.31.10.md +118 -0
  100. package/docs/releases/v0.31.11.md +88 -0
  101. package/docs/releases/v0.31.12.md +105 -0
  102. package/docs/releases/v0.31.13.md +99 -0
  103. package/docs/releases/v0.31.14.md +97 -0
  104. package/docs/releases/v0.31.2.md +115 -0
  105. package/docs/releases/v0.31.3.md +142 -0
  106. package/docs/releases/v0.31.4.md +117 -0
  107. package/docs/releases/v0.31.5.md +155 -0
  108. package/docs/releases/v0.31.6.md +132 -0
  109. package/docs/releases/v0.31.7.md +132 -0
  110. package/docs/releases/v0.31.8.md +120 -0
  111. package/docs/releases/v0.31.9.md +120 -0
  112. package/docs/releases/v0.32.0.md +261 -0
  113. package/docs/releases/v0.32.1.md +59 -0
  114. package/docs/releases/v0.8.0.md +118 -0
  115. package/docs/releases/v0.9.0.md +98 -0
  116. package/docs/releases/v0.9.1.md +83 -0
  117. package/package.json +102 -6
  118. package/plugins/mirror-mind/.claude-plugin/plugin.json +13 -0
  119. package/plugins/mirror-mind/hooks/hooks.json +50 -0
  120. package/plugins/mirror-mind/hooks/log-session-end.sh +98 -0
  121. package/plugins/mirror-mind/hooks/log-user-prompt.sh +98 -0
  122. package/plugins/mirror-mind/hooks/mirror-inject.sh +98 -0
  123. package/plugins/mirror-mind/hooks/session-start.sh +98 -0
  124. package/plugins/mirror-mind/mcp/launch.sh +52 -0
  125. package/plugins/mirror-mind/skills/mm-backup/SKILL.md +27 -0
  126. package/plugins/mirror-mind/skills/mm-build/SKILL.md +1206 -0
  127. package/plugins/mirror-mind/skills/mm-consolidate/SKILL.md +112 -0
  128. package/plugins/mirror-mind/skills/mm-consult/SKILL.md +83 -0
  129. package/plugins/mirror-mind/skills/mm-conversations/SKILL.md +17 -0
  130. package/plugins/mirror-mind/skills/mm-discard/SKILL.md +40 -0
  131. package/plugins/mirror-mind/skills/mm-explore/SKILL.md +241 -0
  132. package/plugins/mirror-mind/skills/mm-help/SKILL.md +104 -0
  133. package/plugins/mirror-mind/skills/mm-identity/SKILL.md +96 -0
  134. package/plugins/mirror-mind/skills/mm-journal/SKILL.md +21 -0
  135. package/plugins/mirror-mind/skills/mm-journey/SKILL.md +37 -0
  136. package/plugins/mirror-mind/skills/mm-journeys/SKILL.md +15 -0
  137. package/plugins/mirror-mind/skills/mm-memories/SKILL.md +20 -0
  138. package/plugins/mirror-mind/skills/mm-mirror/SKILL.md +65 -0
  139. package/plugins/mirror-mind/skills/mm-mute/SKILL.md +18 -0
  140. package/plugins/mirror-mind/skills/mm-new/SKILL.md +18 -0
  141. package/plugins/mirror-mind/skills/mm-recall/SKILL.md +17 -0
  142. package/plugins/mirror-mind/skills/mm-release-notes/SKILL.md +31 -0
  143. package/plugins/mirror-mind/skills/mm-seed/SKILL.md +15 -0
  144. package/plugins/mirror-mind/skills/mm-shadow/SKILL.md +117 -0
  145. package/plugins/mirror-mind/skills/mm-soul/SKILL.md +488 -0
  146. package/plugins/mirror-mind/skills/mm-tasks/SKILL.md +36 -0
  147. package/plugins/mirror-mind/skills/mm-update/SKILL.md +30 -0
  148. package/plugins/mirror-mind/skills/mm-week/SKILL.md +46 -0
  149. package/plugins/mirror-mind/skills/mm-welcome/SKILL.md +22 -0
  150. package/scripts/codex-hooks/session-end.sh +85 -0
  151. package/scripts/codex-hooks/session-start.sh +85 -0
  152. package/scripts/codex-mirror.sh +48 -0
  153. package/templates/identity/README.md +119 -0
  154. package/templates/identity/ego/behavior.yaml +52 -0
  155. package/templates/identity/ego/constraints.yaml +15 -0
  156. package/templates/identity/ego/identity.yaml +43 -0
  157. package/templates/identity/journeys/personal-growth.yaml +39 -0
  158. package/templates/identity/organization/identity.yaml +24 -0
  159. package/templates/identity/organization/principles.yaml +17 -0
  160. package/templates/identity/personas/coach.yaml +94 -0
  161. package/templates/identity/personas/designer.yaml +93 -0
  162. package/templates/identity/personas/doctor.yaml +96 -0
  163. package/templates/identity/personas/engineer.yaml +77 -0
  164. package/templates/identity/personas/financial.yaml +97 -0
  165. package/templates/identity/personas/prompt-engineer.yaml +122 -0
  166. package/templates/identity/personas/researcher.yaml +88 -0
  167. package/templates/identity/personas/strategist.yaml +91 -0
  168. package/templates/identity/personas/teacher.yaml +95 -0
  169. package/templates/identity/personas/therapist.yaml +91 -0
  170. package/templates/identity/personas/thinker.yaml +74 -0
  171. package/templates/identity/personas/writer.yaml +76 -0
  172. package/templates/identity/self/config.yaml +16 -0
  173. package/templates/identity/self/soul.yaml +105 -0
  174. package/templates/identity/user/identity.yaml +30 -0
  175. package/ts/src/backup/staging.ts +62 -0
  176. package/ts/src/backup/zipBackup.ts +267 -0
  177. package/ts/src/backup/zipReader.ts +109 -0
  178. package/ts/src/backup/zipWriter.ts +148 -0
  179. package/ts/src/builder/activeCheckpoint.ts +134 -0
  180. package/ts/src/builder/aggregateStatus.ts +34 -0
  181. package/ts/src/builder/approve.ts +149 -0
  182. package/ts/src/builder/argv.ts +292 -0
  183. package/ts/src/builder/ariadMethod.ts +536 -0
  184. package/ts/src/builder/artifacts/artifactSurfaces.ts +106 -0
  185. package/ts/src/builder/artifacts/artifactWriter.ts +113 -0
  186. package/ts/src/builder/artifacts/closureArtifacts.ts +199 -0
  187. package/ts/src/builder/artifacts/deliveryStoryArtifacts.ts +316 -0
  188. package/ts/src/builder/artifacts/planArtifacts.ts +242 -0
  189. package/ts/src/builder/artifacts/scaffoldSections.ts +273 -0
  190. package/ts/src/builder/artifacts/scaffoldState.ts +227 -0
  191. package/ts/src/builder/artifacts/storyFiles.ts +61 -0
  192. package/ts/src/builder/artifacts/storyIndex.ts +166 -0
  193. package/ts/src/builder/cadence.ts +59 -0
  194. package/ts/src/builder/card.ts +192 -0
  195. package/ts/src/builder/checkpointRefused.ts +66 -0
  196. package/ts/src/builder/closure.ts +964 -0
  197. package/ts/src/builder/commands.ts +2053 -0
  198. package/ts/src/builder/cursorPosition.ts +176 -0
  199. package/ts/src/builder/cursorTransitions.ts +77 -0
  200. package/ts/src/builder/deliveryCursor.ts +577 -0
  201. package/ts/src/builder/deliveryStoryClosure.ts +521 -0
  202. package/ts/src/builder/deliveryStoryPlan.ts +536 -0
  203. package/ts/src/builder/deliveryStoryReady.ts +160 -0
  204. package/ts/src/builder/deliveryStoryRoadmapClosure.ts +151 -0
  205. package/ts/src/builder/expand.ts +336 -0
  206. package/ts/src/builder/flowUnit.ts +339 -0
  207. package/ts/src/builder/homeSurface.ts +122 -0
  208. package/ts/src/builder/implementationGuard.ts +125 -0
  209. package/ts/src/builder/index.ts +11 -0
  210. package/ts/src/builder/lifecycleRefusal.ts +92 -0
  211. package/ts/src/builder/lifecycleRibbon.ts +159 -0
  212. package/ts/src/builder/load.ts +313 -0
  213. package/ts/src/builder/methodAdoption.ts +113 -0
  214. package/ts/src/builder/methodDefinition.ts +429 -0
  215. package/ts/src/builder/methodInspection.ts +371 -0
  216. package/ts/src/builder/plan.ts +408 -0
  217. package/ts/src/builder/planPreauthorization.ts +265 -0
  218. package/ts/src/builder/prepare.ts +225 -0
  219. package/ts/src/builder/projectPaths.ts +64 -0
  220. package/ts/src/builder/pull.ts +356 -0
  221. package/ts/src/builder/pullCandidates.ts +463 -0
  222. package/ts/src/builder/pullCandidatesRender.ts +238 -0
  223. package/ts/src/builder/refinementField.ts +93 -0
  224. package/ts/src/builder/releaseIntent.ts +173 -0
  225. package/ts/src/builder/resumeState.ts +84 -0
  226. package/ts/src/builder/resumeSurface.ts +149 -0
  227. package/ts/src/builder/roadmapGrammar.ts +300 -0
  228. package/ts/src/builder/roadmapScan.ts +97 -0
  229. package/ts/src/builder/roadmapScope.ts +210 -0
  230. package/ts/src/builder/scopePhrases.ts +146 -0
  231. package/ts/src/builder/storyPaths.ts +196 -0
  232. package/ts/src/builder/storyPlanPreauthorization.ts +287 -0
  233. package/ts/src/builder/surfaceProtocol.ts +42 -0
  234. package/ts/src/builder/templateGeneration.ts +148 -0
  235. package/ts/src/builder/transition.ts +178 -0
  236. package/ts/src/consult/args.ts +99 -0
  237. package/ts/src/consult/core.ts +122 -0
  238. package/ts/src/consult/modelCatalog.ts +55 -0
  239. package/ts/src/consult/render.ts +47 -0
  240. package/ts/src/conversation/append.ts +414 -0
  241. package/ts/src/conversation/backfill.ts +387 -0
  242. package/ts/src/conversation/closeTail.ts +467 -0
  243. package/ts/src/conversation/extraction.ts +333 -0
  244. package/ts/src/conversation/extractionDriver.ts +130 -0
  245. package/ts/src/conversation/extractionRun.ts +70 -0
  246. package/ts/src/conversation/journeyInference.ts +165 -0
  247. package/ts/src/conversation/journeyRepair.ts +114 -0
  248. package/ts/src/conversation/lifecycleFaces.ts +197 -0
  249. package/ts/src/conversation/lifecycleWrites.ts +313 -0
  250. package/ts/src/conversation/listing.ts +77 -0
  251. package/ts/src/conversation/logger.ts +576 -0
  252. package/ts/src/conversation/loggerCli.ts +282 -0
  253. package/ts/src/conversation/loggerRuntime.ts +259 -0
  254. package/ts/src/conversation/metadataLifecycle.ts +443 -0
  255. package/ts/src/conversation/recall.ts +66 -0
  256. package/ts/src/conversation/sessionComposites.ts +258 -0
  257. package/ts/src/conversation/sessionImport.ts +90 -0
  258. package/ts/src/conversation/transcriptBackfill.ts +141 -0
  259. package/ts/src/cultivation/applyActions.ts +241 -0
  260. package/ts/src/cultivation/cluster.ts +86 -0
  261. package/ts/src/cultivation/consolidationStore.ts +281 -0
  262. package/ts/src/cultivation/promptContext.ts +62 -0
  263. package/ts/src/cultivation/propose.ts +305 -0
  264. package/ts/src/cultivation/scan.ts +155 -0
  265. package/ts/src/db/backupGate.ts +47 -0
  266. package/ts/src/db/bootstrap.ts +108 -0
  267. package/ts/src/db/bootstrapLock.ts +223 -0
  268. package/ts/src/db/copyGuard.ts +60 -0
  269. package/ts/src/db/database.ts +397 -0
  270. package/ts/src/db/decode.ts +66 -0
  271. package/ts/src/db/ftsIntegrity.ts +41 -0
  272. package/ts/src/db/migrateOnOpen.ts +214 -0
  273. package/ts/src/db/migrations.ts +576 -0
  274. package/ts/src/db/readyOnOpen.ts +35 -0
  275. package/ts/src/db/rowDecode.ts +42 -0
  276. package/ts/src/db/schema.ts +432 -0
  277. package/ts/src/db/schemaInventory.ts +225 -0
  278. package/ts/src/db/schemaInventorySnapshot.ts +2107 -0
  279. package/ts/src/db/schemaState.ts +91 -0
  280. package/ts/src/db/schemaTsDivergence.ts +114 -0
  281. package/ts/src/descriptor/descriptorRead.ts +49 -0
  282. package/ts/src/docs/docsLint.ts +265 -0
  283. package/ts/src/explorer/handoff.ts +522 -0
  284. package/ts/src/explorer/render.ts +335 -0
  285. package/ts/src/explorer/story.ts +769 -0
  286. package/ts/src/explorer/transition.ts +72 -0
  287. package/ts/src/extensions/bindings.ts +170 -0
  288. package/ts/src/extensions/catalog.ts +249 -0
  289. package/ts/src/extensions/catalogCommands.ts +513 -0
  290. package/ts/src/extensions/catalogWrites.ts +652 -0
  291. package/ts/src/extensions/contextRuntime.ts +325 -0
  292. package/ts/src/extensions/dispatch.ts +374 -0
  293. package/ts/src/extensions/errors.ts +24 -0
  294. package/ts/src/extensions/manifest.ts +356 -0
  295. package/ts/src/extensions/migrations.ts +350 -0
  296. package/ts/src/extraction/conversation.ts +304 -0
  297. package/ts/src/extraction/conversationMetadata.ts +206 -0
  298. package/ts/src/extraction/fencing.ts +106 -0
  299. package/ts/src/extraction/json.ts +17 -0
  300. package/ts/src/extraction/prompts.ts +470 -0
  301. package/ts/src/frontDoor/args.ts +30 -0
  302. package/ts/src/frontDoor/argvShape.ts +106 -0
  303. package/ts/src/frontDoor/buildLoadRuntime.ts +139 -0
  304. package/ts/src/frontDoor/buildRoute.ts +398 -0
  305. package/ts/src/frontDoor/cli.ts +1865 -0
  306. package/ts/src/frontDoor/cloneRoleGuard.ts +98 -0
  307. package/ts/src/frontDoor/consultRoute.ts +50 -0
  308. package/ts/src/frontDoor/contentTailRoute.ts +239 -0
  309. package/ts/src/frontDoor/conversationLoggerRoute.ts +73 -0
  310. package/ts/src/frontDoor/cultivationRoute.ts +210 -0
  311. package/ts/src/frontDoor/dbPath.ts +131 -0
  312. package/ts/src/frontDoor/dbSafetyToolsRoute.ts +240 -0
  313. package/ts/src/frontDoor/exploreRoute.ts +572 -0
  314. package/ts/src/frontDoor/extensionCatalogRoute.ts +252 -0
  315. package/ts/src/frontDoor/frontDoorLog.ts +57 -0
  316. package/ts/src/frontDoor/identityWrite.ts +36 -0
  317. package/ts/src/frontDoor/journeyWriteRoute.ts +26 -0
  318. package/ts/src/frontDoor/lifecycleWriteRoute.ts +110 -0
  319. package/ts/src/frontDoor/liveBackup.ts +100 -0
  320. package/ts/src/frontDoor/mirrorModeRoute.ts +163 -0
  321. package/ts/src/frontDoor/namedRefusal.ts +35 -0
  322. package/ts/src/frontDoor/nodeSupport.ts +24 -0
  323. package/ts/src/frontDoor/render/consolidate.ts +199 -0
  324. package/ts/src/frontDoor/render/conversations.ts +33 -0
  325. package/ts/src/frontDoor/render/cultivationShared.ts +21 -0
  326. package/ts/src/frontDoor/render/descriptor.ts +20 -0
  327. package/ts/src/frontDoor/render/detectPersona.ts +50 -0
  328. package/ts/src/frontDoor/render/icons.ts +13 -0
  329. package/ts/src/frontDoor/render/identity.ts +59 -0
  330. package/ts/src/frontDoor/render/identityRows.ts +17 -0
  331. package/ts/src/frontDoor/render/inspectPersona.ts +53 -0
  332. package/ts/src/frontDoor/render/journeyStatus.ts +78 -0
  333. package/ts/src/frontDoor/render/journeys.ts +79 -0
  334. package/ts/src/frontDoor/render/list.ts +41 -0
  335. package/ts/src/frontDoor/render/memories.ts +67 -0
  336. package/ts/src/frontDoor/render/recall.ts +49 -0
  337. package/ts/src/frontDoor/render/shadow.ts +155 -0
  338. package/ts/src/frontDoor/render/tasks.ts +99 -0
  339. package/ts/src/frontDoor/render/tasksImportSync.ts +63 -0
  340. package/ts/src/frontDoor/render/week.ts +113 -0
  341. package/ts/src/frontDoor/routing.ts +999 -0
  342. package/ts/src/frontDoor/runtimeRoute.ts +623 -0
  343. package/ts/src/frontDoor/searchRoute.ts +166 -0
  344. package/ts/src/frontDoor/seedPaths.ts +98 -0
  345. package/ts/src/frontDoor/soulRoute.ts +433 -0
  346. package/ts/src/frontDoor/tasksImportSyncRoute.ts +110 -0
  347. package/ts/src/frontDoor/tasksWriteRoute.ts +101 -0
  348. package/ts/src/frontDoor/usage.ts +176 -0
  349. package/ts/src/guards/claudePlugin.ts +252 -0
  350. package/ts/src/guards/packContents.ts +306 -0
  351. package/ts/src/guards/piSourcedSkills.ts +70 -0
  352. package/ts/src/guards/retiredRouteShadows.ts +57 -0
  353. package/ts/src/guards/retiredSurfaces.ts +564 -0
  354. package/ts/src/hooks/claude.ts +176 -0
  355. package/ts/src/hooks/codex.ts +45 -0
  356. package/ts/src/hooks/gemini.ts +126 -0
  357. package/ts/src/hooks/main.ts +109 -0
  358. package/ts/src/hooks/mirrorState.ts +71 -0
  359. package/ts/src/hooks/payload.ts +68 -0
  360. package/ts/src/hooks/runtime.ts +159 -0
  361. package/ts/src/identity/applyConsolidationIdentityUpdate.ts +67 -0
  362. package/ts/src/identity/descriptorGenerate.ts +162 -0
  363. package/ts/src/identity/identityEdit.ts +143 -0
  364. package/ts/src/identity/identityKey.ts +77 -0
  365. package/ts/src/identity/identityRead.ts +69 -0
  366. package/ts/src/identity/identityStore.ts +80 -0
  367. package/ts/src/identity/journeyListing.ts +53 -0
  368. package/ts/src/identity/personaInspect.ts +44 -0
  369. package/ts/src/identity/personaListing.ts +37 -0
  370. package/ts/src/identity/setIdentity.ts +64 -0
  371. package/ts/src/index.ts +231 -0
  372. package/ts/src/init/init.ts +111 -0
  373. package/ts/src/journey/journeyOptions.ts +131 -0
  374. package/ts/src/journey/journeyRemoval.ts +158 -0
  375. package/ts/src/journey/journeyStatus.ts +149 -0
  376. package/ts/src/journey/journeySyncFile.ts +87 -0
  377. package/ts/src/journey/journeyWrite.ts +203 -0
  378. package/ts/src/journey/parentJourney.ts +41 -0
  379. package/ts/src/journey/validateParentJourney.ts +55 -0
  380. package/ts/src/mcp/boundary.ts +151 -0
  381. package/ts/src/mcp/guards.ts +244 -0
  382. package/ts/src/mcp/main.ts +121 -0
  383. package/ts/src/mcp/payload.ts +141 -0
  384. package/ts/src/mcp/protocol.ts +141 -0
  385. package/ts/src/mcp/readModels.ts +241 -0
  386. package/ts/src/mcp/registry.ts +201 -0
  387. package/ts/src/mcp/serve.ts +120 -0
  388. package/ts/src/mcp/tools/deterministic.ts +137 -0
  389. package/ts/src/mcp/tools/providerCrossing.ts +187 -0
  390. package/ts/src/mcp/wire.ts +8 -0
  391. package/ts/src/memory/journal.ts +180 -0
  392. package/ts/src/memory/listing.ts +107 -0
  393. package/ts/src/memory/memoryWrite.ts +88 -0
  394. package/ts/src/memory/reinforcement.ts +35 -0
  395. package/ts/src/mirror/context.ts +161 -0
  396. package/ts/src/mirror/defaultResolution.ts +199 -0
  397. package/ts/src/mirror/orchestration.ts +364 -0
  398. package/ts/src/mirror/reception.ts +194 -0
  399. package/ts/src/mirror/render.ts +75 -0
  400. package/ts/src/mirror/runtimeSession.ts +205 -0
  401. package/ts/src/mode/operatingMode.ts +148 -0
  402. package/ts/src/observability/callOutcome.ts +115 -0
  403. package/ts/src/observability/inspectLedger.ts +329 -0
  404. package/ts/src/observability/ledgerHooks.ts +126 -0
  405. package/ts/src/observability/llmCalls.ts +154 -0
  406. package/ts/src/persona/detectPersona.ts +81 -0
  407. package/ts/src/planning/promptAssembly.ts +111 -0
  408. package/ts/src/planning/weekPending.ts +81 -0
  409. package/ts/src/planning/weekPlan.ts +183 -0
  410. package/ts/src/planning/weekSave.ts +117 -0
  411. package/ts/src/providers/config.ts +189 -0
  412. package/ts/src/providers/cost.ts +64 -0
  413. package/ts/src/providers/credits.ts +204 -0
  414. package/ts/src/providers/embedding.ts +321 -0
  415. package/ts/src/providers/familyProviders.ts +147 -0
  416. package/ts/src/providers/llm.ts +334 -0
  417. package/ts/src/providers/openrouter.ts +244 -0
  418. package/ts/src/providers/redaction.ts +110 -0
  419. package/ts/src/providers/replay.ts +15 -0
  420. package/ts/src/providers/transport.ts +410 -0
  421. package/ts/src/repair/encodingRepair.ts +253 -0
  422. package/ts/src/runtime/backup.ts +151 -0
  423. package/ts/src/runtime/channel.ts +146 -0
  424. package/ts/src/runtime/config.ts +168 -0
  425. package/ts/src/runtime/diagnose.ts +686 -0
  426. package/ts/src/runtime/git.ts +510 -0
  427. package/ts/src/runtime/installKind.ts +220 -0
  428. package/ts/src/runtime/migrate.ts +154 -0
  429. package/ts/src/runtime/packageIdentity.ts +102 -0
  430. package/ts/src/runtime/releaseNotes.ts +244 -0
  431. package/ts/src/runtime/status.ts +557 -0
  432. package/ts/src/runtime/strategies/clone.ts +200 -0
  433. package/ts/src/runtime/strategies/package.ts +328 -0
  434. package/ts/src/runtime/treeRoot.ts +30 -0
  435. package/ts/src/runtime/update.ts +445 -0
  436. package/ts/src/runtime/updateGate.ts +40 -0
  437. package/ts/src/runtime/updatePipeline.ts +159 -0
  438. package/ts/src/runtime/version.ts +36 -0
  439. package/ts/src/runtime/wiring.ts +130 -0
  440. package/ts/src/search/memorySearch.ts +338 -0
  441. package/ts/src/search/ranker.ts +154 -0
  442. package/ts/src/seed/seed.ts +256 -0
  443. package/ts/src/seed/seedYaml.ts +133 -0
  444. package/ts/src/soul/apply.ts +218 -0
  445. package/ts/src/soul/harvest.ts +267 -0
  446. package/ts/src/soul/prompts/soul_beauty_voice.md +103 -0
  447. package/ts/src/soul/prompts/soul_self_voice.md +219 -0
  448. package/ts/src/soul/prompts/soul_wisdom_voice.md +121 -0
  449. package/ts/src/soul/prompts.ts +85 -0
  450. package/ts/src/soul/render.ts +358 -0
  451. package/ts/src/soul/state.ts +212 -0
  452. package/ts/src/soul/transition.ts +37 -0
  453. package/ts/src/tasks/journeyPathParse.ts +113 -0
  454. package/ts/src/tasks/taskImportSync.ts +142 -0
  455. package/ts/src/tasks/taskStore.ts +312 -0
  456. package/ts/src/tasks/weekView.ts +120 -0
  457. package/ts/src/util/clipCodePoints.ts +26 -0
  458. package/ts/src/util/paths.ts +63 -0
  459. package/ts/src/util/program.ts +9 -0
  460. package/ts/src/util/pyGenerators.ts +144 -0
  461. package/ts/src/util/pythonText.ts +317 -0
  462. package/ts/src/util/semver.ts +45 -0
  463. package/ts/src/util/shellWord.ts +25 -0
  464. package/ts/src/util/slug.ts +64 -0
  465. package/ts/src/welcome/card.ts +339 -0
  466. package/ts/src/welcome/statusLine.ts +101 -0
  467. package/ts/src/welcome/updateCache.ts +129 -0
@@ -0,0 +1,576 @@
1
+ // Incremental database migrations — CV22.DS6.TS2.
2
+ //
3
+ // Independent TS port of `src/memory/db/migrations.py`'s `MIGRATIONS` list and
4
+ // `run_migrations`, function-for-function, preserving every early-return guard
5
+ // exactly. Several of these guards are load-bearing: on a from-scratch fresh
6
+ // database (already proven by CV22.DS6.TS1's createSchema), most migration
7
+ // bodies are dead code — `001`/`005` no-op on the tables that don't exist yet,
8
+ // `008`/`009` explicitly skip ("SCHEMA will create/already includes this on a
9
+ // fresh database"), and `016`'s ADD-COLUMN branch never fires since `015`
10
+ // already creates `display_code` inline. Their real logic only exercises
11
+ // against a genuinely older, already-existing database — which is why this
12
+ // story's validation is a legacy-transition state-diff, not a fresh-DB check.
13
+ //
14
+ // Every migration is idempotent: running it twice is a no-op, matching the
15
+ // Python contract. `runMigrations` commits each migration individually via
16
+ // `withTransaction` and rolls back (and rethrows) only the currently failing
17
+ // one — migrations before it stay applied and recorded, so a retry resumes
18
+ // from exactly that point (see `migrationsWithTransaction`/`runMigrations`).
19
+
20
+ import { nowIso } from "#util/pyGenerators.ts";
21
+ import { type WritableDatabase, withTransaction } from "./database.ts";
22
+
23
+ function tableColumns(db: WritableDatabase, table: string): Set<string> {
24
+ const rows = db.prepare(`PRAGMA table_info("${table}")`).all() as { name: string }[];
25
+ return new Set(rows.map((row) => row.name));
26
+ }
27
+
28
+ function tableExists(db: WritableDatabase, table: string): boolean {
29
+ return (
30
+ db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) !==
31
+ undefined
32
+ );
33
+ }
34
+
35
+ function renameColumnIfNeeded(
36
+ db: WritableDatabase,
37
+ table: string,
38
+ oldName: string,
39
+ newName: string,
40
+ ): void {
41
+ if (!tableExists(db, table)) return;
42
+ const columns = tableColumns(db, table);
43
+ if (columns.has(newName)) return;
44
+ if (!columns.has(oldName)) return;
45
+ db.exec(`ALTER TABLE ${table} RENAME COLUMN ${oldName} TO ${newName}`);
46
+ }
47
+
48
+ function addColumnIfMissing(
49
+ db: WritableDatabase,
50
+ table: string,
51
+ column: string,
52
+ columnType: string,
53
+ ): void {
54
+ if (!tableExists(db, table)) return;
55
+ const columns = tableColumns(db, table);
56
+ if (columns.has(column)) return;
57
+ db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${columnType}`);
58
+ }
59
+
60
+ function backfillDisplayCodes(
61
+ db: WritableDatabase,
62
+ table: string,
63
+ prefix: string,
64
+ orderBy: string,
65
+ ): void {
66
+ const journeys = (
67
+ db
68
+ .prepare(`SELECT DISTINCT journey FROM ${table} WHERE display_code IS NULL ORDER BY journey`)
69
+ .all() as { journey: string }[]
70
+ ).map((row) => row.journey);
71
+ for (const journey of journeys) {
72
+ const rows = db
73
+ .prepare(`SELECT id FROM ${table} WHERE journey = ? ORDER BY ${orderBy}`)
74
+ .all(journey) as { id: string }[];
75
+ rows.forEach((row, index) => {
76
+ const code = `${prefix}${String(index + 1).padStart(3, "0")}`;
77
+ db.prepare(`UPDATE ${table} SET display_code = COALESCE(display_code, ?) WHERE id = ?`).run(
78
+ code,
79
+ row.id,
80
+ );
81
+ });
82
+ }
83
+ }
84
+
85
+ // --- Migration apply functions (all idempotent) ---
86
+
87
+ function migrateProjectToTravessia(db: WritableDatabase): void {
88
+ renameColumnIfNeeded(db, "conversations", "project", "travessia");
89
+ renameColumnIfNeeded(db, "memories", "project", "travessia");
90
+ db.exec("DROP INDEX IF EXISTS idx_memories_project");
91
+ if (tableExists(db, "memories") && tableColumns(db, "memories").has("travessia")) {
92
+ db.exec("CREATE INDEX IF NOT EXISTS idx_memories_travessia ON memories(travessia)");
93
+ }
94
+ if (tableExists(db, "identity")) {
95
+ db.exec("UPDATE identity SET layer = 'travessia' WHERE layer = 'project'");
96
+ }
97
+ }
98
+
99
+ function migrateCreateAttachments(db: WritableDatabase): void {
100
+ if (tableExists(db, "attachments")) return;
101
+ db.exec(`
102
+ CREATE TABLE IF NOT EXISTS attachments (
103
+ id TEXT PRIMARY KEY,
104
+ travessia_id TEXT NOT NULL,
105
+ name TEXT NOT NULL,
106
+ description TEXT,
107
+ content TEXT NOT NULL,
108
+ content_type TEXT NOT NULL DEFAULT 'markdown',
109
+ tags TEXT,
110
+ embedding BLOB,
111
+ created_at TEXT NOT NULL,
112
+ updated_at TEXT NOT NULL,
113
+ metadata TEXT
114
+ );
115
+ CREATE INDEX IF NOT EXISTS idx_attachments_travessia
116
+ ON attachments(travessia_id);
117
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_attachments_travessia_name
118
+ ON attachments(travessia_id, name);
119
+ `);
120
+ }
121
+
122
+ function migrateCreateTasks(db: WritableDatabase): void {
123
+ if (tableExists(db, "tasks")) return;
124
+ db.exec(`
125
+ CREATE TABLE IF NOT EXISTS tasks (
126
+ id TEXT PRIMARY KEY,
127
+ travessia TEXT,
128
+ title TEXT NOT NULL,
129
+ status TEXT NOT NULL DEFAULT 'todo',
130
+ due_date TEXT,
131
+ stage TEXT,
132
+ context TEXT,
133
+ source TEXT NOT NULL DEFAULT 'manual',
134
+ created_at TEXT NOT NULL,
135
+ updated_at TEXT NOT NULL,
136
+ completed_at TEXT,
137
+ metadata TEXT
138
+ );
139
+ CREATE INDEX IF NOT EXISTS idx_tasks_travessia ON tasks(travessia);
140
+ CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
141
+ CREATE INDEX IF NOT EXISTS idx_tasks_due_date ON tasks(due_date);
142
+ `);
143
+ }
144
+
145
+ function migrateTasksTemporalFields(db: WritableDatabase): void {
146
+ addColumnIfMissing(db, "tasks", "scheduled_at", "TEXT");
147
+ addColumnIfMissing(db, "tasks", "time_hint", "TEXT");
148
+ }
149
+
150
+ function migrateTravessiaToJourney(db: WritableDatabase): void {
151
+ db.exec(`
152
+ DROP INDEX IF EXISTS idx_memories_travessia;
153
+ DROP INDEX IF EXISTS idx_tasks_travessia;
154
+ DROP INDEX IF EXISTS idx_attachments_travessia;
155
+ DROP INDEX IF EXISTS idx_attachments_travessia_name;
156
+ `);
157
+
158
+ renameColumnIfNeeded(db, "conversations", "travessia", "journey");
159
+ renameColumnIfNeeded(db, "memories", "travessia", "journey");
160
+ renameColumnIfNeeded(db, "tasks", "travessia", "journey");
161
+ renameColumnIfNeeded(db, "attachments", "travessia_id", "journey_id");
162
+
163
+ if (tableExists(db, "identity")) {
164
+ db.exec("UPDATE identity SET layer = 'journey' WHERE layer = 'travessia'");
165
+ db.exec("UPDATE identity SET layer = 'journey_path' WHERE layer = 'caminho'");
166
+ }
167
+
168
+ if (tableExists(db, "memories")) {
169
+ db.exec("UPDATE memories SET layer = 'journey' WHERE layer = 'travessia'");
170
+ db.exec("UPDATE memories SET layer = 'journey_path' WHERE layer = 'caminho'");
171
+ }
172
+
173
+ if (tableExists(db, "memories") && tableColumns(db, "memories").has("journey")) {
174
+ db.exec("CREATE INDEX IF NOT EXISTS idx_memories_journey ON memories(journey)");
175
+ }
176
+ if (tableExists(db, "tasks") && tableColumns(db, "tasks").has("journey")) {
177
+ db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_journey ON tasks(journey)");
178
+ }
179
+ if (tableExists(db, "attachments") && tableColumns(db, "attachments").has("journey_id")) {
180
+ db.exec(`
181
+ CREATE INDEX IF NOT EXISTS idx_attachments_journey ON attachments(journey_id);
182
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_attachments_journey_name
183
+ ON attachments(journey_id, name);
184
+ `);
185
+ }
186
+ }
187
+
188
+ function migrateCreateLlmCalls(db: WritableDatabase): void {
189
+ if (tableExists(db, "llm_calls")) return;
190
+ db.exec(`
191
+ CREATE TABLE IF NOT EXISTS llm_calls (
192
+ id TEXT PRIMARY KEY,
193
+ role TEXT NOT NULL,
194
+ model TEXT NOT NULL,
195
+ prompt TEXT NOT NULL,
196
+ response TEXT NOT NULL,
197
+ prompt_tokens INTEGER,
198
+ completion_tokens INTEGER,
199
+ latency_ms INTEGER,
200
+ cost_usd REAL,
201
+ conversation_id TEXT REFERENCES conversations(id),
202
+ session_id TEXT,
203
+ called_at TEXT NOT NULL
204
+ );
205
+ CREATE INDEX IF NOT EXISTS idx_llm_calls_conversation ON llm_calls(conversation_id);
206
+ CREATE INDEX IF NOT EXISTS idx_llm_calls_role ON llm_calls(role);
207
+ CREATE INDEX IF NOT EXISTS idx_llm_calls_called_at ON llm_calls(called_at);
208
+ `);
209
+ }
210
+
211
+ function migrateCreateMemoriesFts(db: WritableDatabase): void {
212
+ // Skipped on fresh databases where `memories` does not exist yet — SCHEMA
213
+ // creates memories_fts alongside the other tables in that case.
214
+ if (tableExists(db, "memories_fts")) return;
215
+ if (!tableExists(db, "memories")) return;
216
+ db.exec(`
217
+ CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
218
+ title,
219
+ content,
220
+ context,
221
+ content=memories,
222
+ content_rowid=rowid
223
+ );
224
+
225
+ CREATE TRIGGER IF NOT EXISTS memories_fts_ai AFTER INSERT ON memories BEGIN
226
+ INSERT INTO memories_fts(rowid, title, content, context)
227
+ VALUES (NEW.rowid, NEW.title, NEW.content, COALESCE(NEW.context, ''));
228
+ END;
229
+
230
+ CREATE TRIGGER IF NOT EXISTS memories_fts_ad AFTER DELETE ON memories BEGIN
231
+ INSERT INTO memories_fts(memories_fts, rowid, title, content, context)
232
+ VALUES ('delete', OLD.rowid, OLD.title, OLD.content, COALESCE(OLD.context, ''));
233
+ END;
234
+
235
+ CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories BEGIN
236
+ INSERT INTO memories_fts(memories_fts, rowid, title, content, context)
237
+ VALUES ('delete', OLD.rowid, OLD.title, OLD.content, COALESCE(OLD.context, ''));
238
+ INSERT INTO memories_fts(rowid, title, content, context)
239
+ VALUES (NEW.rowid, NEW.title, NEW.content, COALESCE(NEW.context, ''));
240
+ END;
241
+
242
+ INSERT INTO memories_fts(rowid, title, content, context)
243
+ SELECT rowid, title, content, COALESCE(context, '') FROM memories;
244
+ `);
245
+ }
246
+
247
+ function migrateCreateIdentityDescriptors(db: WritableDatabase): void {
248
+ if (tableExists(db, "identity_descriptors")) return;
249
+ db.exec(`
250
+ CREATE TABLE IF NOT EXISTS identity_descriptors (
251
+ layer TEXT NOT NULL,
252
+ key TEXT NOT NULL,
253
+ descriptor TEXT NOT NULL,
254
+ generated_at TEXT NOT NULL,
255
+ PRIMARY KEY (layer, key)
256
+ );
257
+ `);
258
+ }
259
+
260
+ function migrateMemoriesReinforcementColumns(db: WritableDatabase): void {
261
+ // Fresh database: SCHEMA already includes these columns.
262
+ if (!tableExists(db, "memories")) return;
263
+ const existing = tableColumns(db, "memories");
264
+ if (!existing.has("last_accessed_at")) {
265
+ db.exec("ALTER TABLE memories ADD COLUMN last_accessed_at TEXT");
266
+ }
267
+ if (!existing.has("use_count")) {
268
+ db.exec("ALTER TABLE memories ADD COLUMN use_count INTEGER NOT NULL DEFAULT 0");
269
+ }
270
+ if (!existing.has("readiness_state")) {
271
+ db.exec("ALTER TABLE memories ADD COLUMN readiness_state TEXT NOT NULL DEFAULT 'observed'");
272
+ }
273
+ }
274
+
275
+ function migrateCreateConsolidations(db: WritableDatabase): void {
276
+ if (tableExists(db, "consolidations")) return;
277
+ db.exec(`
278
+ CREATE TABLE IF NOT EXISTS consolidations (
279
+ id TEXT PRIMARY KEY,
280
+ action TEXT NOT NULL,
281
+ proposal TEXT NOT NULL,
282
+ result TEXT,
283
+ source_memory_ids TEXT NOT NULL,
284
+ target_layer TEXT,
285
+ target_key TEXT,
286
+ rationale TEXT,
287
+ status TEXT NOT NULL DEFAULT 'pending',
288
+ created_at TEXT NOT NULL,
289
+ reviewed_at TEXT
290
+ );
291
+ CREATE INDEX IF NOT EXISTS idx_consolidations_status ON consolidations(status);
292
+ CREATE INDEX IF NOT EXISTS idx_consolidations_created ON consolidations(created_at);
293
+ `);
294
+ }
295
+
296
+ function migrateCreateOperationRuns(db: WritableDatabase): void {
297
+ if (tableExists(db, "operation_runs")) return;
298
+ db.exec(`
299
+ CREATE TABLE IF NOT EXISTS operation_runs (
300
+ id TEXT PRIMARY KEY,
301
+ operation_id TEXT NOT NULL,
302
+ status TEXT NOT NULL,
303
+ outcome TEXT,
304
+ parameters_json TEXT NOT NULL,
305
+ summary_json TEXT,
306
+ result_json TEXT,
307
+ error TEXT,
308
+ started_at TEXT NOT NULL,
309
+ completed_at TEXT,
310
+ created_at TEXT NOT NULL
311
+ );
312
+ CREATE INDEX IF NOT EXISTS idx_operation_runs_operation
313
+ ON operation_runs(operation_id);
314
+ CREATE INDEX IF NOT EXISTS idx_operation_runs_started
315
+ ON operation_runs(started_at);
316
+ CREATE INDEX IF NOT EXISTS idx_operation_runs_status
317
+ ON operation_runs(status);
318
+ `);
319
+ }
320
+
321
+ function migrateCreateOperationRunEvents(db: WritableDatabase): void {
322
+ if (tableExists(db, "operation_run_events")) return;
323
+ db.exec(`
324
+ CREATE TABLE IF NOT EXISTS operation_run_events (
325
+ id TEXT PRIMARY KEY,
326
+ run_id TEXT NOT NULL REFERENCES operation_runs(id) ON DELETE CASCADE,
327
+ sequence INTEGER NOT NULL,
328
+ kind TEXT NOT NULL,
329
+ message TEXT NOT NULL,
330
+ details_json TEXT,
331
+ created_at TEXT NOT NULL
332
+ );
333
+ CREATE INDEX IF NOT EXISTS idx_operation_run_events_run
334
+ ON operation_run_events(run_id, sequence);
335
+ `);
336
+ }
337
+
338
+ function migrateCreateExploratoryStories(db: WritableDatabase): void {
339
+ if (tableExists(db, "exploratory_stories")) return;
340
+ db.exec(`
341
+ CREATE TABLE IF NOT EXISTS exploratory_stories (
342
+ id TEXT PRIMARY KEY,
343
+ journey TEXT NOT NULL,
344
+ title TEXT,
345
+ status TEXT NOT NULL DEFAULT 'active',
346
+ current_story TEXT,
347
+ narrative_summary TEXT,
348
+ last_story_card TEXT,
349
+ attractors_json TEXT,
350
+ experiment_proposal_json TEXT,
351
+ builder_handoff_json TEXT,
352
+ source_conversations_json TEXT,
353
+ artifact_dir TEXT,
354
+ created_at TEXT NOT NULL,
355
+ updated_at TEXT NOT NULL,
356
+ promoted_at TEXT,
357
+ archived_at TEXT,
358
+ CHECK(status IN ('active', 'archived', 'promoted'))
359
+ );
360
+ CREATE INDEX IF NOT EXISTS idx_exploratory_stories_journey
361
+ ON exploratory_stories(journey, updated_at);
362
+ CREATE INDEX IF NOT EXISTS idx_exploratory_stories_status
363
+ ON exploratory_stories(status);
364
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_exploratory_stories_one_active_per_journey
365
+ ON exploratory_stories(journey)
366
+ WHERE status = 'active';
367
+ `);
368
+ }
369
+
370
+ function migrateCreateIdentityIntegrations(db: WritableDatabase): void {
371
+ if (tableExists(db, "identity_integrations")) return;
372
+ db.exec(`
373
+ CREATE TABLE IF NOT EXISTS identity_integrations (
374
+ id TEXT PRIMARY KEY,
375
+ layer TEXT NOT NULL,
376
+ key TEXT NOT NULL,
377
+ content TEXT NOT NULL,
378
+ source TEXT NOT NULL DEFAULT 'soul_mode',
379
+ origin TEXT,
380
+ conversation_id TEXT REFERENCES conversations(id),
381
+ journal_id TEXT REFERENCES memories(id),
382
+ created_at TEXT NOT NULL,
383
+ status TEXT NOT NULL DEFAULT 'active',
384
+ metadata TEXT NOT NULL DEFAULT '{}'
385
+ );
386
+ CREATE INDEX IF NOT EXISTS idx_identity_integrations_target
387
+ ON identity_integrations(layer, key, created_at);
388
+ CREATE INDEX IF NOT EXISTS idx_identity_integrations_status
389
+ ON identity_integrations(status);
390
+ `);
391
+ }
392
+
393
+ function migrateCreateBuilderWorkbench(db: WritableDatabase): void {
394
+ db.exec(`
395
+ CREATE TABLE IF NOT EXISTS builder_refinement_stories (
396
+ id TEXT PRIMARY KEY,
397
+ journey TEXT NOT NULL,
398
+ display_code TEXT NOT NULL,
399
+ title TEXT NOT NULL,
400
+ description TEXT,
401
+ status TEXT NOT NULL DEFAULT 'draft',
402
+ position INTEGER NOT NULL DEFAULT 0,
403
+ source TEXT NOT NULL DEFAULT 'manual',
404
+ provenance TEXT,
405
+ created_at TEXT NOT NULL,
406
+ updated_at TEXT NOT NULL,
407
+ pulled_at TEXT,
408
+ closed_at TEXT,
409
+ CHECK(status IN ('draft', 'open', 'active', 'closed', 'parked'))
410
+ );
411
+ CREATE INDEX IF NOT EXISTS idx_builder_refinement_stories_journey_status
412
+ ON builder_refinement_stories(journey, status, position, updated_at);
413
+ CREATE UNIQUE INDEX IF NOT EXISTS ux_builder_refinement_stories_journey_display_code
414
+ ON builder_refinement_stories(journey, display_code);
415
+
416
+ CREATE TABLE IF NOT EXISTS builder_change_requests (
417
+ id TEXT PRIMARY KEY,
418
+ journey TEXT NOT NULL,
419
+ display_code TEXT NOT NULL,
420
+ refinement_story_id TEXT REFERENCES builder_refinement_stories(id),
421
+ title TEXT NOT NULL,
422
+ body TEXT NOT NULL,
423
+ status TEXT NOT NULL DEFAULT 'captured',
424
+ position INTEGER NOT NULL DEFAULT 0,
425
+ source TEXT NOT NULL DEFAULT 'manual',
426
+ provenance TEXT,
427
+ outcome_notes TEXT,
428
+ created_at TEXT NOT NULL,
429
+ updated_at TEXT NOT NULL,
430
+ completed_at TEXT,
431
+ CHECK(status IN (
432
+ 'captured', 'planned', 'active', 'implemented', 'validated',
433
+ 'done', 'parked', 'rejected', 'promoted'
434
+ ))
435
+ );
436
+ CREATE INDEX IF NOT EXISTS idx_builder_change_requests_story_status
437
+ ON builder_change_requests(journey, refinement_story_id, status, position, updated_at);
438
+ CREATE INDEX IF NOT EXISTS idx_builder_change_requests_journey_status
439
+ ON builder_change_requests(journey, status, updated_at);
440
+ CREATE UNIQUE INDEX IF NOT EXISTS ux_builder_change_requests_journey_display_code
441
+ ON builder_change_requests(journey, display_code);
442
+
443
+ CREATE TABLE IF NOT EXISTS builder_refinement_cursors (
444
+ journey TEXT PRIMARY KEY,
445
+ active_refinement_story_id TEXT REFERENCES builder_refinement_stories(id),
446
+ active_change_request_id TEXT REFERENCES builder_change_requests(id),
447
+ last_refinement_event TEXT,
448
+ updated_at TEXT NOT NULL
449
+ );
450
+ `);
451
+ }
452
+
453
+ function migrateBuilderWorkbenchDisplayCodes(db: WritableDatabase): void {
454
+ const storyCols = tableColumns(db, "builder_refinement_stories");
455
+ if (!storyCols.has("display_code")) {
456
+ db.exec("ALTER TABLE builder_refinement_stories ADD COLUMN display_code TEXT");
457
+ }
458
+ const crCols = tableColumns(db, "builder_change_requests");
459
+ if (!crCols.has("display_code")) {
460
+ db.exec("ALTER TABLE builder_change_requests ADD COLUMN display_code TEXT");
461
+ }
462
+
463
+ backfillDisplayCodes(
464
+ db,
465
+ "builder_refinement_stories",
466
+ "RS",
467
+ "position ASC, created_at ASC, id ASC",
468
+ );
469
+ backfillDisplayCodes(db, "builder_change_requests", "CR", "created_at ASC, position ASC, id ASC");
470
+
471
+ db.exec(`
472
+ CREATE UNIQUE INDEX IF NOT EXISTS ux_builder_refinement_stories_journey_display_code
473
+ ON builder_refinement_stories(journey, display_code);
474
+ CREATE UNIQUE INDEX IF NOT EXISTS ux_builder_change_requests_journey_display_code
475
+ ON builder_change_requests(journey, display_code);
476
+ `);
477
+ }
478
+
479
+ /**
480
+ * 017 (CV22.DS6.US2) — the first *new forward* migration authored by the TS
481
+ * engine, graduating journey hierarchy from JSON metadata to a first-class
482
+ * `identity.parent_journey` column. Guarded on table existence: `identity` is
483
+ * created by `createSchema`, which runs AFTER migrations on a fresh database, so
484
+ * on a fresh DB this is a no-op (createSchema adds the column + index) and only a
485
+ * genuinely older, already-existing `identity` table is altered and backfilled
486
+ * here. Idempotent: the column guard, the `parent_journey IS NULL` backfill
487
+ * filter, and `CREATE INDEX IF NOT EXISTS` all no-op on re-run. The value stays
488
+ * mirrored in metadata JSON (dual-source) so the still-present Python surfaces
489
+ * keep reading it until DS7/DS10.
490
+ */
491
+ function migrateJourneyParentColumn(db: WritableDatabase): void {
492
+ if (!tableExists(db, "identity")) return;
493
+ addColumnIfMissing(db, "identity", "parent_journey", "TEXT");
494
+ const rows = db
495
+ .prepare(
496
+ "SELECT id, metadata FROM identity WHERE layer = 'journey' " +
497
+ "AND parent_journey IS NULL AND metadata IS NOT NULL",
498
+ )
499
+ .all() as { id: string; metadata: string }[];
500
+ for (const row of rows) {
501
+ let parent: unknown;
502
+ try {
503
+ parent = (JSON.parse(row.metadata) as Record<string, unknown>).parent_journey;
504
+ } catch {
505
+ continue;
506
+ }
507
+ if (typeof parent === "string" && parent) {
508
+ db.prepare("UPDATE identity SET parent_journey = ? WHERE id = ?").run(parent, row.id);
509
+ }
510
+ }
511
+ db.exec(
512
+ "CREATE INDEX IF NOT EXISTS idx_identity_parent_journey " +
513
+ "ON identity(parent_journey) WHERE parent_journey IS NOT NULL",
514
+ );
515
+ }
516
+
517
+ export type MigrationApply = (db: WritableDatabase) => void;
518
+
519
+ export const MIGRATIONS: readonly (readonly [string, MigrationApply])[] = [
520
+ ["001_project_to_travessia", migrateProjectToTravessia],
521
+ ["002_create_attachments", migrateCreateAttachments],
522
+ ["003_create_tasks", migrateCreateTasks],
523
+ ["004_tasks_temporal_fields", migrateTasksTemporalFields],
524
+ ["005_travessia_to_journey", migrateTravessiaToJourney],
525
+ ["006_create_llm_calls", migrateCreateLlmCalls],
526
+ ["007_create_identity_descriptors", migrateCreateIdentityDescriptors],
527
+ ["008_create_memories_fts", migrateCreateMemoriesFts],
528
+ ["009_memories_reinforcement_columns", migrateMemoriesReinforcementColumns],
529
+ ["010_create_consolidations", migrateCreateConsolidations],
530
+ ["011_create_operation_runs", migrateCreateOperationRuns],
531
+ ["012_create_operation_run_events", migrateCreateOperationRunEvents],
532
+ ["013_create_exploratory_stories", migrateCreateExploratoryStories],
533
+ ["014_create_identity_integrations", migrateCreateIdentityIntegrations],
534
+ ["015_create_builder_workbench", migrateCreateBuilderWorkbench],
535
+ ["016_builder_workbench_display_codes", migrateBuilderWorkbenchDisplayCodes],
536
+ ["017_journey_parent_column", migrateJourneyParentColumn],
537
+ ];
538
+
539
+ /**
540
+ * Run any pending migrations against an existing database. Each migration is
541
+ * idempotent, so running this against a database that was already
542
+ * bootstrapped from `createSchema()` is safe and a no-op.
543
+ *
544
+ * Commits each migration individually (`withTransaction`) and only rolls back
545
+ * (and rethrows) the currently failing one — migrations before it stay
546
+ * applied and recorded, so a retry resumes from exactly that point. Matches
547
+ * `memory.db.migrations.run_migrations`'s documented partial-failure
548
+ * contract.
549
+ */
550
+ export function runMigrations(db: WritableDatabase): void {
551
+ // The ledger has a second reader: `homeBornAt` (conversation/backfill.ts,
552
+ // CR121) takes MIN(applied_at) as the instant this home was born, and
553
+ // session maintenance imports only the Pi sessions newer than it. Never
554
+ // rewrite history here -- no re-stamping, no squash that deletes rows and
555
+ // re-inserts them with a later date. Retiring a migration id moves the
556
+ // minimum forward at worst, which imports less; re-stamping could move it
557
+ // and would be a lie about the home's age.
558
+ db.exec(`
559
+ CREATE TABLE IF NOT EXISTS _migrations (
560
+ id TEXT PRIMARY KEY,
561
+ applied_at TEXT NOT NULL
562
+ )
563
+ `);
564
+
565
+ for (const [migrationId, apply] of MIGRATIONS) {
566
+ const row = db.prepare("SELECT id FROM _migrations WHERE id = ?").get(migrationId);
567
+ if (row) continue;
568
+ withTransaction(db, () => {
569
+ apply(db);
570
+ db.prepare("INSERT OR IGNORE INTO _migrations (id, applied_at) VALUES (?, ?)").run(
571
+ migrationId,
572
+ nowIso(),
573
+ );
574
+ });
575
+ }
576
+ }
@@ -0,0 +1,35 @@
1
+ // Activation every TS serving path performs before opening its connection.
2
+ //
3
+ // Bootstrap a missing file (CV22.DS6.TS4), then apply any pending forward
4
+ // migration (US3 migrate-on-open). Python did the equivalent inside
5
+ // `get_connection`, so every one of its entry points -- including the MCP
6
+ // server -- got it for free; TypeScript has to compose it, and before
7
+ // CV22.DS9.TS2 only the front door did.
8
+ //
9
+ // This order is what lets `assertSchemaState` be strict (CV22.DS10.TS5): by
10
+ // the time it runs, every pending known migration has been applied, so a user
11
+ // never meets a "schema is older" error for work the engine could have done.
12
+ //
13
+ // Deliberately pure: it returns what happened and writes no log. The front door
14
+ // records a redacted `migrate_on_open` event in the front-door log; the MCP
15
+ // server writes one line to stderr, which is where its diagnostics belong. A
16
+ // single function parameterized on a logger would have been more machinery than
17
+ // the two lines it saves.
18
+
19
+ import { bootstrapDatabaseIfMissing } from "./bootstrap.ts";
20
+ import type { MigrateOnOpenResult } from "./migrateOnOpen.ts";
21
+ import { ensureMigratedOnOpen, type MigrateOnOpenOptions } from "./migrateOnOpen.ts";
22
+
23
+ /**
24
+ * Bootstrap-if-missing, then migrate-if-pending. The steady state is a cheap
25
+ * no-op: one read of `_migrations`. A one-time migration takes its own backup
26
+ * under the cross-process bootstrap lock (the DS6 contract), so concurrent
27
+ * openers cannot double-apply it.
28
+ */
29
+ export function ensureDatabaseReady(
30
+ dbPath: string,
31
+ options: MigrateOnOpenOptions = {},
32
+ ): MigrateOnOpenResult {
33
+ bootstrapDatabaseIfMissing(dbPath, options);
34
+ return ensureMigratedOnOpen(dbPath, options);
35
+ }
@@ -0,0 +1,42 @@
1
+ // Row decoding helpers for the database seam (CR010).
2
+ //
3
+ // `Row` is `Record<string, unknown>`, so every consumer would otherwise cast
4
+ // columns with `as string` and hope. These helpers centralize the unsafety and
5
+ // fail with a clear, column-named error when a column has an unexpected shape,
6
+ // turning a silent wrong-type bug into an actionable one.
7
+
8
+ import type { Row } from "./database.ts";
9
+
10
+ function describe(value: unknown): string {
11
+ return value === null ? "null" : typeof value;
12
+ }
13
+
14
+ /** Require a non-null string column, or throw naming the column and actual type. */
15
+ export function requireString(row: Row, column: string): string {
16
+ const value = row[column];
17
+ if (typeof value !== "string") {
18
+ throw new Error(`row column "${column}": expected string, got ${describe(value)}`);
19
+ }
20
+ return value;
21
+ }
22
+
23
+ /** A string column that may be null/absent (returned as null), else validated. */
24
+ export function optionalString(row: Row, column: string): string | null {
25
+ const value = row[column];
26
+ if (value === null || value === undefined) return null;
27
+ if (typeof value !== "string") {
28
+ throw new Error(`row column "${column}": expected string or null, got ${describe(value)}`);
29
+ }
30
+ return value;
31
+ }
32
+
33
+ /** A numeric column that may be null/absent; bigint is narrowed to number. */
34
+ export function optionalNumber(row: Row, column: string): number | null {
35
+ const value = row[column];
36
+ if (value === null || value === undefined) return null;
37
+ if (typeof value === "bigint") return Number(value);
38
+ if (typeof value !== "number") {
39
+ throw new Error(`row column "${column}": expected number or null, got ${describe(value)}`);
40
+ }
41
+ return value;
42
+ }