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,510 @@
1
+ // Read-only git and version inspection for the runtime surface
2
+ // (CV22.DS7.TS3). Port of the read half of `src/memory/cli/runtime.py`.
3
+ //
4
+ // BOUNDARY, enforced by a test that greps this file: nothing here mutates a
5
+ // repository. `merge`, `tag`, `push`, `reset`, `checkout`, `commit`, and
6
+ // `branch <name>` belong to the git-based updater and release machinery, which
7
+ // the 2026-09-07 decision assigned to CV22.DS10 for redesign under npm
8
+ // distribution. Every command below reads: `rev-parse`, `branch
9
+ // --show-current`, `status --porcelain`, `rev-list --count`, `merge-base
10
+ // --is-ancestor`, `cat-file -e`, `config --get`, and the one networked read,
11
+ // `ls-remote`.
12
+ //
13
+ // Timeouts follow the oracle's two budgets, and for the reason recorded there:
14
+ // local inspections are near-instant, while a single shared 2 s budget once
15
+ // made a network operation report failure after it had already succeeded
16
+ // (the v0.30.1 release incident). Network reads get 120 s.
17
+
18
+ import { spawnSync } from "node:child_process";
19
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
20
+ import { join, resolve } from "node:path";
21
+ import { type InstallKind, renderInstallLines } from "#runtime/installKind.ts";
22
+ import { DEFAULT_CHANNEL, KNOWN_CHANNELS } from "#runtime/updatePipeline.ts";
23
+
24
+ export const GIT_LOCAL_TIMEOUT_MS = 2_000;
25
+ export const GIT_NETWORK_TIMEOUT_MS = 120_000;
26
+
27
+ const CLONE_ROLE_FILENAME = ".mirror-clone-role";
28
+ const UPDATE_CHANNEL_FILENAME = ".mirror-update-channel";
29
+ const DEFAULT_CLONE_ROLE = "production";
30
+ const KNOWN_CLONE_ROLES = new Set(["production", "dev"]);
31
+ // The channel vocabulary is the pipeline's (one set for both install kinds
32
+ // since CV22.DS10.US3 plateau 4); these are the names this module used.
33
+ const DEFAULT_UPDATE_CHANNEL = DEFAULT_CHANNEL;
34
+ const KNOWN_UPDATE_CHANNELS = KNOWN_CHANNELS;
35
+
36
+ export interface GitStatus {
37
+ repository: string | null;
38
+ branch: string | null;
39
+ commit: string | null;
40
+ dirty: boolean | null;
41
+ error: string | null;
42
+ }
43
+
44
+ export interface GitWorktreeEntry {
45
+ status: string;
46
+ path: string;
47
+ }
48
+
49
+ export interface MarkerValue {
50
+ value: string;
51
+ /** The marker file the value came from, or null when defaulted. */
52
+ source: string | null;
53
+ note: string | null;
54
+ }
55
+
56
+ export interface RuntimeVersionReport {
57
+ version: string;
58
+ /** How the running front door is installed (CV22.DS10.US3 plateau 4; US2 D3). */
59
+ install: InstallKind;
60
+ git: GitStatus;
61
+ cloneRole: MarkerValue;
62
+ updateChannel: MarkerValue;
63
+ }
64
+
65
+ export interface GitUpdatePlan {
66
+ upstream: string | null;
67
+ ahead: number | null;
68
+ behind: number | null;
69
+ ready: boolean;
70
+ action: string;
71
+ note: string | null;
72
+ }
73
+
74
+ export interface UpdateAvailability {
75
+ version: string;
76
+ upstream: string | null;
77
+ local_commit: string | null;
78
+ remote_commit: string | null;
79
+ status: string;
80
+ note: string | null;
81
+ update_channel: MarkerValue;
82
+ target_release: null;
83
+ }
84
+
85
+ /** `(exit code, trimmed stdout, trimmed stderr)`, tolerant like the oracle's. */
86
+ export function runGit(
87
+ args: readonly string[],
88
+ cwd: string,
89
+ timeoutMs: number = GIT_LOCAL_TIMEOUT_MS,
90
+ ): { code: number; stdout: string; stderr: string } {
91
+ const result = spawnSync("git", [...args], {
92
+ cwd,
93
+ encoding: "utf8",
94
+ timeout: timeoutMs,
95
+ // Arguments are passed as argv, never through a shell, so a ref or remote
96
+ // name cannot become a second command.
97
+ shell: false,
98
+ });
99
+ if (result.error)
100
+ return { code: 1, stdout: "", stderr: String(result.error.message ?? result.error) };
101
+ return {
102
+ code: result.status ?? 1,
103
+ stdout: (result.stdout ?? "").trim(),
104
+ stderr: (result.stderr ?? "").trim(),
105
+ };
106
+ }
107
+
108
+ function resolveRepoRoot(start: string): string | null {
109
+ const { code, stdout } = runGit(["rev-parse", "--show-toplevel"], start);
110
+ if (code !== 0 || !stdout) return null;
111
+ return realpathSync(stdout);
112
+ }
113
+
114
+ /** Port of `_parse_porcelain_line`: two status characters, then the path. */
115
+ function parsePorcelainLine(line: string): GitWorktreeEntry | null {
116
+ if (!line) return null;
117
+ const status = line.slice(0, 2);
118
+ let path = line.slice(2).trim();
119
+ if (path.includes(" -> ")) path = path.split(" -> ", 2)[1] as string;
120
+ return { status, path };
121
+ }
122
+
123
+ export function inspectGitWorktree(repository: string | null): GitWorktreeEntry[] {
124
+ if (repository === null) return [];
125
+ const { code, stdout } = runGit(["status", "--porcelain"], repository);
126
+ if (code !== 0 || !stdout) return [];
127
+ return stdout
128
+ .split("\n")
129
+ .map(parsePorcelainLine)
130
+ .filter((entry): entry is GitWorktreeEntry => entry !== null);
131
+ }
132
+
133
+ export function inspectGit(start: string): GitStatus {
134
+ const top = runGit(["rev-parse", "--show-toplevel"], start);
135
+ if (top.code !== 0 || !top.stdout) {
136
+ return {
137
+ repository: null,
138
+ branch: null,
139
+ commit: null,
140
+ dirty: null,
141
+ error: top.stderr || "not a git repository",
142
+ };
143
+ }
144
+ const repository = realpathSync(top.stdout);
145
+ const branch = runGit(["branch", "--show-current"], repository);
146
+ const commit = runGit(["rev-parse", "--short", "HEAD"], repository);
147
+ const dirty = runGit(["status", "--porcelain"], repository);
148
+
149
+ const errors = [branch, commit, dirty]
150
+ .filter((result) => result.code !== 0 && result.stderr)
151
+ .map((result) => result.stderr);
152
+
153
+ return {
154
+ repository,
155
+ branch: branch.code === 0 && branch.stdout ? branch.stdout : null,
156
+ commit: commit.code === 0 && commit.stdout ? commit.stdout : null,
157
+ dirty: dirty.code === 0 ? Boolean(dirty.stdout) : null,
158
+ error: errors.length > 0 ? errors.join("; ") : null,
159
+ };
160
+ }
161
+
162
+ /** Shared shape of the two marker files: allowlisted value, else the default. */
163
+ function inspectMarker(
164
+ start: string,
165
+ filename: string,
166
+ known: ReadonlySet<string>,
167
+ fallback: string,
168
+ label: string,
169
+ ): MarkerValue {
170
+ const repoRoot = resolveRepoRoot(resolve(start));
171
+ if (repoRoot === null) return { value: fallback, source: null, note: "no repository" };
172
+ const marker = join(repoRoot, filename);
173
+ if (!existsSync(marker)) return { value: fallback, source: null, note: null };
174
+ let raw: string;
175
+ try {
176
+ raw = readFileSync(marker, "utf8");
177
+ } catch (error) {
178
+ const message = error instanceof Error ? error.message : String(error);
179
+ return { value: fallback, source: marker, note: `unreadable: ${message}` };
180
+ }
181
+ const value = raw.trim().toLowerCase();
182
+ if (known.has(value)) return { value, source: marker, note: null };
183
+ return {
184
+ value: fallback,
185
+ source: marker,
186
+ note: `unknown ${label} '${value}', defaulting to ${fallback}`,
187
+ };
188
+ }
189
+
190
+ export function inspectCloneRole(start: string): MarkerValue {
191
+ return inspectMarker(start, CLONE_ROLE_FILENAME, KNOWN_CLONE_ROLES, DEFAULT_CLONE_ROLE, "role");
192
+ }
193
+
194
+ export function inspectUpdateChannel(start: string, override: string | null = null): MarkerValue {
195
+ if (override) {
196
+ const value = override.trim().toLowerCase();
197
+ if (KNOWN_UPDATE_CHANNELS.has(value)) return { value, source: null, note: "command override" };
198
+ return {
199
+ value: DEFAULT_UPDATE_CHANNEL,
200
+ source: null,
201
+ note: `unknown channel '${value}', defaulting to ${DEFAULT_UPDATE_CHANNEL}`,
202
+ };
203
+ }
204
+ return inspectMarker(
205
+ start,
206
+ UPDATE_CHANNEL_FILENAME,
207
+ KNOWN_UPDATE_CHANNELS,
208
+ DEFAULT_UPDATE_CHANNEL,
209
+ "channel",
210
+ );
211
+ }
212
+
213
+ /** `origin/<channel>` — the only place a channel becomes a git ref. */
214
+ export function upstreamFor(channel: MarkerValue): string {
215
+ return `origin/${channel.value}`;
216
+ }
217
+
218
+ // Lives in `runtime/version.ts` now -- the MCP server needs it and should not
219
+ // import this module to get it. Re-exported so runtime call sites do not move.
220
+ export { packageVersion } from "./version.ts";
221
+
222
+ /** Port of `_classify_update_status`: ancestry from the local object database. */
223
+ function classifyUpdateStatus(
224
+ repository: string,
225
+ localCommit: string | null,
226
+ remoteCommit: string,
227
+ ): string {
228
+ if (localCommit && (remoteCommit === localCommit || remoteCommit.startsWith(localCommit))) {
229
+ return "up_to_date";
230
+ }
231
+ if (runGit(["merge-base", "--is-ancestor", remoteCommit, "HEAD"], repository).code === 0) {
232
+ return "local_ahead";
233
+ }
234
+ if (runGit(["merge-base", "--is-ancestor", "HEAD", remoteCommit], repository).code === 0) {
235
+ return "update_available";
236
+ }
237
+ const known = runGit(["cat-file", "-e", `${remoteCommit}^{commit}`], repository);
238
+ return known.code === 0 ? "diverged" : "update_available";
239
+ }
240
+
241
+ function availability(
242
+ version: string,
243
+ updateChannel: MarkerValue,
244
+ fields: Partial<UpdateAvailability>,
245
+ ): UpdateAvailability {
246
+ return {
247
+ version,
248
+ upstream: null,
249
+ local_commit: null,
250
+ remote_commit: null,
251
+ status: "unknown",
252
+ note: null,
253
+ update_channel: updateChannel,
254
+ target_release: null,
255
+ ...fields,
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Is the channel's remote branch ahead of HEAD? The remote query is the only
261
+ * authority: remote-tracking refs are only as fresh as the last fetch, and
262
+ * trusting them is how a clone two releases behind gets told it is ahead.
263
+ */
264
+ export function checkUpdateAvailability(
265
+ start: string,
266
+ channel: string | null,
267
+ version: string,
268
+ ): UpdateAvailability {
269
+ const startPath = resolve(start);
270
+ const git = inspectGit(startPath);
271
+ const updateChannel = inspectUpdateChannel(startPath, channel);
272
+ if (git.repository === null) {
273
+ return availability(version, updateChannel, { note: "repository unavailable" });
274
+ }
275
+
276
+ // With a channel the upstream is always `origin/<channel>`, so the oracle's
277
+ // `no_upstream` branch is unreachable here: whether that ref exists locally
278
+ // is the update PLAN's question (plateau 3), not this check's. An unfetched
279
+ // channel therefore falls through to the remote query, which is the only
280
+ // authority, and reports `unknown` when the branch does not exist remotely.
281
+ const upstream = upstreamFor(updateChannel);
282
+ const [remote, branch] = [
283
+ upstream.split("/", 1)[0] as string,
284
+ upstream.split("/").slice(1).join("/"),
285
+ ];
286
+ if (!remote || !branch) {
287
+ return availability(version, updateChannel, {
288
+ upstream,
289
+ local_commit: git.commit,
290
+ note: "unexpected upstream name",
291
+ });
292
+ }
293
+
294
+ const remoteUrl = runGit(["config", "--get", `remote.${remote}.url`], git.repository);
295
+ if (remoteUrl.code !== 0 || !remoteUrl.stdout) {
296
+ return availability(version, updateChannel, {
297
+ upstream,
298
+ local_commit: git.commit,
299
+ note: remoteUrl.stderr || `remote ${remote} has no url`,
300
+ });
301
+ }
302
+
303
+ const lsRemote = runGit(
304
+ ["ls-remote", remote, `refs/heads/${branch}`],
305
+ git.repository,
306
+ GIT_NETWORK_TIMEOUT_MS,
307
+ );
308
+ if (lsRemote.code !== 0 || !lsRemote.stdout) {
309
+ return availability(version, updateChannel, {
310
+ upstream,
311
+ local_commit: git.commit,
312
+ note: lsRemote.stderr || "remote query failed",
313
+ });
314
+ }
315
+ const parts = lsRemote.stdout.split(/\s+/);
316
+ if (parts.length < 2) {
317
+ return availability(version, updateChannel, {
318
+ upstream,
319
+ local_commit: git.commit,
320
+ note: `unexpected ls-remote output: ${lsRemote.stdout}`,
321
+ });
322
+ }
323
+
324
+ const remoteCommit = parts[0] as string;
325
+ const localFull = runGit(["rev-parse", "HEAD"], git.repository);
326
+ const localCommit = localFull.code === 0 && localFull.stdout ? localFull.stdout : git.commit;
327
+ return availability(version, updateChannel, {
328
+ upstream,
329
+ local_commit: localCommit,
330
+ remote_commit: remoteCommit,
331
+ status: classifyUpdateStatus(git.repository, localCommit, remoteCommit),
332
+ });
333
+ }
334
+
335
+ /**
336
+ * Port of `inspect_git_update_plan`: how far HEAD is from the channel's
337
+ * upstream, and whether a fast-forward is the honest move.
338
+ *
339
+ * Unlike `checkUpdateAvailability`, this asks the LOCAL object database only --
340
+ * it is the plan, not the check, so an unfetched channel is `blocked` here
341
+ * rather than a reason to query the remote.
342
+ */
343
+ export function inspectGitUpdatePlan(
344
+ git: GitStatus,
345
+ updateChannel: MarkerValue | null = null,
346
+ ): GitUpdatePlan {
347
+ const blocked = (upstream: string | null, note: string): GitUpdatePlan => ({
348
+ upstream,
349
+ ahead: null,
350
+ behind: null,
351
+ ready: false,
352
+ action: "blocked",
353
+ note,
354
+ });
355
+ if (git.repository === null) return blocked(null, "repository unavailable");
356
+
357
+ let upstream: string;
358
+ if (updateChannel === null) {
359
+ const resolved = runGit(
360
+ ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
361
+ git.repository,
362
+ );
363
+ if (resolved.code !== 0 || !resolved.stdout) {
364
+ return blocked(null, resolved.stderr || "no upstream configured");
365
+ }
366
+ upstream = resolved.stdout;
367
+ } else {
368
+ upstream = upstreamFor(updateChannel);
369
+ const verified = runGit(["rev-parse", "--verify", upstream], git.repository);
370
+ if (verified.code !== 0) {
371
+ return blocked(
372
+ upstream,
373
+ verified.stderr || `update channel ${updateChannel.value} is not fetched`,
374
+ );
375
+ }
376
+ }
377
+
378
+ const counted = runGit(
379
+ ["rev-list", "--left-right", "--count", `HEAD...${upstream}`],
380
+ git.repository,
381
+ );
382
+ if (counted.code !== 0 || !counted.stdout) {
383
+ return blocked(upstream, counted.stderr || "cannot compare upstream");
384
+ }
385
+ const [aheadText, behindText] = counted.stdout.split(/\s+/);
386
+ const ahead = Number(aheadText);
387
+ const behind = Number(behindText);
388
+ if (
389
+ aheadText === undefined ||
390
+ behindText === undefined ||
391
+ !Number.isInteger(ahead) ||
392
+ !Number.isInteger(behind)
393
+ ) {
394
+ return blocked(upstream, `unexpected git count: ${counted.stdout}`);
395
+ }
396
+
397
+ if (ahead === 0 && behind === 0) {
398
+ return { upstream, ahead, behind, ready: true, action: "none", note: "already up to date" };
399
+ }
400
+ if (ahead === 0 && behind > 0) {
401
+ return {
402
+ upstream,
403
+ ahead,
404
+ behind,
405
+ ready: true,
406
+ action: "pull",
407
+ note: `pull ${behind} remote commit(s)`,
408
+ };
409
+ }
410
+ if (ahead > 0 && behind === 0) {
411
+ return {
412
+ upstream,
413
+ ahead,
414
+ behind,
415
+ ready: false,
416
+ action: "blocked",
417
+ note: "local commits present",
418
+ };
419
+ }
420
+ return { upstream, ahead, behind, ready: false, action: "blocked", note: "branch diverged" };
421
+ }
422
+
423
+ /** A package's git facts: it has none, and none is not an error. */
424
+ export const NO_REPOSITORY: GitStatus = {
425
+ repository: null,
426
+ branch: null,
427
+ commit: null,
428
+ dirty: null,
429
+ error: null,
430
+ };
431
+
432
+ /**
433
+ * The git facts of `start`, for the install's kind: a clone's are inspected,
434
+ * a package's are `NO_REPOSITORY` (CV22.DS10.US3 plateau 4). Grading the cwd
435
+ * of a package install as a tree read "not a git repository" as a git error.
436
+ */
437
+ export function inspectGitFor(install: InstallKind, start: string): GitStatus {
438
+ return install.kind === "package" ? NO_REPOSITORY : inspectGit(start);
439
+ }
440
+
441
+ /**
442
+ * The repository rows of `status` and `version`: the oracle's four for a
443
+ * clone (dirty only where the report carries it), one honest row for a package.
444
+ */
445
+ export function renderRepositoryLines(
446
+ install: InstallKind,
447
+ git: GitStatus,
448
+ withDirty: boolean,
449
+ ): string[] {
450
+ if (install.kind === "package") return ["Repository: none (package install)"];
451
+ const lines = [
452
+ `Repository: ${git.repository ?? "unknown"}`,
453
+ `Git branch: ${git.branch || "unknown"}`,
454
+ `Git commit: ${git.commit || "unknown"}`,
455
+ ];
456
+ if (withDirty)
457
+ lines.push(`Git dirty: ${git.dirty === null ? "unknown" : git.dirty ? "yes" : "no"}`);
458
+ if (git.error) lines.push(`Git status note: ${git.error}`);
459
+ return lines;
460
+ }
461
+
462
+ export function renderRuntimeVersion(report: RuntimeVersionReport): string {
463
+ const lines = ["Mirror runtime version", ""];
464
+ lines.push(`Version: ${report.version}`);
465
+ lines.push(...renderInstallLines(report.install));
466
+ lines.push(...renderRepositoryLines(report.install, report.git, false));
467
+ lines.push(`Clone role: ${report.cloneRole.value}`);
468
+ if (report.cloneRole.note) lines.push(`Clone role note: ${report.cloneRole.note}`);
469
+ lines.push(`Update channel: ${report.updateChannel.value}`);
470
+ if (report.updateChannel.note) lines.push(`Update channel note: ${report.updateChannel.note}`);
471
+ return `${lines.join("\n")}\n`;
472
+ }
473
+
474
+ export function renderRuntimeUpdateAvailability(report: UpdateAvailability): string {
475
+ const lines = ["Mirror runtime update check", ""];
476
+ lines.push(`Version: ${report.version}`);
477
+ lines.push(`Update channel: ${report.update_channel.value}`);
478
+ if (report.update_channel.note) lines.push(`Update channel note: ${report.update_channel.note}`);
479
+ lines.push(`Current: ${report.local_commit ? report.local_commit.slice(0, 7) : "unknown"}`);
480
+ if (report.upstream) {
481
+ const remote = report.remote_commit ? report.remote_commit.slice(0, 7) : "unknown";
482
+ lines.push(`Upstream: ${report.upstream} @ ${remote}`);
483
+ } else {
484
+ lines.push("Upstream: none");
485
+ }
486
+ lines.push(`Availability: ${report.status}`);
487
+ if (report.note) lines.push(`Reason: ${report.note}`);
488
+ if (report.status === "update_available") {
489
+ lines.push("");
490
+ if (report.update_channel.value === "stable") {
491
+ lines.push(
492
+ "Release details: not fetched by this check; dry-run can show them when local refs contain release notes.",
493
+ );
494
+ }
495
+ // CV22.DS10.US2: engine-neutral, changed in the oracle first and
496
+ // regenerated into the golden. The TypeScript core told users to run the
497
+ // interpreter this migration deletes; the COMMAND was always the same on
498
+ // both engines, and the npm-era invocation does not exist until US3
499
+ // defines a `bin`.
500
+ lines.push("Preview:");
501
+ lines.push("runtime update --dry-run");
502
+ lines.push("");
503
+ lines.push("Update:");
504
+ lines.push("runtime update");
505
+ } else if (report.status === "up_to_date") {
506
+ lines.push("");
507
+ lines.push("Next: no update needed");
508
+ }
509
+ return `${lines.join("\n")}\n`;
510
+ }