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,623 @@
1
+ // Front-door routes for the daily-visible tail (CV22.DS7.TS3 plateau 5):
2
+ // `welcome` and the READ-ONLY `runtime` subcommands.
3
+ //
4
+ // The subcommand allowlist here is the enforcement point for the plan's
5
+ // central boundary. `runtime` carries both the read surface this story ports
6
+ // and the git-based updater and release machinery, which the 2026-09-07
7
+ // decision assigned to CV22.DS10 for redesign under npm distribution. Those
8
+ // stay Python by EXPLICIT REFUSAL, never by inheritance (RS009's rule): a
9
+ // future subcommand added to Python must not silently acquire a TS route
10
+ // because the command name already had one.
11
+
12
+ import { accessSync, constants } from "node:fs";
13
+ import { homedir } from "node:os";
14
+ import { join } from "node:path";
15
+ import { createZipBackup } from "#backup/zipBackup.ts";
16
+ import { dbNameForEnv, resolveMirrorHome } from "#frontDoor/dbPath.ts";
17
+ import { frontDoorLogPath, logFrontDoor } from "#frontDoor/frontDoorLog.ts";
18
+ import { renderUnknownSubcommand } from "#frontDoor/usage.ts";
19
+ import {
20
+ renderBackupVerification,
21
+ renderRuntimeBackupCreated,
22
+ verifyBackupArchive,
23
+ } from "#runtime/backup.ts";
24
+ import { channelFor, renderChannel, setChannel } from "#runtime/channel.ts";
25
+ import {
26
+ diagnoseRuntime,
27
+ hookFailureFindings,
28
+ hookNodeFindings,
29
+ probeModelPins,
30
+ renderRuntimeDiagnosis,
31
+ rootStateFindings,
32
+ staleRevertGateFindings,
33
+ } from "#runtime/diagnose.ts";
34
+ import {
35
+ checkUpdateAvailability,
36
+ inspectCloneRole,
37
+ inspectGitFor,
38
+ inspectGitWorktree,
39
+ inspectUpdateChannel,
40
+ packageVersion,
41
+ renderRuntimeUpdateAvailability,
42
+ renderRuntimeVersion,
43
+ upstreamFor,
44
+ } from "#runtime/git.ts";
45
+ import { detectInstallKind, type InstallKind } from "#runtime/installKind.ts";
46
+ import { MIGRATE_DECLINED_EXIT, renderMigrate, runMigrate } from "#runtime/migrate.ts";
47
+ import {
48
+ buildPendingReleaseNotes,
49
+ readReleaseNote,
50
+ renderReleaseNote,
51
+ renderReleaseNotesBundle,
52
+ } from "#runtime/releaseNotes.ts";
53
+ import { buildRuntimeStatus, renderRuntimeStatus, statusVerdict } from "#runtime/status.ts";
54
+ import {
55
+ checkPackageUpdateAvailability,
56
+ npmRootGlobal,
57
+ renderPackageUpdateAvailability,
58
+ } from "#runtime/strategies/package.ts";
59
+ import { runningTreeRoot } from "#runtime/treeRoot.ts";
60
+ import { frontDoorSpawner, postUpdateHints, runUpdate, type UpdateSpawn } from "#runtime/update.ts";
61
+ import { statusAllowsUpdatePreflight } from "#runtime/updateGate.ts";
62
+ import { renderUpdateResult, updateLogDetail } from "#runtime/updatePipeline.ts";
63
+ import { expandHome } from "#util/paths.ts";
64
+ import { composeWelcome, welcomeDisabled } from "#welcome/card.ts";
65
+ import { composeStatusLine } from "#welcome/statusLine.ts";
66
+
67
+ /** The `runtime` subcommands this story ports. */
68
+ export const TS_RUNTIME_READ_SUBCOMMANDS = new Set([
69
+ "status",
70
+ "version",
71
+ "diagnose",
72
+ "release-notes",
73
+ ]);
74
+
75
+ /**
76
+ * Every `runtime` subcommand that EXISTS, in the order the oracle's argparse
77
+ * lists them. One source of names: the usage line an unknown subcommand gets
78
+ * is rendered from this, so it cannot drift from what the build answers.
79
+ */
80
+ export const RUNTIME_SUBCOMMANDS = [
81
+ "status",
82
+ "version",
83
+ "diagnose",
84
+ "update",
85
+ "release-notes",
86
+ "release-doctor",
87
+ "release-promote",
88
+ "backup",
89
+ // CV22.DS10.US2 (D8): not on the oracle. The updater spawns it in a fresh
90
+ // process so the code that migrates is the code that was just installed.
91
+ "migrate",
92
+ // CV22.DS10.US3 (D9): not on the oracle. Shows or sets the channel this
93
+ // install follows, in the file its install kind keeps it in.
94
+ "channel",
95
+ ] as const;
96
+
97
+ /**
98
+ * The `runtime` subcommands that stay Python, each named on purpose.
99
+ *
100
+ * `latest` and `pending` are ARGUMENTS of `release-notes`, not subcommands --
101
+ * the 2026-09-07 decision text and the burn-down ledger's table listed them as
102
+ * subcommands, and DS7.TS3 corrected that.
103
+ *
104
+ * CV22.DS10.US2 finished the correction the line above started: `pull` and
105
+ * `stable` were in this set and have NEVER existed on either engine. `pull` is
106
+ * the update planner's ACTION (`action: "pull"`); `stable` is the CHANNEL.
107
+ * Both answer `invalid choice` with exit 2 on Python, so routing them here
108
+ * claimed DS10 owed a port of something that was never a command. Four names,
109
+ * and each leaves as its story flips it.
110
+ */
111
+ /**
112
+ * The updater family. US2 flipped it one subcommand at a time -- `backup`,
113
+ * then `update` and the `migrate` verb D8 added -- and the set it emptied,
114
+ * `DS10_RUNTIME_SUBCOMMANDS`, is gone: `release-doctor` and `release-promote`
115
+ * were the last two names in it, and they are not ported but RETIRED from the
116
+ * product surface, so they answer from the retired-surface table instead.
117
+ *
118
+ * (Its own revert, `MIRROR_TS_RUNTIME_UPDATE=0`, left with the Python engine at
119
+ * CV22.DS10.TS5.)
120
+ */
121
+ export const TS_RUNTIME_UPDATE_SUBCOMMANDS: ReadonlyMap<string, string> = new Map([
122
+ ["backup", "DS10.US2 runtime backup ported to TS"],
123
+ ["update", "DS10.US2 runtime update ported to TS"],
124
+ ["migrate", "DS10.US2 runtime migrate ported to TS"],
125
+ ["channel", "DS10.US3 runtime channel (D9), TS-native"],
126
+ ]);
127
+
128
+ function optionValue(args: readonly string[], name: string): string | null {
129
+ const index = args.indexOf(name);
130
+ if (index === -1) return null;
131
+ return args[index + 1] ?? null;
132
+ }
133
+
134
+ /**
135
+ * The mirror home for a welcome invocation. An explicit `--mirror-home` is
136
+ * authoritative even when the repository `.env` supplies MIRROR_USER, matching
137
+ * the oracle's `resolve_mirror_home(mirror_home=..., mirror_user="")`: tests
138
+ * and one-off diagnostics must not be shadowed by the ambient user.
139
+ */
140
+ function resolveWelcomeHome(explicit: string | null, env: NodeJS.ProcessEnv): string | null {
141
+ try {
142
+ if (explicit !== null) {
143
+ if (explicit === "") return null;
144
+ return resolveMirrorHome({ MIRROR_HOME: expandHome(explicit), MIRROR_USER: "" });
145
+ }
146
+ return resolveMirrorHome(env);
147
+ } catch {
148
+ return null;
149
+ }
150
+ }
151
+
152
+ export interface RuntimeRouteIo {
153
+ cwd?: string;
154
+ env?: NodeJS.ProcessEnv;
155
+ stdout?: (text: string) => void;
156
+ /** Refusals go to stderr, as argparse's do. */
157
+ stderr?: (text: string) => void;
158
+ }
159
+
160
+ function writeOut(io: RuntimeRouteIo, text: string): void {
161
+ (io.stdout ?? ((value: string) => process.stdout.write(value)))(text);
162
+ }
163
+
164
+ function writeErr(io: RuntimeRouteIo, text: string): void {
165
+ (io.stderr ?? ((value: string) => process.stderr.write(value)))(text);
166
+ }
167
+
168
+ /** Port of `welcome.main`. Always exits 0, like the oracle. */
169
+ export function runWelcomeRoute(argv: readonly string[], io: RuntimeRouteIo = {}): number {
170
+ const env = io.env ?? process.env;
171
+ const cwd = io.cwd ?? process.cwd();
172
+ const args = argv.slice(1);
173
+ if (welcomeDisabled(env)) return 0;
174
+
175
+ const home = resolveWelcomeHome(optionValue(args, "--mirror-home"), env);
176
+
177
+ if (args.includes("--status-line")) {
178
+ const line = composeStatusLine({
179
+ mirrorHome: home,
180
+ sessionId: optionValue(args, "--session-id"),
181
+ env,
182
+ });
183
+ if (line) writeOut(io, `${line}\n`);
184
+ return 0;
185
+ }
186
+
187
+ const version = packageVersion(runningTreeRoot()) ?? "unknown";
188
+ const card = composeWelcome({
189
+ mirrorHome: home,
190
+ cwd,
191
+ treeRoot: runningTreeRoot(),
192
+ env,
193
+ version,
194
+ updateChannel: inspectUpdateChannel(cwd, null),
195
+ });
196
+ if (card) writeOut(io, `${card}\n`);
197
+ return 0;
198
+ }
199
+
200
+ /** Port of the read half of `cmd_runtime`. */
201
+ export async function runRuntimeReadRoute(
202
+ argv: readonly string[],
203
+ io: RuntimeRouteIo = {},
204
+ ): Promise<number> {
205
+ const env = io.env ?? process.env;
206
+ const cwd = io.cwd ?? process.cwd();
207
+ const args = argv.slice(1);
208
+ const subcommand = args[0] ?? "";
209
+ // The version is the running tree's, never the cwd's: for a skill the cwd
210
+ // is the user's project, and for an installed package it is anything
211
+ // (CV22.DS10.US3, the fourth tree reader the plan's list did not name).
212
+ const version = packageVersion(runningTreeRoot()) ?? "unknown";
213
+
214
+ if (subcommand === "version") {
215
+ const startArg = optionValue(args, "--start");
216
+ const start = startArg ? expandHome(startArg) : cwd;
217
+ const install = detectThisInstall();
218
+ writeOut(
219
+ io,
220
+ renderRuntimeVersion({
221
+ version,
222
+ install,
223
+ git: inspectGitFor(install, start),
224
+ cloneRole: inspectCloneRole(start),
225
+ updateChannel:
226
+ install.kind === "package"
227
+ ? channelFor(install, env, homedir(), optionValue(args, "--channel"))
228
+ : inspectUpdateChannel(start, optionValue(args, "--channel")),
229
+ }),
230
+ );
231
+ return 0;
232
+ }
233
+
234
+ if (subcommand === "status") {
235
+ const report = buildRuntimeStatus({
236
+ start: cwd,
237
+ mirrorHome: optionValue(args, "--mirror-home"),
238
+ channel: optionValue(args, "--channel"),
239
+ env,
240
+ version,
241
+ install: detectThisInstall(),
242
+ });
243
+ writeOut(io, renderRuntimeStatus(report, env));
244
+ return statusVerdict(report) === "ready" ? 0 : 1;
245
+ }
246
+
247
+ if (subcommand === "diagnose") {
248
+ const report = buildRuntimeStatus({
249
+ start: cwd,
250
+ mirrorHome: optionValue(args, "--mirror-home"),
251
+ env,
252
+ version,
253
+ install: detectThisInstall(),
254
+ });
255
+ const findings = [
256
+ ...diagnoseRuntime(report, inspectGitWorktree(report.git.repository)),
257
+ ...rootStateFindings(homesRoot(env)),
258
+ // CV22.DS10.TS5: the transition's own leftovers. A stale MIRROR_TS_*
259
+ // gate is inert and silently so; an unresolvable Node makes every hook
260
+ // skip; and hooks.log holds what the hooks met in their own context.
261
+ // All three are invisible without being asked for.
262
+ ...staleRevertGateFindings(env),
263
+ ...hookFailureFindings(report),
264
+ ...hookNodeFindings(env, (path) => {
265
+ try {
266
+ accessSync(path, constants.X_OK);
267
+ return true;
268
+ } catch {
269
+ return false;
270
+ }
271
+ }),
272
+ // No catalog provider until DS8: inconclusive, which is also the
273
+ // oracle's answer when it cannot reach OpenRouter.
274
+ ...(await probeModelPins(null, "")),
275
+ ];
276
+ writeOut(io, renderRuntimeDiagnosis(findings));
277
+ return findings.length === 0 ? 0 : 1;
278
+ }
279
+
280
+ if (subcommand === "release-notes") {
281
+ const target = firstPositional(args.slice(1)) ?? "latest";
282
+ if (target === "pending") {
283
+ writeOut(
284
+ io,
285
+ renderReleaseNotesBundle(
286
+ buildPendingReleaseNotes({
287
+ // `--from` omitted falls back to the checkout's own version,
288
+ // exactly as the oracle does before normalizing.
289
+ currentVersion: optionValue(args, "--from") ?? version,
290
+ ref: optionValue(args, "--ref") ?? "origin/stable",
291
+ fetch: !args.includes("--no-fetch"),
292
+ start: cwd,
293
+ }),
294
+ ),
295
+ );
296
+ } else {
297
+ // The notes ship in the package at the same path as in the checkout
298
+ // (US3 D8), read from the tree that holds the running front door --
299
+ // never from the cwd, which for a skill is the user's project.
300
+ writeOut(io, renderReleaseNote(readReleaseNote(target, runningTreeRoot())));
301
+ }
302
+ return 0;
303
+ }
304
+
305
+ if (subcommand === "backup") return runRuntimeBackup(args.slice(1), io, env);
306
+ if (subcommand === "migrate") return runRuntimeMigrate(args.slice(1), io, env);
307
+ if (subcommand === "update") return runRuntimeUpdate(args.slice(1), io, env, cwd);
308
+ if (subcommand === "channel") return runRuntimeChannel(args.slice(1), io, env);
309
+
310
+ // Routing answers every name it does not recognize before dispatch (the
311
+ // shared usage answer, CV22.DS10.TS5 D2 -- the shape US2 gave `runtime`
312
+ // first). Reaching here means routing and this function disagree about the
313
+ // family's names, so the same answer is given rather than a guess.
314
+ writeErr(io, renderUnknownSubcommand("runtime", RUNTIME_SUBCOMMANDS, subcommand));
315
+ return 2;
316
+ }
317
+
318
+ /**
319
+ * `runtime backup [--mirror-home PATH]` and `runtime backup --verify PATH`.
320
+ *
321
+ * NOT the `backup` command (DS7.TS1). That one creates and stops; this one is
322
+ * the updater's safety stage, so it creates, verifies, and prints the manual
323
+ * recovery route. The exit code follows the VERIFICATION, not the creation:
324
+ * an archive that was written but does not open is a failure here, which is
325
+ * the whole point of the stage.
326
+ */
327
+ function runRuntimeBackup(
328
+ args: readonly string[],
329
+ io: RuntimeRouteIo,
330
+ env: NodeJS.ProcessEnv,
331
+ ): number {
332
+ const verifyTarget = optionValue(args, "--verify");
333
+ if (verifyTarget !== null) {
334
+ const verification = verifyBackupArchive(expandHome(verifyTarget));
335
+ writeOut(io, renderBackupVerification(verification));
336
+ return verification.valid ? 0 : 1;
337
+ }
338
+
339
+ const explicitHome = optionValue(args, "--mirror-home");
340
+ let mirrorHome: string;
341
+ try {
342
+ mirrorHome =
343
+ explicitHome !== null
344
+ ? expandHome(explicitHome)
345
+ : resolveMirrorHome(env as Record<string, string | undefined>);
346
+ } catch (error) {
347
+ // Python writes the ValueError's own text and exits 1.
348
+ writeErr(io, `${error instanceof Error ? error.message : String(error)}\n`);
349
+ return 1;
350
+ }
351
+
352
+ const dbPath = join(mirrorHome, dbNameForEnv(env.MEMORY_ENV || "production"));
353
+ const backupPath = createZipBackup({
354
+ dbPath,
355
+ mirrorHome,
356
+ backupDir: null,
357
+ // The oracle passes `silent=True`: creation chatter would sit in the
358
+ // middle of this command's own render.
359
+ silent: true,
360
+ env,
361
+ });
362
+ if (backupPath === null) {
363
+ writeErr(io, `Database not found: ${dbPath}\n`);
364
+ return 1;
365
+ }
366
+
367
+ const verification = verifyBackupArchive(backupPath);
368
+ writeOut(io, renderRuntimeBackupCreated({ backupPath, mirrorHome, verification }));
369
+ return verification.valid ? 0 : 1;
370
+ }
371
+
372
+ /** The mirror home this invocation addresses, or an error to print. */
373
+ function homeFor(
374
+ args: readonly string[],
375
+ env: NodeJS.ProcessEnv,
376
+ ): { home: string } | { error: string } {
377
+ const explicit = optionValue(args, "--mirror-home");
378
+ try {
379
+ return {
380
+ home:
381
+ explicit !== null
382
+ ? expandHome(explicit)
383
+ : resolveMirrorHome(env as Record<string, string | undefined>),
384
+ };
385
+ } catch (error) {
386
+ return { error: error instanceof Error ? error.message : String(error) };
387
+ }
388
+ }
389
+
390
+ /** `runtime migrate [--mirror-home PATH]` (CV22.DS10.US2, D8). */
391
+ function runRuntimeMigrate(
392
+ args: readonly string[],
393
+ io: RuntimeRouteIo,
394
+ env: NodeJS.ProcessEnv,
395
+ ): number {
396
+ const resolved = homeFor(args, env);
397
+ if ("error" in resolved) {
398
+ writeErr(io, `${resolved.error}\n`);
399
+ return 1;
400
+ }
401
+ const dbPath = join(resolved.home, dbNameForEnv(env.MEMORY_ENV || "production"));
402
+ const outcome = runMigrate(dbPath);
403
+ writeOut(io, renderMigrate(outcome));
404
+ // A DECLINED migration exits non-zero (CV22.DS10.US2 debt D-025, paid in
405
+ // TS5). The updater's migrate stage already fails on a non-zero code, so
406
+ // this one line is what turns "the engine refused work it could not safely
407
+ // do" from a passing stage into a failing one. Before this, `declined` and
408
+ // `nothing pending` were the same exit 0.
409
+ if (outcome.error !== null) return 1;
410
+ return outcome.verdict === "declined" ? MIGRATE_DECLINED_EXIT : 0;
411
+ }
412
+
413
+ /**
414
+ * `runtime channel [stable|main]` (CV22.DS10.US3, D9): show the channel this
415
+ * install follows, or set it. The file is the install kind's own; the
416
+ * vocabulary is the pipeline's; nothing else is touched.
417
+ */
418
+ function runRuntimeChannel(
419
+ args: readonly string[],
420
+ io: RuntimeRouteIo,
421
+ env: NodeJS.ProcessEnv,
422
+ ): number {
423
+ const install = detectThisInstall();
424
+ const requested = args.find((arg) => !arg.startsWith("-")) ?? null;
425
+ // (A channel is read and written by layout evidence alone: a package user
426
+ // with npm off the PATH can still choose one.)
427
+ if (requested === null) {
428
+ writeOut(io, renderChannel({ install, channel: channelFor(install, env), written: null }));
429
+ return 0;
430
+ }
431
+ const written = setChannel(install, requested, env);
432
+ if (!written.ok) {
433
+ writeErr(io, `Error: ${written.reason}\n`);
434
+ return written.exitCode;
435
+ }
436
+ writeOut(
437
+ io,
438
+ renderChannel({
439
+ install,
440
+ channel: channelFor(install, env),
441
+ written: { previous: written.previous },
442
+ }),
443
+ );
444
+ return 0;
445
+ }
446
+
447
+ /**
448
+ * `runtime update [--check|--dry-run|--repair-updater] [--no-fetch]
449
+ * [--skip-migrations] [--mirror-home PATH] [--channel stable|main]`.
450
+ */
451
+ function runRuntimeUpdate(
452
+ args: readonly string[],
453
+ io: RuntimeRouteIo,
454
+ env: NodeJS.ProcessEnv,
455
+ cwd: string,
456
+ ): number {
457
+ const version = packageVersion(runningTreeRoot()) ?? "unknown";
458
+ const channelOverride = optionValue(args, "--channel");
459
+ // The update lane asks npm, once, whether `-g` addresses this install: a
460
+ // package outside npm's own global root is not the one `npm install -g`
461
+ // would replace. The read routes do not pay for the probe.
462
+ const install = detectInstallKind({
463
+ frontDoorPath: frontDoorSelfPath(),
464
+ npmRootGlobal: npmRootGlobal(),
465
+ });
466
+ const start = install.kind === "clone" ? install.repository : cwd;
467
+ const channel = channelFor(install, env, homedir(), channelOverride);
468
+
469
+ if (args.includes("--check")) {
470
+ // A package asks the registry the question the pipeline's plan stage
471
+ // asks, and says which way the channel lies; a clone asks its remote.
472
+ // Until CV22.DS10.US3 plateau 4 both asked git, from the cwd.
473
+ if (install.kind === "package") {
474
+ const availability = checkPackageUpdateAvailability(install, channel);
475
+ writeOut(io, renderPackageUpdateAvailability(availability));
476
+ return availability.status === "up_to_date" || availability.status === "update_available"
477
+ ? 0
478
+ : 1;
479
+ }
480
+ const availability = checkUpdateAvailability(start, channelOverride, version);
481
+ writeOut(io, renderRuntimeUpdateAvailability(availability));
482
+ return availability.status === "up_to_date" || availability.status === "update_available"
483
+ ? 0
484
+ : 1;
485
+ }
486
+
487
+ const resolved = homeFor(args, env);
488
+ if ("error" in resolved) {
489
+ writeErr(io, `${resolved.error}\n`);
490
+ return 1;
491
+ }
492
+ const mirrorHome = resolved.home;
493
+ const dbPath = join(mirrorHome, dbNameForEnv(env.MEMORY_ENV || "production"));
494
+
495
+ // The repair lane is entered on request, and AUTOMATICALLY when the gate
496
+ // throws rather than merely reporting trouble: an updater that cannot
497
+ // evaluate its own status is exactly the failure the lane exists for, and
498
+ // asking the broken status to authorize its own repair is circular.
499
+ let repair = args.includes("--repair-updater");
500
+ let repairReason = repair ? "requested with --repair-updater" : "";
501
+
502
+ const gate = (): { ready: boolean; allowed: boolean; detail: string } => {
503
+ const report = buildRuntimeStatus({
504
+ start,
505
+ mirrorHome,
506
+ channel: channelOverride,
507
+ env,
508
+ version,
509
+ install,
510
+ });
511
+ const verdict = statusAllowsUpdatePreflight(report);
512
+ return { ready: statusVerdict(report) === "ready", ...verdict };
513
+ };
514
+
515
+ if (!repair) {
516
+ try {
517
+ gate();
518
+ } catch (error) {
519
+ repair = true;
520
+ repairReason = `runtime status crashed before update planning: ${
521
+ error instanceof Error ? error.message.split("\n")[0] : String(error)
522
+ }`;
523
+ }
524
+ }
525
+
526
+ const result = runUpdate({
527
+ install,
528
+ upstream: install.kind === "clone" ? upstreamFor(channel) : null,
529
+ channel: channel.value,
530
+ mirrorHome,
531
+ gate,
532
+ // Re-read through a FRESH process, so the verdict comes from the code that
533
+ // was just installed rather than from the modules this one imported.
534
+ statusReady: () => {
535
+ const probe = spawner(env)(["runtime", "status", "--mirror-home", mirrorHome]);
536
+ return {
537
+ ready: probe.code === 0,
538
+ detail: probe.code === 0 ? "" : "runtime status is not ready",
539
+ };
540
+ },
541
+ createBackup: () => createZipBackup({ dbPath, mirrorHome, backupDir: null, silent: true, env }),
542
+ spawnFrontDoor: spawner(env),
543
+ fetch: !args.includes("--no-fetch"),
544
+ migrate: !args.includes("--skip-migrations"),
545
+ dryRun: args.includes("--dry-run"),
546
+ repair,
547
+ ...(repairReason ? { repairReason } : {}),
548
+ });
549
+
550
+ writeOut(io, renderUpdateResult(result));
551
+ if (repair && result.success) {
552
+ // After the stages, not before them: the instruction is what to do NEXT,
553
+ // and it reads as a caption on a result the operator has already seen.
554
+ writeOut(
555
+ io,
556
+ "\nThe updater was repaired. Run `runtime update` again to complete the update.\n",
557
+ );
558
+ }
559
+ for (const hint of postUpdateHints(install, result, env)) writeOut(io, `\n${hint}\n`);
560
+ // The log takes the install KIND word and the short refs, never the
561
+ // repository path: this file's contract is "never argument values", and the
562
+ // migrate_on_open entry beside it records a basename for the same reason.
563
+ logFrontDoor(frontDoorLogPath(dbPath), {
564
+ command: "runtime",
565
+ route: "ts",
566
+ exitCode: result.success ? 0 : 1,
567
+ detail: updateLogDetail(install.kind, channel.value, result),
568
+ });
569
+ return result.success ? 0 : 1;
570
+ }
571
+
572
+ /**
573
+ * The front door, spawned again on the code now installed. Through the bin
574
+ * (`bin/mirror.js`, D15), never `cli.ts` itself: under `node_modules` Node
575
+ * refuses to strip types, so a package's fresh-process migrate and validate
576
+ * crashed at the first `.ts` import -- found by the update smoke's package
577
+ * lane (CV22.DS10.US3 plateau 4). A checkout runs the same bin, as `npm link`
578
+ * does.
579
+ */
580
+ function spawner(env: NodeJS.ProcessEnv): UpdateSpawn {
581
+ return frontDoorSpawner(join(runningTreeRoot(), "bin", "mirror.js"), env);
582
+ }
583
+
584
+ /** This front door's own path, which is also how the install kind is read. */
585
+ function frontDoorSelfPath(): string {
586
+ return new URL("./cli.ts", import.meta.url).pathname;
587
+ }
588
+
589
+ /**
590
+ * How THIS front door is installed, by what the filesystem shows and nothing
591
+ * spawned: a checkout by its `.git`, a package by npm's global layout and the
592
+ * bin linked into it. The one place that needs npm's own word, the update
593
+ * lane, probes `npm root -g` itself.
594
+ */
595
+ function detectThisInstall(): InstallKind {
596
+ return detectInstallKind({ frontDoorPath: frontDoorSelfPath() });
597
+ }
598
+
599
+ /**
600
+ * argparse's positional for `release-notes`: the first bare token that is not
601
+ * consumed as the VALUE of `--from` or `--ref`. Walking the list is the only
602
+ * way to tell `release-notes --ref pending` (a ref named pending) from
603
+ * `release-notes pending` (the bundle).
604
+ */
605
+ function firstPositional(args: readonly string[]): string | null {
606
+ const valued = new Set(["--from", "--ref"]);
607
+ for (let index = 0; index < args.length; index += 1) {
608
+ const arg = args[index] as string;
609
+ if (valued.has(arg)) {
610
+ index += 1;
611
+ continue;
612
+ }
613
+ if (arg.startsWith("-")) continue;
614
+ return arg;
615
+ }
616
+ return null;
617
+ }
618
+
619
+ /** Python's ambient `DEFAULT_USER_HOMES_DIR`: `<home>/.mirror-minds`. */
620
+ function homesRoot(env: NodeJS.ProcessEnv): string {
621
+ const home = env.HOME ?? env.USERPROFILE ?? "";
622
+ return join(home, ".mirror-minds");
623
+ }