@herbertgao/pi-extensions 2026.9.19 → 2026.10.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 (444) hide show
  1. package/README.md +14 -16
  2. package/THIRD_PARTY_NOTICES.md +29 -3
  3. package/node_modules/@herbertgao/pi-bark/README.md +39 -3
  4. package/node_modules/@herbertgao/pi-bark/package.json +1 -1
  5. package/node_modules/@herbertgao/pi-bark/src/index.ts +275 -15
  6. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +85 -68
  7. package/node_modules/@herbertgao/pi-cc-extensions/README.md +79 -62
  8. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/preview.webp +0 -0
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +116 -34
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +370 -118
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +6 -36
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/index.ts +2 -2
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +31 -33
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +330 -360
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/index.ts +56 -108
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/session.ts +97 -15
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/reference/subagent.ts +80 -45
  18. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/flush-docked-bash.ts +36 -0
  19. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer-layout.ts +229 -0
  20. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/footer.ts +521 -0
  21. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/mcp-chip.ts +136 -0
  22. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/startup-header.ts +92 -61
  23. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/working-message.ts +58 -38
  24. package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +19 -3
  25. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +1127 -231
  26. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +267 -262
  27. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +38 -48
  28. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +8 -2
  29. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +2 -7
  30. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +287 -114
  31. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +15 -6
  32. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +18 -72
  33. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +61 -26
  34. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/codemode.ts +303 -0
  35. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/ansi-utils.ts +25 -57
  36. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-component.ts +125 -0
  37. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-edit-render.ts +227 -0
  38. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-header.ts +136 -0
  39. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-highlight.ts +151 -0
  40. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-inline.ts +324 -0
  41. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-layout.ts +762 -0
  42. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-limits.ts +152 -0
  43. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-palette.ts +410 -0
  44. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-parse.ts +535 -0
  45. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-presentation.ts +4 -4
  46. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +21 -3219
  47. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-text.ts +44 -0
  48. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-write-render.ts +568 -0
  49. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/index.ts +103 -48
  50. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/line-width-safety.ts +8 -7
  51. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-execution.ts +2 -1
  52. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +171 -196
  53. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/mcp-title.ts +39 -0
  54. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{message-display.ts → tool/message-display.ts} +27 -93
  55. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/names.ts +429 -0
  56. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +259 -164
  57. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/{show-more-hint.ts → tool/show-more-hint.ts} +10 -0
  58. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/transcript-refresh.ts +8 -26
  59. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-color.ts +44 -0
  60. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/ansi-text.ts +77 -0
  61. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/component-tree.ts +34 -0
  62. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/format.ts +28 -0
  63. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/fullscreen-detect.ts +51 -0
  64. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/patch-keys.ts +124 -0
  65. package/node_modules/@herbertgao/pi-cc-extensions/extensions/utils/sgr-mouse.ts +70 -0
  66. package/node_modules/@herbertgao/pi-cc-extensions/package.json +10 -8
  67. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  68. package/node_modules/@herbertgao/pi-subagents/package.json +1 -1
  69. package/node_modules/@herbertgao/pi-subagents/src/mention-clone.ts +3 -2
  70. package/node_modules/@herbertgao/sol-pi/CONTRIBUTING.md +22 -0
  71. package/node_modules/@herbertgao/sol-pi/README.md +36 -17
  72. package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +10 -6
  73. package/node_modules/@herbertgao/sol-pi/agents-install.md +15 -12
  74. package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +24 -8
  75. package/node_modules/@herbertgao/sol-pi/docs/configuration.md +2 -2
  76. package/node_modules/@herbertgao/sol-pi/docs/star-history.md +18 -0
  77. package/node_modules/@herbertgao/sol-pi/package.json +4 -2
  78. package/node_modules/@herbertgao/sol-pi/scripts/check-sol-pi-config.mjs +1 -1
  79. package/node_modules/@herbertgao/sol-pi/src/sol-pi/config.ts +1 -1
  80. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/file-queue.ts +23 -4
  81. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +32 -1
  82. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/then-run.ts +3 -2
  83. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/observation.ts +1 -1
  84. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +27 -7
  85. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +137 -41
  86. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/index.ts +1 -0
  87. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/plan.ts +2 -1
  88. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/projection.ts +58 -0
  89. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +28 -6
  90. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/tools.ts +2 -1
  91. package/node_modules/@herbertgao/sol-pi/src/sol-pi/runtime-paths.ts +15 -2
  92. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  93. package/node_modules/@pi-plugins/fast-mode/README.md +7 -1
  94. package/node_modules/@pi-plugins/fast-mode/dist/index.d.mts.map +1 -1
  95. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +7 -1
  96. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  97. package/node_modules/@pi-plugins/fast-mode/package.json +5 -5
  98. package/node_modules/pi-antigravity/README.md +3 -0
  99. package/node_modules/pi-antigravity/package.json +8 -8
  100. package/node_modules/pi-antigravity/src/auth/oauth.ts +6 -3
  101. package/node_modules/pi-antigravity/src/index.ts +114 -110
  102. package/node_modules/pi-antigravity/src/stream/stream.ts +1 -1
  103. package/node_modules/pi-antigravity/src/utils/util.ts +18 -1
  104. package/node_modules/pi-multi-account/CHANGELOG.md +20 -0
  105. package/node_modules/pi-multi-account/README.md +46 -8
  106. package/node_modules/pi-multi-account/config-file-transaction.ts +42 -0
  107. package/node_modules/pi-multi-account/index.ts +255 -269
  108. package/node_modules/pi-multi-account/model-pins.ts +36 -0
  109. package/node_modules/pi-multi-account/package.json +9 -7
  110. package/node_modules/pi-multi-account/slot-proxy-auth.ts +12 -2
  111. package/node_modules/pi-multi-account/slot-proxy.ts +27 -5
  112. package/node_modules/pi-web-access/CHANGELOG.md +17 -0
  113. package/node_modules/pi-web-access/README.md +6 -3
  114. package/node_modules/pi-web-access/brave-rate-limit.ts +170 -0
  115. package/node_modules/pi-web-access/brave.ts +28 -11
  116. package/node_modules/pi-web-access/dist/index.js +202 -33
  117. package/node_modules/pi-web-access/gemini-search.ts +2 -5
  118. package/node_modules/pi-web-access/index.ts +13 -7
  119. package/node_modules/pi-web-access/openai-search.ts +24 -10
  120. package/node_modules/pi-web-access/package.json +1 -1
  121. package/node_modules/pi-web-access/summary-review.ts +8 -2
  122. package/node_modules/{@herbertgao/resume-from → resume-from}/README.md +16 -12
  123. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/adapter.d.ts +0 -5
  124. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/adapter.js +2 -3
  125. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/contract.d.ts +2 -2
  126. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/reader.d.ts +3 -0
  127. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/reader.js +27 -15
  128. package/node_modules/{@herbertgao/resume-from/dist/adapters/codex → resume-from/dist/adapters/claude-code}/redaction.js +16 -3
  129. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/writer.d.ts +2 -4
  130. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/writer.js +1 -1
  131. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/contract.d.ts +2 -4
  132. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/index.js +1 -2
  133. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/read.d.ts +16 -0
  134. package/node_modules/resume-from/dist/adapters/codex/read.js +723 -0
  135. package/node_modules/{@herbertgao/resume-from/dist/adapters/pi → resume-from/dist/adapters/codex}/redaction.js +16 -3
  136. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/rollout.d.ts +44 -4
  137. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/rollout.js +88 -4
  138. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/write.d.ts +2 -2
  139. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/write.js +2 -2
  140. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/contract.d.ts +5 -1
  141. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/adapter.js +10 -6
  142. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/contract.d.ts +2 -2
  143. package/node_modules/{@herbertgao/resume-from/dist/adapters/claude-code → resume-from/dist/adapters/pi}/redaction.js +16 -3
  144. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/serialize.d.ts +2 -4
  145. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/serialize.js +2 -2
  146. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/render.d.ts +1 -1
  147. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/render.js +4 -4
  148. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/runner.js +2 -2
  149. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/contract.d.ts +2 -2
  150. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/command.js +31 -8
  151. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/wiring.d.ts +1 -1
  152. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/wiring.js +1 -2
  153. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/confirmation.d.ts +4 -1
  154. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/confirmation.js +2 -2
  155. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/contract.d.ts +8 -6
  156. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/contract.d.ts +10 -5
  157. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/finder.d.ts +2 -1
  158. package/node_modules/resume-from/dist/import/discovery/finder.js +269 -0
  159. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/contract.d.ts +3 -3
  160. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/lander.js +3 -3
  161. package/node_modules/resume-from/dist/import/pipeline.d.ts +28 -0
  162. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/pipeline.js +31 -11
  163. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/builder.d.ts +2 -2
  164. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/builder.js +9 -5
  165. package/node_modules/resume-from/dist/import/preview/warnings.d.ts +14 -0
  166. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/warnings.js +26 -20
  167. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/wiring.js +12 -2
  168. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/contract.d.ts +9 -3
  169. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/git.d.ts +4 -4
  170. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/git.js +7 -4
  171. package/node_modules/resume-from/dist/platform/repo/reader.d.ts +3 -0
  172. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/reader.js +60 -20
  173. package/node_modules/{@herbertgao/resume-from → resume-from}/dist/session/contract.d.ts +8 -1
  174. package/node_modules/{@herbertgao/resume-from → resume-from}/package.json +19 -32
  175. package/node_modules/{@herbertgao/resume-from → resume-from}/shims/pi/extensions/resume-from.js +2 -2
  176. package/package.json +18 -22
  177. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.en.svg +0 -101
  178. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/hero.svg +0 -101
  179. package/node_modules/@herbertgao/pi-cc-extensions/assets/readme/welcome.webp +0 -0
  180. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/render-utils.ts +0 -5
  181. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +0 -30
  182. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/write-display-utils.ts +0 -12
  183. package/node_modules/@herbertgao/resume-from/dist/adapters/codex/read.js +0 -270
  184. package/node_modules/@herbertgao/resume-from/dist/import/discovery/finder.js +0 -129
  185. package/node_modules/@herbertgao/resume-from/dist/import/pipeline.d.ts +0 -17
  186. package/node_modules/@herbertgao/resume-from/dist/import/preview/warnings.d.ts +0 -11
  187. package/node_modules/@herbertgao/resume-from/dist/platform/repo/reader.d.ts +0 -8
  188. package/node_modules/pi-footer/CHANGELOG.md +0 -145
  189. package/node_modules/pi-footer/LICENSE +0 -21
  190. package/node_modules/pi-footer/README.md +0 -354
  191. package/node_modules/pi-footer/package.json +0 -68
  192. package/node_modules/pi-footer/src/cache.ts +0 -106
  193. package/node_modules/pi-footer/src/colors.ts +0 -237
  194. package/node_modules/pi-footer/src/config.ts +0 -202
  195. package/node_modules/pi-footer/src/event-widgets.ts +0 -41
  196. package/node_modules/pi-footer/src/extension-statuses.ts +0 -102
  197. package/node_modules/pi-footer/src/git.ts +0 -135
  198. package/node_modules/pi-footer/src/index.ts +0 -268
  199. package/node_modules/pi-footer/src/metrics.ts +0 -141
  200. package/node_modules/pi-footer/src/presets.ts +0 -383
  201. package/node_modules/pi-footer/src/render.ts +0 -114
  202. package/node_modules/pi-footer/src/separators.ts +0 -52
  203. package/node_modules/pi-footer/src/types.ts +0 -122
  204. package/node_modules/pi-footer/src/ui/color-level-confirm.ts +0 -22
  205. package/node_modules/pi-footer/src/ui/color-options.ts +0 -195
  206. package/node_modules/pi-footer/src/ui/config-lifecycle.ts +0 -61
  207. package/node_modules/pi-footer/src/ui/edit-colors.ts +0 -13
  208. package/node_modules/pi-footer/src/ui/events.ts +0 -35
  209. package/node_modules/pi-footer/src/ui/extension-status-picker.ts +0 -60
  210. package/node_modules/pi-footer/src/ui/extension-statuses.ts +0 -73
  211. package/node_modules/pi-footer/src/ui/fields.ts +0 -252
  212. package/node_modules/pi-footer/src/ui/global-menu.ts +0 -126
  213. package/node_modules/pi-footer/src/ui/helpers.ts +0 -44
  214. package/node_modules/pi-footer/src/ui/layout.ts +0 -17
  215. package/node_modules/pi-footer/src/ui/line-list.ts +0 -19
  216. package/node_modules/pi-footer/src/ui/model.ts +0 -64
  217. package/node_modules/pi-footer/src/ui/navigation.ts +0 -29
  218. package/node_modules/pi-footer/src/ui/option-edit.ts +0 -93
  219. package/node_modules/pi-footer/src/ui/overlay-render.ts +0 -103
  220. package/node_modules/pi-footer/src/ui/screen-context.ts +0 -18
  221. package/node_modules/pi-footer/src/ui/screen-controller.ts +0 -27
  222. package/node_modules/pi-footer/src/ui/screen-render.ts +0 -32
  223. package/node_modules/pi-footer/src/ui/screen-state.ts +0 -20
  224. package/node_modules/pi-footer/src/ui/screen.ts +0 -243
  225. package/node_modules/pi-footer/src/ui/screens/add-widget.ts +0 -92
  226. package/node_modules/pi-footer/src/ui/screens/confirm-exit.ts +0 -52
  227. package/node_modules/pi-footer/src/ui/screens/controller.ts +0 -12
  228. package/node_modules/pi-footer/src/ui/screens/edit-colors.ts +0 -68
  229. package/node_modules/pi-footer/src/ui/screens/edit-widget.ts +0 -115
  230. package/node_modules/pi-footer/src/ui/screens/extension-status-row.ts +0 -61
  231. package/node_modules/pi-footer/src/ui/screens/global.ts +0 -75
  232. package/node_modules/pi-footer/src/ui/screens/line-list.ts +0 -108
  233. package/node_modules/pi-footer/src/ui/screens/main.ts +0 -99
  234. package/node_modules/pi-footer/src/ui/screens/terminal.ts +0 -121
  235. package/node_modules/pi-footer/src/ui/screens/widget-list.ts +0 -154
  236. package/node_modules/pi-footer/src/ui/terminal-menu.ts +0 -32
  237. package/node_modules/pi-footer/src/ui/theme.ts +0 -48
  238. package/node_modules/pi-footer/src/ui/title-bar.ts +0 -100
  239. package/node_modules/pi-footer/src/ui/widget-actions.ts +0 -76
  240. package/node_modules/pi-footer/src/ui.ts +0 -66
  241. package/node_modules/pi-footer/src/widgets/context.ts +0 -28
  242. package/node_modules/pi-footer/src/widgets/core/active-tools.ts +0 -17
  243. package/node_modules/pi-footer/src/widgets/core/context-window.ts +0 -24
  244. package/node_modules/pi-footer/src/widgets/core/cwd-basename.ts +0 -19
  245. package/node_modules/pi-footer/src/widgets/core/cwd.ts +0 -108
  246. package/node_modules/pi-footer/src/widgets/core/event.ts +0 -34
  247. package/node_modules/pi-footer/src/widgets/core/external-status.ts +0 -102
  248. package/node_modules/pi-footer/src/widgets/core/model-provider.ts +0 -20
  249. package/node_modules/pi-footer/src/widgets/core/model.ts +0 -35
  250. package/node_modules/pi-footer/src/widgets/core/provider.ts +0 -17
  251. package/node_modules/pi-footer/src/widgets/core/session-name.ts +0 -17
  252. package/node_modules/pi-footer/src/widgets/core/text-verbosity.ts +0 -17
  253. package/node_modules/pi-footer/src/widgets/core/thinking-level.ts +0 -17
  254. package/node_modules/pi-footer/src/widgets/git/ahead-behind.ts +0 -17
  255. package/node_modules/pi-footer/src/widgets/git/branch.ts +0 -81
  256. package/node_modules/pi-footer/src/widgets/git/clean.ts +0 -19
  257. package/node_modules/pi-footer/src/widgets/git/deletions.ts +0 -17
  258. package/node_modules/pi-footer/src/widgets/git/diff.ts +0 -38
  259. package/node_modules/pi-footer/src/widgets/git/insertions.ts +0 -17
  260. package/node_modules/pi-footer/src/widgets/git/remote.ts +0 -17
  261. package/node_modules/pi-footer/src/widgets/git/root.ts +0 -17
  262. package/node_modules/pi-footer/src/widgets/git/sha.ts +0 -17
  263. package/node_modules/pi-footer/src/widgets/git/staged.ts +0 -17
  264. package/node_modules/pi-footer/src/widgets/git/status.ts +0 -19
  265. package/node_modules/pi-footer/src/widgets/git/unstaged.ts +0 -17
  266. package/node_modules/pi-footer/src/widgets/git/untracked.ts +0 -17
  267. package/node_modules/pi-footer/src/widgets/instance.ts +0 -118
  268. package/node_modules/pi-footer/src/widgets/layout/custom-text.ts +0 -18
  269. package/node_modules/pi-footer/src/widgets/layout/flex-separator.ts +0 -32
  270. package/node_modules/pi-footer/src/widgets/layout/separator.ts +0 -57
  271. package/node_modules/pi-footer/src/widgets/layout/spacer.ts +0 -31
  272. package/node_modules/pi-footer/src/widgets/options.ts +0 -122
  273. package/node_modules/pi-footer/src/widgets/project/runtime.ts +0 -361
  274. package/node_modules/pi-footer/src/widgets/registry.ts +0 -223
  275. package/node_modules/pi-footer/src/widgets/session/assistant-messages.ts +0 -17
  276. package/node_modules/pi-footer/src/widgets/session/compactions.ts +0 -17
  277. package/node_modules/pi-footer/src/widgets/session/elapsed.ts +0 -18
  278. package/node_modules/pi-footer/src/widgets/session/last-activity.ts +0 -18
  279. package/node_modules/pi-footer/src/widgets/session/messages.ts +0 -19
  280. package/node_modules/pi-footer/src/widgets/session/session-id.ts +0 -17
  281. package/node_modules/pi-footer/src/widgets/session/session-start.ts +0 -18
  282. package/node_modules/pi-footer/src/widgets/session/tool-results.ts +0 -17
  283. package/node_modules/pi-footer/src/widgets/session/total-messages.ts +0 -19
  284. package/node_modules/pi-footer/src/widgets/session/total-time.ts +0 -18
  285. package/node_modules/pi-footer/src/widgets/session/user-messages.ts +0 -17
  286. package/node_modules/pi-footer/src/widgets/store.ts +0 -26
  287. package/node_modules/pi-footer/src/widgets/tokens/cache-hit-rate.ts +0 -55
  288. package/node_modules/pi-footer/src/widgets/tokens/cache-read.ts +0 -18
  289. package/node_modules/pi-footer/src/widgets/tokens/cache-write.ts +0 -18
  290. package/node_modules/pi-footer/src/widgets/tokens/context-bar.ts +0 -108
  291. package/node_modules/pi-footer/src/widgets/tokens/context-length.ts +0 -26
  292. package/node_modules/pi-footer/src/widgets/tokens/context-remaining.ts +0 -29
  293. package/node_modules/pi-footer/src/widgets/tokens/context.ts +0 -29
  294. package/node_modules/pi-footer/src/widgets/tokens/cost.ts +0 -51
  295. package/node_modules/pi-footer/src/widgets/tokens/input-speed.ts +0 -25
  296. package/node_modules/pi-footer/src/widgets/tokens/input-tokens.ts +0 -18
  297. package/node_modules/pi-footer/src/widgets/tokens/output-speed.ts +0 -25
  298. package/node_modules/pi-footer/src/widgets/tokens/output-tokens.ts +0 -18
  299. package/node_modules/pi-footer/src/widgets/tokens/tokens.ts +0 -20
  300. package/node_modules/pi-footer/src/widgets/tokens/total-speed.ts +0 -25
  301. package/node_modules/pi-footer/src/widgets/tokens/total-tokens.ts +0 -18
  302. package/node_modules/pi-footer/src/widgets/types.ts +0 -181
  303. package/node_modules/pi-footer/src/widgets/utils/colors.ts +0 -11
  304. package/node_modules/pi-footer/src/widgets/utils/context.ts +0 -112
  305. package/node_modules/pi-footer/src/widgets/utils/session.ts +0 -19
  306. package/node_modules/pi-footer/src/widgets/utils/token-format.ts +0 -78
  307. /package/node_modules/{@herbertgao/resume-from → resume-from}/LICENSE +0 -0
  308. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/contract.js +0 -0
  309. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/entries.d.ts +0 -0
  310. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/entries.js +0 -0
  311. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/index.d.ts +0 -0
  312. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/index.js +0 -0
  313. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/layout.d.ts +0 -0
  314. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/layout.js +0 -0
  315. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/readback.d.ts +0 -0
  316. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/readback.js +0 -0
  317. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/redaction.d.ts +0 -0
  318. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/validation.d.ts +0 -0
  319. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/claude-code/validation.js +0 -0
  320. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/contract.js +0 -0
  321. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/index.d.ts +0 -0
  322. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/readback.d.ts +0 -0
  323. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/readback.js +0 -0
  324. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/redaction.d.ts +0 -0
  325. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/validation.d.ts +0 -0
  326. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/codex/validation.js +0 -0
  327. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/contract.js +0 -0
  328. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/adapter.d.ts +0 -0
  329. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/contract.js +0 -0
  330. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/format.d.ts +0 -0
  331. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/format.js +0 -0
  332. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/index.d.ts +0 -0
  333. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/index.js +0 -0
  334. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/parse.d.ts +0 -0
  335. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/parse.js +0 -0
  336. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/redaction.d.ts +0 -0
  337. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/validate.d.ts +0 -0
  338. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/adapters/pi/validate.js +0 -0
  339. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/bin.d.ts +0 -0
  340. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/bin.js +0 -0
  341. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/contract.d.ts +0 -0
  342. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/contract.js +0 -0
  343. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/agents.d.ts +0 -0
  344. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/agents.js +0 -0
  345. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/args.d.ts +0 -0
  346. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/args.js +0 -0
  347. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/contract.d.ts +0 -0
  348. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/contract.js +0 -0
  349. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/index.d.ts +0 -0
  350. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/index.js +0 -0
  351. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/presentation.d.ts +0 -0
  352. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/presentation.js +0 -0
  353. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/cli/runner.d.ts +0 -0
  354. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/contract.js +0 -0
  355. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/entry.d.ts +0 -0
  356. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/entry.js +0 -0
  357. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/index.d.ts +0 -0
  358. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/index.js +0 -0
  359. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/command.d.ts +0 -0
  360. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/contract.d.ts +0 -0
  361. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/contract.js +0 -0
  362. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/index.d.ts +0 -0
  363. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/index.js +0 -0
  364. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/picker.d.ts +0 -0
  365. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/picker.js +0 -0
  366. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/presentation.d.ts +0 -0
  367. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/presentation.js +0 -0
  368. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/register.d.ts +0 -0
  369. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/register.js +0 -0
  370. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/ui.d.ts +0 -0
  371. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/pi-extension/ui.js +0 -0
  372. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/profile.d.ts +0 -0
  373. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/profile.js +0 -0
  374. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/registry.d.ts +0 -0
  375. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/host/registry.js +0 -0
  376. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/contract.js +0 -0
  377. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/contract.js +0 -0
  378. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/errors.d.ts +0 -0
  379. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/errors.js +0 -0
  380. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/homes.d.ts +0 -0
  381. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/homes.js +0 -0
  382. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/index.d.ts +0 -0
  383. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/index.js +0 -0
  384. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/ordering.d.ts +0 -0
  385. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/discovery/ordering.js +0 -0
  386. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/errors.d.ts +0 -0
  387. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/errors.js +0 -0
  388. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/index.d.ts +0 -0
  389. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/index.js +0 -0
  390. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/contract.js +0 -0
  391. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/errors.d.ts +0 -0
  392. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/errors.js +0 -0
  393. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/handover.d.ts +0 -0
  394. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/handover.js +0 -0
  395. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/index.d.ts +0 -0
  396. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/index.js +0 -0
  397. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/lander.d.ts +0 -0
  398. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/marker.d.ts +0 -0
  399. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/landing/marker.js +0 -0
  400. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/contract.d.ts +0 -0
  401. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/contract.js +0 -0
  402. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/format.d.ts +0 -0
  403. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/format.js +0 -0
  404. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/index.d.ts +0 -0
  405. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/preview/index.js +0 -0
  406. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/contract.d.ts +0 -0
  407. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/contract.js +0 -0
  408. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/index.d.ts +0 -0
  409. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/index.js +0 -0
  410. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/rules.d.ts +0 -0
  411. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/transfer/rules.js +0 -0
  412. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/import/wiring.d.ts +0 -0
  413. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/index.d.ts +0 -0
  414. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/index.js +0 -0
  415. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/contract.d.ts +0 -0
  416. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/contract.js +0 -0
  417. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/defaults.d.ts +0 -0
  418. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/defaults.js +0 -0
  419. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/errors.d.ts +0 -0
  420. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/errors.js +0 -0
  421. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/index.d.ts +0 -0
  422. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/index.js +0 -0
  423. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/loader.d.ts +0 -0
  424. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/loader.js +0 -0
  425. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/paths.d.ts +0 -0
  426. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/paths.js +0 -0
  427. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/validate.d.ts +0 -0
  428. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/config/validate.js +0 -0
  429. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/contract.js +0 -0
  430. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/index.d.ts +0 -0
  431. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/repo/index.js +0 -0
  432. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/contract.d.ts +0 -0
  433. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/contract.js +0 -0
  434. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/file-committer.d.ts +0 -0
  435. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/file-committer.js +0 -0
  436. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/index.d.ts +0 -0
  437. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/store/index.js +0 -0
  438. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/contract.d.ts +0 -0
  439. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/contract.js +0 -0
  440. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/estimator.d.ts +0 -0
  441. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/estimator.js +0 -0
  442. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/index.d.ts +0 -0
  443. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/platform/tokens/index.js +0 -0
  444. /package/node_modules/{@herbertgao/resume-from → resume-from}/dist/session/contract.js +0 -0
@@ -33,26 +33,31 @@ export interface SelectionError {
33
33
  /** What failed, and what the user can do next. */
34
34
  message: string;
35
35
  }
36
- /** One home that could not be searched. The listing continues without it. */
36
+ /** One home or session that could not be included. The listing continues without it. */
37
37
  export interface HomeFailure {
38
38
  home: HomePath;
39
39
  agent: AgentId;
40
- /** Why the home was skipped, in one line. */
40
+ /** Why the home or session was skipped, in one line. */
41
41
  message: string;
42
42
  }
43
43
  /** What a listing produced, including what it could not read. */
44
44
  export interface Listing {
45
45
  /** Newest first, across every agent and home (FR-14, FR-15). */
46
46
  rows: SessionDescriptor[];
47
- /** Homes that were skipped. Reported to the user, never silent. */
47
+ /** Homes or sessions that were skipped. Reported to the user, never silent. */
48
48
  failures: HomeFailure[];
49
49
  }
50
+ /** Fresh destination facts resolved by the caller for this listing only. */
51
+ export interface DiscoveryDestination {
52
+ canonicalCwd: string;
53
+ identity: RepoIdentity;
54
+ }
50
55
  /** Finds, filters, orders and loads source sessions. It never writes. */
51
56
  export interface SessionFinder {
52
57
  /** Newest first (FR-14), only sessions of the current repository (FR-13). */
53
- list(scope: SearchScope): Promise<Listing>;
58
+ list(scope: SearchScope, destination?: DiscoveryDestination): Promise<Listing>;
54
59
  /** Resolves a choice against the same ordering list() produced. Rejects with SelectionError. */
55
- resolve(scope: SearchScope, input: SelectionInput): Promise<SessionDescriptor>;
60
+ resolve(scope: SearchScope, input: SelectionInput, destination?: DiscoveryDestination): Promise<SessionDescriptor>;
56
61
  /** Reads one session into the neutral vocabulary, through its source adapter. */
57
62
  load(descriptor: SessionDescriptor): Promise<CanonicalSession>;
58
63
  }
@@ -1,4 +1,4 @@
1
- import type { ImportConfig, SessionFinder } from "./contract.js";
1
+ import type { ImportConfig, RepoReader, SessionFinder } from "./contract.js";
2
2
  import { type SourceAdapter } from "./homes.js";
3
3
  export type { SourceAdapter };
4
4
  /** Everything the finder needs. The adapter list arrives from `src/import/`; it holds none. */
@@ -6,5 +6,6 @@ export interface DiscoveryDeps {
6
6
  adapters: readonly SourceAdapter[];
7
7
  /** Only `extraHomes` is read. */
8
8
  config: Pick<ImportConfig, "extraHomes">;
9
+ repo: Pick<RepoReader, "identify" | "checkCancellation">;
9
10
  }
10
11
  export declare function createSessionFinder(deps: DiscoveryDeps): SessionFinder;
@@ -0,0 +1,269 @@
1
+ // The source side of the tool: find the sessions of this repository, order them, resolve the
2
+ // user's choice, and load it. It never writes and never calls a model (NG-1, AC-4, FR-8).
3
+ import { realpath } from "node:fs/promises";
4
+ import { resolve } from "node:path";
5
+ import { SessionSelectionError } from "./errors.js";
6
+ import { buildSearchList, canonicalPath, isDirectory, } from "./homes.js";
7
+ import { compareDescriptors } from "./ordering.js";
8
+ const NEXT_STEP = "Run the list again to see the sessions available in this repository.";
9
+ function reasonLine(reason) {
10
+ const text = reason instanceof Error ? reason.message : String(reason);
11
+ return text.split("\n")[0] ?? "unknown error";
12
+ }
13
+ /** One recorded directory against this destination: the same directory, or the same repository. */
14
+ function isMatch(evidence, destination) {
15
+ return (evidence.directory === destination?.directory ||
16
+ (evidence.commonDir !== null && evidence.commonDir === destination?.commonDir));
17
+ }
18
+ function isCancellation(reason) {
19
+ return reason instanceof Error && reason.name === "AbortError";
20
+ }
21
+ export function createSessionFinder(deps) {
22
+ async function collect(target, destination, lookup) {
23
+ deps.repo.checkCancellation();
24
+ // A home the user named must never fail silently: adapters swallow a missing
25
+ // directory (an absent default home is normal), but a typo'd --home is not (FR-2).
26
+ if (target.named === true && !(await isDirectory(target.home))) {
27
+ deps.repo.checkCancellation();
28
+ return {
29
+ rows: [],
30
+ failures: [
31
+ {
32
+ home: target.home,
33
+ agent: target.agent,
34
+ message: "home not searched: no such directory",
35
+ },
36
+ ],
37
+ };
38
+ }
39
+ let found;
40
+ try {
41
+ deps.repo.checkCancellation();
42
+ found = await target.adapter.listSessions(target.home);
43
+ deps.repo.checkCancellation();
44
+ }
45
+ catch (reason) {
46
+ deps.repo.checkCancellation();
47
+ if (isCancellation(reason))
48
+ throw reason;
49
+ // One bad home never empties the listing.
50
+ return {
51
+ rows: [],
52
+ failures: [
53
+ {
54
+ home: target.home,
55
+ agent: target.agent,
56
+ message: `home not searched: ${reasonLine(reason)}`,
57
+ },
58
+ ],
59
+ };
60
+ }
61
+ const rows = [];
62
+ const failures = [];
63
+ for (const descriptor of found) {
64
+ deps.repo.checkCancellation();
65
+ let diagnostic = null;
66
+ try {
67
+ let matched = false;
68
+ let conflictingGitIdentity = false;
69
+ let existing = false;
70
+ // Do not accept early: a later candidate can disprove the membership.
71
+ for (const candidate of descriptor.repoPaths) {
72
+ const evidence = await lookup(candidate);
73
+ if (evidence === null)
74
+ continue;
75
+ existing = true;
76
+ matched ||= isMatch(evidence, destination);
77
+ if (evidence.commonDir !== null) {
78
+ conflictingGitIdentity ||= evidence.commonDir !== destination?.commonDir;
79
+ }
80
+ }
81
+ // The primary decision (FR-13): a match includes, a conflict excludes, and a match never
82
+ // overrides a conflict.
83
+ const matchedHere = matched && !conflictingGitIdentity;
84
+ // The start directory is a last resort: it settles the case where no recorded candidate
85
+ // matched at all, and it never overrides a match or a conflict (issue #5).
86
+ const startDirectory = descriptor.startDirectory;
87
+ // A start directory that is already a recorded candidate adds nothing: the loop above looked
88
+ // it up with the same rule. Skipping it keeps the fallback from spending a second lookup on
89
+ // every session it cannot list (adapters whose header directory is their only candidate).
90
+ const startIsCandidate = startDirectory !== null && descriptor.repoPaths.includes(startDirectory);
91
+ const startEvidence = matchedHere || conflictingGitIdentity || startDirectory === null || startIsCandidate
92
+ ? null
93
+ : await lookup(startDirectory);
94
+ const startedHere = startEvidence !== null && isMatch(startEvidence, destination);
95
+ if (matchedHere || startedHere) {
96
+ rows.push(descriptor);
97
+ }
98
+ else if (conflictingGitIdentity) {
99
+ diagnostic =
100
+ "has conflicting repository identity evidence; its recorded directories cannot unambiguously belong to this destination";
101
+ }
102
+ else if (descriptor.repoPaths.length === 0) {
103
+ diagnostic = "records no repository, so it cannot be listed here";
104
+ }
105
+ else {
106
+ diagnostic = existing
107
+ ? "has unresolved recorded directories with no matching repository evidence"
108
+ : "has only missing recorded directories; repository membership cannot be established";
109
+ }
110
+ }
111
+ catch (reason) {
112
+ deps.repo.checkCancellation();
113
+ if (isCancellation(reason))
114
+ throw reason;
115
+ diagnostic = `repository lookup failed: ${reasonLine(reason)}`;
116
+ }
117
+ if (diagnostic !== null) {
118
+ failures.push({
119
+ home: target.home,
120
+ agent: target.agent,
121
+ message: `session ${descriptor.ref.id} ${diagnostic}`,
122
+ });
123
+ }
124
+ }
125
+ return { rows, failures };
126
+ }
127
+ /** The single listing both `list` and `resolve` use, so the two always agree (FR-10). */
128
+ async function buildListing(scope, supplied) {
129
+ deps.repo.checkCancellation();
130
+ // Both caches live for this listing only. The spelling cache shares missing paths and
131
+ // filesystem failures; the canonical cache also shares Git lookups through symlink aliases.
132
+ const directories = new Map();
133
+ const identities = new Map();
134
+ const lookup = async (directory) => {
135
+ deps.repo.checkCancellation();
136
+ const absolute = resolve(directory);
137
+ let pending = directories.get(absolute);
138
+ if (!pending) {
139
+ pending = (async () => {
140
+ let canonical;
141
+ try {
142
+ canonical = await realpath(absolute);
143
+ deps.repo.checkCancellation();
144
+ }
145
+ catch (reason) {
146
+ if (reason.code === "ENOENT") {
147
+ // The reader still observes cancellation on missing-path short circuits.
148
+ await deps.repo.identify(absolute);
149
+ return null;
150
+ }
151
+ throw reason;
152
+ }
153
+ let identity = identities.get(canonical);
154
+ if (!identity) {
155
+ identity = Promise.resolve().then(() => deps.repo.identify(canonical));
156
+ identities.set(canonical, identity);
157
+ }
158
+ return { directory: canonical, commonDir: (await identity).commonDir };
159
+ })();
160
+ directories.set(absolute, pending);
161
+ }
162
+ const evidence = await pending;
163
+ deps.repo.checkCancellation();
164
+ return evidence;
165
+ };
166
+ let destination;
167
+ try {
168
+ if (supplied !== undefined) {
169
+ const canonical = await realpath(scope.repoRoot);
170
+ deps.repo.checkCancellation();
171
+ if (canonical !== supplied.canonicalCwd) {
172
+ throw new Error("Destination evidence does not match the requested directory");
173
+ }
174
+ identities.set(canonical, Promise.resolve(supplied.identity));
175
+ directories.set(resolve(scope.repoRoot), Promise.resolve({
176
+ directory: canonical,
177
+ commonDir: supplied.identity.commonDir,
178
+ }));
179
+ }
180
+ destination = await lookup(scope.repoRoot);
181
+ }
182
+ catch (reason) {
183
+ deps.repo.checkCancellation();
184
+ if (isCancellation(reason))
185
+ throw reason;
186
+ throw new Error(`Destination repository lookup failed: ${reasonLine(reason)}`, {
187
+ cause: reason,
188
+ });
189
+ }
190
+ const targets = await buildSearchList(deps.adapters, deps.config, scope);
191
+ deps.repo.checkCancellation();
192
+ const collected = await Promise.all(targets.map((target) => collect(target, destination, lookup)));
193
+ deps.repo.checkCancellation();
194
+ const rows = [];
195
+ const failures = [];
196
+ for (const part of collected) {
197
+ rows.push(...part.rows);
198
+ failures.push(...part.failures);
199
+ }
200
+ rows.sort(compareDescriptors);
201
+ return { rows, failures };
202
+ }
203
+ async function resolveRow(rows, row, diagnostics) {
204
+ const chosen = Number.isInteger(row) && row >= 1 ? rows[row - 1] : undefined;
205
+ if (!chosen) {
206
+ throw new SessionSelectionError(String(row), `Row ${row} is not in this repository's session list, which has ${rows.length} row(s). ${NEXT_STEP}${diagnostics}`);
207
+ }
208
+ return chosen;
209
+ }
210
+ return {
211
+ async list(scope, destination) {
212
+ return await buildListing(scope, destination);
213
+ },
214
+ async resolve(scope, input, destination) {
215
+ const { rows, failures } = await buildListing(scope, destination);
216
+ const diagnostics = failures.length === 0
217
+ ? ""
218
+ : ` Skipped: ${failures.map((failure) => `${failure.agent} at "${failure.home}": ${failure.message}`).join("; ")}.`;
219
+ switch (input.by) {
220
+ case "row":
221
+ return await resolveRow(rows, input.row, diagnostics);
222
+ case "session-id": {
223
+ const matches = rows.filter((row) => row.ref.id === input.id);
224
+ const found = matches[0];
225
+ if (!found) {
226
+ throw new SessionSelectionError(input.id, `No session "${input.id}" belongs to this repository. ${NEXT_STEP}${diagnostics}`);
227
+ }
228
+ if (matches.length > 1) {
229
+ const locations = matches
230
+ .map((row) => `${row.ref.agent} at "${row.ref.home}" (${row.filePath})`)
231
+ .join("; ");
232
+ throw new SessionSelectionError(input.id, `Session ID "${input.id}" matches ${matches.length} sessions: ${locations}. ` +
233
+ "Select a numbered row or exact file path, or narrow the search with an agent and --home.");
234
+ }
235
+ return found;
236
+ }
237
+ case "file-path": {
238
+ const wanted = await canonicalPath(input.path);
239
+ deps.repo.checkCancellation();
240
+ for (const row of rows) {
241
+ const filePath = await canonicalPath(row.filePath);
242
+ deps.repo.checkCancellation();
243
+ if (filePath === wanted)
244
+ return row;
245
+ }
246
+ // Selection by path is a convenience, not a way around the repository filter (NG-9).
247
+ throw new SessionSelectionError(input.path, `"${input.path}" is not a session of this repository. ${NEXT_STEP}${diagnostics}`);
248
+ }
249
+ }
250
+ },
251
+ async load(descriptor) {
252
+ deps.repo.checkCancellation();
253
+ const adapter = deps.adapters.find((candidate) => {
254
+ const capabilities = candidate.capabilities();
255
+ return capabilities.agent === descriptor.ref.agent && capabilities.roles.includes("source");
256
+ });
257
+ if (!adapter) {
258
+ throw new Error(`no source adapter for agent "${descriptor.ref.agent}"`);
259
+ }
260
+ // Returned unchanged: the rules of sections D and E belong to src/import/transfer/.
261
+ try {
262
+ return await adapter.loadSession(descriptor);
263
+ }
264
+ finally {
265
+ deps.repo.checkCancellation();
266
+ }
267
+ },
268
+ };
269
+ }
@@ -1,5 +1,5 @@
1
- import type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, LandingLevel, ProvenanceSupport, SelectionLevel, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect } from "../../adapters/contract.js";
2
- export type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, LandingLevel, ProvenanceSupport, SelectionLevel, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect, };
1
+ import type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, LandingLevel, ProvenanceSupport, SelectionLevel, SerializationContext, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect } from "../../adapters/contract.js";
2
+ export type { AdapterRole, AgentAdapter, AgentCapabilities, AgentRuntime, LandingLevel, ProvenanceSupport, SelectionLevel, SerializationContext, SerializedSession, StoredSessionFacts, SwitchOutcome, ValidationDefect, };
3
3
  import type { DropReason, PinReason, TransferPlan, TurnDrop, TurnPin } from "../transfer/contract.js";
4
4
  export type { DropReason, PinReason, TransferPlan, TurnDrop, TurnPin };
5
5
  import type { Bytes, CommitError, CommitHandle, CommitRefusal, FileCommitter, PendingFile } from "../../platform/store/contract.js";
@@ -40,5 +40,5 @@ export interface SessionLander {
40
40
  * Runs after the user confirmed the preview (FR-20).
41
41
  * Rejects with a LandingError, leaving the target home unchanged.
42
42
  */
43
- land(plan: TransferPlan, adapter: AgentAdapter, committer: FileCommitter, runtime: AgentRuntime, importedAt: string): Promise<LandingResult>;
43
+ land(plan: TransferPlan, adapter: AgentAdapter, committer: FileCommitter, runtime: AgentRuntime, importedAt: string, context: SerializationContext): Promise<LandingResult>;
44
44
  }
@@ -39,7 +39,7 @@ function failAfterCommit(createdPaths, stage, what, home) {
39
39
  : `The committed paths were preserved because automatic removal could delete replacements. Inspect them before retrying: ${createdPaths.join(", ")}.`;
40
40
  return new LandingFailure(stage, `${what} ${preserved} ${RETRY}`);
41
41
  }
42
- async function runLanding(plan, adapter, committer, runtime, importedAt, buildCommand) {
42
+ async function runLanding(plan, adapter, committer, runtime, importedAt, context, buildCommand) {
43
43
  const home = plan.target.home;
44
44
  const target = plan.target.agent;
45
45
  // Second gate: the preview should already have stopped this plan (FR-33).
@@ -56,7 +56,7 @@ async function runLanding(plan, adapter, committer, runtime, importedAt, buildCo
56
56
  };
57
57
  let serialized;
58
58
  try {
59
- serialized = adapter.serialize(session, plan.target, marker);
59
+ serialized = adapter.serialize(session, plan.target, marker, context);
60
60
  }
61
61
  catch (cause) {
62
62
  throw new LandingFailure("serialize", `The ${target} adapter could not turn the plan into its own session format: ${reasonOf(cause)}. Nothing was written to ${home}. ${RETRY}`);
@@ -128,6 +128,6 @@ async function runLanding(plan, adapter, committer, runtime, importedAt, buildCo
128
128
  export function createSessionLander(options = {}) {
129
129
  const buildCommand = options.handoverCommand ?? describeSession;
130
130
  return {
131
- land: (plan, adapter, committer, runtime, importedAt) => runLanding(plan, adapter, committer, runtime, importedAt, buildCommand),
131
+ land: (plan, adapter, committer, runtime, importedAt, context) => runLanding(plan, adapter, committer, runtime, importedAt, context, buildCommand),
132
132
  };
133
133
  }
@@ -0,0 +1,28 @@
1
+ import type { RepoIdentity } from "../platform/repo/contract.js";
2
+ import type { AgentAdapter, FileCommitter, ImportConfig, ImportPipeline, PreviewBuilder, SessionDescriptor, SessionFinder, SessionLander, TokenEstimator, TransferRules } from "./contract.js";
3
+ /** Fresh destination facts for one request; native spelling stays distinct from canonical identity. */
4
+ export interface DestinationContext {
5
+ cwd: string;
6
+ canonicalCwd: string;
7
+ identity: RepoIdentity;
8
+ }
9
+ /** The four stages, and the services they are driven with. `wiring.ts` builds them. */
10
+ export interface PipelineStages {
11
+ /** Observe the repository reader's cancellation even when no Git lookup is needed. */
12
+ checkCancellation(): void;
13
+ finder: SessionFinder;
14
+ rules: TransferRules;
15
+ /** Resolve fresh destination facts, without replacing the host's native cwd spelling. */
16
+ destinationFor(cwd: string): Promise<DestinationContext>;
17
+ /** A preview builder that reads the repository the request names. */
18
+ previewFor(destination: DestinationContext, descriptor: SessionDescriptor): PreviewBuilder;
19
+ lander: SessionLander;
20
+ /** Every adapter the composition root constructed. This module only looks one up. */
21
+ adapters: readonly AgentAdapter[];
22
+ config: ImportConfig;
23
+ estimator: TokenEstimator;
24
+ committer: FileCommitter;
25
+ /** ISO-8601 UTC. Only the landing reads it, so a preview and a commit agree (FR-47). */
26
+ now(): string;
27
+ }
28
+ export declare function createPipelineFromStages(stages: PipelineStages): ImportPipeline;
@@ -9,7 +9,7 @@ const PREVIEW_AGAIN = "Preview it again, then confirm.";
9
9
  const IMPORT_AGAIN = "Fix the cause, then run the import again.";
10
10
  function scopeOf(request) {
11
11
  return {
12
- repoRoot: request.repoRoot,
12
+ repoRoot: request.destinationCwd,
13
13
  onlyAgent: request.onlyAgent,
14
14
  onlyHome: request.onlyHome,
15
15
  };
@@ -34,9 +34,21 @@ function isLandingError(cause) {
34
34
  return cause instanceof Error && "stage" in cause && "defects" in cause;
35
35
  }
36
36
  export function createPipelineFromStages(stages) {
37
- async function resolve(request) {
37
+ async function destinationFor(cwd) {
38
38
  try {
39
- return await stages.finder.resolve(scopeOf(request), request.selection);
39
+ const destination = await stages.destinationFor(cwd);
40
+ if (destination.identity.isBare) {
41
+ throw new Error("A bare repository cannot be an import destination. Run the import from a linked worktree instead.");
42
+ }
43
+ return destination;
44
+ }
45
+ catch (cause) {
46
+ throw new ImportFailure("preview", `The destination ${cwd} could not be used: ${reasonOf(cause)} Nothing was written. Check the destination directory and preview again.`, { cause });
47
+ }
48
+ }
49
+ async function resolve(request, destination) {
50
+ try {
51
+ return await stages.finder.resolve(scopeOf(request), request.selection, destination);
40
52
  }
41
53
  catch (cause) {
42
54
  throw new ImportFailure("discovery", `The session could not be chosen: ${reasonOf(cause)}`, {
@@ -58,7 +70,8 @@ export function createPipelineFromStages(stages) {
58
70
  * processes, and a plan cannot travel between them.
59
71
  */
60
72
  async function compute(request) {
61
- const descriptor = await resolve(request);
73
+ const destination = await destinationFor(request.destinationCwd);
74
+ const descriptor = await resolve(request, destination);
62
75
  const session = await load(descriptor);
63
76
  let plan;
64
77
  try {
@@ -69,14 +82,19 @@ export function createPipelineFromStages(stages) {
69
82
  }
70
83
  let report;
71
84
  try {
72
- report = await stages.previewFor(request.repoRoot).build(plan);
85
+ report = await stages.previewFor(destination, descriptor).build(plan);
86
+ stages.checkCancellation();
73
87
  }
74
88
  catch (cause) {
75
89
  throw new ImportFailure("preview", `The preview of session ${descriptor.ref.id} could not be built: ${reasonOf(cause)}. Nothing was written. ${IMPORT_AGAIN}`, { cause });
76
90
  }
77
- const token = confirmationToken(descriptor, plan, report);
91
+ const token = confirmationToken(descriptor, plan, report, {
92
+ canonicalCwd: destination.canonicalCwd,
93
+ commonDir: destination.identity.commonDir,
94
+ });
78
95
  return {
79
96
  descriptor,
97
+ destination,
80
98
  plan,
81
99
  report: { ...report, confirmationToken: token },
82
100
  };
@@ -84,10 +102,11 @@ export function createPipelineFromStages(stages) {
84
102
  return {
85
103
  async list(request) {
86
104
  try {
87
- return await stages.finder.list(scopeOf(request));
105
+ const destination = await destinationFor(request.destinationCwd);
106
+ return await stages.finder.list(scopeOf(request), destination);
88
107
  }
89
108
  catch (cause) {
90
- throw new ImportFailure("discovery", `The sessions of this repository could not be listed: ${reasonOf(cause)}. Check that ${request.repoRoot} is readable, then run the list again.`, { cause });
109
+ throw new ImportFailure("discovery", `The sessions of this repository could not be listed: ${reasonOf(cause)}. Check that ${request.destinationCwd} is readable, then run the list again.`, { cause });
91
110
  }
92
111
  },
93
112
  async preview(request) {
@@ -99,9 +118,9 @@ export function createPipelineFromStages(stages) {
99
118
  },
100
119
  async commit(request, runtime, suppliedToken) {
101
120
  const adapter = targetAdapter(stages.adapters, request.target);
102
- const { descriptor, plan, report } = await compute(request);
121
+ const { descriptor, destination, plan, report } = await compute(request);
103
122
  if (!confirmationMatches(report.confirmationToken, suppliedToken)) {
104
- throw new ImportFailure("confirmation", `The source session or preview changed after confirmation. Nothing was written to ${request.target.home}. ${PREVIEW_AGAIN}`);
123
+ throw new ImportFailure("confirmation", `The source session, destination, or preview changed after confirmation. Nothing was written to ${request.target.home}. ${PREVIEW_AGAIN}`);
105
124
  }
106
125
  if (plan.blockedReason !== null) {
107
126
  // blockedReason already ends in a sentence and carries the cause-specific
@@ -115,7 +134,8 @@ export function createPipelineFromStages(stages) {
115
134
  throw new ImportFailure("source-changed", `The source session ${descriptor.ref.id} changed after the preview: ${descriptor.filePath} was last written at ${descriptor.updatedAt}, and the conversation the preview showed ends at ${plan.provenance.updatedAt}. Nothing was written. ${PREVIEW_AGAIN}`);
116
135
  }
117
136
  try {
118
- return await stages.lander.land(plan, adapter, stages.committer, runtime, stages.now());
137
+ stages.checkCancellation();
138
+ return await stages.lander.land(plan, adapter, stages.committer, runtime, stages.now(), destination);
119
139
  }
120
140
  catch (cause) {
121
141
  // The landing states what failed and what to do next for every one of its stages;
@@ -1,6 +1,6 @@
1
- import type { PreviewBuilder, RepoReader } from "./contract.js";
1
+ import type { PreviewBuilder, RepoIdentity, RepoReader } from "./contract.js";
2
2
  /**
3
3
  * Builds the preview from a plan and the repository state read at the moment of the call.
4
4
  * It writes nothing (FR-16) and renders one shape for every direction (FR-21).
5
5
  */
6
- export declare function createPreviewBuilder(repo: RepoReader, cwd: string): PreviewBuilder;
6
+ export declare function createPreviewBuilder(repo: RepoReader, cwd: string, canonicalCwd?: string, identity?: RepoIdentity, recordedDirectories?: readonly string[]): PreviewBuilder;
@@ -1,17 +1,18 @@
1
1
  import { formatTokens, oneLine, plural } from "./format.js";
2
- import { planWarnings, repoWarning, sortWarnings } from "./warnings.js";
2
+ import { directoryWarning, planWarnings, repoWarning, sortWarnings } from "./warnings.js";
3
3
  /** Paths are longer than titles and are not shortened to the same length. */
4
4
  const MAX_PATH_LENGTH = 160;
5
5
  const MAX_REASON_LENGTH = 200;
6
6
  const UNTITLED = "(untitled)";
7
7
  // Each blockedReason now carries its own cause-specific advice (FR-33, FR-56), so no
8
8
  // single fallback string is accurate for all block causes.
9
- function headerLines(plan) {
9
+ function headerLines(plan, canonicalCwd) {
10
10
  const source = plan.provenance.ref;
11
11
  const title = oneLine(plan.provenance.title) || UNTITLED;
12
12
  return [
13
13
  `Source: ${source.agent} — ${title} (${oneLine(source.home, MAX_PATH_LENGTH)})`,
14
14
  `Target: ${plan.target.agent} (${oneLine(plan.target.home, MAX_PATH_LENGTH)})`,
15
+ `Destination: ${oneLine(canonicalCwd, Number.POSITIVE_INFINITY)}`,
15
16
  countLine(plan),
16
17
  ];
17
18
  }
@@ -44,15 +45,18 @@ function blockedLines(blockedReason) {
44
45
  * Builds the preview from a plan and the repository state read at the moment of the call.
45
46
  * It writes nothing (FR-16) and renders one shape for every direction (FR-21).
46
47
  */
47
- export function createPreviewBuilder(repo, cwd) {
48
+ export function createPreviewBuilder(repo, cwd, canonicalCwd = cwd, identity, recordedDirectories = []) {
48
49
  return {
49
50
  async build(plan) {
50
51
  const collected = planWarnings(plan);
51
- const fromRepo = await repoWarning(plan, repo, cwd);
52
+ const fromDirectory = await directoryWarning(recordedDirectories, canonicalCwd);
53
+ if (fromDirectory !== null)
54
+ collected.push(fromDirectory);
55
+ const fromRepo = await repoWarning(plan, repo, cwd, identity);
52
56
  if (fromRepo !== null)
53
57
  collected.push(fromRepo);
54
58
  const warnings = sortWarnings(collected);
55
- const header = headerLines(plan);
59
+ const header = headerLines(plan, canonicalCwd);
56
60
  const budgetLine = `Budget: ${formatTokens(plan.estimatedTokens)} tokens of a ${formatTokens(plan.target.windowTokens)} window`;
57
61
  const drops = dropLines(plan);
58
62
  const blocked = plan.blockedReason !== null;
@@ -0,0 +1,14 @@
1
+ import type { PreviewWarning, RepoIdentity, RepoReader, TransferPlan } from "./contract.js";
2
+ /** Orders warnings by kind, keeping the order they were added within one kind. */
3
+ export declare function sortWarnings(warnings: PreviewWarning[]): PreviewWarning[];
4
+ /**
5
+ * Compares the source commit with the destination HEAD (FR-37, FR-38). Returned
6
+ * unresolved identities and unavailable commits produce non-blocking unknown-state
7
+ * warnings (FR-36, FR-39). Rejected operational lookups, including cancellation,
8
+ * propagate so the pipeline stops before any import write.
9
+ */
10
+ export declare function repoWarning(plan: TransferPlan, repo: RepoReader, cwd: string, identified?: RepoIdentity): Promise<PreviewWarning | null>;
11
+ /** Missing historical paths are neutral; only an existing canonical path proves a difference. */
12
+ export declare function directoryWarning(recordedDirectories: readonly string[], canonicalCwd: string): Promise<PreviewWarning | null>;
13
+ /** The warnings that come from the plan alone. */
14
+ export declare function planWarnings(plan: TransferPlan): PreviewWarning[];
@@ -1,3 +1,4 @@
1
+ import { realpath } from "node:fs/promises";
1
2
  import { formatTokens, plural, sameCommit, shortCommit } from "./format.js";
2
3
  /** Repository warnings sort first (FR-19); the rest follow this order. */
3
4
  const KIND_ORDER = ["repo-state", "budget", "broken-tail", "capability"];
@@ -22,26 +23,20 @@ function describeGap({ ahead, behind }) {
22
23
  return "";
23
24
  }
24
25
  /**
25
- * Compares the source commit with the current HEAD (FR-37, FR-38). A repository that
26
- * cannot be read, or a commit this tree does not have, is said to be unknown — never
27
- * guessed and never left out (FR-36). None of these block (FR-39).
26
+ * Compares the source commit with the destination HEAD (FR-37, FR-38). Returned
27
+ * unresolved identities and unavailable commits produce non-blocking unknown-state
28
+ * warnings (FR-36, FR-39). Rejected operational lookups, including cancellation,
29
+ * propagate so the pipeline stops before any import write.
28
30
  */
29
- export async function repoWarning(plan, repo, cwd) {
30
- const unreadable = repoState(`${GLYPH} The repository state could not be read, so the source commit is ${NOT_KNOWN}.`);
31
- let identity;
32
- try {
33
- identity = await repo.identify(cwd);
34
- }
35
- catch {
36
- return unreadable;
37
- }
31
+ export async function repoWarning(plan, repo, cwd, identified) {
32
+ const identity = identified ?? (await repo.identify(cwd));
38
33
  const sourceCommit = plan.provenance.repo.commit;
39
34
  if (sourceCommit === null || sourceCommit.trim() === "") {
40
35
  return repoState(`${GLYPH} The source session did not record a commit, so the repository state is ${NOT_KNOWN}.`);
41
36
  }
42
37
  const source = shortCommit(sourceCommit);
43
38
  if (identity.root === null) {
44
- return repoState(`${GLYPH} Source ran at ${source}. This directory is not a repository, so the repository state is ${NOT_KNOWN}.`);
39
+ return repoState(`${GLYPH} Source ran at ${source}. This directory's repository identity is unresolved, so the repository state is ${NOT_KNOWN}.`);
45
40
  }
46
41
  if (identity.head === null) {
47
42
  return repoState(`${GLYPH} Source ran at ${source}. This repository has no commit yet, so the repository state is ${NOT_KNOWN}.`);
@@ -49,18 +44,29 @@ export async function repoWarning(plan, repo, cwd) {
49
44
  if (sameCommit(sourceCommit, identity.head))
50
45
  return null;
51
46
  const head = shortCommit(identity.head);
52
- let distance;
53
- try {
54
- distance = await repo.distanceFrom(sourceCommit);
55
- }
56
- catch {
57
- return unreadable;
58
- }
47
+ const distance = await repo.distanceFrom(cwd, sourceCommit);
59
48
  if (!distance.known) {
60
49
  return repoState(`${GLYPH} Source ran at ${source}, which is ${NOT_KNOWN}. The tree is now at ${head}.`);
61
50
  }
62
51
  return repoState(`${GLYPH} Source ran at ${source}. The tree is now at ${head}${describeGap(distance)}.`);
63
52
  }
53
+ /** Missing historical paths are neutral; only an existing canonical path proves a difference. */
54
+ export async function directoryWarning(recordedDirectories, canonicalCwd) {
55
+ let differs = false;
56
+ for (const directory of recordedDirectories) {
57
+ try {
58
+ if ((await realpath(directory)) !== canonicalCwd)
59
+ differs = true;
60
+ }
61
+ catch (cause) {
62
+ if (cause.code !== "ENOENT")
63
+ throw cause;
64
+ }
65
+ }
66
+ return differs
67
+ ? repoState(`${GLYPH} The source session records a different directory. Conversation import does not transfer uncommitted work, switch branches, or recreate removed worktrees.`)
68
+ : null;
69
+ }
64
70
  /** The warnings that come from the plan alone. */
65
71
  export function planWarnings(plan) {
66
72
  const warnings = [];