mirror-mind 0.0.1 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (474) hide show
  1. package/.claude/hooks/log-assistant-reply.sh +85 -0
  2. package/.claude/hooks/log-session-end.sh +85 -0
  3. package/.claude/hooks/log-user-prompt.sh +85 -0
  4. package/.claude/hooks/mirror-inject.sh +85 -0
  5. package/.claude/hooks/session-start.sh +85 -0
  6. package/.gemini/hooks/log-assistant.sh +85 -0
  7. package/.gemini/hooks/log-user.sh +85 -0
  8. package/.gemini/hooks/session-end.sh +85 -0
  9. package/.gemini/hooks/session-start.sh +85 -0
  10. package/.pi/extensions/mirror-logger.ts +646 -0
  11. package/.pi/skills/mm-backup/SKILL.md +21 -0
  12. package/.pi/skills/mm-build/SKILL.md +1206 -0
  13. package/.pi/skills/mm-consolidate/SKILL.md +112 -0
  14. package/.pi/skills/mm-consult/SKILL.md +70 -0
  15. package/.pi/skills/mm-conversations/SKILL.md +16 -0
  16. package/.pi/skills/mm-discard/SKILL.md +39 -0
  17. package/.pi/skills/mm-explore/SKILL.md +255 -0
  18. package/.pi/skills/mm-help/SKILL.md +74 -0
  19. package/.pi/skills/mm-identity/SKILL.md +96 -0
  20. package/.pi/skills/mm-journal/SKILL.md +16 -0
  21. package/.pi/skills/mm-journey/SKILL.md +23 -0
  22. package/.pi/skills/mm-journeys/SKILL.md +15 -0
  23. package/.pi/skills/mm-memories/SKILL.md +17 -0
  24. package/.pi/skills/mm-mirror/SKILL.md +98 -0
  25. package/.pi/skills/mm-mute/SKILL.md +18 -0
  26. package/.pi/skills/mm-new/SKILL.md +18 -0
  27. package/.pi/skills/mm-recall/SKILL.md +17 -0
  28. package/.pi/skills/mm-release-notes/SKILL.md +52 -0
  29. package/.pi/skills/mm-seed/SKILL.md +19 -0
  30. package/.pi/skills/mm-shadow/SKILL.md +117 -0
  31. package/.pi/skills/mm-soul/SKILL.md +502 -0
  32. package/.pi/skills/mm-tasks/SKILL.md +24 -0
  33. package/.pi/skills/mm-update/SKILL.md +32 -0
  34. package/.pi/skills/mm-week/SKILL.md +28 -0
  35. package/.pi/skills/mm-welcome/SKILL.md +24 -0
  36. package/AGENTS.md +188 -0
  37. package/README.md +126 -9
  38. package/bin/loader.js +67 -0
  39. package/bin/mirror-hook.js +7 -0
  40. package/bin/mirror.js +7 -0
  41. package/docs/releases/index.md +100 -0
  42. package/docs/releases/pending-cutoffs.md +510 -0
  43. package/docs/releases/v0.10.0.md +123 -0
  44. package/docs/releases/v0.10.1.md +66 -0
  45. package/docs/releases/v0.10.10.md +51 -0
  46. package/docs/releases/v0.10.11.md +39 -0
  47. package/docs/releases/v0.10.12.md +57 -0
  48. package/docs/releases/v0.10.13.md +35 -0
  49. package/docs/releases/v0.10.14.md +42 -0
  50. package/docs/releases/v0.10.15.md +53 -0
  51. package/docs/releases/v0.10.16.md +35 -0
  52. package/docs/releases/v0.10.17.md +43 -0
  53. package/docs/releases/v0.10.2.md +64 -0
  54. package/docs/releases/v0.10.3.md +78 -0
  55. package/docs/releases/v0.10.4.md +42 -0
  56. package/docs/releases/v0.10.5.md +57 -0
  57. package/docs/releases/v0.10.6.md +47 -0
  58. package/docs/releases/v0.10.7.md +53 -0
  59. package/docs/releases/v0.10.8.md +49 -0
  60. package/docs/releases/v0.10.9.md +37 -0
  61. package/docs/releases/v0.11.0.md +86 -0
  62. package/docs/releases/v0.12.0.md +67 -0
  63. package/docs/releases/v0.13.0.md +64 -0
  64. package/docs/releases/v0.14.0.md +68 -0
  65. package/docs/releases/v0.15.0.md +48 -0
  66. package/docs/releases/v0.16.0.md +50 -0
  67. package/docs/releases/v0.16.1.md +55 -0
  68. package/docs/releases/v0.16.2.md +36 -0
  69. package/docs/releases/v0.17.0.md +50 -0
  70. package/docs/releases/v0.17.1.md +58 -0
  71. package/docs/releases/v0.17.2.md +42 -0
  72. package/docs/releases/v0.17.3.md +58 -0
  73. package/docs/releases/v0.18.0.md +84 -0
  74. package/docs/releases/v0.18.1.md +51 -0
  75. package/docs/releases/v0.18.2.md +69 -0
  76. package/docs/releases/v0.19.0.md +85 -0
  77. package/docs/releases/v0.19.1.md +46 -0
  78. package/docs/releases/v0.20.0.md +85 -0
  79. package/docs/releases/v0.21.0.md +61 -0
  80. package/docs/releases/v0.21.1.md +47 -0
  81. package/docs/releases/v0.22.0.md +77 -0
  82. package/docs/releases/v0.22.1.md +42 -0
  83. package/docs/releases/v0.23.0.md +105 -0
  84. package/docs/releases/v0.24.0.md +125 -0
  85. package/docs/releases/v0.25.0.md +107 -0
  86. package/docs/releases/v0.26.0.md +139 -0
  87. package/docs/releases/v0.26.1.md +65 -0
  88. package/docs/releases/v0.26.2.md +43 -0
  89. package/docs/releases/v0.27.0.md +63 -0
  90. package/docs/releases/v0.28.0.md +59 -0
  91. package/docs/releases/v0.29.0.md +61 -0
  92. package/docs/releases/v0.29.1.md +59 -0
  93. package/docs/releases/v0.29.2.md +59 -0
  94. package/docs/releases/v0.29.3.md +93 -0
  95. package/docs/releases/v0.30.0.md +75 -0
  96. package/docs/releases/v0.30.1.md +93 -0
  97. package/docs/releases/v0.30.2.md +66 -0
  98. package/docs/releases/v0.31.0.md +122 -0
  99. package/docs/releases/v0.31.1.md +142 -0
  100. package/docs/releases/v0.31.10.md +118 -0
  101. package/docs/releases/v0.31.11.md +88 -0
  102. package/docs/releases/v0.31.12.md +105 -0
  103. package/docs/releases/v0.31.13.md +99 -0
  104. package/docs/releases/v0.31.14.md +97 -0
  105. package/docs/releases/v0.31.2.md +115 -0
  106. package/docs/releases/v0.31.3.md +142 -0
  107. package/docs/releases/v0.31.4.md +117 -0
  108. package/docs/releases/v0.31.5.md +155 -0
  109. package/docs/releases/v0.31.6.md +132 -0
  110. package/docs/releases/v0.31.7.md +132 -0
  111. package/docs/releases/v0.31.8.md +120 -0
  112. package/docs/releases/v0.31.9.md +120 -0
  113. package/docs/releases/v0.32.0.md +261 -0
  114. package/docs/releases/v0.32.1.md +59 -0
  115. package/docs/releases/v0.33.0.md +164 -0
  116. package/docs/releases/v0.8.0.md +118 -0
  117. package/docs/releases/v0.9.0.md +98 -0
  118. package/docs/releases/v0.9.1.md +83 -0
  119. package/package.json +102 -6
  120. package/plugins/mirror-mind/.claude-plugin/plugin.json +17 -0
  121. package/plugins/mirror-mind/hooks/hooks.json +62 -0
  122. package/plugins/mirror-mind/hooks/log-assistant-reply.sh +98 -0
  123. package/plugins/mirror-mind/hooks/log-session-end.sh +98 -0
  124. package/plugins/mirror-mind/hooks/log-user-prompt.sh +98 -0
  125. package/plugins/mirror-mind/hooks/mirror-inject.sh +98 -0
  126. package/plugins/mirror-mind/hooks/session-start.sh +98 -0
  127. package/plugins/mirror-mind/skills/mm-backup/SKILL.md +27 -0
  128. package/plugins/mirror-mind/skills/mm-build/SKILL.md +1206 -0
  129. package/plugins/mirror-mind/skills/mm-consolidate/SKILL.md +112 -0
  130. package/plugins/mirror-mind/skills/mm-consult/SKILL.md +83 -0
  131. package/plugins/mirror-mind/skills/mm-conversations/SKILL.md +17 -0
  132. package/plugins/mirror-mind/skills/mm-discard/SKILL.md +40 -0
  133. package/plugins/mirror-mind/skills/mm-explore/SKILL.md +241 -0
  134. package/plugins/mirror-mind/skills/mm-help/SKILL.md +104 -0
  135. package/plugins/mirror-mind/skills/mm-identity/SKILL.md +96 -0
  136. package/plugins/mirror-mind/skills/mm-journal/SKILL.md +21 -0
  137. package/plugins/mirror-mind/skills/mm-journey/SKILL.md +37 -0
  138. package/plugins/mirror-mind/skills/mm-journeys/SKILL.md +15 -0
  139. package/plugins/mirror-mind/skills/mm-memories/SKILL.md +20 -0
  140. package/plugins/mirror-mind/skills/mm-mirror/SKILL.md +67 -0
  141. package/plugins/mirror-mind/skills/mm-mute/SKILL.md +18 -0
  142. package/plugins/mirror-mind/skills/mm-new/SKILL.md +18 -0
  143. package/plugins/mirror-mind/skills/mm-recall/SKILL.md +17 -0
  144. package/plugins/mirror-mind/skills/mm-release-notes/SKILL.md +31 -0
  145. package/plugins/mirror-mind/skills/mm-seed/SKILL.md +15 -0
  146. package/plugins/mirror-mind/skills/mm-shadow/SKILL.md +117 -0
  147. package/plugins/mirror-mind/skills/mm-soul/SKILL.md +488 -0
  148. package/plugins/mirror-mind/skills/mm-tasks/SKILL.md +36 -0
  149. package/plugins/mirror-mind/skills/mm-update/SKILL.md +30 -0
  150. package/plugins/mirror-mind/skills/mm-week/SKILL.md +46 -0
  151. package/plugins/mirror-mind/skills/mm-welcome/SKILL.md +22 -0
  152. package/scripts/codex-hooks/session-end.sh +85 -0
  153. package/scripts/codex-hooks/session-start.sh +85 -0
  154. package/scripts/codex-mirror.sh +48 -0
  155. package/templates/identity/README.md +119 -0
  156. package/templates/identity/ego/behavior.yaml +52 -0
  157. package/templates/identity/ego/constraints.yaml +15 -0
  158. package/templates/identity/ego/identity.yaml +43 -0
  159. package/templates/identity/journeys/personal-growth.yaml +39 -0
  160. package/templates/identity/organization/identity.yaml +24 -0
  161. package/templates/identity/organization/principles.yaml +17 -0
  162. package/templates/identity/personas/coach.yaml +94 -0
  163. package/templates/identity/personas/designer.yaml +93 -0
  164. package/templates/identity/personas/doctor.yaml +96 -0
  165. package/templates/identity/personas/engineer.yaml +77 -0
  166. package/templates/identity/personas/financial.yaml +97 -0
  167. package/templates/identity/personas/prompt-engineer.yaml +122 -0
  168. package/templates/identity/personas/researcher.yaml +88 -0
  169. package/templates/identity/personas/strategist.yaml +91 -0
  170. package/templates/identity/personas/teacher.yaml +95 -0
  171. package/templates/identity/personas/therapist.yaml +91 -0
  172. package/templates/identity/personas/thinker.yaml +74 -0
  173. package/templates/identity/personas/writer.yaml +76 -0
  174. package/templates/identity/self/config.yaml +16 -0
  175. package/templates/identity/self/soul.yaml +105 -0
  176. package/templates/identity/user/identity.yaml +30 -0
  177. package/ts/src/backup/staging.ts +62 -0
  178. package/ts/src/backup/zipBackup.ts +267 -0
  179. package/ts/src/backup/zipReader.ts +109 -0
  180. package/ts/src/backup/zipWriter.ts +148 -0
  181. package/ts/src/builder/activeCheckpoint.ts +134 -0
  182. package/ts/src/builder/aggregateStatus.ts +34 -0
  183. package/ts/src/builder/approve.ts +149 -0
  184. package/ts/src/builder/argv.ts +292 -0
  185. package/ts/src/builder/ariadMethod.ts +536 -0
  186. package/ts/src/builder/artifacts/artifactSurfaces.ts +106 -0
  187. package/ts/src/builder/artifacts/artifactWriter.ts +113 -0
  188. package/ts/src/builder/artifacts/closureArtifacts.ts +199 -0
  189. package/ts/src/builder/artifacts/deliveryStoryArtifacts.ts +316 -0
  190. package/ts/src/builder/artifacts/planArtifacts.ts +242 -0
  191. package/ts/src/builder/artifacts/scaffoldSections.ts +273 -0
  192. package/ts/src/builder/artifacts/scaffoldState.ts +227 -0
  193. package/ts/src/builder/artifacts/storyFiles.ts +61 -0
  194. package/ts/src/builder/artifacts/storyIndex.ts +166 -0
  195. package/ts/src/builder/cadence.ts +59 -0
  196. package/ts/src/builder/card.ts +192 -0
  197. package/ts/src/builder/checkpointRefused.ts +66 -0
  198. package/ts/src/builder/closure.ts +964 -0
  199. package/ts/src/builder/commands.ts +2053 -0
  200. package/ts/src/builder/cursorPosition.ts +176 -0
  201. package/ts/src/builder/cursorTransitions.ts +77 -0
  202. package/ts/src/builder/deliveryCursor.ts +577 -0
  203. package/ts/src/builder/deliveryStoryClosure.ts +521 -0
  204. package/ts/src/builder/deliveryStoryPlan.ts +536 -0
  205. package/ts/src/builder/deliveryStoryReady.ts +160 -0
  206. package/ts/src/builder/deliveryStoryRoadmapClosure.ts +151 -0
  207. package/ts/src/builder/expand.ts +336 -0
  208. package/ts/src/builder/flowUnit.ts +339 -0
  209. package/ts/src/builder/homeSurface.ts +122 -0
  210. package/ts/src/builder/implementationGuard.ts +125 -0
  211. package/ts/src/builder/index.ts +11 -0
  212. package/ts/src/builder/lifecycleRefusal.ts +92 -0
  213. package/ts/src/builder/lifecycleRibbon.ts +159 -0
  214. package/ts/src/builder/load.ts +313 -0
  215. package/ts/src/builder/methodAdoption.ts +113 -0
  216. package/ts/src/builder/methodDefinition.ts +429 -0
  217. package/ts/src/builder/methodInspection.ts +371 -0
  218. package/ts/src/builder/plan.ts +408 -0
  219. package/ts/src/builder/planPreauthorization.ts +265 -0
  220. package/ts/src/builder/prepare.ts +225 -0
  221. package/ts/src/builder/projectPaths.ts +64 -0
  222. package/ts/src/builder/pull.ts +356 -0
  223. package/ts/src/builder/pullCandidates.ts +463 -0
  224. package/ts/src/builder/pullCandidatesRender.ts +238 -0
  225. package/ts/src/builder/refinementField.ts +93 -0
  226. package/ts/src/builder/releaseIntent.ts +173 -0
  227. package/ts/src/builder/resumeState.ts +84 -0
  228. package/ts/src/builder/resumeSurface.ts +149 -0
  229. package/ts/src/builder/roadmapGrammar.ts +300 -0
  230. package/ts/src/builder/roadmapScan.ts +97 -0
  231. package/ts/src/builder/roadmapScope.ts +210 -0
  232. package/ts/src/builder/scopePhrases.ts +146 -0
  233. package/ts/src/builder/storyPaths.ts +196 -0
  234. package/ts/src/builder/storyPlanPreauthorization.ts +287 -0
  235. package/ts/src/builder/surfaceProtocol.ts +42 -0
  236. package/ts/src/builder/templateGeneration.ts +148 -0
  237. package/ts/src/builder/transition.ts +178 -0
  238. package/ts/src/consult/args.ts +99 -0
  239. package/ts/src/consult/core.ts +122 -0
  240. package/ts/src/consult/modelCatalog.ts +55 -0
  241. package/ts/src/consult/render.ts +47 -0
  242. package/ts/src/conversation/append.ts +414 -0
  243. package/ts/src/conversation/backfill.ts +387 -0
  244. package/ts/src/conversation/closeTail.ts +467 -0
  245. package/ts/src/conversation/extraction.ts +333 -0
  246. package/ts/src/conversation/extractionDriver.ts +130 -0
  247. package/ts/src/conversation/extractionRun.ts +70 -0
  248. package/ts/src/conversation/hookPayload.ts +51 -0
  249. package/ts/src/conversation/journeyInference.ts +165 -0
  250. package/ts/src/conversation/journeyRepair.ts +114 -0
  251. package/ts/src/conversation/lifecycleFaces.ts +197 -0
  252. package/ts/src/conversation/lifecycleWrites.ts +313 -0
  253. package/ts/src/conversation/listing.ts +77 -0
  254. package/ts/src/conversation/logger.ts +851 -0
  255. package/ts/src/conversation/loggerCli.ts +321 -0
  256. package/ts/src/conversation/loggerRuntime.ts +259 -0
  257. package/ts/src/conversation/metadataLifecycle.ts +443 -0
  258. package/ts/src/conversation/recall.ts +66 -0
  259. package/ts/src/conversation/sessionComposites.ts +258 -0
  260. package/ts/src/conversation/sessionImport.ts +90 -0
  261. package/ts/src/conversation/transcriptBackfill.ts +141 -0
  262. package/ts/src/cultivation/applyActions.ts +241 -0
  263. package/ts/src/cultivation/cluster.ts +86 -0
  264. package/ts/src/cultivation/consolidationStore.ts +281 -0
  265. package/ts/src/cultivation/promptContext.ts +62 -0
  266. package/ts/src/cultivation/propose.ts +305 -0
  267. package/ts/src/cultivation/scan.ts +155 -0
  268. package/ts/src/db/backupGate.ts +47 -0
  269. package/ts/src/db/bootstrap.ts +108 -0
  270. package/ts/src/db/bootstrapLock.ts +223 -0
  271. package/ts/src/db/copyGuard.ts +60 -0
  272. package/ts/src/db/database.ts +397 -0
  273. package/ts/src/db/decode.ts +66 -0
  274. package/ts/src/db/ftsIntegrity.ts +41 -0
  275. package/ts/src/db/migrateOnOpen.ts +214 -0
  276. package/ts/src/db/migrations.ts +576 -0
  277. package/ts/src/db/readyOnOpen.ts +35 -0
  278. package/ts/src/db/rowDecode.ts +42 -0
  279. package/ts/src/db/schema.ts +432 -0
  280. package/ts/src/db/schemaInventory.ts +225 -0
  281. package/ts/src/db/schemaInventorySnapshot.ts +2107 -0
  282. package/ts/src/db/schemaState.ts +91 -0
  283. package/ts/src/db/schemaTsDivergence.ts +114 -0
  284. package/ts/src/descriptor/descriptorRead.ts +49 -0
  285. package/ts/src/docs/docsLint.ts +265 -0
  286. package/ts/src/explorer/handoff.ts +522 -0
  287. package/ts/src/explorer/render.ts +335 -0
  288. package/ts/src/explorer/story.ts +769 -0
  289. package/ts/src/explorer/transition.ts +72 -0
  290. package/ts/src/extensions/bindings.ts +170 -0
  291. package/ts/src/extensions/catalog.ts +249 -0
  292. package/ts/src/extensions/catalogCommands.ts +513 -0
  293. package/ts/src/extensions/catalogWrites.ts +652 -0
  294. package/ts/src/extensions/contextRuntime.ts +325 -0
  295. package/ts/src/extensions/dispatch.ts +374 -0
  296. package/ts/src/extensions/errors.ts +24 -0
  297. package/ts/src/extensions/manifest.ts +356 -0
  298. package/ts/src/extensions/migrations.ts +350 -0
  299. package/ts/src/extraction/conversation.ts +304 -0
  300. package/ts/src/extraction/conversationMetadata.ts +206 -0
  301. package/ts/src/extraction/fencing.ts +106 -0
  302. package/ts/src/extraction/json.ts +17 -0
  303. package/ts/src/extraction/prompts.ts +470 -0
  304. package/ts/src/frontDoor/args.ts +30 -0
  305. package/ts/src/frontDoor/argvShape.ts +106 -0
  306. package/ts/src/frontDoor/buildLoadRuntime.ts +139 -0
  307. package/ts/src/frontDoor/buildRoute.ts +398 -0
  308. package/ts/src/frontDoor/cli.ts +1872 -0
  309. package/ts/src/frontDoor/cloneRoleGuard.ts +98 -0
  310. package/ts/src/frontDoor/consultRoute.ts +50 -0
  311. package/ts/src/frontDoor/contentTailRoute.ts +239 -0
  312. package/ts/src/frontDoor/conversationLoggerRoute.ts +83 -0
  313. package/ts/src/frontDoor/cultivationRoute.ts +210 -0
  314. package/ts/src/frontDoor/dbPath.ts +131 -0
  315. package/ts/src/frontDoor/dbSafetyToolsRoute.ts +240 -0
  316. package/ts/src/frontDoor/exploreRoute.ts +572 -0
  317. package/ts/src/frontDoor/extensionCatalogRoute.ts +252 -0
  318. package/ts/src/frontDoor/frontDoorLog.ts +57 -0
  319. package/ts/src/frontDoor/identityWrite.ts +36 -0
  320. package/ts/src/frontDoor/journeyWriteRoute.ts +26 -0
  321. package/ts/src/frontDoor/lifecycleWriteRoute.ts +110 -0
  322. package/ts/src/frontDoor/liveBackup.ts +100 -0
  323. package/ts/src/frontDoor/mirrorModeRoute.ts +163 -0
  324. package/ts/src/frontDoor/namedRefusal.ts +35 -0
  325. package/ts/src/frontDoor/nodeSupport.ts +24 -0
  326. package/ts/src/frontDoor/render/consolidate.ts +199 -0
  327. package/ts/src/frontDoor/render/conversations.ts +33 -0
  328. package/ts/src/frontDoor/render/cultivationShared.ts +21 -0
  329. package/ts/src/frontDoor/render/descriptor.ts +20 -0
  330. package/ts/src/frontDoor/render/detectPersona.ts +50 -0
  331. package/ts/src/frontDoor/render/icons.ts +13 -0
  332. package/ts/src/frontDoor/render/identity.ts +59 -0
  333. package/ts/src/frontDoor/render/identityRows.ts +17 -0
  334. package/ts/src/frontDoor/render/inspectPersona.ts +53 -0
  335. package/ts/src/frontDoor/render/journeyStatus.ts +78 -0
  336. package/ts/src/frontDoor/render/journeys.ts +79 -0
  337. package/ts/src/frontDoor/render/list.ts +41 -0
  338. package/ts/src/frontDoor/render/memories.ts +67 -0
  339. package/ts/src/frontDoor/render/recall.ts +49 -0
  340. package/ts/src/frontDoor/render/shadow.ts +155 -0
  341. package/ts/src/frontDoor/render/tasks.ts +99 -0
  342. package/ts/src/frontDoor/render/tasksImportSync.ts +63 -0
  343. package/ts/src/frontDoor/render/week.ts +113 -0
  344. package/ts/src/frontDoor/routing.ts +1001 -0
  345. package/ts/src/frontDoor/runtimeRoute.ts +623 -0
  346. package/ts/src/frontDoor/searchRoute.ts +166 -0
  347. package/ts/src/frontDoor/seedPaths.ts +98 -0
  348. package/ts/src/frontDoor/sessionStartWelcomeRoute.ts +166 -0
  349. package/ts/src/frontDoor/soulRoute.ts +433 -0
  350. package/ts/src/frontDoor/stdinSource.ts +37 -0
  351. package/ts/src/frontDoor/tasksImportSyncRoute.ts +110 -0
  352. package/ts/src/frontDoor/tasksWriteRoute.ts +101 -0
  353. package/ts/src/frontDoor/usage.ts +176 -0
  354. package/ts/src/guards/claudePlugin.ts +298 -0
  355. package/ts/src/guards/packContents.ts +306 -0
  356. package/ts/src/guards/piSourcedSkills.ts +70 -0
  357. package/ts/src/guards/retiredRouteShadows.ts +57 -0
  358. package/ts/src/guards/retiredSurfaces.ts +564 -0
  359. package/ts/src/hooks/claude.ts +214 -0
  360. package/ts/src/hooks/codex.ts +45 -0
  361. package/ts/src/hooks/gemini.ts +126 -0
  362. package/ts/src/hooks/main.ts +109 -0
  363. package/ts/src/hooks/mirrorState.ts +71 -0
  364. package/ts/src/hooks/payload.ts +73 -0
  365. package/ts/src/hooks/runtime.ts +179 -0
  366. package/ts/src/hooks/runtimeDetection.ts +34 -0
  367. package/ts/src/identity/applyConsolidationIdentityUpdate.ts +67 -0
  368. package/ts/src/identity/descriptorGenerate.ts +162 -0
  369. package/ts/src/identity/identityEdit.ts +143 -0
  370. package/ts/src/identity/identityKey.ts +77 -0
  371. package/ts/src/identity/identityRead.ts +69 -0
  372. package/ts/src/identity/identityStore.ts +80 -0
  373. package/ts/src/identity/journeyListing.ts +53 -0
  374. package/ts/src/identity/personaInspect.ts +44 -0
  375. package/ts/src/identity/personaListing.ts +37 -0
  376. package/ts/src/identity/setIdentity.ts +64 -0
  377. package/ts/src/index.ts +231 -0
  378. package/ts/src/init/init.ts +111 -0
  379. package/ts/src/journey/journeyOptions.ts +131 -0
  380. package/ts/src/journey/journeyRemoval.ts +158 -0
  381. package/ts/src/journey/journeyStatus.ts +149 -0
  382. package/ts/src/journey/journeySyncFile.ts +87 -0
  383. package/ts/src/journey/journeyWrite.ts +203 -0
  384. package/ts/src/journey/parentJourney.ts +41 -0
  385. package/ts/src/journey/validateParentJourney.ts +55 -0
  386. package/ts/src/mcp/boundary.ts +151 -0
  387. package/ts/src/mcp/guards.ts +244 -0
  388. package/ts/src/mcp/main.ts +121 -0
  389. package/ts/src/mcp/payload.ts +141 -0
  390. package/ts/src/mcp/protocol.ts +141 -0
  391. package/ts/src/mcp/readModels.ts +241 -0
  392. package/ts/src/mcp/registry.ts +201 -0
  393. package/ts/src/mcp/serve.ts +120 -0
  394. package/ts/src/mcp/tools/deterministic.ts +137 -0
  395. package/ts/src/mcp/tools/providerCrossing.ts +187 -0
  396. package/ts/src/mcp/wire.ts +8 -0
  397. package/ts/src/memory/journal.ts +180 -0
  398. package/ts/src/memory/listing.ts +107 -0
  399. package/ts/src/memory/memoryWrite.ts +88 -0
  400. package/ts/src/memory/reinforcement.ts +35 -0
  401. package/ts/src/mirror/context.ts +161 -0
  402. package/ts/src/mirror/defaultResolution.ts +199 -0
  403. package/ts/src/mirror/mirrorForm.ts +43 -0
  404. package/ts/src/mirror/orchestration.ts +364 -0
  405. package/ts/src/mirror/reception.ts +194 -0
  406. package/ts/src/mirror/render.ts +75 -0
  407. package/ts/src/mirror/runtimeSession.ts +205 -0
  408. package/ts/src/mode/operatingMode.ts +148 -0
  409. package/ts/src/observability/callOutcome.ts +115 -0
  410. package/ts/src/observability/inspectLedger.ts +329 -0
  411. package/ts/src/observability/ledgerHooks.ts +126 -0
  412. package/ts/src/observability/llmCalls.ts +154 -0
  413. package/ts/src/persona/detectPersona.ts +81 -0
  414. package/ts/src/planning/promptAssembly.ts +111 -0
  415. package/ts/src/planning/weekPending.ts +81 -0
  416. package/ts/src/planning/weekPlan.ts +183 -0
  417. package/ts/src/planning/weekSave.ts +117 -0
  418. package/ts/src/providers/config.ts +189 -0
  419. package/ts/src/providers/cost.ts +64 -0
  420. package/ts/src/providers/credits.ts +204 -0
  421. package/ts/src/providers/embedding.ts +321 -0
  422. package/ts/src/providers/familyProviders.ts +147 -0
  423. package/ts/src/providers/llm.ts +334 -0
  424. package/ts/src/providers/openrouter.ts +244 -0
  425. package/ts/src/providers/redaction.ts +110 -0
  426. package/ts/src/providers/replay.ts +15 -0
  427. package/ts/src/providers/transport.ts +410 -0
  428. package/ts/src/repair/encodingRepair.ts +253 -0
  429. package/ts/src/runtime/backup.ts +151 -0
  430. package/ts/src/runtime/channel.ts +146 -0
  431. package/ts/src/runtime/config.ts +168 -0
  432. package/ts/src/runtime/diagnose.ts +686 -0
  433. package/ts/src/runtime/git.ts +510 -0
  434. package/ts/src/runtime/installKind.ts +220 -0
  435. package/ts/src/runtime/migrate.ts +154 -0
  436. package/ts/src/runtime/packageIdentity.ts +102 -0
  437. package/ts/src/runtime/releaseNotes.ts +244 -0
  438. package/ts/src/runtime/status.ts +557 -0
  439. package/ts/src/runtime/strategies/clone.ts +200 -0
  440. package/ts/src/runtime/strategies/package.ts +328 -0
  441. package/ts/src/runtime/treeRoot.ts +30 -0
  442. package/ts/src/runtime/update.ts +445 -0
  443. package/ts/src/runtime/updateGate.ts +40 -0
  444. package/ts/src/runtime/updatePipeline.ts +159 -0
  445. package/ts/src/runtime/version.ts +36 -0
  446. package/ts/src/runtime/wiring.ts +130 -0
  447. package/ts/src/search/memorySearch.ts +338 -0
  448. package/ts/src/search/ranker.ts +154 -0
  449. package/ts/src/seed/seed.ts +256 -0
  450. package/ts/src/seed/seedYaml.ts +133 -0
  451. package/ts/src/soul/apply.ts +218 -0
  452. package/ts/src/soul/harvest.ts +267 -0
  453. package/ts/src/soul/prompts/soul_beauty_voice.md +103 -0
  454. package/ts/src/soul/prompts/soul_self_voice.md +219 -0
  455. package/ts/src/soul/prompts/soul_wisdom_voice.md +121 -0
  456. package/ts/src/soul/prompts.ts +85 -0
  457. package/ts/src/soul/render.ts +358 -0
  458. package/ts/src/soul/state.ts +212 -0
  459. package/ts/src/soul/transition.ts +37 -0
  460. package/ts/src/tasks/journeyPathParse.ts +113 -0
  461. package/ts/src/tasks/taskImportSync.ts +142 -0
  462. package/ts/src/tasks/taskStore.ts +312 -0
  463. package/ts/src/tasks/weekView.ts +120 -0
  464. package/ts/src/util/clipCodePoints.ts +26 -0
  465. package/ts/src/util/paths.ts +63 -0
  466. package/ts/src/util/program.ts +9 -0
  467. package/ts/src/util/pyGenerators.ts +144 -0
  468. package/ts/src/util/pythonText.ts +317 -0
  469. package/ts/src/util/semver.ts +45 -0
  470. package/ts/src/util/shellWord.ts +25 -0
  471. package/ts/src/util/slug.ts +64 -0
  472. package/ts/src/welcome/card.ts +339 -0
  473. package/ts/src/welcome/statusLine.ts +101 -0
  474. package/ts/src/welcome/updateCache.ts +129 -0
@@ -0,0 +1,200 @@
1
+ // The `clone` apply strategy: a git checkout following `origin/<channel>`.
2
+ // (CV22.DS10.US2)
3
+ //
4
+ // This is how every Mirror installed today receives code, and it stays the
5
+ // strategy for a checkout after npm distribution exists: the safety chain is
6
+ // the product's promise, and the transport underneath it is two git commands.
7
+ //
8
+ // Every git invocation goes through an injectable runner so the pipeline's
9
+ // decisions can be driven in tests without a remote, and so this module can be
10
+ // read as "what we ask git for" rather than "how we spawn it".
11
+
12
+ import { runGit } from "#runtime/git.ts";
13
+ import type { ApplyStrategy } from "#runtime/updatePipeline.ts";
14
+
15
+ export type GitRunner = (
16
+ args: readonly string[],
17
+ cwd: string,
18
+ ) => { code: number; stdout: string; stderr: string };
19
+
20
+ export const defaultGitRunner: GitRunner = (args, cwd) => runGit([...args], cwd);
21
+
22
+ /** `origin/main` -> `["origin", "main"]`; anything else is refused. */
23
+ export function splitUpstream(upstream: string): [string, string] | null {
24
+ const index = upstream.indexOf("/");
25
+ if (index <= 0 || index === upstream.length - 1) return null;
26
+ const remote = upstream.slice(0, index);
27
+ const branch = upstream.slice(index + 1);
28
+ if (remote.startsWith("-") || branch.startsWith("-")) return null;
29
+ return [remote, branch];
30
+ }
31
+
32
+ /** The commit this install is on, read BEFORE anything moves. */
33
+ export function captureCommit(repository: string, git: GitRunner): string | null {
34
+ const result = git(["rev-parse", "--short", "HEAD"], repository);
35
+ const value = result.stdout.trim();
36
+ return result.code === 0 && value ? value : null;
37
+ }
38
+
39
+ export function fetchUpstream(
40
+ repository: string,
41
+ upstream: string,
42
+ git: GitRunner,
43
+ ): { ok: boolean; detail: string } {
44
+ const split = splitUpstream(upstream);
45
+ if (split === null) return { ok: false, detail: "unexpected upstream name" };
46
+ const [remote, branch] = split;
47
+ const result = git(["fetch", remote, branch], repository);
48
+ return result.code === 0
49
+ ? { ok: true, detail: `${remote} ${branch}` }
50
+ : { ok: false, detail: result.stderr.trim() || "fetch failed" };
51
+ }
52
+
53
+ /**
54
+ * Fast-forward only, never a merge. A clone that cannot fast-forward has local
55
+ * work or has diverged, and resolving that is a decision the updater must not
56
+ * take on someone's behalf.
57
+ */
58
+ export function fastForward(
59
+ repository: string,
60
+ upstream: string,
61
+ git: GitRunner,
62
+ ): { ok: boolean; detail: string } {
63
+ const result = git(["merge", "--ff-only", upstream], repository);
64
+ return result.code === 0
65
+ ? { ok: true, detail: "" }
66
+ : { ok: false, detail: result.stderr.trim() || "fast-forward refused" };
67
+ }
68
+
69
+ /** One-line subjects installed by this update, for the render. */
70
+ export function installedChanges(
71
+ repository: string,
72
+ previous: string | null,
73
+ next: string | null,
74
+ git: GitRunner,
75
+ ): string[] {
76
+ if (!previous || !next || previous === next) return [];
77
+ const result = git(["log", "--oneline", "--no-decorate", `${previous}..${next}`], repository);
78
+ if (result.code !== 0) return [];
79
+ return result.stdout
80
+ .split("\n")
81
+ .map((line) => line.trim())
82
+ .filter(Boolean)
83
+ .slice(0, 20);
84
+ }
85
+
86
+ /** The pasteable route back, with the captured value in it. */
87
+ export function cloneRecoveryCommand(previous: string | null): string {
88
+ return previous === null ? "git reset --hard <previous commit>" : `git reset --hard ${previous}`;
89
+ }
90
+
91
+ function countCommits(repository: string, range: string, git: GitRunner): number | null {
92
+ const result = git(["rev-list", "--count", range], repository);
93
+ if (result.code !== 0) return null;
94
+ const value = Number.parseInt(result.stdout.trim(), 10);
95
+ return Number.isNaN(value) ? null : value;
96
+ }
97
+
98
+ /**
99
+ * The clone's answers to the pipeline's questions. A ref is a short commit;
100
+ * the channel is `origin/<channel>`; moving is a fast-forward and nothing
101
+ * else; the way back is a hard reset to the captured commit.
102
+ */
103
+ export function cloneStrategy(repository: string, upstream: string, git: GitRunner): ApplyStrategy {
104
+ return {
105
+ kind: "clone",
106
+ applyStage: "fast-forward",
107
+
108
+ // The ordinary gate reads the status report; a tree too broken for that
109
+ // still has one thing the repair lane can check without it.
110
+ repairGate: () => {
111
+ const dirty = git(["status", "--porcelain"], repository);
112
+ if (dirty.code !== 0 || dirty.stdout.trim() !== "") {
113
+ return {
114
+ ok: false,
115
+ detail: "git tree is dirty",
116
+ recovery: ["Commit or stash local changes, then retry runtime update --repair-updater."],
117
+ };
118
+ }
119
+ return { ok: true };
120
+ },
121
+
122
+ capture: () => {
123
+ const ref = captureCommit(repository, git);
124
+ return ref === null
125
+ ? {
126
+ ok: false,
127
+ detail: "could not read the current commit",
128
+ recovery: ["Mirror must be a readable git checkout to update in place."],
129
+ }
130
+ : { ok: true, ref, detail: ref };
131
+ },
132
+
133
+ fetch: () => {
134
+ const fetched = fetchUpstream(repository, upstream, git);
135
+ return fetched.ok
136
+ ? { ok: true, detail: fetched.detail }
137
+ : {
138
+ ok: false,
139
+ detail: fetched.detail,
140
+ recovery: [
141
+ "Check network connectivity and remote access.",
142
+ "Retry runtime update, or use --no-fetch to plan from local refs only.",
143
+ ],
144
+ };
145
+ },
146
+
147
+ plan: (previousRef) => {
148
+ const ahead = countCommits(repository, `${upstream}..HEAD`, git);
149
+ const behind = countCommits(repository, `HEAD..${upstream}`, git);
150
+ if (ahead === null || behind === null) {
151
+ return {
152
+ kind: "blocked",
153
+ detail: `cannot compare against ${upstream}`,
154
+ recovery: [`Resolve upstream tracking for ${upstream}, then retry runtime update.`],
155
+ };
156
+ }
157
+ if (ahead === 0 && behind === 0) return { kind: "current", detail: "already up to date" };
158
+ if (ahead > 0) {
159
+ return {
160
+ kind: "blocked",
161
+ detail: behind > 0 ? "branch diverged" : "local commits present",
162
+ recovery: [
163
+ behind > 0
164
+ ? "Branch diverged; reconcile local and upstream commits manually."
165
+ : "Local branch is ahead of upstream; push or reset before updating.",
166
+ "The working tree and the database are unchanged.",
167
+ `Current commit: ${previousRef}`,
168
+ ],
169
+ };
170
+ }
171
+ return {
172
+ kind: "ahead",
173
+ target: upstream,
174
+ detail: `pull ${behind} remote commit(s)`,
175
+ dryRun: `would pull ${behind} commit(s) from ${upstream}`,
176
+ };
177
+ },
178
+
179
+ apply: (previousRef, target) => {
180
+ const applied = fastForward(repository, target, git);
181
+ if (!applied.ok) {
182
+ return {
183
+ ok: false,
184
+ detail: applied.detail,
185
+ recovery: ["Working tree is unchanged because fast-forward refused."],
186
+ };
187
+ }
188
+ const newRef = captureCommit(repository, git);
189
+ return {
190
+ ok: true,
191
+ newRef,
192
+ detail: `${previousRef} -> ${newRef ?? "unknown"}`,
193
+ changes: installedChanges(repository, previousRef, newRef, git),
194
+ };
195
+ },
196
+
197
+ recoveryCommand: cloneRecoveryCommand,
198
+ installedState: (newRef) => `Code is on ${newRef ?? "the new commit"}`,
199
+ };
200
+ }
@@ -0,0 +1,328 @@
1
+ // The `package` apply strategy: a global npm install following a dist-tag.
2
+ // (CV22.DS10.US2)
3
+ //
4
+ // This is the mechanism npm distribution makes possible and the git updater
5
+ // never could: the Frame's command registry says so in its own words --
6
+ // `memory runtime update` "atualizaria só o clone, deixando o executável
7
+ // instalado operando contra uma minor futura sem contrato de
8
+ // compatibilidade". A versioned install is what that comment is waiting for.
9
+ //
10
+ // Every npm invocation goes through an injectable runner, like the git one, so
11
+ // the pipeline's decisions are testable without a registry.
12
+
13
+ import { execFileSync } from "node:child_process";
14
+ import { type ApplyStrategy, KNOWN_CHANNELS } from "#runtime/updatePipeline.ts";
15
+ import { compareSemver, isPlainSemver } from "#util/semver.ts";
16
+
17
+ /** `cwd` matters to the one npm command that reads a tree, `publish`; the rest ignore it. */
18
+ export type NpmRunner = (
19
+ args: readonly string[],
20
+ cwd?: string,
21
+ ) => {
22
+ code: number;
23
+ stdout: string;
24
+ stderr: string;
25
+ };
26
+
27
+ export const defaultNpmRunner: NpmRunner = (args, cwd) => {
28
+ try {
29
+ const stdout = execFileSync("npm", [...args], {
30
+ encoding: "utf8",
31
+ stdio: ["ignore", "pipe", "pipe"],
32
+ ...(cwd === undefined ? {} : { cwd }),
33
+ });
34
+ return { code: 0, stdout, stderr: "" };
35
+ } catch (error) {
36
+ const shaped = error as { status?: number; stdout?: string; stderr?: string };
37
+ return {
38
+ code: shaped.status ?? -1,
39
+ stdout: shaped.stdout ?? "",
40
+ stderr: shaped.stderr ?? String(error),
41
+ };
42
+ }
43
+ };
44
+
45
+ /** `npm root -g`, or null when npm is not usable. Resolved once per run. */
46
+ export function npmRootGlobal(npm: NpmRunner = defaultNpmRunner): string | null {
47
+ const result = npm(["root", "-g"]);
48
+ const value = result.stdout.trim();
49
+ return result.code === 0 && value ? value : null;
50
+ }
51
+
52
+ // The package channel's location and reader live in `#runtime/channel.ts`
53
+ // with the clone's, since CV22.DS10.US3 plateau 4 gave both a writer.
54
+
55
+ export type DistTags = { ok: true; tags: Record<string, string> } | { ok: false; detail: string };
56
+
57
+ /** `npm view <name> dist-tags --json`, read once per run. */
58
+ export function readDistTags(name: string, npm: NpmRunner = defaultNpmRunner): DistTags {
59
+ const result = npm(["view", name, "dist-tags", "--json"]);
60
+ if (result.code !== 0)
61
+ return { ok: false, detail: firstLine(result.stderr) || "npm view failed" };
62
+ let parsed: unknown;
63
+ try {
64
+ parsed = JSON.parse(result.stdout);
65
+ } catch {
66
+ return { ok: false, detail: "npm view returned unreadable JSON" };
67
+ }
68
+ if (typeof parsed !== "object" || parsed === null) {
69
+ return { ok: false, detail: "npm view returned no dist-tags" };
70
+ }
71
+ const tags: Record<string, string> = {};
72
+ for (const [tag, value] of Object.entries(parsed as Record<string, unknown>)) {
73
+ if (typeof value === "string") tags[tag] = value;
74
+ }
75
+ return { ok: true, tags };
76
+ }
77
+
78
+ /**
79
+ * Resolve a dist-tag to a CONCRETE version before anything is installed.
80
+ *
81
+ * A bare `npm install -g name@stable` installs whatever the tag pointed at in
82
+ * that instant and reports nothing about it. Resolving first means the version
83
+ * is printed by `--check` and `--dry-run`, recorded in the stage detail and
84
+ * the log, and available as the value the recovery route needs. Following a
85
+ * mutable tag is the normal posture of `npm update -g`; being able to say what
86
+ * you got is the proportional control.
87
+ *
88
+ * The registry is a boundary. Its answer becomes the spec of
89
+ * `npm install -g <name>@<value>`, and npm's spec grammar admits tags, ranges,
90
+ * URLs, and paths beside versions, so a value that is not a plain version is
91
+ * refused here, before it is printed or installed (CV22.DS10.US3 plateau 4).
92
+ */
93
+ function resolveFrom(
94
+ tags: Record<string, string>,
95
+ name: string,
96
+ channel: string,
97
+ ): { ok: true; version: string } | { ok: false; detail: string } {
98
+ const version = tags[channel];
99
+ if (version === undefined || version === "") {
100
+ return { ok: false, detail: `no dist-tag '${channel}' for ${name}` };
101
+ }
102
+ if (!isPlainSemver(version)) {
103
+ return { ok: false, detail: `dist-tag '${channel}' is not a version: ${version}` };
104
+ }
105
+ return { ok: true, version };
106
+ }
107
+
108
+ /**
109
+ * Which way the channel lies from the installed version. Migrations run one
110
+ * way, so a channel BEHIND the install is not an update to take: it is a
111
+ * downgrade, refused at plan, and the person is told which channel carries
112
+ * what they have.
113
+ */
114
+ export type ChannelDirection =
115
+ | { kind: "current"; version: string }
116
+ | { kind: "ahead"; version: string }
117
+ | { kind: "behind"; version: string; detail: string; carriedBy: string | null }
118
+ | { kind: "unresolved"; detail: string };
119
+
120
+ export function channelDirection(
121
+ install: { name: string; version: string },
122
+ channel: string,
123
+ npm: NpmRunner = defaultNpmRunner,
124
+ ): ChannelDirection {
125
+ const read = readDistTags(install.name, npm);
126
+ if (!read.ok) return { kind: "unresolved", detail: read.detail };
127
+ const resolved = resolveFrom(read.tags, install.name, channel);
128
+ if (!resolved.ok) return { kind: "unresolved", detail: resolved.detail };
129
+ const order = compareSemver(resolved.version, install.version);
130
+ if (order === 0) return { kind: "current", version: resolved.version };
131
+ if (order > 0) return { kind: "ahead", version: resolved.version };
132
+ const carriedBy =
133
+ Object.entries(read.tags).find(
134
+ ([tag, version]) =>
135
+ tag !== channel &&
136
+ KNOWN_CHANNELS.has(tag) &&
137
+ isPlainSemver(version) &&
138
+ compareSemver(version, install.version) >= 0,
139
+ )?.[0] ?? null;
140
+ return {
141
+ kind: "behind",
142
+ version: resolved.version,
143
+ detail: `'${channel}' is behind the installed version (${resolved.version} < ${install.version})`,
144
+ carriedBy,
145
+ };
146
+ }
147
+
148
+ // --- `runtime update --check` for a package ----------------------------------
149
+
150
+ export type PackageAvailabilityStatus =
151
+ | "up_to_date"
152
+ | "update_available"
153
+ | "channel_behind"
154
+ | "unresolved";
155
+
156
+ export interface PackageUpdateAvailability {
157
+ name: string;
158
+ installed: string;
159
+ channel: { value: string; note: string | null };
160
+ resolved: string | null;
161
+ status: PackageAvailabilityStatus;
162
+ note: string | null;
163
+ /** The known channel at or past the installed version, when this one is behind. */
164
+ carriedBy: string | null;
165
+ }
166
+
167
+ export function checkPackageUpdateAvailability(
168
+ install: { name: string; version: string },
169
+ channel: { value: string; note: string | null },
170
+ npm: NpmRunner = defaultNpmRunner,
171
+ ): PackageUpdateAvailability {
172
+ const base = { name: install.name, installed: install.version, channel, carriedBy: null };
173
+ const direction = channelDirection(install, channel.value, npm);
174
+ switch (direction.kind) {
175
+ case "current":
176
+ return { ...base, resolved: direction.version, status: "up_to_date", note: null };
177
+ case "ahead":
178
+ return { ...base, resolved: direction.version, status: "update_available", note: null };
179
+ case "behind":
180
+ return {
181
+ ...base,
182
+ resolved: direction.version,
183
+ status: "channel_behind",
184
+ note: direction.detail,
185
+ carriedBy: direction.carriedBy,
186
+ };
187
+ case "unresolved":
188
+ return { ...base, resolved: null, status: "unresolved", note: direction.detail };
189
+ }
190
+ }
191
+
192
+ /** The package's counterpart of `renderRuntimeUpdateAvailability`, same shape. */
193
+ export function renderPackageUpdateAvailability(report: PackageUpdateAvailability): string {
194
+ const lines = ["Mirror runtime update check", ""];
195
+ lines.push(`Version: ${report.installed}`);
196
+ lines.push(`Install: package (${report.name}@${report.installed})`);
197
+ lines.push(`Update channel: ${report.channel.value}`);
198
+ if (report.channel.note) lines.push(`Update channel note: ${report.channel.note}`);
199
+ lines.push(`Channel version: ${report.resolved ?? "unresolved"}`);
200
+ lines.push(`Availability: ${report.status}`);
201
+ if (report.note) lines.push(`Reason: ${report.note}`);
202
+ if (report.status === "update_available") {
203
+ lines.push("");
204
+ lines.push("Preview:");
205
+ lines.push("runtime update --dry-run");
206
+ lines.push("");
207
+ lines.push("Update:");
208
+ lines.push("runtime update");
209
+ } else if (report.status === "up_to_date") {
210
+ lines.push("");
211
+ lines.push("Next: no update needed");
212
+ } else if (report.status === "channel_behind") {
213
+ lines.push("");
214
+ lines.push(
215
+ report.carriedBy
216
+ ? `Next: runtime channel ${report.carriedBy}`
217
+ : `Next: stay on ${report.installed} until '${report.channel.value}' reaches it`,
218
+ );
219
+ }
220
+ return `${lines.join("\n")}\n`;
221
+ }
222
+
223
+ /** Install one exact version globally. Never a bare tag. */
224
+ export function installGlobal(
225
+ name: string,
226
+ version: string,
227
+ npm: NpmRunner = defaultNpmRunner,
228
+ ): { ok: boolean; detail: string } {
229
+ const result = npm(["install", "-g", `${name}@${version}`]);
230
+ return result.code === 0
231
+ ? { ok: true, detail: `${name}@${version}` }
232
+ : { ok: false, detail: firstLine(result.stderr) || "npm install failed" };
233
+ }
234
+
235
+ /** The pasteable route back, with the captured version in it. */
236
+ export function packageRecoveryCommand(name: string, previousVersion: string | null): string {
237
+ return previousVersion === null
238
+ ? `npm install -g ${name}@<previous version>`
239
+ : `npm install -g ${name}@${previousVersion}`;
240
+ }
241
+
242
+ /**
243
+ * The package's answers to the pipeline's questions. A ref is an installed
244
+ * version, read from the manifest before anything is installed over it (npm's
245
+ * global install is not atomic, so a pinned reinstall is the only rollback
246
+ * there is); the channel is a dist-tag resolved to a concrete version at plan
247
+ * time; moving is one global install of exactly that version; the way back is
248
+ * the same install of the captured one. Nothing is fetched: the registry is
249
+ * asked once, at plan.
250
+ */
251
+ export function packageStrategy(
252
+ install: { name: string; version: string },
253
+ channel: string,
254
+ npm: NpmRunner,
255
+ ): ApplyStrategy {
256
+ return {
257
+ kind: "package",
258
+ applyStage: "apply",
259
+
260
+ // A package has no tree to be dirty: the status gate is the only gate, and
261
+ // the repair lane simply forgoes it.
262
+ repairGate: () => ({ ok: true }),
263
+
264
+ capture: () => ({
265
+ ok: true,
266
+ ref: install.version,
267
+ detail: `${install.name}@${install.version}`,
268
+ }),
269
+
270
+ plan: (previousRef) => {
271
+ const direction = channelDirection(
272
+ { name: install.name, version: previousRef },
273
+ channel,
274
+ npm,
275
+ );
276
+ switch (direction.kind) {
277
+ case "unresolved":
278
+ return {
279
+ kind: "blocked",
280
+ detail: direction.detail,
281
+ recovery: [
282
+ `Could not resolve the '${channel}' dist-tag for ${install.name}.`,
283
+ "Check network access to the npm registry, then retry runtime update.",
284
+ ],
285
+ };
286
+ case "current":
287
+ return { kind: "current", detail: `already up to date (${direction.version})` };
288
+ case "behind":
289
+ return {
290
+ kind: "blocked",
291
+ detail: direction.detail,
292
+ recovery: [
293
+ "A downgrade is refused: migrations do not run backwards.",
294
+ direction.carriedBy
295
+ ? `Follow the channel that carries ${previousRef}: runtime channel ${direction.carriedBy}`
296
+ : `Stay on ${previousRef} until '${channel}' reaches it.`,
297
+ "Nothing was installed and the database is unchanged.",
298
+ ],
299
+ };
300
+ case "ahead":
301
+ return {
302
+ kind: "ahead",
303
+ target: direction.version,
304
+ detail: `${previousRef} -> ${direction.version}`,
305
+ dryRun: `would install ${install.name}@${direction.version}`,
306
+ };
307
+ }
308
+ },
309
+
310
+ apply: (_previousRef, target) => {
311
+ const applied = installGlobal(install.name, target, npm);
312
+ return applied.ok
313
+ ? { ok: true, newRef: target, detail: applied.detail, changes: [] }
314
+ : {
315
+ ok: false,
316
+ detail: applied.detail,
317
+ recovery: ["A global npm install is not atomic; this one did not complete."],
318
+ };
319
+ },
320
+
321
+ recoveryCommand: (previousRef) => packageRecoveryCommand(install.name, previousRef),
322
+ installedState: (newRef) => `${install.name}@${newRef ?? "<unknown>"} is installed`,
323
+ };
324
+ }
325
+
326
+ function firstLine(text: string): string {
327
+ return text.trim().split("\n")[0] ?? "";
328
+ }
@@ -0,0 +1,30 @@
1
+ // The tree that holds the running program. CV22.DS10.US3 plateau 1.
2
+ //
3
+ // Three readers used to locate the tree three ways: `init` walked up from its
4
+ // own file for `templates/identity`; `runtime release-notes` asked
5
+ // `git rev-parse --show-toplevel` and fell back to the cwd; the welcome card
6
+ // read `<cwd>/docs/releases/<version>.md`. Only the first worked for an
7
+ // installed package, and the third answered for whatever directory the person
8
+ // happened to be in. Now there is one answer, from the same walk the version
9
+ // and the checkout guard already use (`packageIdentity.ts`), anchored at this
10
+ // file -- so it is the tree the code came from, in a checkout, through
11
+ // `npm link`, or under `npm root -g` alike. Never the cwd, never git.
12
+
13
+ import { findPackageIdentity } from "./packageIdentity.ts";
14
+
15
+ export class TreeRootNotFoundError extends Error {}
16
+
17
+ /**
18
+ * The root of the tree this module was loaded from: the directory holding the
19
+ * manifest and the front door. Throws when there is none, which means the
20
+ * program is running from a copy that is not a Mirror Mind tree at all.
21
+ */
22
+ export function runningTreeRoot(): string {
23
+ const identity = findPackageIdentity(import.meta.dirname);
24
+ if (identity === null) {
25
+ throw new TreeRootNotFoundError(
26
+ `no Mirror Mind tree holds ${import.meta.filename}: package.json and ts/src/frontDoor/cli.ts not found above it`,
27
+ );
28
+ }
29
+ return identity.root;
30
+ }