mirror-mind 0.0.1 → 0.32.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (467) hide show
  1. package/.claude/hooks/log-session-end.sh +85 -0
  2. package/.claude/hooks/log-user-prompt.sh +85 -0
  3. package/.claude/hooks/mirror-inject.sh +85 -0
  4. package/.claude/hooks/session-start.sh +85 -0
  5. package/.gemini/hooks/log-assistant.sh +85 -0
  6. package/.gemini/hooks/log-user.sh +85 -0
  7. package/.gemini/hooks/session-end.sh +85 -0
  8. package/.gemini/hooks/session-start.sh +85 -0
  9. package/.pi/extensions/mirror-logger.ts +561 -0
  10. package/.pi/skills/mm-backup/SKILL.md +21 -0
  11. package/.pi/skills/mm-build/SKILL.md +1206 -0
  12. package/.pi/skills/mm-consolidate/SKILL.md +112 -0
  13. package/.pi/skills/mm-consult/SKILL.md +70 -0
  14. package/.pi/skills/mm-conversations/SKILL.md +16 -0
  15. package/.pi/skills/mm-discard/SKILL.md +39 -0
  16. package/.pi/skills/mm-explore/SKILL.md +255 -0
  17. package/.pi/skills/mm-help/SKILL.md +74 -0
  18. package/.pi/skills/mm-identity/SKILL.md +96 -0
  19. package/.pi/skills/mm-journal/SKILL.md +16 -0
  20. package/.pi/skills/mm-journey/SKILL.md +23 -0
  21. package/.pi/skills/mm-journeys/SKILL.md +15 -0
  22. package/.pi/skills/mm-memories/SKILL.md +17 -0
  23. package/.pi/skills/mm-mirror/SKILL.md +98 -0
  24. package/.pi/skills/mm-mute/SKILL.md +18 -0
  25. package/.pi/skills/mm-new/SKILL.md +18 -0
  26. package/.pi/skills/mm-recall/SKILL.md +17 -0
  27. package/.pi/skills/mm-release-notes/SKILL.md +52 -0
  28. package/.pi/skills/mm-seed/SKILL.md +19 -0
  29. package/.pi/skills/mm-shadow/SKILL.md +117 -0
  30. package/.pi/skills/mm-soul/SKILL.md +502 -0
  31. package/.pi/skills/mm-tasks/SKILL.md +24 -0
  32. package/.pi/skills/mm-update/SKILL.md +32 -0
  33. package/.pi/skills/mm-week/SKILL.md +28 -0
  34. package/.pi/skills/mm-welcome/SKILL.md +24 -0
  35. package/AGENTS.md +188 -0
  36. package/README.md +126 -9
  37. package/bin/loader.js +67 -0
  38. package/bin/mirror-hook.js +7 -0
  39. package/bin/mirror.js +7 -0
  40. package/docs/releases/index.md +99 -0
  41. package/docs/releases/pending-cutoffs.md +510 -0
  42. package/docs/releases/v0.10.0.md +123 -0
  43. package/docs/releases/v0.10.1.md +66 -0
  44. package/docs/releases/v0.10.10.md +51 -0
  45. package/docs/releases/v0.10.11.md +39 -0
  46. package/docs/releases/v0.10.12.md +57 -0
  47. package/docs/releases/v0.10.13.md +35 -0
  48. package/docs/releases/v0.10.14.md +42 -0
  49. package/docs/releases/v0.10.15.md +53 -0
  50. package/docs/releases/v0.10.16.md +35 -0
  51. package/docs/releases/v0.10.17.md +43 -0
  52. package/docs/releases/v0.10.2.md +64 -0
  53. package/docs/releases/v0.10.3.md +78 -0
  54. package/docs/releases/v0.10.4.md +42 -0
  55. package/docs/releases/v0.10.5.md +57 -0
  56. package/docs/releases/v0.10.6.md +47 -0
  57. package/docs/releases/v0.10.7.md +53 -0
  58. package/docs/releases/v0.10.8.md +49 -0
  59. package/docs/releases/v0.10.9.md +37 -0
  60. package/docs/releases/v0.11.0.md +86 -0
  61. package/docs/releases/v0.12.0.md +67 -0
  62. package/docs/releases/v0.13.0.md +64 -0
  63. package/docs/releases/v0.14.0.md +68 -0
  64. package/docs/releases/v0.15.0.md +48 -0
  65. package/docs/releases/v0.16.0.md +50 -0
  66. package/docs/releases/v0.16.1.md +55 -0
  67. package/docs/releases/v0.16.2.md +36 -0
  68. package/docs/releases/v0.17.0.md +50 -0
  69. package/docs/releases/v0.17.1.md +58 -0
  70. package/docs/releases/v0.17.2.md +42 -0
  71. package/docs/releases/v0.17.3.md +58 -0
  72. package/docs/releases/v0.18.0.md +84 -0
  73. package/docs/releases/v0.18.1.md +51 -0
  74. package/docs/releases/v0.18.2.md +69 -0
  75. package/docs/releases/v0.19.0.md +85 -0
  76. package/docs/releases/v0.19.1.md +46 -0
  77. package/docs/releases/v0.20.0.md +85 -0
  78. package/docs/releases/v0.21.0.md +61 -0
  79. package/docs/releases/v0.21.1.md +47 -0
  80. package/docs/releases/v0.22.0.md +77 -0
  81. package/docs/releases/v0.22.1.md +42 -0
  82. package/docs/releases/v0.23.0.md +105 -0
  83. package/docs/releases/v0.24.0.md +125 -0
  84. package/docs/releases/v0.25.0.md +107 -0
  85. package/docs/releases/v0.26.0.md +139 -0
  86. package/docs/releases/v0.26.1.md +65 -0
  87. package/docs/releases/v0.26.2.md +43 -0
  88. package/docs/releases/v0.27.0.md +63 -0
  89. package/docs/releases/v0.28.0.md +59 -0
  90. package/docs/releases/v0.29.0.md +61 -0
  91. package/docs/releases/v0.29.1.md +59 -0
  92. package/docs/releases/v0.29.2.md +59 -0
  93. package/docs/releases/v0.29.3.md +93 -0
  94. package/docs/releases/v0.30.0.md +75 -0
  95. package/docs/releases/v0.30.1.md +93 -0
  96. package/docs/releases/v0.30.2.md +66 -0
  97. package/docs/releases/v0.31.0.md +122 -0
  98. package/docs/releases/v0.31.1.md +142 -0
  99. package/docs/releases/v0.31.10.md +118 -0
  100. package/docs/releases/v0.31.11.md +88 -0
  101. package/docs/releases/v0.31.12.md +105 -0
  102. package/docs/releases/v0.31.13.md +99 -0
  103. package/docs/releases/v0.31.14.md +97 -0
  104. package/docs/releases/v0.31.2.md +115 -0
  105. package/docs/releases/v0.31.3.md +142 -0
  106. package/docs/releases/v0.31.4.md +117 -0
  107. package/docs/releases/v0.31.5.md +155 -0
  108. package/docs/releases/v0.31.6.md +132 -0
  109. package/docs/releases/v0.31.7.md +132 -0
  110. package/docs/releases/v0.31.8.md +120 -0
  111. package/docs/releases/v0.31.9.md +120 -0
  112. package/docs/releases/v0.32.0.md +261 -0
  113. package/docs/releases/v0.32.1.md +59 -0
  114. package/docs/releases/v0.8.0.md +118 -0
  115. package/docs/releases/v0.9.0.md +98 -0
  116. package/docs/releases/v0.9.1.md +83 -0
  117. package/package.json +102 -6
  118. package/plugins/mirror-mind/.claude-plugin/plugin.json +13 -0
  119. package/plugins/mirror-mind/hooks/hooks.json +50 -0
  120. package/plugins/mirror-mind/hooks/log-session-end.sh +98 -0
  121. package/plugins/mirror-mind/hooks/log-user-prompt.sh +98 -0
  122. package/plugins/mirror-mind/hooks/mirror-inject.sh +98 -0
  123. package/plugins/mirror-mind/hooks/session-start.sh +98 -0
  124. package/plugins/mirror-mind/mcp/launch.sh +52 -0
  125. package/plugins/mirror-mind/skills/mm-backup/SKILL.md +27 -0
  126. package/plugins/mirror-mind/skills/mm-build/SKILL.md +1206 -0
  127. package/plugins/mirror-mind/skills/mm-consolidate/SKILL.md +112 -0
  128. package/plugins/mirror-mind/skills/mm-consult/SKILL.md +83 -0
  129. package/plugins/mirror-mind/skills/mm-conversations/SKILL.md +17 -0
  130. package/plugins/mirror-mind/skills/mm-discard/SKILL.md +40 -0
  131. package/plugins/mirror-mind/skills/mm-explore/SKILL.md +241 -0
  132. package/plugins/mirror-mind/skills/mm-help/SKILL.md +104 -0
  133. package/plugins/mirror-mind/skills/mm-identity/SKILL.md +96 -0
  134. package/plugins/mirror-mind/skills/mm-journal/SKILL.md +21 -0
  135. package/plugins/mirror-mind/skills/mm-journey/SKILL.md +37 -0
  136. package/plugins/mirror-mind/skills/mm-journeys/SKILL.md +15 -0
  137. package/plugins/mirror-mind/skills/mm-memories/SKILL.md +20 -0
  138. package/plugins/mirror-mind/skills/mm-mirror/SKILL.md +65 -0
  139. package/plugins/mirror-mind/skills/mm-mute/SKILL.md +18 -0
  140. package/plugins/mirror-mind/skills/mm-new/SKILL.md +18 -0
  141. package/plugins/mirror-mind/skills/mm-recall/SKILL.md +17 -0
  142. package/plugins/mirror-mind/skills/mm-release-notes/SKILL.md +31 -0
  143. package/plugins/mirror-mind/skills/mm-seed/SKILL.md +15 -0
  144. package/plugins/mirror-mind/skills/mm-shadow/SKILL.md +117 -0
  145. package/plugins/mirror-mind/skills/mm-soul/SKILL.md +488 -0
  146. package/plugins/mirror-mind/skills/mm-tasks/SKILL.md +36 -0
  147. package/plugins/mirror-mind/skills/mm-update/SKILL.md +30 -0
  148. package/plugins/mirror-mind/skills/mm-week/SKILL.md +46 -0
  149. package/plugins/mirror-mind/skills/mm-welcome/SKILL.md +22 -0
  150. package/scripts/codex-hooks/session-end.sh +85 -0
  151. package/scripts/codex-hooks/session-start.sh +85 -0
  152. package/scripts/codex-mirror.sh +48 -0
  153. package/templates/identity/README.md +119 -0
  154. package/templates/identity/ego/behavior.yaml +52 -0
  155. package/templates/identity/ego/constraints.yaml +15 -0
  156. package/templates/identity/ego/identity.yaml +43 -0
  157. package/templates/identity/journeys/personal-growth.yaml +39 -0
  158. package/templates/identity/organization/identity.yaml +24 -0
  159. package/templates/identity/organization/principles.yaml +17 -0
  160. package/templates/identity/personas/coach.yaml +94 -0
  161. package/templates/identity/personas/designer.yaml +93 -0
  162. package/templates/identity/personas/doctor.yaml +96 -0
  163. package/templates/identity/personas/engineer.yaml +77 -0
  164. package/templates/identity/personas/financial.yaml +97 -0
  165. package/templates/identity/personas/prompt-engineer.yaml +122 -0
  166. package/templates/identity/personas/researcher.yaml +88 -0
  167. package/templates/identity/personas/strategist.yaml +91 -0
  168. package/templates/identity/personas/teacher.yaml +95 -0
  169. package/templates/identity/personas/therapist.yaml +91 -0
  170. package/templates/identity/personas/thinker.yaml +74 -0
  171. package/templates/identity/personas/writer.yaml +76 -0
  172. package/templates/identity/self/config.yaml +16 -0
  173. package/templates/identity/self/soul.yaml +105 -0
  174. package/templates/identity/user/identity.yaml +30 -0
  175. package/ts/src/backup/staging.ts +62 -0
  176. package/ts/src/backup/zipBackup.ts +267 -0
  177. package/ts/src/backup/zipReader.ts +109 -0
  178. package/ts/src/backup/zipWriter.ts +148 -0
  179. package/ts/src/builder/activeCheckpoint.ts +134 -0
  180. package/ts/src/builder/aggregateStatus.ts +34 -0
  181. package/ts/src/builder/approve.ts +149 -0
  182. package/ts/src/builder/argv.ts +292 -0
  183. package/ts/src/builder/ariadMethod.ts +536 -0
  184. package/ts/src/builder/artifacts/artifactSurfaces.ts +106 -0
  185. package/ts/src/builder/artifacts/artifactWriter.ts +113 -0
  186. package/ts/src/builder/artifacts/closureArtifacts.ts +199 -0
  187. package/ts/src/builder/artifacts/deliveryStoryArtifacts.ts +316 -0
  188. package/ts/src/builder/artifacts/planArtifacts.ts +242 -0
  189. package/ts/src/builder/artifacts/scaffoldSections.ts +273 -0
  190. package/ts/src/builder/artifacts/scaffoldState.ts +227 -0
  191. package/ts/src/builder/artifacts/storyFiles.ts +61 -0
  192. package/ts/src/builder/artifacts/storyIndex.ts +166 -0
  193. package/ts/src/builder/cadence.ts +59 -0
  194. package/ts/src/builder/card.ts +192 -0
  195. package/ts/src/builder/checkpointRefused.ts +66 -0
  196. package/ts/src/builder/closure.ts +964 -0
  197. package/ts/src/builder/commands.ts +2053 -0
  198. package/ts/src/builder/cursorPosition.ts +176 -0
  199. package/ts/src/builder/cursorTransitions.ts +77 -0
  200. package/ts/src/builder/deliveryCursor.ts +577 -0
  201. package/ts/src/builder/deliveryStoryClosure.ts +521 -0
  202. package/ts/src/builder/deliveryStoryPlan.ts +536 -0
  203. package/ts/src/builder/deliveryStoryReady.ts +160 -0
  204. package/ts/src/builder/deliveryStoryRoadmapClosure.ts +151 -0
  205. package/ts/src/builder/expand.ts +336 -0
  206. package/ts/src/builder/flowUnit.ts +339 -0
  207. package/ts/src/builder/homeSurface.ts +122 -0
  208. package/ts/src/builder/implementationGuard.ts +125 -0
  209. package/ts/src/builder/index.ts +11 -0
  210. package/ts/src/builder/lifecycleRefusal.ts +92 -0
  211. package/ts/src/builder/lifecycleRibbon.ts +159 -0
  212. package/ts/src/builder/load.ts +313 -0
  213. package/ts/src/builder/methodAdoption.ts +113 -0
  214. package/ts/src/builder/methodDefinition.ts +429 -0
  215. package/ts/src/builder/methodInspection.ts +371 -0
  216. package/ts/src/builder/plan.ts +408 -0
  217. package/ts/src/builder/planPreauthorization.ts +265 -0
  218. package/ts/src/builder/prepare.ts +225 -0
  219. package/ts/src/builder/projectPaths.ts +64 -0
  220. package/ts/src/builder/pull.ts +356 -0
  221. package/ts/src/builder/pullCandidates.ts +463 -0
  222. package/ts/src/builder/pullCandidatesRender.ts +238 -0
  223. package/ts/src/builder/refinementField.ts +93 -0
  224. package/ts/src/builder/releaseIntent.ts +173 -0
  225. package/ts/src/builder/resumeState.ts +84 -0
  226. package/ts/src/builder/resumeSurface.ts +149 -0
  227. package/ts/src/builder/roadmapGrammar.ts +300 -0
  228. package/ts/src/builder/roadmapScan.ts +97 -0
  229. package/ts/src/builder/roadmapScope.ts +210 -0
  230. package/ts/src/builder/scopePhrases.ts +146 -0
  231. package/ts/src/builder/storyPaths.ts +196 -0
  232. package/ts/src/builder/storyPlanPreauthorization.ts +287 -0
  233. package/ts/src/builder/surfaceProtocol.ts +42 -0
  234. package/ts/src/builder/templateGeneration.ts +148 -0
  235. package/ts/src/builder/transition.ts +178 -0
  236. package/ts/src/consult/args.ts +99 -0
  237. package/ts/src/consult/core.ts +122 -0
  238. package/ts/src/consult/modelCatalog.ts +55 -0
  239. package/ts/src/consult/render.ts +47 -0
  240. package/ts/src/conversation/append.ts +414 -0
  241. package/ts/src/conversation/backfill.ts +387 -0
  242. package/ts/src/conversation/closeTail.ts +467 -0
  243. package/ts/src/conversation/extraction.ts +333 -0
  244. package/ts/src/conversation/extractionDriver.ts +130 -0
  245. package/ts/src/conversation/extractionRun.ts +70 -0
  246. package/ts/src/conversation/journeyInference.ts +165 -0
  247. package/ts/src/conversation/journeyRepair.ts +114 -0
  248. package/ts/src/conversation/lifecycleFaces.ts +197 -0
  249. package/ts/src/conversation/lifecycleWrites.ts +313 -0
  250. package/ts/src/conversation/listing.ts +77 -0
  251. package/ts/src/conversation/logger.ts +576 -0
  252. package/ts/src/conversation/loggerCli.ts +282 -0
  253. package/ts/src/conversation/loggerRuntime.ts +259 -0
  254. package/ts/src/conversation/metadataLifecycle.ts +443 -0
  255. package/ts/src/conversation/recall.ts +66 -0
  256. package/ts/src/conversation/sessionComposites.ts +258 -0
  257. package/ts/src/conversation/sessionImport.ts +90 -0
  258. package/ts/src/conversation/transcriptBackfill.ts +141 -0
  259. package/ts/src/cultivation/applyActions.ts +241 -0
  260. package/ts/src/cultivation/cluster.ts +86 -0
  261. package/ts/src/cultivation/consolidationStore.ts +281 -0
  262. package/ts/src/cultivation/promptContext.ts +62 -0
  263. package/ts/src/cultivation/propose.ts +305 -0
  264. package/ts/src/cultivation/scan.ts +155 -0
  265. package/ts/src/db/backupGate.ts +47 -0
  266. package/ts/src/db/bootstrap.ts +108 -0
  267. package/ts/src/db/bootstrapLock.ts +223 -0
  268. package/ts/src/db/copyGuard.ts +60 -0
  269. package/ts/src/db/database.ts +397 -0
  270. package/ts/src/db/decode.ts +66 -0
  271. package/ts/src/db/ftsIntegrity.ts +41 -0
  272. package/ts/src/db/migrateOnOpen.ts +214 -0
  273. package/ts/src/db/migrations.ts +576 -0
  274. package/ts/src/db/readyOnOpen.ts +35 -0
  275. package/ts/src/db/rowDecode.ts +42 -0
  276. package/ts/src/db/schema.ts +432 -0
  277. package/ts/src/db/schemaInventory.ts +225 -0
  278. package/ts/src/db/schemaInventorySnapshot.ts +2107 -0
  279. package/ts/src/db/schemaState.ts +91 -0
  280. package/ts/src/db/schemaTsDivergence.ts +114 -0
  281. package/ts/src/descriptor/descriptorRead.ts +49 -0
  282. package/ts/src/docs/docsLint.ts +265 -0
  283. package/ts/src/explorer/handoff.ts +522 -0
  284. package/ts/src/explorer/render.ts +335 -0
  285. package/ts/src/explorer/story.ts +769 -0
  286. package/ts/src/explorer/transition.ts +72 -0
  287. package/ts/src/extensions/bindings.ts +170 -0
  288. package/ts/src/extensions/catalog.ts +249 -0
  289. package/ts/src/extensions/catalogCommands.ts +513 -0
  290. package/ts/src/extensions/catalogWrites.ts +652 -0
  291. package/ts/src/extensions/contextRuntime.ts +325 -0
  292. package/ts/src/extensions/dispatch.ts +374 -0
  293. package/ts/src/extensions/errors.ts +24 -0
  294. package/ts/src/extensions/manifest.ts +356 -0
  295. package/ts/src/extensions/migrations.ts +350 -0
  296. package/ts/src/extraction/conversation.ts +304 -0
  297. package/ts/src/extraction/conversationMetadata.ts +206 -0
  298. package/ts/src/extraction/fencing.ts +106 -0
  299. package/ts/src/extraction/json.ts +17 -0
  300. package/ts/src/extraction/prompts.ts +470 -0
  301. package/ts/src/frontDoor/args.ts +30 -0
  302. package/ts/src/frontDoor/argvShape.ts +106 -0
  303. package/ts/src/frontDoor/buildLoadRuntime.ts +139 -0
  304. package/ts/src/frontDoor/buildRoute.ts +398 -0
  305. package/ts/src/frontDoor/cli.ts +1865 -0
  306. package/ts/src/frontDoor/cloneRoleGuard.ts +98 -0
  307. package/ts/src/frontDoor/consultRoute.ts +50 -0
  308. package/ts/src/frontDoor/contentTailRoute.ts +239 -0
  309. package/ts/src/frontDoor/conversationLoggerRoute.ts +73 -0
  310. package/ts/src/frontDoor/cultivationRoute.ts +210 -0
  311. package/ts/src/frontDoor/dbPath.ts +131 -0
  312. package/ts/src/frontDoor/dbSafetyToolsRoute.ts +240 -0
  313. package/ts/src/frontDoor/exploreRoute.ts +572 -0
  314. package/ts/src/frontDoor/extensionCatalogRoute.ts +252 -0
  315. package/ts/src/frontDoor/frontDoorLog.ts +57 -0
  316. package/ts/src/frontDoor/identityWrite.ts +36 -0
  317. package/ts/src/frontDoor/journeyWriteRoute.ts +26 -0
  318. package/ts/src/frontDoor/lifecycleWriteRoute.ts +110 -0
  319. package/ts/src/frontDoor/liveBackup.ts +100 -0
  320. package/ts/src/frontDoor/mirrorModeRoute.ts +163 -0
  321. package/ts/src/frontDoor/namedRefusal.ts +35 -0
  322. package/ts/src/frontDoor/nodeSupport.ts +24 -0
  323. package/ts/src/frontDoor/render/consolidate.ts +199 -0
  324. package/ts/src/frontDoor/render/conversations.ts +33 -0
  325. package/ts/src/frontDoor/render/cultivationShared.ts +21 -0
  326. package/ts/src/frontDoor/render/descriptor.ts +20 -0
  327. package/ts/src/frontDoor/render/detectPersona.ts +50 -0
  328. package/ts/src/frontDoor/render/icons.ts +13 -0
  329. package/ts/src/frontDoor/render/identity.ts +59 -0
  330. package/ts/src/frontDoor/render/identityRows.ts +17 -0
  331. package/ts/src/frontDoor/render/inspectPersona.ts +53 -0
  332. package/ts/src/frontDoor/render/journeyStatus.ts +78 -0
  333. package/ts/src/frontDoor/render/journeys.ts +79 -0
  334. package/ts/src/frontDoor/render/list.ts +41 -0
  335. package/ts/src/frontDoor/render/memories.ts +67 -0
  336. package/ts/src/frontDoor/render/recall.ts +49 -0
  337. package/ts/src/frontDoor/render/shadow.ts +155 -0
  338. package/ts/src/frontDoor/render/tasks.ts +99 -0
  339. package/ts/src/frontDoor/render/tasksImportSync.ts +63 -0
  340. package/ts/src/frontDoor/render/week.ts +113 -0
  341. package/ts/src/frontDoor/routing.ts +999 -0
  342. package/ts/src/frontDoor/runtimeRoute.ts +623 -0
  343. package/ts/src/frontDoor/searchRoute.ts +166 -0
  344. package/ts/src/frontDoor/seedPaths.ts +98 -0
  345. package/ts/src/frontDoor/soulRoute.ts +433 -0
  346. package/ts/src/frontDoor/tasksImportSyncRoute.ts +110 -0
  347. package/ts/src/frontDoor/tasksWriteRoute.ts +101 -0
  348. package/ts/src/frontDoor/usage.ts +176 -0
  349. package/ts/src/guards/claudePlugin.ts +252 -0
  350. package/ts/src/guards/packContents.ts +306 -0
  351. package/ts/src/guards/piSourcedSkills.ts +70 -0
  352. package/ts/src/guards/retiredRouteShadows.ts +57 -0
  353. package/ts/src/guards/retiredSurfaces.ts +564 -0
  354. package/ts/src/hooks/claude.ts +176 -0
  355. package/ts/src/hooks/codex.ts +45 -0
  356. package/ts/src/hooks/gemini.ts +126 -0
  357. package/ts/src/hooks/main.ts +109 -0
  358. package/ts/src/hooks/mirrorState.ts +71 -0
  359. package/ts/src/hooks/payload.ts +68 -0
  360. package/ts/src/hooks/runtime.ts +159 -0
  361. package/ts/src/identity/applyConsolidationIdentityUpdate.ts +67 -0
  362. package/ts/src/identity/descriptorGenerate.ts +162 -0
  363. package/ts/src/identity/identityEdit.ts +143 -0
  364. package/ts/src/identity/identityKey.ts +77 -0
  365. package/ts/src/identity/identityRead.ts +69 -0
  366. package/ts/src/identity/identityStore.ts +80 -0
  367. package/ts/src/identity/journeyListing.ts +53 -0
  368. package/ts/src/identity/personaInspect.ts +44 -0
  369. package/ts/src/identity/personaListing.ts +37 -0
  370. package/ts/src/identity/setIdentity.ts +64 -0
  371. package/ts/src/index.ts +231 -0
  372. package/ts/src/init/init.ts +111 -0
  373. package/ts/src/journey/journeyOptions.ts +131 -0
  374. package/ts/src/journey/journeyRemoval.ts +158 -0
  375. package/ts/src/journey/journeyStatus.ts +149 -0
  376. package/ts/src/journey/journeySyncFile.ts +87 -0
  377. package/ts/src/journey/journeyWrite.ts +203 -0
  378. package/ts/src/journey/parentJourney.ts +41 -0
  379. package/ts/src/journey/validateParentJourney.ts +55 -0
  380. package/ts/src/mcp/boundary.ts +151 -0
  381. package/ts/src/mcp/guards.ts +244 -0
  382. package/ts/src/mcp/main.ts +121 -0
  383. package/ts/src/mcp/payload.ts +141 -0
  384. package/ts/src/mcp/protocol.ts +141 -0
  385. package/ts/src/mcp/readModels.ts +241 -0
  386. package/ts/src/mcp/registry.ts +201 -0
  387. package/ts/src/mcp/serve.ts +120 -0
  388. package/ts/src/mcp/tools/deterministic.ts +137 -0
  389. package/ts/src/mcp/tools/providerCrossing.ts +187 -0
  390. package/ts/src/mcp/wire.ts +8 -0
  391. package/ts/src/memory/journal.ts +180 -0
  392. package/ts/src/memory/listing.ts +107 -0
  393. package/ts/src/memory/memoryWrite.ts +88 -0
  394. package/ts/src/memory/reinforcement.ts +35 -0
  395. package/ts/src/mirror/context.ts +161 -0
  396. package/ts/src/mirror/defaultResolution.ts +199 -0
  397. package/ts/src/mirror/orchestration.ts +364 -0
  398. package/ts/src/mirror/reception.ts +194 -0
  399. package/ts/src/mirror/render.ts +75 -0
  400. package/ts/src/mirror/runtimeSession.ts +205 -0
  401. package/ts/src/mode/operatingMode.ts +148 -0
  402. package/ts/src/observability/callOutcome.ts +115 -0
  403. package/ts/src/observability/inspectLedger.ts +329 -0
  404. package/ts/src/observability/ledgerHooks.ts +126 -0
  405. package/ts/src/observability/llmCalls.ts +154 -0
  406. package/ts/src/persona/detectPersona.ts +81 -0
  407. package/ts/src/planning/promptAssembly.ts +111 -0
  408. package/ts/src/planning/weekPending.ts +81 -0
  409. package/ts/src/planning/weekPlan.ts +183 -0
  410. package/ts/src/planning/weekSave.ts +117 -0
  411. package/ts/src/providers/config.ts +189 -0
  412. package/ts/src/providers/cost.ts +64 -0
  413. package/ts/src/providers/credits.ts +204 -0
  414. package/ts/src/providers/embedding.ts +321 -0
  415. package/ts/src/providers/familyProviders.ts +147 -0
  416. package/ts/src/providers/llm.ts +334 -0
  417. package/ts/src/providers/openrouter.ts +244 -0
  418. package/ts/src/providers/redaction.ts +110 -0
  419. package/ts/src/providers/replay.ts +15 -0
  420. package/ts/src/providers/transport.ts +410 -0
  421. package/ts/src/repair/encodingRepair.ts +253 -0
  422. package/ts/src/runtime/backup.ts +151 -0
  423. package/ts/src/runtime/channel.ts +146 -0
  424. package/ts/src/runtime/config.ts +168 -0
  425. package/ts/src/runtime/diagnose.ts +686 -0
  426. package/ts/src/runtime/git.ts +510 -0
  427. package/ts/src/runtime/installKind.ts +220 -0
  428. package/ts/src/runtime/migrate.ts +154 -0
  429. package/ts/src/runtime/packageIdentity.ts +102 -0
  430. package/ts/src/runtime/releaseNotes.ts +244 -0
  431. package/ts/src/runtime/status.ts +557 -0
  432. package/ts/src/runtime/strategies/clone.ts +200 -0
  433. package/ts/src/runtime/strategies/package.ts +328 -0
  434. package/ts/src/runtime/treeRoot.ts +30 -0
  435. package/ts/src/runtime/update.ts +445 -0
  436. package/ts/src/runtime/updateGate.ts +40 -0
  437. package/ts/src/runtime/updatePipeline.ts +159 -0
  438. package/ts/src/runtime/version.ts +36 -0
  439. package/ts/src/runtime/wiring.ts +130 -0
  440. package/ts/src/search/memorySearch.ts +338 -0
  441. package/ts/src/search/ranker.ts +154 -0
  442. package/ts/src/seed/seed.ts +256 -0
  443. package/ts/src/seed/seedYaml.ts +133 -0
  444. package/ts/src/soul/apply.ts +218 -0
  445. package/ts/src/soul/harvest.ts +267 -0
  446. package/ts/src/soul/prompts/soul_beauty_voice.md +103 -0
  447. package/ts/src/soul/prompts/soul_self_voice.md +219 -0
  448. package/ts/src/soul/prompts/soul_wisdom_voice.md +121 -0
  449. package/ts/src/soul/prompts.ts +85 -0
  450. package/ts/src/soul/render.ts +358 -0
  451. package/ts/src/soul/state.ts +212 -0
  452. package/ts/src/soul/transition.ts +37 -0
  453. package/ts/src/tasks/journeyPathParse.ts +113 -0
  454. package/ts/src/tasks/taskImportSync.ts +142 -0
  455. package/ts/src/tasks/taskStore.ts +312 -0
  456. package/ts/src/tasks/weekView.ts +120 -0
  457. package/ts/src/util/clipCodePoints.ts +26 -0
  458. package/ts/src/util/paths.ts +63 -0
  459. package/ts/src/util/program.ts +9 -0
  460. package/ts/src/util/pyGenerators.ts +144 -0
  461. package/ts/src/util/pythonText.ts +317 -0
  462. package/ts/src/util/semver.ts +45 -0
  463. package/ts/src/util/shellWord.ts +25 -0
  464. package/ts/src/util/slug.ts +64 -0
  465. package/ts/src/welcome/card.ts +339 -0
  466. package/ts/src/welcome/statusLine.ts +101 -0
  467. package/ts/src/welcome/updateCache.ts +129 -0
@@ -0,0 +1,964 @@
1
+ // CV22.DS7.US8 plateau 4 — story closure: Validate, Debt Review, Coherence, Done.
2
+ //
3
+ // Port of the second half of `src/memory/builder/lifecycle.py`.
4
+ //
5
+ // The four verbs share one shape, and it is the shape a port gets wrong: each
6
+ // computes a MISSING-EVIDENCE tuple, and that tuple decides three cursor fields at
7
+ // once — `activeCheckpoint`, `pendingConfirmation`, and `lastDeliveryEvent`. So
8
+ // "incomplete" is not an error and not a different surface; it is the same surface
9
+ // over a different persisted state. A port can render the right card and write the
10
+ // wrong three fields, which is why the corpus grades every branch as a sequence.
11
+ //
12
+ // Two of the four allow EXACT-STATE re-entry to answer their own pending
13
+ // confirmation — Review for `navigator_debt_decision`, Coherence for
14
+ // `navigator_coherence` — because without it `--decision pending` deadlocks the
15
+ // lifecycle: every verb refuses while the confirmation it would resolve stays
16
+ // pending. That was found live on another project, not reasoned about. Done allows no
17
+ // re-entry at all and refuses any pending confirmation its predecessors left behind.
18
+ //
19
+ // Until CV22.DS10.TS1 all four ordered a Journey projection refresh after their
20
+ // artifact existed. The projection subsystem retired with the Python core, so the
21
+ // ordering dance is gone and the cursor write is the whole write.
22
+ //
23
+ // They live in one module rather than four because they are one state machine over
24
+ // one cursor, sharing the missing-evidence idiom and the guard vocabulary. Splitting
25
+ // them would duplicate the shared normalizers without separating any concern.
26
+
27
+ import type { WritableDatabase } from "#db/database.ts";
28
+ import { pyStrip, sortByCodePoint } from "#util/pythonText.ts";
29
+ import type { ArtifactOutcome } from "./artifacts/artifactWriter.ts";
30
+ import {
31
+ renderCoherenceArtifact,
32
+ renderDoneArtifact,
33
+ renderReviewArtifact,
34
+ renderValidationArtifact,
35
+ writeClosureArtifact,
36
+ } from "./artifacts/closureArtifacts.ts";
37
+ import { artifactState } from "./artifacts/scaffoldState.ts";
38
+ import { cardPrefixed, cardText, cardWrapped } from "./card.ts";
39
+ import { normalizeRequired } from "./cursorTransitions.ts";
40
+ import {
41
+ type BuilderDeliveryCursor,
42
+ type CursorWriteDeps,
43
+ getDeliveryCursor,
44
+ setDeliveryCursor,
45
+ } from "./deliveryCursor.ts";
46
+ import { LifecycleRefusal, refuseIfAlreadyComplete } from "./lifecycleRefusal.ts";
47
+ import { renderLifecycleRibbon } from "./lifecycleRibbon.ts";
48
+ import type { ContractDefinition, MethodDefinition } from "./methodDefinition.ts";
49
+ import { displayPath, targetLine } from "./projectPaths.ts";
50
+ import { wrapAriadSurface } from "./surfaceProtocol.ts";
51
+
52
+ /** Python `_contract_for`. */
53
+ function contractFor(method: MethodDefinition, contractId: string): ContractDefinition {
54
+ const contract = method.contracts.find((candidate) => candidate.id === contractId);
55
+ if (contract === undefined) {
56
+ throw new Error(`method ${method.id} is missing contract ${contractId}`);
57
+ }
58
+ return contract;
59
+ }
60
+
61
+ /**
62
+ * Python `_normalize_validation_choice`.
63
+ *
64
+ * Lowercases and maps `-` to `_` before the membership test, and the refusal lists
65
+ * the allowed values SORTED — so the message is stable regardless of the order the
66
+ * call site declared them in.
67
+ */
68
+ function normalizeChoice(value: string, field: string, allowed: readonly string[]): string {
69
+ const normalized =
70
+ typeof value === "string" ? pyStrip(value).toLowerCase().replaceAll("-", "_") : "";
71
+ if (!allowed.includes(normalized)) {
72
+ throw new Error(`${field} must be one of ${sortByCodePoint([...allowed]).join(", ")}`);
73
+ }
74
+ return normalized;
75
+ }
76
+
77
+ /** Python's `tuple(x.strip() for x in items if x.strip())`. */
78
+ function normalizedList(items: readonly string[]): string[] {
79
+ return items.map((item) => pyStrip(item)).filter((item) => item !== "");
80
+ }
81
+
82
+ /** Python's `(value or default).strip()`. */
83
+ function textOr(value: string | null | undefined, fallback: string): string {
84
+ return pyStrip(value || fallback);
85
+ }
86
+
87
+ /** Python's `x.strip() if x and x.strip() else None`. */
88
+ function optionalText(value: string | null | undefined): string | null {
89
+ if (!value) return null;
90
+ const stripped = pyStrip(value);
91
+ return stripped || null;
92
+ }
93
+
94
+ // --- Validation ------------------------------------------------------------
95
+
96
+ export interface BuilderValidationReport {
97
+ readonly journey: string;
98
+ readonly method: string;
99
+ readonly activeItem: string;
100
+ readonly activeItemTitle: string | null;
101
+ readonly automatedChecks: readonly string[];
102
+ readonly checksStatus: string;
103
+ readonly e2eDecision: string;
104
+ readonly e2eEvidence: string | null;
105
+ readonly navigatorValidationRoute: string;
106
+ readonly navigatorAccepted: boolean;
107
+ readonly expectedObservation: string;
108
+ readonly passCondition: string;
109
+ readonly failCondition: string;
110
+ readonly missingEvidence: readonly string[];
111
+ readonly validationContract: ContractDefinition;
112
+ readonly cursor: BuilderDeliveryCursor;
113
+ readonly validationArtifactPath: string | null;
114
+ /** The project the record was written under: the card names it relative (CR082). */
115
+ readonly projectRoot: string | null;
116
+ /** What the writer did with the record (CR079); absent when there is no artifact path. */
117
+ readonly validationArtifactOutcome?: ArtifactOutcome | null;
118
+ readonly nextEvent: string;
119
+ }
120
+
121
+ /**
122
+ * Python `_validation_missing_evidence`.
123
+ *
124
+ * Order is behavior: the tuple is rendered as a list, so a port that reorders these
125
+ * produces a different surface. Note the `elif` on acceptance — a MISSING route is
126
+ * reported instead of an unaccepted one, never both.
127
+ */
128
+ function validationMissingEvidence(input: {
129
+ checks: readonly string[];
130
+ checksStatus: string;
131
+ e2eDecision: string;
132
+ e2eEvidence: string | null | undefined;
133
+ navigatorValidationRoute: string;
134
+ navigatorAccepted: boolean;
135
+ }): string[] {
136
+ const missing: string[] = [];
137
+ if (input.checks.length === 0) missing.push("automated checks are not declared");
138
+ if (input.checksStatus !== "passed") {
139
+ missing.push(`automated checks status is ${input.checksStatus}`);
140
+ }
141
+ const evidence = input.e2eEvidence && pyStrip(input.e2eEvidence) ? input.e2eEvidence : null;
142
+ if (input.e2eDecision === "required" && evidence === null) {
143
+ missing.push("required E2E evidence is missing");
144
+ }
145
+ if (input.e2eDecision === "skipped" && evidence === null) {
146
+ missing.push("skipped E2E requires an explicit reason");
147
+ }
148
+ if (!pyStrip(input.navigatorValidationRoute)) {
149
+ missing.push("Navigator validation route is missing");
150
+ } else if (!input.navigatorAccepted) {
151
+ missing.push("Navigator validation has not been accepted");
152
+ }
153
+ return missing;
154
+ }
155
+
156
+ export interface ValidateOptions {
157
+ readonly journey: string;
158
+ readonly method: MethodDefinition;
159
+ readonly automatedChecks?: readonly string[];
160
+ readonly checksStatus?: string;
161
+ readonly e2eDecision?: string;
162
+ readonly e2eEvidence?: string | null;
163
+ readonly navigatorValidationRoute?: string | null;
164
+ readonly navigatorAccepted?: boolean;
165
+ readonly expectedObservation?: string | null;
166
+ readonly passCondition?: string | null;
167
+ readonly failCondition?: string | null;
168
+ readonly implementationComplete?: boolean;
169
+ readonly validationArtifactPath?: string | null;
170
+ /** The project the artifact must stay inside (CR079). */
171
+ readonly projectRoot?: string | null;
172
+ }
173
+
174
+ const PLAN_EVENTS = new Set(["plan_approved", "delivery_story_plan_approved"]);
175
+
176
+ /** Python `validate_lifecycle_item`. */
177
+ export function validateLifecycleItem(
178
+ db: WritableDatabase,
179
+ options: ValidateOptions,
180
+ deps: CursorWriteDeps,
181
+ ): BuilderValidationReport {
182
+ const journey = normalizeRequired(options.journey, "journey");
183
+ const existing = getDeliveryCursor(db, journey);
184
+ if (existing === null) throw new Error("delivery cursor is required before validation");
185
+ if (!existing.activeItem) throw new Error("active item is required before validation");
186
+ refuseIfAlreadyComplete("validate", existing);
187
+ if (existing.pendingConfirmation && existing.pendingConfirmation !== "navigator_validation") {
188
+ throw new LifecycleRefusal(
189
+ "validate",
190
+ "pending_confirmation",
191
+ `Validation is blocked: pending confirmation ${existing.pendingConfirmation}.`,
192
+ );
193
+ }
194
+ const navigatorAccepted = options.navigatorAccepted ?? false;
195
+ if (existing.pendingConfirmation === "navigator_validation" && !navigatorAccepted) {
196
+ throw new LifecycleRefusal(
197
+ "validate",
198
+ "pending_confirmation",
199
+ "Validation is blocked: pending Navigator validation acceptance.",
200
+ );
201
+ }
202
+ const lastEvent = existing.lastDeliveryEvent ?? "";
203
+ if (
204
+ !(
205
+ PLAN_EVENTS.has(lastEvent) ||
206
+ lastEvent === "implementation_complete" ||
207
+ lastEvent === "validate"
208
+ )
209
+ ) {
210
+ throw new LifecycleRefusal(
211
+ "validate",
212
+ "not_reached",
213
+ "Validation requires an approved Plan and completed implementation",
214
+ );
215
+ }
216
+ if (PLAN_EVENTS.has(lastEvent) && !(options.implementationComplete ?? false)) {
217
+ throw new LifecycleRefusal(
218
+ "validate",
219
+ "missing_evidence",
220
+ "Validation requires implementation completion evidence",
221
+ );
222
+ }
223
+
224
+ const checks = normalizedList(options.automatedChecks ?? []);
225
+ const checksStatus = normalizeChoice(options.checksStatus ?? "not_run", "checks_status", [
226
+ "passed",
227
+ "failed",
228
+ "not_run",
229
+ ]);
230
+ const e2eDecision = normalizeChoice(options.e2eDecision ?? "not_required", "e2e_decision", [
231
+ "required",
232
+ "not_required",
233
+ "waived",
234
+ "skipped",
235
+ ]);
236
+ const route = textOr(
237
+ options.navigatorValidationRoute,
238
+ "Navigator validates the behavior described by the Plan.",
239
+ );
240
+ const observation = textOr(
241
+ options.expectedObservation,
242
+ "Expected behavior from the Plan is observable.",
243
+ );
244
+ const passText = textOr(options.passCondition, "Navigator accepts the observed behavior.");
245
+ const failText = textOr(options.failCondition, "Navigator cannot observe the planned behavior.");
246
+ const missing = validationMissingEvidence({
247
+ checks,
248
+ checksStatus,
249
+ e2eDecision,
250
+ e2eEvidence: options.e2eEvidence,
251
+ navigatorValidationRoute: route,
252
+ navigatorAccepted,
253
+ });
254
+
255
+ const cursor = setDeliveryCursor(
256
+ db,
257
+ {
258
+ journey,
259
+ method: options.method.id,
260
+ activeItem: existing.activeItem,
261
+ activeItemTitle: existing.activeItemTitle,
262
+ activeItemLevel: existing.activeItemLevel,
263
+ activeCheckpoint: missing.length > 0 ? "after_validation" : null,
264
+ pendingConfirmation: missing.length > 0 ? "navigator_validation" : null,
265
+ lastDeliveryEvent: missing.length > 0 ? "validate" : "validation_passed",
266
+ cadenceProfile: existing.cadenceProfile,
267
+ cadenceLimits: existing.cadenceLimits,
268
+ granularityDecision: existing.granularityDecision,
269
+ navigatorFlowUnit: existing.navigatorFlowUnit,
270
+ childWorkItems: existing.childWorkItems,
271
+ aggregateCheckpointStatus: existing.aggregateCheckpointStatus,
272
+ },
273
+ deps,
274
+ );
275
+
276
+ const report: BuilderValidationReport = {
277
+ journey,
278
+ method: options.method.id,
279
+ activeItem: existing.activeItem,
280
+ activeItemTitle: existing.activeItemTitle,
281
+ automatedChecks: checks,
282
+ checksStatus,
283
+ e2eDecision,
284
+ e2eEvidence: optionalText(options.e2eEvidence),
285
+ navigatorValidationRoute: route,
286
+ navigatorAccepted,
287
+ expectedObservation: observation,
288
+ passCondition: passText,
289
+ failCondition: failText,
290
+ missingEvidence: missing,
291
+ validationContract: contractFor(options.method, "validation_contract"),
292
+ cursor,
293
+ validationArtifactPath: options.validationArtifactPath ?? null,
294
+ projectRoot: options.projectRoot ?? null,
295
+ nextEvent: "debt_review",
296
+ };
297
+ if (report.validationArtifactPath === null) return report;
298
+ const validationArtifactOutcome = writeClosureArtifact(
299
+ report.validationArtifactPath,
300
+ renderValidationArtifact(report),
301
+ options.projectRoot,
302
+ );
303
+ return { ...report, validationArtifactOutcome };
304
+ }
305
+
306
+ /** Python `render_validation_checkpoint`. */
307
+ export function renderValidationCheckpoint(report: BuilderValidationReport): string {
308
+ const blocked = report.missingEvidence.length > 0;
309
+ const body = `${[
310
+ "Delivery",
311
+ renderLifecycleRibbon("validate", report.cursor.activeItemLevel),
312
+ "",
313
+ "╭────────────────────────────────────────────────────────╮",
314
+ "│ 🧪■ VALIDATION CHECKPOINT │",
315
+ "│ │",
316
+ cardText("active item"),
317
+ cardText(report.activeItem),
318
+ "│ │",
319
+ cardText("status"),
320
+ cardText(blocked ? "pending_navigator_validation" : "passed"),
321
+ "│ │",
322
+ cardText("automated checks"),
323
+ ...cardPrefixed(
324
+ report.automatedChecks.length > 0
325
+ ? report.automatedChecks
326
+ : ["No automated checks declared."],
327
+ "✓",
328
+ ),
329
+ "│ │",
330
+ cardText("checks status"),
331
+ cardText(report.checksStatus),
332
+ "│ │",
333
+ cardText("e2e decision"),
334
+ cardText(report.e2eDecision),
335
+ "│ │",
336
+ cardText("e2e evidence"),
337
+ ...cardWrapped(report.e2eEvidence || "none"),
338
+ "│ │",
339
+ cardText("navigator validation route"),
340
+ ...cardWrapped(report.navigatorValidationRoute),
341
+ "│ │",
342
+ cardText("navigator accepted"),
343
+ cardText(report.navigatorAccepted ? "yes" : "no"),
344
+ "│ │",
345
+ cardText("expected observation"),
346
+ ...cardWrapped(report.expectedObservation),
347
+ "│ │",
348
+ cardText("pass condition"),
349
+ ...cardWrapped(report.passCondition),
350
+ "│ │",
351
+ cardText("fail condition"),
352
+ ...cardWrapped(report.failCondition),
353
+ "│ │",
354
+ cardText("missing evidence"),
355
+ ...cardPrefixed(blocked ? report.missingEvidence : ["none"], blocked ? "✕" : "✓"),
356
+ "│ │",
357
+ cardText("validation contract"),
358
+ ...cardPrefixed(report.validationContract.rules, "✓"),
359
+ "│ │",
360
+ cardText("validation artifact"),
361
+ ...recordRows(report.validationArtifactPath, report.projectRoot, report.journey),
362
+ ...preservedNote(report.validationArtifactOutcome),
363
+ "│ │",
364
+ cardText("boundary"),
365
+ ...cardWrapped(
366
+ blocked
367
+ ? "Do not move past Validation until missing evidence is resolved."
368
+ : "Validation is complete; Builder may proceed to Debt Review.",
369
+ ),
370
+ "╰────────────────────────────────────────────────────────╯",
371
+ ].join("\n")}\n`;
372
+ return wrapAriadSurface("validation_checkpoint", body);
373
+ }
374
+
375
+ // --- Debt Review -----------------------------------------------------------
376
+
377
+ export interface BuilderReviewReport {
378
+ readonly journey: string;
379
+ readonly method: string;
380
+ readonly activeItem: string;
381
+ readonly activeItemTitle: string | null;
382
+ readonly debtFindings: readonly string[];
383
+ readonly debtDecision: string;
384
+ readonly deferReason: string | null;
385
+ readonly revisitTrigger: string | null;
386
+ readonly missingDecision: readonly string[];
387
+ readonly debtReviewContract: ContractDefinition;
388
+ readonly cursor: BuilderDeliveryCursor;
389
+ readonly reviewArtifactPath: string | null;
390
+ /** The project the record was written under: the card names it relative (CR082). */
391
+ readonly projectRoot: string | null;
392
+ /** What the writer did with the record (CR079); absent when there is no artifact path. */
393
+ readonly reviewArtifactOutcome?: ArtifactOutcome | null;
394
+ readonly nextEvent: string;
395
+ }
396
+
397
+ /** Python `_review_missing_decision`. */
398
+ function reviewMissingDecision(input: {
399
+ debtDecision: string;
400
+ deferReason: string | null | undefined;
401
+ revisitTrigger: string | null | undefined;
402
+ }): string[] {
403
+ const missing: string[] = [];
404
+ if (input.debtDecision === "pending") missing.push("Navigator debt decision is required");
405
+ if (input.debtDecision === "defer") {
406
+ if (!(input.deferReason && pyStrip(input.deferReason))) {
407
+ missing.push("deferred debt requires a reason");
408
+ }
409
+ if (!(input.revisitTrigger && pyStrip(input.revisitTrigger))) {
410
+ missing.push("deferred debt requires a revisit trigger");
411
+ }
412
+ }
413
+ // `pay_now` is never complete here: it must route through a Refactor loop first,
414
+ // so Debt Review cannot be the thing that closes it.
415
+ if (input.debtDecision === "pay_now") {
416
+ missing.push("pay-now debt must route through Refactor before Done");
417
+ }
418
+ return missing;
419
+ }
420
+
421
+ export interface ReviewOptions {
422
+ readonly journey: string;
423
+ readonly method: MethodDefinition;
424
+ readonly debtFindings?: readonly string[];
425
+ readonly debtDecision?: string;
426
+ readonly deferReason?: string | null;
427
+ readonly revisitTrigger?: string | null;
428
+ readonly reviewArtifactPath?: string | null;
429
+ /** The project the artifact must stay inside (CR079). */
430
+ readonly projectRoot?: string | null;
431
+ }
432
+
433
+ /** Python `review_lifecycle_item`. */
434
+ export function reviewLifecycleItem(
435
+ db: WritableDatabase,
436
+ options: ReviewOptions,
437
+ deps: CursorWriteDeps,
438
+ ): BuilderReviewReport {
439
+ const journey = normalizeRequired(options.journey, "journey");
440
+ const existing = getDeliveryCursor(db, journey);
441
+ if (existing === null) throw new Error("delivery cursor is required before review");
442
+ if (!existing.activeItem) throw new Error("active item is required before review");
443
+ refuseIfAlreadyComplete("debt_review", existing);
444
+
445
+ const reentering =
446
+ existing.pendingConfirmation === "navigator_debt_decision" &&
447
+ existing.lastDeliveryEvent === "review";
448
+ if (existing.pendingConfirmation && !reentering) {
449
+ throw new LifecycleRefusal(
450
+ "debt_review",
451
+ "pending_confirmation",
452
+ `Review is blocked: pending confirmation ${existing.pendingConfirmation}.`,
453
+ );
454
+ }
455
+ if (existing.lastDeliveryEvent !== "validation_passed" && !reentering) {
456
+ throw new LifecycleRefusal(
457
+ "debt_review",
458
+ "not_reached",
459
+ "Debt Review requires passed Validation",
460
+ );
461
+ }
462
+
463
+ const decision = normalizeChoice(options.debtDecision ?? "pending", "debt_decision", [
464
+ "pending",
465
+ "no_action",
466
+ "defer",
467
+ "pay_now",
468
+ ]);
469
+ const findings = normalizedList(options.debtFindings ?? []);
470
+ const missing = reviewMissingDecision({
471
+ debtDecision: decision,
472
+ deferReason: options.deferReason,
473
+ revisitTrigger: options.revisitTrigger,
474
+ });
475
+
476
+ const cursor = setDeliveryCursor(
477
+ db,
478
+ {
479
+ journey,
480
+ method: options.method.id,
481
+ activeItem: existing.activeItem,
482
+ activeItemTitle: existing.activeItemTitle,
483
+ activeItemLevel: existing.activeItemLevel,
484
+ activeCheckpoint: missing.length > 0 ? "review_decision" : null,
485
+ pendingConfirmation: missing.length > 0 ? "navigator_debt_decision" : null,
486
+ lastDeliveryEvent: missing.length > 0 ? "review" : "review_complete",
487
+ cadenceProfile: existing.cadenceProfile,
488
+ cadenceLimits: existing.cadenceLimits,
489
+ granularityDecision: existing.granularityDecision,
490
+ navigatorFlowUnit: existing.navigatorFlowUnit,
491
+ childWorkItems: existing.childWorkItems,
492
+ aggregateCheckpointStatus: existing.aggregateCheckpointStatus,
493
+ },
494
+ deps,
495
+ );
496
+
497
+ const report: BuilderReviewReport = {
498
+ journey,
499
+ method: options.method.id,
500
+ activeItem: existing.activeItem,
501
+ activeItemTitle: existing.activeItemTitle,
502
+ debtFindings: findings,
503
+ debtDecision: decision,
504
+ deferReason: optionalText(options.deferReason),
505
+ revisitTrigger: optionalText(options.revisitTrigger),
506
+ missingDecision: missing,
507
+ debtReviewContract: contractFor(options.method, "debt_review_contract"),
508
+ cursor,
509
+ reviewArtifactPath: options.reviewArtifactPath ?? null,
510
+ projectRoot: options.projectRoot ?? null,
511
+ nextEvent: "coherence",
512
+ };
513
+ if (report.reviewArtifactPath === null) return report;
514
+ const reviewArtifactOutcome = writeClosureArtifact(
515
+ report.reviewArtifactPath,
516
+ renderReviewArtifact(report),
517
+ options.projectRoot,
518
+ );
519
+ return { ...report, reviewArtifactOutcome };
520
+ }
521
+
522
+ /** Python `render_review_checkpoint`. */
523
+ export function renderReviewCheckpoint(report: BuilderReviewReport): string {
524
+ const blocked = report.missingDecision.length > 0;
525
+ const body = `${[
526
+ "Delivery",
527
+ renderLifecycleRibbon("debt_review", report.cursor.activeItemLevel),
528
+ "",
529
+ "╭────────────────────────────────────────────────────────╮",
530
+ "│ 🔎■ DEBT REVIEW CHECKPOINT │",
531
+ "│ │",
532
+ cardText("active item"),
533
+ cardText(report.activeItem),
534
+ "│ │",
535
+ cardText("status"),
536
+ cardText(blocked ? "pending_debt_decision" : "reviewed"),
537
+ "│ │",
538
+ cardText("debt findings"),
539
+ ...cardPrefixed(
540
+ report.debtFindings.length > 0 ? report.debtFindings : ["No debt findings declared."],
541
+ "△",
542
+ ),
543
+ "│ │",
544
+ cardText("debt decision"),
545
+ cardText(report.debtDecision),
546
+ "│ │",
547
+ cardText("defer reason"),
548
+ ...cardWrapped(report.deferReason || "none"),
549
+ "│ │",
550
+ cardText("revisit trigger"),
551
+ ...cardWrapped(report.revisitTrigger || "none"),
552
+ "│ │",
553
+ cardText("missing decision"),
554
+ ...cardPrefixed(blocked ? report.missingDecision : ["none"], blocked ? "✕" : "✓"),
555
+ "│ │",
556
+ cardText("debt review contract"),
557
+ ...cardPrefixed(report.debtReviewContract.rules, "✓"),
558
+ "│ │",
559
+ cardText("review artifact"),
560
+ ...recordRows(report.reviewArtifactPath, report.projectRoot, report.journey),
561
+ ...preservedNote(report.reviewArtifactOutcome),
562
+ "│ │",
563
+ cardText("boundary"),
564
+ ...cardWrapped(
565
+ blocked
566
+ ? "Do not move past Debt Review until the Navigator debt decision is resolved."
567
+ : "Debt Review is complete; Builder may proceed to Done.",
568
+ ),
569
+ "╰────────────────────────────────────────────────────────╯",
570
+ ].join("\n")}\n`;
571
+ return wrapAriadSurface("debt_review_checkpoint", body);
572
+ }
573
+
574
+ // --- Coherence -------------------------------------------------------------
575
+
576
+ export interface BuilderCoherenceReport {
577
+ readonly journey: string;
578
+ readonly method: string;
579
+ readonly activeItem: string;
580
+ readonly activeItemTitle: string | null;
581
+ readonly processAlignment: string;
582
+ readonly projectAlignment: string;
583
+ readonly productAlignment: string;
584
+ readonly localDifferences: readonly string[];
585
+ readonly missingCoherence: readonly string[];
586
+ readonly coherenceContract: ContractDefinition;
587
+ readonly cursor: BuilderDeliveryCursor;
588
+ readonly coherenceArtifactPath: string | null;
589
+ /** The project the record was written under: the card names it relative (CR082). */
590
+ readonly projectRoot: string | null;
591
+ /** What the writer did with the record (CR079); absent when there is no artifact path. */
592
+ readonly coherenceArtifactOutcome?: ArtifactOutcome | null;
593
+ readonly nextEvent: string;
594
+ }
595
+
596
+ export interface CoherenceOptions {
597
+ readonly journey: string;
598
+ readonly method: MethodDefinition;
599
+ readonly processAlignment?: string | null;
600
+ readonly projectAlignment?: string | null;
601
+ readonly productAlignment?: string | null;
602
+ readonly localDifferences?: readonly string[];
603
+ readonly coherenceArtifactPath?: string | null;
604
+ /** The project the artifact must stay inside (CR079). */
605
+ readonly projectRoot?: string | null;
606
+ }
607
+
608
+ /** Python `coherence_lifecycle_item`. */
609
+ export function coherenceLifecycleItem(
610
+ db: WritableDatabase,
611
+ options: CoherenceOptions,
612
+ deps: CursorWriteDeps,
613
+ ): BuilderCoherenceReport {
614
+ const journey = normalizeRequired(options.journey, "journey");
615
+ const existing = getDeliveryCursor(db, journey);
616
+ if (existing === null) throw new Error("delivery cursor is required before coherence");
617
+ if (!existing.activeItem) throw new Error("active item is required before coherence");
618
+ refuseIfAlreadyComplete("coherence", existing);
619
+
620
+ const reentering =
621
+ existing.pendingConfirmation === "navigator_coherence" &&
622
+ existing.lastDeliveryEvent === "coherence";
623
+ if (existing.pendingConfirmation && !reentering) {
624
+ throw new LifecycleRefusal(
625
+ "coherence",
626
+ "pending_confirmation",
627
+ `Coherence is blocked: pending confirmation ${existing.pendingConfirmation}.`,
628
+ );
629
+ }
630
+ if (existing.lastDeliveryEvent !== "review_complete" && !reentering) {
631
+ throw new LifecycleRefusal(
632
+ "coherence",
633
+ "not_reached",
634
+ "Coherence requires completed Debt Review",
635
+ );
636
+ }
637
+
638
+ const process = textOr(
639
+ options.processAlignment,
640
+ "Process evidence is aligned with the Ariad lifecycle.",
641
+ );
642
+ const project = textOr(
643
+ options.projectAlignment,
644
+ "Project docs and artifacts reflect the validated change.",
645
+ );
646
+ const product = textOr(
647
+ options.productAlignment,
648
+ "Product behavior matches the accepted validation evidence.",
649
+ );
650
+ const differences = normalizedList(options.localDifferences ?? []);
651
+ // Python `_coherence_missing`: a blank string defaults ABOVE, so the only way to
652
+ // reach these is an argument that was whitespace before the default could apply.
653
+ const missing: string[] = [];
654
+ if (!pyStrip(process)) missing.push("process alignment is missing");
655
+ if (!pyStrip(project)) missing.push("project alignment is missing");
656
+ if (!pyStrip(product)) missing.push("product alignment is missing");
657
+
658
+ const cursor = setDeliveryCursor(
659
+ db,
660
+ {
661
+ journey,
662
+ method: options.method.id,
663
+ activeItem: existing.activeItem,
664
+ activeItemTitle: existing.activeItemTitle,
665
+ activeItemLevel: existing.activeItemLevel,
666
+ activeCheckpoint: missing.length > 0 ? "coherence" : null,
667
+ pendingConfirmation: missing.length > 0 ? "navigator_coherence" : null,
668
+ lastDeliveryEvent: missing.length > 0 ? "coherence" : "coherence_complete",
669
+ cadenceProfile: existing.cadenceProfile,
670
+ cadenceLimits: existing.cadenceLimits,
671
+ granularityDecision: existing.granularityDecision,
672
+ navigatorFlowUnit: existing.navigatorFlowUnit,
673
+ childWorkItems: existing.childWorkItems,
674
+ aggregateCheckpointStatus: existing.aggregateCheckpointStatus,
675
+ },
676
+ deps,
677
+ );
678
+
679
+ const report: BuilderCoherenceReport = {
680
+ journey,
681
+ method: options.method.id,
682
+ activeItem: existing.activeItem,
683
+ activeItemTitle: existing.activeItemTitle,
684
+ processAlignment: process,
685
+ projectAlignment: project,
686
+ productAlignment: product,
687
+ localDifferences: differences,
688
+ missingCoherence: missing,
689
+ coherenceContract: contractFor(options.method, "coherence_contract"),
690
+ cursor,
691
+ coherenceArtifactPath: options.coherenceArtifactPath ?? null,
692
+ projectRoot: options.projectRoot ?? null,
693
+ nextEvent: "done",
694
+ };
695
+ if (report.coherenceArtifactPath === null) return report;
696
+ const coherenceArtifactOutcome = writeClosureArtifact(
697
+ report.coherenceArtifactPath,
698
+ renderCoherenceArtifact(report),
699
+ options.projectRoot,
700
+ );
701
+ return { ...report, coherenceArtifactOutcome };
702
+ }
703
+
704
+ /** Python `render_coherence_checkpoint`: note the ribbon says `done`, not `coherence`. */
705
+ export function renderCoherenceCheckpoint(report: BuilderCoherenceReport): string {
706
+ const blocked = report.missingCoherence.length > 0;
707
+ const body = `${[
708
+ "Delivery",
709
+ renderLifecycleRibbon("done", report.cursor.activeItemLevel),
710
+ "",
711
+ "╭────────────────────────────────────────────────────────╮",
712
+ "│ ◉■ COHERENCE CHECKPOINT │",
713
+ "│ │",
714
+ cardText("active item"),
715
+ cardText(report.activeItem),
716
+ "│ │",
717
+ cardText("status"),
718
+ cardText(blocked ? "pending_coherence" : "coherent"),
719
+ "│ │",
720
+ cardText("process alignment"),
721
+ ...cardWrapped(report.processAlignment),
722
+ "│ │",
723
+ cardText("project alignment"),
724
+ ...cardWrapped(report.projectAlignment),
725
+ "│ │",
726
+ cardText("product alignment"),
727
+ ...cardWrapped(report.productAlignment),
728
+ "│ │",
729
+ cardText("local guide differences"),
730
+ ...cardPrefixed(report.localDifferences.length > 0 ? report.localDifferences : ["none"], "△"),
731
+ "│ │",
732
+ cardText("missing coherence"),
733
+ ...cardPrefixed(blocked ? report.missingCoherence : ["none"], blocked ? "✕" : "✓"),
734
+ "│ │",
735
+ cardText("coherence contract"),
736
+ ...cardPrefixed(report.coherenceContract.rules, "✓"),
737
+ "│ │",
738
+ cardText("coherence artifact"),
739
+ ...recordRows(report.coherenceArtifactPath, report.projectRoot, report.journey),
740
+ ...preservedNote(report.coherenceArtifactOutcome),
741
+ "│ │",
742
+ cardText("boundary"),
743
+ ...cardWrapped(
744
+ blocked
745
+ ? "Do not move to Done until coherence gaps are resolved."
746
+ : "Coherence is complete; Builder may proceed to Done.",
747
+ ),
748
+ "╰────────────────────────────────────────────────────────╯",
749
+ ].join("\n")}\n`;
750
+ return wrapAriadSurface("coherence_checkpoint", body);
751
+ }
752
+
753
+ // --- Done ------------------------------------------------------------------
754
+
755
+ export interface BuilderDoneReport {
756
+ readonly journey: string;
757
+ readonly method: string;
758
+ readonly activeItem: string;
759
+ readonly activeItemTitle: string | null;
760
+ readonly historyAction: string;
761
+ readonly roadmapUpdate: string;
762
+ readonly nextRecommendation: string;
763
+ readonly missingDone: readonly string[];
764
+ readonly doneContract: ContractDefinition;
765
+ readonly cursor: BuilderDeliveryCursor;
766
+ readonly doneArtifactPath: string | null;
767
+ /** The project the record was written under: the card names it relative (CR082). */
768
+ readonly projectRoot: string | null;
769
+ /** What the writer did with the record (CR079); absent when there is no artifact path. */
770
+ readonly doneArtifactOutcome?: ArtifactOutcome | null;
771
+ }
772
+
773
+ export interface DoneOptions {
774
+ readonly journey: string;
775
+ readonly method: MethodDefinition;
776
+ readonly historyAction?: string | null;
777
+ readonly roadmapUpdate?: string | null;
778
+ readonly nextRecommendation?: string | null;
779
+ readonly doneArtifactPath?: string | null;
780
+ /** The project the artifact must stay inside (CR079). */
781
+ readonly projectRoot?: string | null;
782
+ /**
783
+ * The story's `index.md` (CR112). Done refuses while its placeholder sections are
784
+ * still the scaffold's; `null` when there is no project, and no file to read.
785
+ * Required, not optional: `continue-lifecycle` once reached Done without it, and a
786
+ * story closed with its record still the scaffold (CR112's handoff review).
787
+ */
788
+ readonly indexArtifactPath: string | null;
789
+ }
790
+
791
+ /**
792
+ * CR112, decision D4: a story does not close while its own record still says what
793
+ * Expand or Plan wrote -- "I want to <title>". Only the placeholder headings the file
794
+ * has are judged, so an index in the Driver's own structure is never refused.
795
+ */
796
+ function refuseUnauthoredIndex(indexPath: string | null, projectRoot: string | null): void {
797
+ if (indexPath === null) return;
798
+ const verdict = artifactState("index.md", indexPath);
799
+ if (verdict.toAuthor.length === 0) return;
800
+ throw new LifecycleRefusal(
801
+ "done",
802
+ "missing_evidence",
803
+ `Done needs the story's own record. Still to author in ${displayPath(indexPath, projectRoot ?? null)}: ${verdict.toAuthor.join(", ")}.`,
804
+ );
805
+ }
806
+
807
+ /** Python `done_lifecycle_item`. */
808
+ export function doneLifecycleItem(
809
+ db: WritableDatabase,
810
+ options: DoneOptions,
811
+ deps: CursorWriteDeps,
812
+ ): BuilderDoneReport {
813
+ const journey = normalizeRequired(options.journey, "journey");
814
+ const existing = getDeliveryCursor(db, journey);
815
+ if (existing === null) throw new Error("delivery cursor is required before done");
816
+ if (!existing.activeItem) throw new Error("active item is required before done");
817
+ refuseIfAlreadyComplete("done", existing);
818
+ // No re-entry: Done refuses every pending confirmation, including the ones its own
819
+ // predecessors left behind.
820
+ if (existing.pendingConfirmation) {
821
+ throw new LifecycleRefusal(
822
+ "done",
823
+ "pending_confirmation",
824
+ `Done is blocked: pending confirmation ${existing.pendingConfirmation}.`,
825
+ );
826
+ }
827
+ // `review_complete` is accepted DIRECTLY: Coherence is an option, not a
828
+ // precondition. A port that requires `coherence_complete` blocks a legal closure.
829
+ if (
830
+ existing.lastDeliveryEvent !== "review_complete" &&
831
+ existing.lastDeliveryEvent !== "coherence_complete"
832
+ ) {
833
+ throw new LifecycleRefusal("done", "not_reached", "Done requires completed Debt Review");
834
+ }
835
+ refuseUnauthoredIndex(options.indexArtifactPath, options.projectRoot ?? null);
836
+
837
+ const history = textOr(
838
+ options.historyAction,
839
+ "History action recorded according to project policy.",
840
+ );
841
+ const roadmap = textOr(options.roadmapUpdate, "Roadmap/story package reflects the closed story.");
842
+ const nextStep = textOr(
843
+ options.nextRecommendation,
844
+ "Inspect pull candidates for the next Ariad movement.",
845
+ );
846
+ const missing: string[] = [];
847
+ if (!pyStrip(history)) missing.push("history action is missing");
848
+ if (!pyStrip(roadmap)) missing.push("roadmap update is missing");
849
+ if (!pyStrip(nextStep)) missing.push("next recommendation is missing");
850
+
851
+ const cursor = setDeliveryCursor(
852
+ db,
853
+ {
854
+ journey,
855
+ method: options.method.id,
856
+ activeItem: existing.activeItem,
857
+ activeItemTitle: existing.activeItemTitle,
858
+ activeItemLevel: existing.activeItemLevel,
859
+ activeCheckpoint: missing.length > 0 ? "done" : null,
860
+ pendingConfirmation: missing.length > 0 ? "navigator_done" : null,
861
+ lastDeliveryEvent: missing.length > 0 ? "done" : "done_complete",
862
+ cadenceProfile: existing.cadenceProfile,
863
+ cadenceLimits: existing.cadenceLimits,
864
+ granularityDecision: existing.granularityDecision,
865
+ navigatorFlowUnit: existing.navigatorFlowUnit,
866
+ childWorkItems: existing.childWorkItems,
867
+ aggregateCheckpointStatus: existing.aggregateCheckpointStatus,
868
+ },
869
+ deps,
870
+ );
871
+
872
+ const report: BuilderDoneReport = {
873
+ journey,
874
+ method: options.method.id,
875
+ activeItem: existing.activeItem,
876
+ activeItemTitle: existing.activeItemTitle,
877
+ historyAction: history,
878
+ roadmapUpdate: roadmap,
879
+ nextRecommendation: nextStep,
880
+ missingDone: missing,
881
+ doneContract: contractFor(options.method, "done_contract"),
882
+ cursor,
883
+ doneArtifactPath: options.doneArtifactPath ?? null,
884
+ projectRoot: options.projectRoot ?? null,
885
+ };
886
+ if (report.doneArtifactPath === null) return report;
887
+ const doneArtifactOutcome = writeClosureArtifact(
888
+ report.doneArtifactPath,
889
+ renderDoneArtifact(report),
890
+ options.projectRoot,
891
+ );
892
+ return { ...report, doneArtifactOutcome };
893
+ }
894
+
895
+ /** Python `render_done_checkpoint`. */
896
+ export function renderDoneCheckpoint(report: BuilderDoneReport): string {
897
+ const blocked = report.missingDone.length > 0;
898
+ const body = `${[
899
+ "Delivery",
900
+ renderLifecycleRibbon("done", report.cursor.activeItemLevel),
901
+ "",
902
+ "╭────────────────────────────────────────────────────────╮",
903
+ "│ 🟩■ DONE CHECKPOINT │",
904
+ "│ │",
905
+ cardText("active item"),
906
+ cardText(report.activeItem),
907
+ "│ │",
908
+ cardText("status"),
909
+ cardText(blocked ? "pending_done" : "done"),
910
+ "│ │",
911
+ cardText("history action"),
912
+ ...cardWrapped(report.historyAction),
913
+ "│ │",
914
+ cardText("roadmap update"),
915
+ ...cardWrapped(report.roadmapUpdate),
916
+ "│ │",
917
+ cardText("next recommendation"),
918
+ ...cardWrapped(report.nextRecommendation),
919
+ "│ │",
920
+ cardText("missing done"),
921
+ ...cardPrefixed(blocked ? report.missingDone : ["none"], blocked ? "✕" : "✓"),
922
+ "│ │",
923
+ cardText("done contract"),
924
+ ...cardPrefixed(report.doneContract.rules, "✓"),
925
+ "│ │",
926
+ cardText("done artifact"),
927
+ ...recordRows(report.doneArtifactPath, report.projectRoot, report.journey),
928
+ ...preservedNote(report.doneArtifactOutcome),
929
+ "│ │",
930
+ cardText("boundary"),
931
+ ...cardWrapped(
932
+ blocked
933
+ ? "Do not close the story until Done gaps are resolved."
934
+ : "Story closure is complete; Builder may recommend the next Pull.",
935
+ ),
936
+ "╰────────────────────────────────────────────────────────╯",
937
+ ].join("\n")}\n`;
938
+ return wrapAriadSurface("done_checkpoint", body);
939
+ }
940
+
941
+ /**
942
+ * A closure record's rows: the project and journey it was written for (CR009), then its
943
+ * path relative to that project (CR082), or `not materialized` when the journey has no
944
+ * project, and nothing was written.
945
+ */
946
+ function recordRows(path: string | null, projectRoot: string | null, journey: string): string[] {
947
+ if (path === null) return cardWrapped("not materialized");
948
+ const target = projectRoot === null ? [] : cardWrapped(targetLine(projectRoot, journey));
949
+ return [...target, ...cardWrapped(displayPath(path, projectRoot))];
950
+ }
951
+
952
+ /**
953
+ * CR079: said only when a closure record was preserved rather than written, the
954
+ * one case a reader cannot assume. Created and updated records hold this
955
+ * checkpoint's fields, as they always have.
956
+ */
957
+ function preservedNote(outcome: ArtifactOutcome | null | undefined): string[] {
958
+ return outcome === "preserved"
959
+ ? cardWrapped(
960
+ "preserved as it is: Ariad did not write this file, or it was edited since. " +
961
+ "This checkpoint's fields are shown here, not written to it.",
962
+ )
963
+ : [];
964
+ }