@nanonets/graft 0.24.1 → 0.25.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 (480) hide show
  1. package/README.md +26 -21
  2. package/dist/blast/render.js +1 -1
  3. package/dist/blast/render.js.map +1 -1
  4. package/dist/brand.js +1 -1
  5. package/dist/brand.js.map +1 -1
  6. package/dist/check/learning-edits.d.ts +18 -3
  7. package/dist/check/learning-edits.d.ts.map +1 -1
  8. package/dist/check/learning-edits.js +54 -10
  9. package/dist/check/learning-edits.js.map +1 -1
  10. package/dist/check/local-check.d.ts +7 -3
  11. package/dist/check/local-check.d.ts.map +1 -1
  12. package/dist/check/local-check.js +55 -11
  13. package/dist/check/local-check.js.map +1 -1
  14. package/dist/check/types.d.ts +11 -2
  15. package/dist/check/types.d.ts.map +1 -1
  16. package/dist/claude/format.d.ts +11 -7
  17. package/dist/claude/format.d.ts.map +1 -1
  18. package/dist/claude/format.js +50 -28
  19. package/dist/claude/format.js.map +1 -1
  20. package/dist/claude/hook-io.js +1 -1
  21. package/dist/claude/hook-io.js.map +1 -1
  22. package/dist/claude/hook-layers.d.ts +4 -2
  23. package/dist/claude/hook-layers.d.ts.map +1 -1
  24. package/dist/claude/hook-layers.js +21 -4
  25. package/dist/claude/hook-layers.js.map +1 -1
  26. package/dist/claude/hooks.d.ts +9 -32
  27. package/dist/claude/hooks.d.ts.map +1 -1
  28. package/dist/claude/hooks.js +154 -350
  29. package/dist/claude/hooks.js.map +1 -1
  30. package/dist/claude/init.d.ts.map +1 -1
  31. package/dist/claude/init.js +56 -18
  32. package/dist/claude/init.js.map +1 -1
  33. package/dist/claude/note-signals.d.ts +6 -0
  34. package/dist/claude/note-signals.d.ts.map +1 -1
  35. package/dist/claude/note-signals.js +14 -3
  36. package/dist/claude/note-signals.js.map +1 -1
  37. package/dist/claude/post-bash.d.ts +26 -0
  38. package/dist/claude/post-bash.d.ts.map +1 -0
  39. package/dist/claude/post-bash.js +191 -0
  40. package/dist/claude/post-bash.js.map +1 -0
  41. package/dist/claude/pre-bash-skills.d.ts +21 -0
  42. package/dist/claude/pre-bash-skills.d.ts.map +1 -0
  43. package/dist/claude/pre-bash-skills.js +253 -0
  44. package/dist/claude/pre-bash-skills.js.map +1 -0
  45. package/dist/claude/pre-bash.d.ts +50 -0
  46. package/dist/claude/pre-bash.d.ts.map +1 -0
  47. package/dist/claude/pre-bash.js +245 -0
  48. package/dist/claude/pre-bash.js.map +1 -0
  49. package/dist/claude/prompt-consent.d.ts +19 -0
  50. package/dist/claude/prompt-consent.d.ts.map +1 -0
  51. package/dist/claude/prompt-consent.js +14 -0
  52. package/dist/claude/prompt-consent.js.map +1 -0
  53. package/dist/claude/prompt-hook.d.ts +76 -0
  54. package/dist/claude/prompt-hook.d.ts.map +1 -0
  55. package/dist/claude/prompt-hook.js +303 -0
  56. package/dist/claude/prompt-hook.js.map +1 -0
  57. package/dist/claude/prompt-skills.d.ts +19 -0
  58. package/dist/claude/prompt-skills.d.ts.map +1 -0
  59. package/dist/claude/prompt-skills.js +305 -0
  60. package/dist/claude/prompt-skills.js.map +1 -0
  61. package/dist/claude/session-metrics.js +4 -4
  62. package/dist/claude/session-metrics.js.map +1 -1
  63. package/dist/claude/settings-merge.d.ts +10 -0
  64. package/dist/claude/settings-merge.d.ts.map +1 -1
  65. package/dist/claude/settings-merge.js +46 -17
  66. package/dist/claude/settings-merge.js.map +1 -1
  67. package/dist/claude/shim-template.d.ts.map +1 -1
  68. package/dist/claude/shim-template.js +86 -28
  69. package/dist/claude/shim-template.js.map +1 -1
  70. package/dist/claude/skill-template.d.ts +2 -0
  71. package/dist/claude/skill-template.d.ts.map +1 -1
  72. package/dist/claude/skill-template.js +53 -34
  73. package/dist/claude/skill-template.js.map +1 -1
  74. package/dist/claude/skill-use.d.ts +16 -0
  75. package/dist/claude/skill-use.d.ts.map +1 -0
  76. package/dist/claude/skill-use.js +78 -0
  77. package/dist/claude/skill-use.js.map +1 -0
  78. package/dist/claude/skills-wiring.d.ts +26 -0
  79. package/dist/claude/skills-wiring.d.ts.map +1 -0
  80. package/dist/claude/skills-wiring.js +110 -0
  81. package/dist/claude/skills-wiring.js.map +1 -0
  82. package/dist/claude/start-init.d.ts +13 -0
  83. package/dist/claude/start-init.d.ts.map +1 -0
  84. package/dist/claude/start-init.js +75 -0
  85. package/dist/claude/start-init.js.map +1 -0
  86. package/dist/claude/start-skills.d.ts +31 -0
  87. package/dist/claude/start-skills.d.ts.map +1 -0
  88. package/dist/claude/start-skills.js +274 -0
  89. package/dist/claude/start-skills.js.map +1 -0
  90. package/dist/claude/state.d.ts +19 -7
  91. package/dist/claude/state.d.ts.map +1 -1
  92. package/dist/claude/state.js +59 -4
  93. package/dist/claude/state.js.map +1 -1
  94. package/dist/claude/stop-skills.d.ts +23 -0
  95. package/dist/claude/stop-skills.d.ts.map +1 -0
  96. package/dist/claude/stop-skills.js +233 -0
  97. package/dist/claude/stop-skills.js.map +1 -0
  98. package/dist/claude/stop.d.ts +23 -0
  99. package/dist/claude/stop.d.ts.map +1 -0
  100. package/dist/claude/stop.js +219 -0
  101. package/dist/claude/stop.js.map +1 -0
  102. package/dist/claude/tally.d.ts +29 -41
  103. package/dist/claude/tally.d.ts.map +1 -1
  104. package/dist/claude/tally.js +111 -165
  105. package/dist/claude/tally.js.map +1 -1
  106. package/dist/claude/walls-hook.d.ts +52 -0
  107. package/dist/claude/walls-hook.d.ts.map +1 -0
  108. package/dist/claude/walls-hook.js +279 -0
  109. package/dist/claude/walls-hook.js.map +1 -0
  110. package/dist/cli-epilogue.d.ts.map +1 -1
  111. package/dist/cli-epilogue.js +24 -14
  112. package/dist/cli-epilogue.js.map +1 -1
  113. package/dist/cli-meta.js +3 -3
  114. package/dist/cli-meta.js.map +1 -1
  115. package/dist/cli-picker.d.ts.map +1 -1
  116. package/dist/cli-picker.js +8 -6
  117. package/dist/cli-picker.js.map +1 -1
  118. package/dist/cli.d.ts.map +1 -1
  119. package/dist/cli.js +238 -402
  120. package/dist/cli.js.map +1 -1
  121. package/dist/cloud/head-learnings.d.ts +13 -0
  122. package/dist/cloud/head-learnings.d.ts.map +1 -0
  123. package/dist/cloud/head-learnings.js +84 -0
  124. package/dist/cloud/head-learnings.js.map +1 -0
  125. package/dist/cloud/lookup-activity.d.ts +5 -3
  126. package/dist/cloud/lookup-activity.d.ts.map +1 -1
  127. package/dist/cloud/lookup-activity.js +8 -8
  128. package/dist/cloud/lookup-activity.js.map +1 -1
  129. package/dist/cloud/nudge.d.ts +15 -7
  130. package/dist/cloud/nudge.d.ts.map +1 -1
  131. package/dist/cloud/nudge.js +42 -33
  132. package/dist/cloud/nudge.js.map +1 -1
  133. package/dist/cloud/onboarding.d.ts +37 -1
  134. package/dist/cloud/onboarding.d.ts.map +1 -1
  135. package/dist/cloud/onboarding.js +77 -1
  136. package/dist/cloud/onboarding.js.map +1 -1
  137. package/dist/cloud/other-repos.d.ts +39 -0
  138. package/dist/cloud/other-repos.d.ts.map +1 -0
  139. package/dist/cloud/other-repos.js +137 -0
  140. package/dist/cloud/other-repos.js.map +1 -0
  141. package/dist/cloud/pair.d.ts +17 -7
  142. package/dist/cloud/pair.d.ts.map +1 -1
  143. package/dist/cloud/pair.js +81 -60
  144. package/dist/cloud/pair.js.map +1 -1
  145. package/dist/cloud/workspace-sync.d.ts +67 -11
  146. package/dist/cloud/workspace-sync.d.ts.map +1 -1
  147. package/dist/cloud/workspace-sync.js +299 -55
  148. package/dist/cloud/workspace-sync.js.map +1 -1
  149. package/dist/cloud/workspace.d.ts +74 -10
  150. package/dist/cloud/workspace.d.ts.map +1 -1
  151. package/dist/cloud/workspace.js +96 -8
  152. package/dist/cloud/workspace.js.map +1 -1
  153. package/dist/hosts/claude-global.js +1 -1
  154. package/dist/hosts/claude-global.js.map +1 -1
  155. package/dist/hosts/codex-hooks.d.ts +6 -0
  156. package/dist/hosts/codex-hooks.d.ts.map +1 -1
  157. package/dist/hosts/codex-hooks.js +89 -16
  158. package/dist/hosts/codex-hooks.js.map +1 -1
  159. package/dist/hosts/codex-trust.d.ts +28 -0
  160. package/dist/hosts/codex-trust.d.ts.map +1 -0
  161. package/dist/hosts/codex-trust.js +280 -0
  162. package/dist/hosts/codex-trust.js.map +1 -0
  163. package/dist/hosts/cursor-hooks.d.ts.map +1 -1
  164. package/dist/hosts/cursor-hooks.js +3 -1
  165. package/dist/hosts/cursor-hooks.js.map +1 -1
  166. package/dist/init/candidates.d.ts +60 -0
  167. package/dist/init/candidates.d.ts.map +1 -0
  168. package/dist/init/candidates.js +202 -0
  169. package/dist/init/candidates.js.map +1 -0
  170. package/dist/init/claude-call.d.ts +51 -0
  171. package/dist/init/claude-call.d.ts.map +1 -0
  172. package/dist/init/claude-call.js +199 -0
  173. package/dist/init/claude-call.js.map +1 -0
  174. package/dist/init/discover-worker.d.ts +18 -0
  175. package/dist/init/discover-worker.d.ts.map +1 -0
  176. package/dist/init/discover-worker.js +111 -0
  177. package/dist/init/discover-worker.js.map +1 -0
  178. package/dist/init/handover.d.ts +16 -0
  179. package/dist/init/handover.d.ts.map +1 -0
  180. package/dist/init/handover.js +92 -0
  181. package/dist/init/handover.js.map +1 -0
  182. package/dist/init/howtos.d.ts +20 -0
  183. package/dist/init/howtos.d.ts.map +1 -0
  184. package/dist/init/howtos.js +90 -0
  185. package/dist/init/howtos.js.map +1 -0
  186. package/dist/init/init-record.d.ts +134 -0
  187. package/dist/init/init-record.d.ts.map +1 -0
  188. package/dist/init/init-record.js +339 -0
  189. package/dist/init/init-record.js.map +1 -0
  190. package/dist/init/install-paths.d.ts +6 -0
  191. package/dist/init/install-paths.d.ts.map +1 -0
  192. package/dist/init/install-paths.js +87 -0
  193. package/dist/init/install-paths.js.map +1 -0
  194. package/dist/init/keep-answer.d.ts +43 -0
  195. package/dist/init/keep-answer.d.ts.map +1 -0
  196. package/dist/init/keep-answer.js +118 -0
  197. package/dist/init/keep-answer.js.map +1 -0
  198. package/dist/init/keep-gate.d.ts +30 -0
  199. package/dist/init/keep-gate.d.ts.map +1 -0
  200. package/dist/init/keep-gate.js +178 -0
  201. package/dist/init/keep-gate.js.map +1 -0
  202. package/dist/init/keep-list.d.ts +67 -0
  203. package/dist/init/keep-list.d.ts.map +1 -0
  204. package/dist/init/keep-list.js +232 -0
  205. package/dist/init/keep-list.js.map +1 -0
  206. package/dist/init/keep.d.ts +52 -0
  207. package/dist/init/keep.d.ts.map +1 -0
  208. package/dist/init/keep.js +393 -0
  209. package/dist/init/keep.js.map +1 -0
  210. package/dist/init/look-back-mine.d.ts +37 -0
  211. package/dist/init/look-back-mine.d.ts.map +1 -0
  212. package/dist/init/look-back-mine.js +215 -0
  213. package/dist/init/look-back-mine.js.map +1 -0
  214. package/dist/init/look-back.d.ts +81 -0
  215. package/dist/init/look-back.d.ts.map +1 -0
  216. package/dist/init/look-back.js +170 -0
  217. package/dist/init/look-back.js.map +1 -0
  218. package/dist/init/miners.d.ts +46 -0
  219. package/dist/init/miners.d.ts.map +1 -0
  220. package/dist/init/miners.js +141 -0
  221. package/dist/init/miners.js.map +1 -0
  222. package/dist/init/name-call.d.ts +37 -0
  223. package/dist/init/name-call.d.ts.map +1 -0
  224. package/dist/init/name-call.js +151 -0
  225. package/dist/init/name-call.js.map +1 -0
  226. package/dist/init/plain-file.d.ts.map +1 -1
  227. package/dist/init/plain-file.js +3 -0
  228. package/dist/init/plain-file.js.map +1 -1
  229. package/dist/init/prefs.d.ts +70 -0
  230. package/dist/init/prefs.d.ts.map +1 -0
  231. package/dist/init/prefs.js +282 -0
  232. package/dist/init/prefs.js.map +1 -0
  233. package/dist/init/relay.d.ts +15 -0
  234. package/dist/init/relay.d.ts.map +1 -0
  235. package/dist/init/relay.js +15 -0
  236. package/dist/init/relay.js.map +1 -0
  237. package/dist/init/replay-runs.d.ts +121 -0
  238. package/dist/init/replay-runs.d.ts.map +1 -0
  239. package/dist/init/replay-runs.js +457 -0
  240. package/dist/init/replay-runs.js.map +1 -0
  241. package/dist/init/replay-tamper.d.ts +18 -0
  242. package/dist/init/replay-tamper.d.ts.map +1 -0
  243. package/dist/init/replay-tamper.js +87 -0
  244. package/dist/init/replay-tamper.js.map +1 -0
  245. package/dist/init/review-screen.d.ts +74 -0
  246. package/dist/init/review-screen.d.ts.map +1 -0
  247. package/dist/init/review-screen.js +258 -0
  248. package/dist/init/review-screen.js.map +1 -0
  249. package/dist/init/review-tty.d.ts +29 -0
  250. package/dist/init/review-tty.d.ts.map +1 -0
  251. package/dist/init/review-tty.js +218 -0
  252. package/dist/init/review-tty.js.map +1 -0
  253. package/dist/init/review.d.ts +12 -0
  254. package/dist/init/review.d.ts.map +1 -0
  255. package/dist/init/review.js +12 -0
  256. package/dist/init/review.js.map +1 -0
  257. package/dist/init/run.d.ts +87 -0
  258. package/dist/init/run.d.ts.map +1 -0
  259. package/dist/init/run.js +347 -0
  260. package/dist/init/run.js.map +1 -0
  261. package/dist/init/sessions.d.ts +63 -0
  262. package/dist/init/sessions.d.ts.map +1 -0
  263. package/dist/init/sessions.js +377 -0
  264. package/dist/init/sessions.js.map +1 -0
  265. package/dist/init/transcript.d.ts +81 -0
  266. package/dist/init/transcript.d.ts.map +1 -0
  267. package/dist/init/transcript.js +216 -0
  268. package/dist/init/transcript.js.map +1 -0
  269. package/dist/init/types.d.ts +139 -0
  270. package/dist/init/types.d.ts.map +1 -0
  271. package/dist/init/types.js +2 -0
  272. package/dist/init/types.js.map +1 -0
  273. package/dist/notes/cold-start.d.ts +5 -213
  274. package/dist/notes/cold-start.d.ts.map +1 -1
  275. package/dist/notes/cold-start.js +5 -654
  276. package/dist/notes/cold-start.js.map +1 -1
  277. package/dist/notes/edit-overlap.d.ts.map +1 -1
  278. package/dist/notes/edit-overlap.js +4 -1
  279. package/dist/notes/edit-overlap.js.map +1 -1
  280. package/dist/notes/notes.d.ts +8 -4
  281. package/dist/notes/notes.d.ts.map +1 -1
  282. package/dist/notes/notes.js +9 -7
  283. package/dist/notes/notes.js.map +1 -1
  284. package/dist/notes/pr-reviews.d.ts +4 -0
  285. package/dist/notes/pr-reviews.d.ts.map +1 -1
  286. package/dist/notes/pr-reviews.js +6 -5
  287. package/dist/notes/pr-reviews.js.map +1 -1
  288. package/dist/notes/repo-trail.d.ts +1 -1
  289. package/dist/notes/repo-trail.d.ts.map +1 -1
  290. package/dist/notes/repo-trail.js +24 -4
  291. package/dist/notes/repo-trail.js.map +1 -1
  292. package/dist/search/grep.d.ts.map +1 -1
  293. package/dist/search/grep.js +4 -2
  294. package/dist/search/grep.js.map +1 -1
  295. package/dist/search/user-regexp.d.ts +26 -0
  296. package/dist/search/user-regexp.d.ts.map +1 -0
  297. package/dist/search/user-regexp.js +150 -0
  298. package/dist/search/user-regexp.js.map +1 -0
  299. package/dist/skills/anchors-cli.d.ts +5 -0
  300. package/dist/skills/anchors-cli.d.ts.map +1 -1
  301. package/dist/skills/anchors-cli.js +7 -2
  302. package/dist/skills/anchors-cli.js.map +1 -1
  303. package/dist/skills/anchors-wide.js +2 -2
  304. package/dist/skills/anchors-wide.js.map +1 -1
  305. package/dist/skills/cli-skills-1b.d.ts +17 -0
  306. package/dist/skills/cli-skills-1b.d.ts.map +1 -0
  307. package/dist/skills/cli-skills-1b.js +166 -0
  308. package/dist/skills/cli-skills-1b.js.map +1 -0
  309. package/dist/skills/cli-skills-2.d.ts +35 -0
  310. package/dist/skills/cli-skills-2.d.ts.map +1 -0
  311. package/dist/skills/cli-skills-2.js +129 -0
  312. package/dist/skills/cli-skills-2.js.map +1 -0
  313. package/dist/skills/cli-skills-report-1b.d.ts +49 -0
  314. package/dist/skills/cli-skills-report-1b.d.ts.map +1 -0
  315. package/dist/skills/cli-skills-report-1b.js +191 -0
  316. package/dist/skills/cli-skills-report-1b.js.map +1 -0
  317. package/dist/skills/cli-skills-report.d.ts +86 -0
  318. package/dist/skills/cli-skills-report.d.ts.map +1 -0
  319. package/dist/skills/cli-skills-report.js +121 -0
  320. package/dist/skills/cli-skills-report.js.map +1 -0
  321. package/dist/skills/cli-skills.d.ts +30 -0
  322. package/dist/skills/cli-skills.d.ts.map +1 -0
  323. package/dist/skills/cli-skills.js +379 -0
  324. package/dist/skills/cli-skills.js.map +1 -0
  325. package/dist/skills/compile-split.d.ts.map +1 -1
  326. package/dist/skills/compile-split.js +18 -0
  327. package/dist/skills/compile-split.js.map +1 -1
  328. package/dist/skills/compile-words.d.ts +4 -1
  329. package/dist/skills/compile-words.d.ts.map +1 -1
  330. package/dist/skills/compile-words.js +68 -8
  331. package/dist/skills/compile-words.js.map +1 -1
  332. package/dist/skills/compile.d.ts +7 -0
  333. package/dist/skills/compile.d.ts.map +1 -1
  334. package/dist/skills/compile.js +17 -0
  335. package/dist/skills/compile.js.map +1 -1
  336. package/dist/skills/credit.d.ts +86 -0
  337. package/dist/skills/credit.d.ts.map +1 -0
  338. package/dist/skills/credit.js +259 -0
  339. package/dist/skills/credit.js.map +1 -0
  340. package/dist/skills/fold-gated.d.ts +3 -0
  341. package/dist/skills/fold-gated.d.ts.map +1 -0
  342. package/dist/skills/fold-gated.js +78 -0
  343. package/dist/skills/fold-gated.js.map +1 -0
  344. package/dist/skills/fold.d.ts +87 -0
  345. package/dist/skills/fold.d.ts.map +1 -0
  346. package/dist/skills/fold.js +348 -0
  347. package/dist/skills/fold.js.map +1 -0
  348. package/dist/skills/follow-learnings.d.ts +128 -0
  349. package/dist/skills/follow-learnings.d.ts.map +1 -0
  350. package/dist/skills/follow-learnings.js +278 -0
  351. package/dist/skills/follow-learnings.js.map +1 -0
  352. package/dist/skills/learning-steps.d.ts +43 -0
  353. package/dist/skills/learning-steps.d.ts.map +1 -0
  354. package/dist/skills/learning-steps.js +294 -0
  355. package/dist/skills/learning-steps.js.map +1 -0
  356. package/dist/skills/lesson-gate.d.ts +25 -0
  357. package/dist/skills/lesson-gate.d.ts.map +1 -0
  358. package/dist/skills/lesson-gate.js +316 -0
  359. package/dist/skills/lesson-gate.js.map +1 -0
  360. package/dist/skills/offer-drift.d.ts +35 -0
  361. package/dist/skills/offer-drift.d.ts.map +1 -0
  362. package/dist/skills/offer-drift.js +98 -0
  363. package/dist/skills/offer-drift.js.map +1 -0
  364. package/dist/skills/offer-lesson.d.ts +31 -0
  365. package/dist/skills/offer-lesson.d.ts.map +1 -0
  366. package/dist/skills/offer-lesson.js +123 -0
  367. package/dist/skills/offer-lesson.js.map +1 -0
  368. package/dist/skills/offer-lines.d.ts +40 -0
  369. package/dist/skills/offer-lines.d.ts.map +1 -0
  370. package/dist/skills/offer-lines.js +80 -0
  371. package/dist/skills/offer-lines.js.map +1 -0
  372. package/dist/skills/offer-moment.d.ts +102 -0
  373. package/dist/skills/offer-moment.d.ts.map +1 -0
  374. package/dist/skills/offer-moment.js +260 -0
  375. package/dist/skills/offer-moment.js.map +1 -0
  376. package/dist/skills/offer-repair.d.ts +36 -0
  377. package/dist/skills/offer-repair.d.ts.map +1 -0
  378. package/dist/skills/offer-repair.js +212 -0
  379. package/dist/skills/offer-repair.js.map +1 -0
  380. package/dist/skills/offer-retire.d.ts +53 -0
  381. package/dist/skills/offer-retire.d.ts.map +1 -0
  382. package/dist/skills/offer-retire.js +149 -0
  383. package/dist/skills/offer-retire.js.map +1 -0
  384. package/dist/skills/offer-update.d.ts +54 -0
  385. package/dist/skills/offer-update.d.ts.map +1 -0
  386. package/dist/skills/offer-update.js +115 -0
  387. package/dist/skills/offer-update.js.map +1 -0
  388. package/dist/skills/offer-words-1b.d.ts +32 -0
  389. package/dist/skills/offer-words-1b.d.ts.map +1 -0
  390. package/dist/skills/offer-words-1b.js +80 -0
  391. package/dist/skills/offer-words-1b.js.map +1 -0
  392. package/dist/skills/offer-words-2.d.ts +123 -0
  393. package/dist/skills/offer-words-2.d.ts.map +1 -0
  394. package/dist/skills/offer-words-2.js +194 -0
  395. package/dist/skills/offer-words-2.js.map +1 -0
  396. package/dist/skills/offer-words.d.ts +65 -0
  397. package/dist/skills/offer-words.d.ts.map +1 -0
  398. package/dist/skills/offer-words.js +205 -0
  399. package/dist/skills/offer-words.js.map +1 -0
  400. package/dist/skills/offers.d.ts +66 -0
  401. package/dist/skills/offers.d.ts.map +1 -0
  402. package/dist/skills/offers.js +284 -0
  403. package/dist/skills/offers.js.map +1 -0
  404. package/dist/skills/runblock.d.ts +2 -0
  405. package/dist/skills/runblock.d.ts.map +1 -1
  406. package/dist/skills/runblock.js +11 -6
  407. package/dist/skills/runblock.js.map +1 -1
  408. package/dist/skills/save-gate.d.ts +64 -0
  409. package/dist/skills/save-gate.d.ts.map +1 -0
  410. package/dist/skills/save-gate.js +354 -0
  411. package/dist/skills/save-gate.js.map +1 -0
  412. package/dist/skills/save-verify.d.ts +59 -0
  413. package/dist/skills/save-verify.d.ts.map +1 -0
  414. package/dist/skills/save-verify.js +390 -0
  415. package/dist/skills/save-verify.js.map +1 -0
  416. package/dist/skills/settings.d.ts +12 -2
  417. package/dist/skills/settings.d.ts.map +1 -1
  418. package/dist/skills/settings.js +24 -2
  419. package/dist/skills/settings.js.map +1 -1
  420. package/dist/skills/skills.d.ts +26 -8
  421. package/dist/skills/skills.d.ts.map +1 -1
  422. package/dist/skills/skills.js +105 -52
  423. package/dist/skills/skills.js.map +1 -1
  424. package/dist/skills/types.d.ts +8 -0
  425. package/dist/skills/types.d.ts.map +1 -1
  426. package/dist/skills/update-gate.d.ts +36 -0
  427. package/dist/skills/update-gate.d.ts.map +1 -0
  428. package/dist/skills/update-gate.js +357 -0
  429. package/dist/skills/update-gate.js.map +1 -0
  430. package/dist/skills/update-plan.d.ts +40 -0
  431. package/dist/skills/update-plan.d.ts.map +1 -0
  432. package/dist/skills/update-plan.js +196 -0
  433. package/dist/skills/update-plan.js.map +1 -0
  434. package/dist/skills/value-line.d.ts +94 -0
  435. package/dist/skills/value-line.d.ts.map +1 -0
  436. package/dist/skills/value-line.js +355 -0
  437. package/dist/skills/value-line.js.map +1 -0
  438. package/dist/telemetry/contract.d.ts +15 -1
  439. package/dist/telemetry/contract.d.ts.map +1 -1
  440. package/dist/telemetry/contract.js +80 -11
  441. package/dist/telemetry/contract.js.map +1 -1
  442. package/dist/telemetry/gate.js +4 -4
  443. package/dist/telemetry/gate.js.map +1 -1
  444. package/dist/telemetry/index.d.ts +1 -1
  445. package/dist/telemetry/index.d.ts.map +1 -1
  446. package/dist/telemetry/index.js +1 -1
  447. package/dist/telemetry/index.js.map +1 -1
  448. package/dist/telemetry/notice.js +5 -5
  449. package/dist/telemetry/notice.js.map +1 -1
  450. package/dist/telemetry/queue.d.ts.map +1 -1
  451. package/dist/telemetry/queue.js +7 -7
  452. package/dist/telemetry/queue.js.map +1 -1
  453. package/dist/telemetry/track.d.ts.map +1 -1
  454. package/dist/telemetry/track.js +4 -3
  455. package/dist/telemetry/track.js.map +1 -1
  456. package/dist/trace/checks.d.ts.map +1 -1
  457. package/dist/trace/checks.js +10 -2
  458. package/dist/trace/checks.js.map +1 -1
  459. package/dist/trace/gate-file.d.ts +1 -1
  460. package/dist/trace/gate-file.d.ts.map +1 -1
  461. package/dist/trace/gate-file.js +3 -3
  462. package/dist/trace/gate-file.js.map +1 -1
  463. package/dist/upkeep-run.d.ts.map +1 -1
  464. package/dist/upkeep-run.js +2 -23
  465. package/dist/upkeep-run.js.map +1 -1
  466. package/dist/upkeep.d.ts.map +1 -1
  467. package/dist/upkeep.js +2 -3
  468. package/dist/upkeep.js.map +1 -1
  469. package/dist/util/private-fs.d.ts +6 -0
  470. package/dist/util/private-fs.d.ts.map +1 -1
  471. package/dist/util/private-fs.js +9 -1
  472. package/dist/util/private-fs.js.map +1 -1
  473. package/dist/util/state.d.ts.map +1 -1
  474. package/dist/util/state.js +17 -3
  475. package/dist/util/state.js.map +1 -1
  476. package/package.json +1 -1
  477. package/dist/skills/found-skill.d.ts +0 -35
  478. package/dist/skills/found-skill.d.ts.map +0 -1
  479. package/dist/skills/found-skill.js +0 -66
  480. package/dist/skills/found-skill.js.map +0 -1
@@ -0,0 +1,123 @@
1
+ /**
2
+ * Moment 4 (design 4.14, J07): the person corrected a skill Trail brought
3
+ * in, within 2 typed prompts of its use, in a form Trail can read as a
4
+ * lesson ("no, it didn't push the tag"). At the Stop of that turn Trail
5
+ * offers to add the lesson to the skill, with its exact text in line 2.
6
+ *
7
+ * The prompt hook only records the correction's sha (`creditWindow`); the
8
+ * offer needs the fold to have found the person's own typed line with that
9
+ * sha (`corrected.offset`, `noteCorrectionLine`), so the hook's payload alone
10
+ * never makes an offer and the agent's text can't fill it (R27). The lesson
11
+ * starts from the person's words, read back by that pointer; the fix command
12
+ * is the first new step that worked after the correction, held to the rules
13
+ * every skill step and every repair delta meets (R27, D104).
14
+ *
15
+ * Nothing typed is written: the pending offer keeps the pointer, the fix
16
+ * command and the lesson's sha, and its lines are rebuilt by `offerLinesOf`.
17
+ */
18
+ import { homedir } from 'node:os';
19
+ import { useFor } from '../trace/dialect.js';
20
+ import { commandKind, relativizePaths, stepMatches } from '../trace/shell.js';
21
+ import { secretReason } from '../notes/secrets.js';
22
+ import { gatedKind } from './risk.js';
23
+ import { neverSave } from './never-save.js';
24
+ import { riskyCommand } from './risk-delta.js';
25
+ import { listAllPersonal, readSkill } from './store.js';
26
+ import { readLessons, lessonRefused, lessonSha, lessonText, correctionPhrase } from './lessons.js';
27
+ import { newOfferId, offerBudget } from './offers.js';
28
+ import { typedLineAt } from './offer-lines.js';
29
+ export { offerLinesOf, correctionLesson, correctionLines, typedLineAt } from './offer-lines.js';
30
+ /** A skill with this many lessons gets no more offers (4.14 step 4). */
31
+ export const MAX_LESSONS = 10;
32
+ /** A fix command longer than this is not used: the lesson is the phrase alone (4.14 step 3). */
33
+ const FIX_MAX = 300;
34
+ /** The calls the session still holds that came after `offset` in the transcript, in transcript order. */
35
+ function callsAfter(st, offset) {
36
+ const all = st.runs.flatMap((r) => (Array.isArray(r.calls) ? r.calls : []));
37
+ return all.filter((c) => Number.isInteger(c.src?.use) && c.src.use > offset).sort((a, b) => a.src.use - b.src.use);
38
+ }
39
+ /** A call that ran and worked, with its whole command: a result read, not failed, not in the background. */
40
+ const worked = (c) => !c.failed && typeof c.cmd === 'string' && !c.truncated && !c.secret && c.bg !== true
41
+ && (c.src?.result != null || c.fromMark === true);
42
+ /**
43
+ * 4.14 step 3: the first call after the correction that worked, is a step-kind call and matches no step of the
44
+ * skill, as the lesson holds it: params put back by `lessonText`, paths relativized here. Null (the phrase alone)
45
+ * when there is none, or it carries a secret, is on the never-save list, is gated, teaches a way around a check
46
+ * (D104) or runs past 300 characters. `id` is the call's, also when its command isn't used.
47
+ */
48
+ export function fixCommand(st, offset, steps, params, where) {
49
+ for (const c of callsAfter(st, offset)) {
50
+ if (!worked(c) || c.kind !== 'step' || commandKind(c.cmd) !== 'step')
51
+ continue;
52
+ if (steps.some((s) => stepMatches(s, c.cmd, params)))
53
+ continue;
54
+ const cmd = relativizePaths(c.cmd, where.checkout, where.home).trim();
55
+ const bad = !cmd || cmd.length > FIX_MAX || secretReason(cmd) !== null || neverSave(cmd) !== null || gatedKind(cmd) !== null || riskyCommand(cmd);
56
+ return { id: c.id, cmd: bad ? null : cmd };
57
+ }
58
+ return { id: null, cmd: null };
59
+ }
60
+ /**
61
+ * Moment 4 (4.14). Called first by offerDue at Stop, inside the session lock. Due: the offer to hold as
62
+ * `pendingOffer`, its lines null (rebuilt by offerLinesOf). Writes nothing.
63
+ */
64
+ export function lessonOfferDue(i) {
65
+ const { run, verdict, st, ctx, channel } = i;
66
+ const env = ctx.env;
67
+ if (!ctx.learn)
68
+ return { due: false, why: 'learn' };
69
+ if (st.pendingOffer)
70
+ return { due: false, why: 'pending' };
71
+ const watch = st.lessonWatch;
72
+ if (!watch)
73
+ return { due: false, why: 'no-watch' };
74
+ const credit = st.credit.find((c) => c.useId === watch.useId && c.skillId === watch.skillId && c.corrected?.sha === watch.typedSha);
75
+ const offset = credit?.corrected?.offset;
76
+ // R27: only once the fold met the person's own typed line with the hook's sha.
77
+ if (!credit || typeof offset !== 'number' || !ctx.transcriptPath)
78
+ return { due: false, why: 'no-line' };
79
+ if (verdict.end === 'failure' || verdict.end === 'question')
80
+ return { due: false, why: 'end' };
81
+ const ref = listAllPersonal(env).find((r) => r.id === watch.skillId);
82
+ const skill = ref ? readSkill(ref) : null;
83
+ if (!ref || !skill)
84
+ return { due: false, why: 'skill' };
85
+ if (readLessons(ref.dir).length >= MAX_LESSONS)
86
+ return { due: false, why: 'lessons' };
87
+ const typed = typedLineAt(ctx.transcriptPath, offset, watch.typedSha, env, useFor(st.host, st));
88
+ const phrase = typed === null ? null : correctionPhrase(typed);
89
+ if (!phrase)
90
+ return { due: false, why: 'phrase' };
91
+ const repo = run.repoKey || ctx.repoKey;
92
+ const key = `${watch.skillId}|correction`;
93
+ // P18, R40: a pending offer this same correction withdrew frees the session's slot for this one offer only.
94
+ const freed = st.withdrewFor?.typedSha === watch.typedSha;
95
+ const budget = offerBudget({ repoKey: repo, key, sessionOfferUsed: st.offerUsed && !freed, now: ctx.now, env });
96
+ if (!budget.ok)
97
+ return { due: false, why: `budget:${budget.why}` };
98
+ const inj = st.injected.find((x) => x.injId === credit.injId);
99
+ const params = inj && inj.params && typeof inj.params === 'object' ? inj.params : {};
100
+ const fix = fixCommand(st, offset, skill.steps.map((s) => s.cmd), params, { checkout: ctx.checkout, home: env.HOME || homedir() });
101
+ let text = lessonText(phrase, fix.cmd, params);
102
+ const alone = lessonText(phrase, null, params);
103
+ if (!text || !alone)
104
+ return { due: false, why: 'phrase' };
105
+ // The fix as the lesson holds it (params put back), so offerLinesOf rebuilds this very text from the typed line.
106
+ let kept = fix.cmd && text.startsWith(`${alone}: `) ? text.slice(alone.length + 2) : null;
107
+ if (kept !== null && lessonText(phrase, kept, {}) !== text)
108
+ kept = null;
109
+ if (kept === null || lessonRefused(text)) {
110
+ kept = null;
111
+ text = alone;
112
+ }
113
+ // D109: the final text is held to the run block's rule too (a skip-the-ask lesson is never offered).
114
+ if (lessonRefused(text))
115
+ return { due: false, why: 'refused' };
116
+ const offer = {
117
+ offerId: newOfferId(), moment: 'correction', runId: credit.runId ?? run.id, name: skill.name, key, lines: null, channel,
118
+ shownAt: channel === 'post-tool' ? null : ctx.now.toISOString(), showMe: false, yes: null, typedAfter: [], repo,
119
+ correction: { skillId: watch.skillId, useId: watch.useId, typed: { offset, sha: watch.typedSha }, fixCallId: fix.id, lessonSha: lessonSha(text), fix: kept },
120
+ };
121
+ return { due: true, offer };
122
+ }
123
+ //# sourceMappingURL=offer-lesson.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offer-lesson.js","sourceRoot":"","sources":["../../src/skills/offer-lesson.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * The two lines of a pending offer (design 1.4, P17, R12). A moment-2 or
3
+ * moment-3 offer keeps them in the session file. A moment-4 offer can't: its
4
+ * first line quotes the person's correction and its lesson starts from their
5
+ * words, and no typed text is ever written to disk (0 rule 6). So it keeps a
6
+ * pointer to the typed line (offset and sha), the fix command and the
7
+ * lesson's sha, and its lines are rebuilt here from the transcript each time
8
+ * they are read. When the line is gone, isn't the person's, or no longer
9
+ * gives the same lesson, there are no lines: the offer is dropped, never
10
+ * shown or answered with other words.
11
+ *
12
+ * Every reader of `PendingOffer.lines` goes through `offerLinesOf` (R12).
13
+ * Re-exported from `offer-lesson.ts`, where the design names it.
14
+ */
15
+ import type { PendingOffer } from '../trace/types.js';
16
+ import { type DialectUse } from '../trace/dialect.js';
17
+ /** What a reader needs of an offer to know its lines. */
18
+ export type OfferLinesIn = Pick<PendingOffer, 'lines'> & Partial<Pick<PendingOffer, 'moment' | 'name' | 'correction'>>;
19
+ /**
20
+ * The person's typed line at `offset`, when its words still hash to `sha`; null otherwise. D133: read through the
21
+ * host's dialect when `use` is given (a Codex line is the person's only by its keyed hash, P30); Claude's reader without.
22
+ */
23
+ export declare function typedLineAt(transcriptPath: string, offset: number, sha: string, env?: NodeJS.ProcessEnv, use?: DialectUse): string | null;
24
+ /**
25
+ * Moment 4's lesson and the words it quotes, from the correction line and the fix command (4.14 steps 2 and 5):
26
+ * null when the line can't be read back, has no correction phrase, or gives a lesson whose sha isn't `lessonSha`.
27
+ */
28
+ export declare function correctionLesson(c: NonNullable<PendingOffer['correction']>, transcriptPath: string | null, env?: NodeJS.ProcessEnv, use?: DialectUse): {
29
+ said: string;
30
+ text: string;
31
+ kind: 'lesson' | 'guardrail';
32
+ } | null;
33
+ /** Moment 4's 2 lines (J07): `You corrected {skill}: {said}.` and the question with the lesson's exact text. */
34
+ export declare function correctionLines(skill: string, said: string, text: string): [string, string];
35
+ /**
36
+ * The two lines of any pending offer: `o.lines`, or for a 'correction' rebuilt from the transcript (a correction's
37
+ * stored lines are never read). Null when the correction line is gone or its sha changed, or the offer has none.
38
+ */
39
+ export declare function offerLinesOf(o: OfferLinesIn | null | undefined, transcriptPath: string | null, env?: NodeJS.ProcessEnv, use?: DialectUse): [string, string] | null;
40
+ //# sourceMappingURL=offer-lines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offer-lines.d.ts","sourceRoot":"","sources":["../../src/skills/offer-lines.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AASnE,yDAAyD;AACzD,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,QAAQ,GAAG,MAAM,GAAG,YAAY,CAAC,CAAC,CAAC;AAEvH;;;GAGG;AACH,wBAAgB,WAAW,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAiBtJ;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,GAAG,CAAC,EAAE,UAAU,GAChK;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,WAAW,CAAA;CAAE,GAAG,IAAI,CAQpE;AAED,gHAAgH;AAChH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAM3F;AAID;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,GAAG,SAAS,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAY/K"}
@@ -0,0 +1,80 @@
1
+ import { isTypedByPerson, typedText } from '../trace/claude.js';
2
+ import { typedOnLine } from '../trace/dialect.js';
3
+ import { typedSha } from '../trace/typed.js';
4
+ import { flatLine } from '../notes/flatten.js';
5
+ import { lineAt } from './receipts.js';
6
+ import { correctionPhrase, LESSON_COPY, lessonRefused, lessonSha, lessonText } from './lessons.js';
7
+ const LINE_MAX = 400;
8
+ const fill = (t, v) => t.replace(/\{(\w+)\}/g, (m, k) => v[k] ?? m);
9
+ /**
10
+ * The person's typed line at `offset`, when its words still hash to `sha`; null otherwise. D133: read through the
11
+ * host's dialect when `use` is given (a Codex line is the person's only by its keyed hash, P30); Claude's reader without.
12
+ */
13
+ export function typedLineAt(transcriptPath, offset, sha, env = process.env, use) {
14
+ if (!Number.isInteger(offset) || offset < 0 || typeof sha !== 'string')
15
+ return null;
16
+ const line = lineAt(transcriptPath, offset);
17
+ if (line === null)
18
+ return null;
19
+ let entry;
20
+ try {
21
+ entry = JSON.parse(line);
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ if (use && use.dialect.host !== 'claude') {
27
+ const said = typedOnLine(entry, use, env);
28
+ return said && typedSha(said) === sha ? said : null;
29
+ }
30
+ if (!isTypedByPerson(entry, env))
31
+ return null;
32
+ const text = typedText(entry, env);
33
+ return typedSha(text) === sha ? text : null;
34
+ }
35
+ /**
36
+ * Moment 4's lesson and the words it quotes, from the correction line and the fix command (4.14 steps 2 and 5):
37
+ * null when the line can't be read back, has no correction phrase, or gives a lesson whose sha isn't `lessonSha`.
38
+ */
39
+ export function correctionLesson(c, transcriptPath, env = process.env, use) {
40
+ if (!transcriptPath || !c || !c.typed)
41
+ return null;
42
+ const typed = typedLineAt(transcriptPath, c.typed.offset, c.typed.sha, env, use);
43
+ const phrase = typed === null ? null : correctionPhrase(typed);
44
+ if (!phrase)
45
+ return null;
46
+ const text = lessonText(phrase, typeof c.fix === 'string' && c.fix ? c.fix : null, {});
47
+ if (!text || lessonRefused(text) || lessonSha(text) !== c.lessonSha)
48
+ return null;
49
+ return { said: phrase.said, text, kind: phrase.kind };
50
+ }
51
+ /** Moment 4's 2 lines (J07): `You corrected {skill}: {said}.` and the question with the lesson's exact text. */
52
+ export function correctionLines(skill, said, text) {
53
+ return [
54
+ flatLine(fill(LESSON_COPY.offerFirst, { skill: flatLine(skill, 60), said: flatLine(said, 120) }), LINE_MAX),
55
+ // D114 (3), as moment 3's line 2 (b7 review): the quotes inside the quoted lesson become single ones.
56
+ flatLine(fill(LESSON_COPY.offerSecond, { lesson: flatLine(text, 200).replace(/["\u201c\u201d]/g, "'") }), LINE_MAX),
57
+ ];
58
+ }
59
+ const pair = (v) => Array.isArray(v) && v.length === 2 && typeof v[0] === 'string' && typeof v[1] === 'string' && !!v[0] && !!v[1];
60
+ /**
61
+ * The two lines of any pending offer: `o.lines`, or for a 'correction' rebuilt from the transcript (a correction's
62
+ * stored lines are never read). Null when the correction line is gone or its sha changed, or the offer has none.
63
+ */
64
+ export function offerLinesOf(o, transcriptPath, env = process.env, use) {
65
+ try {
66
+ if (!o)
67
+ return null;
68
+ if (o.moment === 'correction') {
69
+ if (!o.correction)
70
+ return null;
71
+ const l = correctionLesson(o.correction, transcriptPath, env, use);
72
+ return l ? correctionLines(String(o.name ?? ''), l.said, l.text) : null;
73
+ }
74
+ return pair(o.lines) ? o.lines : null;
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ //# sourceMappingURL=offer-lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offer-lines.js","sourceRoot":"","sources":["../../src/skills/offer-lines.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,WAAW,EAAmB,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEnG,MAAM,QAAQ,GAAG,GAAG,CAAC;AACrB,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,CAAyB,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAK5G;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,cAAsB,EAAE,MAAc,EAAE,GAAW,EAAE,MAAyB,OAAO,CAAC,GAAG,EAAE,GAAgB;IACrI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACpF,MAAM,IAAI,GAAG,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/B,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;QAC1C,OAAO,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACtD,CAAC;IACD,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,CAA0C,EAAE,cAA6B,EAAE,MAAyB,OAAO,CAAC,GAAG,EAAE,GAAgB;IAEhK,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,KAAK,GAAG,WAAW,CAAC,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACjF,MAAM,MAAM,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACvF,IAAI,CAAC,IAAI,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IACjF,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;AACxD,CAAC;AAED,gHAAgH;AAChH,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,IAAY,EAAE,IAAY;IACvE,OAAO;QACL,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,UAAW,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC;QAC5G,sGAAsG;QACtG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,WAAY,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC;KACrH,CAAC;AACJ,CAAC;AAED,MAAM,IAAI,GAAG,CAAC,CAAU,EAAyB,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEnK;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,CAAkC,EAAE,cAA6B,EAAE,MAAyB,OAAO,CAAC,GAAG,EAAE,GAAgB;IACpJ,IAAI,CAAC;QACH,IAAI,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;QACpB,IAAI,CAAC,CAAC,MAAM,KAAK,YAAY,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,CAAC,UAAU;gBAAE,OAAO,IAAI,CAAC;YAC/B,MAAM,CAAC,GAAG,gBAAgB,CAAC,CAAC,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACnE,OAAO,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC1E,CAAC;QACD,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,102 @@
1
+ import type { CheckedVerdict, FoldResult } from '../trace/runs.js';
2
+ import type { GateCtx } from '../trace/skill-session.js';
3
+ import type { OfferChannel, PendingOffer, RunSheet, RunState, SkillSessionState, TypedAnswer } from '../trace/types.js';
4
+ import type { CompiledSkill, HookOut } from './types.js';
5
+ import { compileRun } from './compile.js';
6
+ import { type OfferLinesIn } from './offer-lines.js';
7
+ import type { FoldPlanner } from './offer-update.js';
8
+ import type { Fired, Settled } from './credit.js';
9
+ import { type DialectUse } from '../trace/dialect.js';
10
+ /**
11
+ * What a yes to an offer agrees to: the skill's steps (the calls each was copied from, and its text with the
12
+ * skill's own name taken out) and its check. The gate saves only a skill with the same sha (4.9 step 5): steps run
13
+ * after the offer, or a run sheet changed since, are not what the person said yes to.
14
+ */
15
+ export declare function skillSha(c: CompiledSkill): string;
16
+ /**
17
+ * The repo an offer is for: its `repo` (1b), else from its key, '<repoKey>|job:<job>' or '<repoKey>|wall:<cls>|<program>'.
18
+ * A skill-keyed offer ('<skillId>|correction', phase 2's update, drift and retire keys) names no repo: '' without
19
+ * `repo` (D126).
20
+ */
21
+ export declare function offerRepo(o: Pick<PendingOffer, 'key'> & {
22
+ repo?: unknown;
23
+ }): string;
24
+ export interface Captured {
25
+ /** Return this now (a directive for yes, show me or no); null: go on to 3.2 step 5. */
26
+ out: HookOut | null;
27
+ /** Going on: context to add first (the agent said the offer and the person moved on). */
28
+ extra?: string;
29
+ /** For telemetry `skill_answer`: the class, or why the offer was dropped unanswered; null with no offer, or for a
30
+ * second yes after the first (ignored, D70: nothing to send). */
31
+ answer: TypedAnswer | 'stale' | 'not-shown' | null;
32
+ /** Phase 2 (4.9): the prompt hook retired the skill on this answer (for telemetry `skill_changed{retire}`). */
33
+ changed?: 'retire';
34
+ }
35
+ /**
36
+ * 3.2 step 4, on the session state inside the prompt hook's lock. Only the first typed prompt after the offer
37
+ * answers it, or the second after one "show me". A `yes` sets `pendingOffer.yes` from this prompt's own words
38
+ * (hashed), which the gate later matches against the person's line in the transcript.
39
+ */
40
+ export declare function captureAnswer(st: SkillSessionState, typed: string, env?: NodeJS.ProcessEnv, now?: Date, o?: {
41
+ transcriptPath?: string | null;
42
+ }): Captured;
43
+ /**
44
+ * 3.2 step 6.4: the person asked to keep a run. Spends the session's offer, withdraws a pending one, and records
45
+ * the request with this prompt's words hashed. When this hook's catch-up already folded the typed line (Claude Code
46
+ * wrote it before the hook ran), its offset is taken from `fold.typed` now: the fold only fills `typed` for a line
47
+ * it meets after the request exists. `skill` is the skill compiled for this ask (3.2 step 6.3); its `skillSha` is
48
+ * kept (D73): the gate keeps only that skill, so steps run or written into the sheet after the ask are not what was
49
+ * asked for.
50
+ */
51
+ export declare function noteSaveRequest(st: SkillSessionState, fold: Pick<FoldResult, 'typed'> | null, req: {
52
+ runId: string;
53
+ typed: string;
54
+ scope: NonNullable<SkillSessionState['saveRequest']>['scope'];
55
+ skill: CompiledSkill;
56
+ }, env?: NodeJS.ProcessEnv, now?: Date): void;
57
+ export interface OfferInput {
58
+ run: RunState;
59
+ /** checkedSuccess(run, lastAssistant) (Stop) or with lastAssistant null (post-tool, 3.4). */
60
+ verdict: CheckedVerdict;
61
+ /** The run's sheet as written for this verdict. */
62
+ sheet: RunSheet | null;
63
+ st: SkillSessionState;
64
+ /** 1b: Stop passes its whole GateCtx; moment 4 reads the transcript (no transcript: no moment 4). */
65
+ ctx: Pick<GateCtx, 'learn' | 'checkout' | 'repoKey' | 'env' | 'now'> & Partial<Pick<GateCtx, 'transcriptPath'>>;
66
+ channel: OfferChannel;
67
+ /** Phase 2 (moments 5 and 6): c2's foldInputFor and replan (update-gate.ts); without them neither is due. */
68
+ plan?: FoldPlanner;
69
+ /** Phase 2: the uses this Stop's settle flushed (moment 5 needs this run's, checked). */
70
+ settled?: Settled[];
71
+ /** Phase 2: the firings this Stop's settle wrote (the retire proposal needs a not-followed one). */
72
+ fired?: Fired[];
73
+ }
74
+ export type OfferDue = {
75
+ due: true;
76
+ offer: PendingOffer;
77
+ } | {
78
+ due: false;
79
+ why: 'learn' | 'pending' | 'job' | 'skill' | 'not-checked' | 'family' | 'no-repo' | 'covered' | 'not-repeated' | 'no-sheet' | 'compile' | 'one-step' | 'unknown-repo' | `budget:${string}`;
80
+ };
81
+ /** Phase 2 (4.10, P18): the order offerDue tries the moments in; the first that is due is the offer. */
82
+ export declare const OFFER_ORDER: readonly ["correction", "drift", "update", "repaired", "repeated", "retire"];
83
+ /**
84
+ * 1b (4.13, 4.14, 3.5 step 6), phase 2 (4.10, P18): moment 4, 6, 5, 3, 2, then the retire proposal, the first that is
85
+ * due. All but moment 2 are Stop's only (stop and notice channels, R13); none due, the answer is moment 2's. Writes
86
+ * nothing: the caller records it shown.
87
+ */
88
+ export declare function offerDue(i: OfferInput): OfferDue;
89
+ /** What compile makes of an offer's run, exactly as the save gate's compile of its yes will (moments 2 and 3, R58). */
90
+ export declare function compileOffered(sheet: RunSheet, st: SkillSessionState, ctx: OfferInput['ctx']): ReturnType<typeof compileRun>;
91
+ /**
92
+ * Moment 2: 4.12 conditions 1 to 6, in order. Due: the offer to hold as `pendingOffer` (shown now for `stop` and
93
+ * `notice`; `shownAt` null for `post-tool`, set when the reply carries it). Writes nothing.
94
+ */
95
+ export declare function repeatedOfferDue(i: OfferInput): OfferDue;
96
+ /**
97
+ * For g7's Stop (3.5 steps 6 and 7): the agent's reply carried the offer, as its last line. A reply that adds a
98
+ * question of its own after the offer, or leaves it out, did not: the offer is recorded not shown and dropped, so
99
+ * the person's next yes can't be taken as a yes to the skill.
100
+ */
101
+ export declare function offerEndsReply(o: OfferLinesIn, reply: string | null, transcriptPath?: string | null, use?: DialectUse): boolean;
102
+ //# sourceMappingURL=offer-moment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"offer-moment.d.ts","sourceRoot":"","sources":["../../src/skills/offer-moment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,260 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { homedir } from 'node:os';
3
+ import { typedSha } from '../trace/typed.js';
4
+ import { OFFER_FAMILIES } from '../trace/jobs.js';
5
+ import { readPool, repeatedEnough } from '../trace/pool.js';
6
+ import { findPriorSheet, joinCarriedSheet, readRunSheet } from '../trace/runs.js';
7
+ import { compileRun } from './compile.js';
8
+ import { stableBranches } from './compile-words.js';
9
+ import { jobCovered, nameTaken } from './store.js';
10
+ import { stepsTotal } from './store-fs.js';
11
+ import { answerDirective, endsWithLine, newOfferId, offerBudget, offerLines, recordAnswer, recordNotShown } from './offers.js';
12
+ import { offerLinesOf } from './offer-lines.js';
13
+ import { isLessonOffer } from './offer-words-1b.js';
14
+ import { lessonOfferDue } from './offer-lesson.js';
15
+ import { repairOfferDue } from './offer-repair.js';
16
+ import { classifyFor } from './offer-answers.js';
17
+ import { updateOfferDue } from './offer-update.js';
18
+ import { driftOfferDue } from './offer-drift.js';
19
+ import { replyEndedWithOffer, retireOfferDue, retireSkill } from './offer-retire.js';
20
+ import { answer2 } from './offer-words-2.js';
21
+ import { skillOfOfferKey } from './offers.js';
22
+ import { runCheckout } from './run-checkout.js';
23
+ import { repoKnown } from '../trace/known-repo.js';
24
+ import { useFor } from '../trace/dialect.js';
25
+ import { stepLearnings, withFollowLine } from './follow-learnings.js';
26
+ const SAME_LINE_MS = 5000;
27
+ /**
28
+ * What a yes to an offer agrees to: the skill's steps (the calls each was copied from, and its text with the
29
+ * skill's own name taken out) and its check. The gate saves only a skill with the same sha (4.9 step 5): steps run
30
+ * after the offer, or a run sheet changed since, are not what the person said yes to.
31
+ */
32
+ export function skillSha(c) {
33
+ const own = (t) => (c.name ? t.split(c.name).join('\u0000') : t);
34
+ const steps = c.steps.map((s) => [(s.from ?? []).join(','), own(s.cmd)]);
35
+ return createHash('sha256').update(JSON.stringify([steps, own(c.check), c.checkIsStep])).digest('hex');
36
+ }
37
+ /**
38
+ * The repo an offer is for: its `repo` (1b), else from its key, '<repoKey>|job:<job>' or '<repoKey>|wall:<cls>|<program>'.
39
+ * A skill-keyed offer ('<skillId>|correction', phase 2's update, drift and retire keys) names no repo: '' without
40
+ * `repo` (D126).
41
+ */
42
+ export function offerRepo(o) {
43
+ if (typeof o.repo === 'string' && o.repo)
44
+ return o.repo;
45
+ if (skillOfOfferKey(o.key) !== null)
46
+ return '';
47
+ const i = o.key.lastIndexOf('|job:');
48
+ if (i >= 0)
49
+ return o.key.slice(0, i);
50
+ const w = o.key.indexOf('|wall:');
51
+ return w < 0 ? o.key : o.key.slice(0, w);
52
+ }
53
+ /**
54
+ * 3.2 step 4, on the session state inside the prompt hook's lock. Only the first typed prompt after the offer
55
+ * answers it, or the second after one "show me". A `yes` sets `pendingOffer.yes` from this prompt's own words
56
+ * (hashed), which the gate later matches against the person's line in the transcript.
57
+ */
58
+ export function captureAnswer(st, typed, env = process.env, now = new Date(), o = {}) {
59
+ const po = st.pendingOffer;
60
+ if (!po)
61
+ return { out: null, answer: null };
62
+ const repo = offerRepo(po);
63
+ const plain = { paused: false, firstNo: false };
64
+ if (po.yes) {
65
+ // D70: two quick yeses keep the save once. The first counts (its line is the consent); the second is
66
+ // ignored: no second directive, no answer recorded, the offer stays for the agent's add.
67
+ if (classifyFor(po.moment, typed, po.showMe) === 'yes')
68
+ return { out: null, answer: null };
69
+ // Anything else: answered in an earlier prompt, and the agent had that turn to save.
70
+ st.pendingOffer = null;
71
+ return { out: null, answer: 'stale' };
72
+ }
73
+ if (po.shownAt === null) {
74
+ recordNotShown(po, repo, env, now);
75
+ st.pendingOffer = null;
76
+ return { out: null, answer: 'not-shown' };
77
+ }
78
+ // Phase 2 (4.10): by the offer's own words (drift's replace is its yes, retire is retire).
79
+ const said = classifyFor(po.moment, typed, po.showMe);
80
+ // 1b: a lesson offer asks yes or no; its whole text is already in line 2, so "show me" is no answer to it.
81
+ // Phase 2 (D72, R1): a retire moves the skill only after the agent's reply ended with the offer's line 2.
82
+ const a = said === 'show' && isLessonOffer(po) ? 'other'
83
+ : said === 'retire' && !(po.retire && replyEndedWithOffer(po, typed, o.transcriptPath ?? null, env, useFor(st.host, st))) ? 'other' : said;
84
+ switch (a) {
85
+ case 'retire': {
86
+ // 4.9, P12: the one write the prompt hook makes on an answer: a move `trail skills restore` undoes.
87
+ const r = retireSkill(po.retire.name, 'retire-offer', env, now, po.retire.skillId);
88
+ recordAnswer(po, repo, 'yes', env, now, 'retire');
89
+ st.pendingOffer = null;
90
+ return { out: answer2('retire', po, { ...plain, retired: r.ok ? po.retire.name : null }, env, typed, st.host), answer: 'retire', ...(r.ok ? { changed: 'retire' } : {}) };
91
+ }
92
+ case 'yes':
93
+ recordAnswer(po, repo, 'yes', env, now, po.fold?.op);
94
+ po.yes = { at: now.toISOString(), typedSha: typedSha(typed) };
95
+ return { out: answerDirective('yes', po, plain, env, typed, st.host), answer: 'yes' };
96
+ case 'show':
97
+ recordAnswer(po, repo, 'show', env, now);
98
+ po.showMe = true;
99
+ return { out: answerDirective('show', po, plain, env, typed, st.host), answer: 'show' };
100
+ case 'no': {
101
+ const c = recordAnswer(po, repo, 'no', env, now);
102
+ st.pendingOffer = null;
103
+ return { out: answerDirective('no', po, c, env, typed, st.host), answer: 'no' };
104
+ }
105
+ case 'correction':
106
+ recordAnswer(po, repo, 'withdrawn', env, now);
107
+ st.pendingOffer = null;
108
+ // P18, R40: only the lesson offer for this same correction may use the slot it freed, at this turn's Stop. A
109
+ // withdrawn lesson offer frees nothing: the slot is for a pending offer of another moment (4.14, b4 review).
110
+ st.withdrewFor = po.moment === 'correction' ? null : { typedSha: typedSha(typed) };
111
+ return { out: null, answer: 'correction' };
112
+ default: {
113
+ recordAnswer(po, repo, 'none', env, now);
114
+ st.pendingOffer = null;
115
+ const d = answerDirective('other', po, plain, env, typed, st.host);
116
+ return d.context ? { out: null, extra: d.context, answer: 'other' } : { out: null, answer: 'other' };
117
+ }
118
+ }
119
+ }
120
+ /**
121
+ * 3.2 step 6.4: the person asked to keep a run. Spends the session's offer, withdraws a pending one, and records
122
+ * the request with this prompt's words hashed. When this hook's catch-up already folded the typed line (Claude Code
123
+ * wrote it before the hook ran), its offset is taken from `fold.typed` now: the fold only fills `typed` for a line
124
+ * it meets after the request exists. `skill` is the skill compiled for this ask (3.2 step 6.3); its `skillSha` is
125
+ * kept (D73): the gate keeps only that skill, so steps run or written into the sheet after the ask are not what was
126
+ * asked for.
127
+ */
128
+ export function noteSaveRequest(st, fold, req, env = process.env, now = new Date()) {
129
+ const sha = typedSha(req.typed);
130
+ const line = (fold?.typed ?? []).filter((t) => t.sha === sha && t.offset >= 0 && Date.parse(t.at) >= now.getTime() - SAME_LINE_MS).pop();
131
+ if (st.pendingOffer) {
132
+ recordAnswer(st.pendingOffer, offerRepo(st.pendingOffer), 'withdrawn', env, now);
133
+ st.pendingOffer = null;
134
+ }
135
+ st.saveRequest = {
136
+ runId: req.runId, at: now.toISOString(), typedSha: sha, scope: req.scope, typed: line ? { offset: line.offset, sha } : null, skillSha: skillSha(req.skill), name: req.skill.name,
137
+ };
138
+ st.offerUsed = true;
139
+ st.offerUsedBy = 'asked';
140
+ }
141
+ /** Phase 2 (4.10, P18): the order offerDue tries the moments in; the first that is due is the offer. */
142
+ export const OFFER_ORDER = ['correction', 'drift', 'update', 'repaired', 'repeated', 'retire'];
143
+ /**
144
+ * 1b (4.13, 4.14, 3.5 step 6), phase 2 (4.10, P18): moment 4, 6, 5, 3, 2, then the retire proposal, the first that is
145
+ * due. All but moment 2 are Stop's only (stop and notice channels, R13); none due, the answer is moment 2's. Writes
146
+ * nothing: the caller records it shown.
147
+ */
148
+ export function offerDue(i) {
149
+ // D117 (3), J16: no offer in a repo Trail doesn't know (no .trail/, not in the repo index).
150
+ if (!repoKnown(i.run.repoKey, i.run.checkout ?? (i.run.repoKey === i.ctx.repoKey ? i.ctx.checkout : ''), i.ctx.env))
151
+ return { due: false, why: 'unknown-repo' };
152
+ const atStop = i.channel !== 'post-tool' && i.ctx.learn && !i.st.pendingOffer;
153
+ if (atStop) {
154
+ const m4 = lessonOfferDue({ ...i, ctx: { ...i.ctx, transcriptPath: i.ctx.transcriptPath ?? null } });
155
+ if (m4.due)
156
+ return m4;
157
+ const m6 = driftOfferDue(i);
158
+ if (m6.due)
159
+ return m6;
160
+ const m5 = updateOfferDue(i);
161
+ if (m5.due)
162
+ return m5;
163
+ const m3 = repairOfferDue(i);
164
+ if (m3.due)
165
+ return m3;
166
+ }
167
+ const m2 = repeatedOfferDue(i);
168
+ if (m2.due || !atStop)
169
+ return m2;
170
+ const retire = retireOfferDue(i, i.fired ?? []);
171
+ return retire.due ? retire : m2;
172
+ }
173
+ /** What compile makes of an offer's run, exactly as the save gate's compile of its yes will (moments 2 and 3, R58). */
174
+ export function compileOffered(sheet, st, ctx) {
175
+ const env = ctx.env;
176
+ const scope = { repoKeys: [...new Set([...st.scopeKeys, sheet.repoKey])], checkout: ctx.checkout, env };
177
+ const read = (id) => readRunSheet(id, env);
178
+ // D93: the run's own checkout, as both halves of the save gate compile it.
179
+ const root = runCheckout(sheet, env, ctx.repoKey === sheet.repoKey ? ctx.checkout : '');
180
+ return compileRun(sheet, {
181
+ repoRoot: root, home: env.HOME || homedir(), platform: process.platform,
182
+ prior: findPriorSheet(sheet, env), moment: 'repeated', applies: sheet.repoKey, now: ctx.now, readSheet: read,
183
+ taken: (n) => nameTaken(n, { ...scope, checkout: root || scope.checkout }) !== null,
184
+ learnings: stepLearnings({ repoKeys: [sheet.repoKey], checkout: root, env }),
185
+ });
186
+ }
187
+ /**
188
+ * Moment 2: 4.12 conditions 1 to 6, in order. Due: the offer to hold as `pendingOffer` (shown now for `stop` and
189
+ * `notice`; `shownAt` null for `post-tool`, set when the reply carries it). Writes nothing.
190
+ */
191
+ export function repeatedOfferDue(i) {
192
+ const { run, verdict, st, ctx, channel } = i;
193
+ const env = ctx.env;
194
+ const now = ctx.now;
195
+ if (!ctx.learn)
196
+ return { due: false, why: 'learn' };
197
+ if (st.pendingOffer)
198
+ return { due: false, why: 'pending' };
199
+ const job = run.job;
200
+ const families = job ? OFFER_FAMILIES[job] : undefined;
201
+ if (!job || !families)
202
+ return { due: false, why: 'job' };
203
+ if (run.skillId)
204
+ return { due: false, why: 'skill' };
205
+ if (!verdict.checked || verdict.checkIndex === null)
206
+ return { due: false, why: 'not-checked' };
207
+ const hit = run.calls[verdict.checkIndex]?.check;
208
+ if (!hit || !hit.passed || !families.includes(hit.family))
209
+ return { due: false, why: 'family' };
210
+ if (!run.repoKey)
211
+ return { due: false, why: 'no-repo' };
212
+ const scope = { repoKeys: [...new Set([...st.scopeKeys, run.repoKey])], checkout: ctx.checkout, env };
213
+ if (jobCovered(job, scope))
214
+ return { due: false, why: 'covered' };
215
+ const key = `${run.repoKey}|job:${job}`;
216
+ const budget = offerBudget({ repoKey: run.repoKey, key, sessionOfferUsed: st.offerUsed, now, env });
217
+ if (!budget.ok)
218
+ return { due: false, why: `budget:${budget.why}` };
219
+ const pool = readPool(run.repoKey, env).jobs[job];
220
+ const rep = pool ? repeatedEnough(pool, budget.extraDay, now) : null;
221
+ if (!rep || !rep.ok)
222
+ return { due: false, why: 'not-repeated' };
223
+ const sheet = i.sheet;
224
+ if (!sheet || sheet.id !== run.id)
225
+ return { due: false, why: 'no-sheet' };
226
+ const read = (id) => readRunSheet(id, env);
227
+ const compiled = compileOffered(sheet, st, ctx);
228
+ if (!compiled.ok)
229
+ return { due: false, why: 'compile' };
230
+ // D70: a skill of one Run step is not offered; a one-command job is better kept as a lesson.
231
+ if (compiled.skill.steps.length < 2)
232
+ return { due: false, why: 'one-step' };
233
+ const joined = joinCarriedSheet(sheet, read);
234
+ const ownDates = rep.dates === rep.sessionDays;
235
+ const seen = { n: ownDates ? rep.dates : rep.sessionDays, unit: ownDates ? 'day' : 'time' };
236
+ const lines = withFollowLine(offerLines({
237
+ job, check: hit, ordinal: seen.n, unit: seen.unit,
238
+ commands: joined.counts.commands, failed: joined.counts.failed, steps: stepsTotal(compiled.skill), where: 'this repo',
239
+ branches: job === 'ship' ? stableBranches(joined.calls, joined.jobWords) : [],
240
+ }), compiled.skill.followed);
241
+ return {
242
+ due: true,
243
+ offer: {
244
+ offerId: newOfferId(), moment: 'repeated', runId: run.id, name: compiled.skill.name, key, lines, channel,
245
+ shownAt: channel === 'post-tool' ? null : now.toISOString(), showMe: false, yes: null, typedAfter: [],
246
+ skillSha: skillSha(compiled.skill), seen,
247
+ },
248
+ };
249
+ }
250
+ /**
251
+ * For g7's Stop (3.5 steps 6 and 7): the agent's reply carried the offer, as its last line. A reply that adds a
252
+ * question of its own after the offer, or leaves it out, did not: the offer is recorded not shown and dropped, so
253
+ * the person's next yes can't be taken as a yes to the skill.
254
+ */
255
+ export function offerEndsReply(o, reply, transcriptPath = null, use) {
256
+ // 1b (R12): through offerLinesOf; an offer with no lines (a correction whose line is gone or changed) never ends a reply.
257
+ const l = reply === null ? null : offerLinesOf(o, transcriptPath, process.env, use);
258
+ return l !== null && endsWithLine(reply, l[1]);
259
+ }
260
+ //# sourceMappingURL=offer-moment.js.map