@productbrain/cli 0.1.0-beta.108 → 0.1.0-beta.1087

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 (412) hide show
  1. package/dist/__tests__/audit.test.js +5 -0
  2. package/dist/__tests__/audit.test.js.map +1 -1
  3. package/dist/__tests__/canonicalRefs.vocab.test.d.ts +2 -0
  4. package/dist/__tests__/canonicalRefs.vocab.test.d.ts.map +1 -0
  5. package/dist/__tests__/canonicalRefs.vocab.test.js +251 -0
  6. package/dist/__tests__/canonicalRefs.vocab.test.js.map +1 -0
  7. package/dist/__tests__/config.test.js +272 -2
  8. package/dist/__tests__/config.test.js.map +1 -1
  9. package/dist/__tests__/constants.test.js +6 -1
  10. package/dist/__tests__/constants.test.js.map +1 -1
  11. package/dist/__tests__/envelope-contract.test.js +29 -3
  12. package/dist/__tests__/envelope-contract.test.js.map +1 -1
  13. package/dist/__tests__/errors.test.js +1 -0
  14. package/dist/__tests__/errors.test.js.map +1 -1
  15. package/dist/__tests__/handshake-augment.test.d.ts +2 -0
  16. package/dist/__tests__/handshake-augment.test.d.ts.map +1 -0
  17. package/dist/__tests__/handshake-augment.test.js +423 -0
  18. package/dist/__tests__/handshake-augment.test.js.map +1 -0
  19. package/dist/__tests__/handshake-dormancy.test.d.ts +2 -0
  20. package/dist/__tests__/handshake-dormancy.test.d.ts.map +1 -0
  21. package/dist/__tests__/handshake-dormancy.test.js +207 -0
  22. package/dist/__tests__/handshake-dormancy.test.js.map +1 -0
  23. package/dist/__tests__/handshake-formatter.test.d.ts +2 -0
  24. package/dist/__tests__/handshake-formatter.test.d.ts.map +1 -0
  25. package/dist/__tests__/handshake-formatter.test.js +67 -0
  26. package/dist/__tests__/handshake-formatter.test.js.map +1 -0
  27. package/dist/__tests__/handshake-preview.test.js +566 -4
  28. package/dist/__tests__/handshake-preview.test.js.map +1 -1
  29. package/dist/__tests__/handshake.e2e.test.d.ts +2 -0
  30. package/dist/__tests__/handshake.e2e.test.d.ts.map +1 -0
  31. package/dist/__tests__/handshake.e2e.test.js +1252 -0
  32. package/dist/__tests__/handshake.e2e.test.js.map +1 -0
  33. package/dist/__tests__/handshake.test.js +255 -5
  34. package/dist/__tests__/handshake.test.js.map +1 -1
  35. package/dist/__tests__/manifest.test.js +118 -1
  36. package/dist/__tests__/manifest.test.js.map +1 -1
  37. package/dist/__tests__/notice-marker.test.d.ts +2 -0
  38. package/dist/__tests__/notice-marker.test.d.ts.map +1 -0
  39. package/dist/__tests__/notice-marker.test.js +41 -0
  40. package/dist/__tests__/notice-marker.test.js.map +1 -0
  41. package/dist/__tests__/onboarding-path-b.test.js +4 -4
  42. package/dist/__tests__/onboarding-path-b.test.js.map +1 -1
  43. package/dist/__tests__/orient.test.js +117 -26
  44. package/dist/__tests__/orient.test.js.map +1 -1
  45. package/dist/__tests__/perimeter.test.d.ts +2 -0
  46. package/dist/__tests__/perimeter.test.d.ts.map +1 -0
  47. package/dist/__tests__/perimeter.test.js +165 -0
  48. package/dist/__tests__/perimeter.test.js.map +1 -0
  49. package/dist/__tests__/preview-key-refresh.test.d.ts +2 -0
  50. package/dist/__tests__/preview-key-refresh.test.d.ts.map +1 -0
  51. package/dist/__tests__/preview-key-refresh.test.js +126 -0
  52. package/dist/__tests__/preview-key-refresh.test.js.map +1 -0
  53. package/dist/__tests__/profiles.test.js +106 -2
  54. package/dist/__tests__/profiles.test.js.map +1 -1
  55. package/dist/__tests__/promote.test.js +2 -2
  56. package/dist/__tests__/promote.test.js.map +1 -1
  57. package/dist/__tests__/session-reset.test.d.ts +2 -0
  58. package/dist/__tests__/session-reset.test.d.ts.map +1 -0
  59. package/dist/__tests__/session-reset.test.js +122 -0
  60. package/dist/__tests__/session-reset.test.js.map +1 -0
  61. package/dist/__tests__/session-resume-backstop.test.d.ts +2 -0
  62. package/dist/__tests__/session-resume-backstop.test.d.ts.map +1 -0
  63. package/dist/__tests__/session-resume-backstop.test.js +97 -0
  64. package/dist/__tests__/session-resume-backstop.test.js.map +1 -0
  65. package/dist/__tests__/session-start-key-refresh.test.d.ts +2 -0
  66. package/dist/__tests__/session-start-key-refresh.test.d.ts.map +1 -0
  67. package/dist/__tests__/session-start-key-refresh.test.js +178 -0
  68. package/dist/__tests__/session-start-key-refresh.test.js.map +1 -0
  69. package/dist/__tests__/session-state-machine.test.js +45 -1
  70. package/dist/__tests__/session-state-machine.test.js.map +1 -1
  71. package/dist/__tests__/session-switch.test.d.ts +2 -0
  72. package/dist/__tests__/session-switch.test.d.ts.map +1 -0
  73. package/dist/__tests__/session-switch.test.js +130 -0
  74. package/dist/__tests__/session-switch.test.js.map +1 -0
  75. package/dist/__tests__/setup-ingest.test.js +16 -0
  76. package/dist/__tests__/setup-ingest.test.js.map +1 -1
  77. package/dist/__tests__/skill-vocabulary.test.d.ts +21 -0
  78. package/dist/__tests__/skill-vocabulary.test.d.ts.map +1 -0
  79. package/dist/__tests__/skill-vocabulary.test.js +187 -0
  80. package/dist/__tests__/skill-vocabulary.test.js.map +1 -0
  81. package/dist/__tests__/update-check.test.d.ts +2 -0
  82. package/dist/__tests__/update-check.test.d.ts.map +1 -0
  83. package/dist/__tests__/update-check.test.js +215 -0
  84. package/dist/__tests__/update-check.test.js.map +1 -0
  85. package/dist/__tests__/upgrade-runner.test.d.ts +2 -0
  86. package/dist/__tests__/upgrade-runner.test.d.ts.map +1 -0
  87. package/dist/__tests__/upgrade-runner.test.js +54 -0
  88. package/dist/__tests__/upgrade-runner.test.js.map +1 -0
  89. package/dist/__tests__/upgrade.test.d.ts +2 -0
  90. package/dist/__tests__/upgrade.test.d.ts.map +1 -0
  91. package/dist/__tests__/upgrade.test.js +56 -0
  92. package/dist/__tests__/upgrade.test.js.map +1 -0
  93. package/dist/__tests__/vocabulary-leak.test.d.ts +39 -0
  94. package/dist/__tests__/vocabulary-leak.test.d.ts.map +1 -0
  95. package/dist/__tests__/vocabulary-leak.test.js +534 -0
  96. package/dist/__tests__/vocabulary-leak.test.js.map +1 -0
  97. package/dist/commands/__tests__/connect-handoff.test.d.ts +11 -0
  98. package/dist/commands/__tests__/connect-handoff.test.d.ts.map +1 -0
  99. package/dist/commands/__tests__/connect-handoff.test.js +111 -0
  100. package/dist/commands/__tests__/connect-handoff.test.js.map +1 -0
  101. package/dist/commands/__tests__/setup-detect-surfaces.test.d.ts +15 -0
  102. package/dist/commands/__tests__/setup-detect-surfaces.test.d.ts.map +1 -0
  103. package/dist/commands/__tests__/setup-detect-surfaces.test.js +149 -0
  104. package/dist/commands/__tests__/setup-detect-surfaces.test.js.map +1 -0
  105. package/dist/commands/__tests__/setup-state.test.d.ts +2 -0
  106. package/dist/commands/__tests__/setup-state.test.d.ts.map +1 -0
  107. package/dist/commands/__tests__/setup-state.test.js +194 -0
  108. package/dist/commands/__tests__/setup-state.test.js.map +1 -0
  109. package/dist/commands/admin/seed.d.ts +32 -2
  110. package/dist/commands/admin/seed.d.ts.map +1 -1
  111. package/dist/commands/admin/seed.js +279 -33
  112. package/dist/commands/admin/seed.js.map +1 -1
  113. package/dist/commands/admin/seed.test.js +7 -0
  114. package/dist/commands/admin/seed.test.js.map +1 -1
  115. package/dist/commands/admin/seedRegistryEntries.generated.d.ts +14 -0
  116. package/dist/commands/admin/seedRegistryEntries.generated.d.ts.map +1 -0
  117. package/dist/commands/admin/seedRegistryEntries.generated.js +117 -0
  118. package/dist/commands/admin/seedRegistryEntries.generated.js.map +1 -0
  119. package/dist/commands/admin/seedRegistryEntries.test.d.ts +11 -0
  120. package/dist/commands/admin/seedRegistryEntries.test.d.ts.map +1 -0
  121. package/dist/commands/admin/seedRegistryEntries.test.js +67 -0
  122. package/dist/commands/admin/seedRegistryEntries.test.js.map +1 -0
  123. package/dist/commands/audit.d.ts.map +1 -1
  124. package/dist/commands/audit.js +30 -3
  125. package/dist/commands/audit.js.map +1 -1
  126. package/dist/commands/authority-domains.d.ts +7 -1
  127. package/dist/commands/authority-domains.d.ts.map +1 -1
  128. package/dist/commands/authority-domains.js +19 -4
  129. package/dist/commands/authority-domains.js.map +1 -1
  130. package/dist/commands/capture.d.ts +2 -0
  131. package/dist/commands/capture.d.ts.map +1 -1
  132. package/dist/commands/capture.js +8 -3
  133. package/dist/commands/capture.js.map +1 -1
  134. package/dist/commands/codex-prep.js +6 -6
  135. package/dist/commands/codex-prep.js.map +1 -1
  136. package/dist/commands/connect-config.test.d.ts +2 -0
  137. package/dist/commands/connect-config.test.d.ts.map +1 -0
  138. package/dist/commands/connect-config.test.js +44 -0
  139. package/dist/commands/connect-config.test.js.map +1 -0
  140. package/dist/commands/connect-context.d.ts +45 -0
  141. package/dist/commands/connect-context.d.ts.map +1 -0
  142. package/dist/commands/connect-context.js +64 -0
  143. package/dist/commands/connect-context.js.map +1 -0
  144. package/dist/commands/connect-context.test.d.ts +2 -0
  145. package/dist/commands/connect-context.test.d.ts.map +1 -0
  146. package/dist/commands/connect-context.test.js +110 -0
  147. package/dist/commands/connect-context.test.js.map +1 -0
  148. package/dist/commands/connect-handoff.d.ts +51 -0
  149. package/dist/commands/connect-handoff.d.ts.map +1 -0
  150. package/dist/commands/connect-handoff.js +70 -0
  151. package/dist/commands/connect-handoff.js.map +1 -0
  152. package/dist/commands/connect-integration.test.js +13 -12
  153. package/dist/commands/connect-integration.test.js.map +1 -1
  154. package/dist/commands/connect-screens.d.ts +7 -8
  155. package/dist/commands/connect-screens.d.ts.map +1 -1
  156. package/dist/commands/connect-screens.js +30 -37
  157. package/dist/commands/connect-screens.js.map +1 -1
  158. package/dist/commands/connect.d.ts +19 -6
  159. package/dist/commands/connect.d.ts.map +1 -1
  160. package/dist/commands/connect.js +31 -56
  161. package/dist/commands/connect.js.map +1 -1
  162. package/dist/commands/doctor.d.ts.map +1 -1
  163. package/dist/commands/doctor.js +67 -2
  164. package/dist/commands/doctor.js.map +1 -1
  165. package/dist/commands/doctor.test.js +150 -0
  166. package/dist/commands/doctor.test.js.map +1 -1
  167. package/dist/commands/handshake.d.ts +84 -4
  168. package/dist/commands/handshake.d.ts.map +1 -1
  169. package/dist/commands/handshake.js +1169 -97
  170. package/dist/commands/handshake.js.map +1 -1
  171. package/dist/commands/method.d.ts.map +1 -1
  172. package/dist/commands/method.js +5 -1
  173. package/dist/commands/method.js.map +1 -1
  174. package/dist/commands/orient.d.ts +52 -2
  175. package/dist/commands/orient.d.ts.map +1 -1
  176. package/dist/commands/orient.js +41 -7
  177. package/dist/commands/orient.js.map +1 -1
  178. package/dist/commands/profile.d.ts +1 -14
  179. package/dist/commands/profile.d.ts.map +1 -1
  180. package/dist/commands/profile.js +89 -72
  181. package/dist/commands/profile.js.map +1 -1
  182. package/dist/commands/reject.d.ts.map +1 -1
  183. package/dist/commands/reject.js +2 -1
  184. package/dist/commands/reject.js.map +1 -1
  185. package/dist/commands/relate.d.ts.map +1 -1
  186. package/dist/commands/relate.js +4 -2
  187. package/dist/commands/relate.js.map +1 -1
  188. package/dist/commands/session.d.ts +26 -2
  189. package/dist/commands/session.d.ts.map +1 -1
  190. package/dist/commands/session.js +216 -31
  191. package/dist/commands/session.js.map +1 -1
  192. package/dist/commands/setup-audit.d.ts +59 -0
  193. package/dist/commands/setup-audit.d.ts.map +1 -0
  194. package/dist/commands/setup-audit.js +250 -0
  195. package/dist/commands/setup-audit.js.map +1 -0
  196. package/dist/commands/setup-detect-surfaces.d.ts +38 -0
  197. package/dist/commands/setup-detect-surfaces.d.ts.map +1 -0
  198. package/dist/commands/setup-detect-surfaces.js +76 -0
  199. package/dist/commands/setup-detect-surfaces.js.map +1 -0
  200. package/dist/commands/setup-ingest.d.ts.map +1 -1
  201. package/dist/commands/setup-ingest.js +4 -2
  202. package/dist/commands/setup-ingest.js.map +1 -1
  203. package/dist/commands/setup-state.d.ts +42 -0
  204. package/dist/commands/setup-state.d.ts.map +1 -0
  205. package/dist/commands/setup-state.js +93 -0
  206. package/dist/commands/setup-state.js.map +1 -0
  207. package/dist/commands/setup.d.ts +17 -9
  208. package/dist/commands/setup.d.ts.map +1 -1
  209. package/dist/commands/setup.js +52 -131
  210. package/dist/commands/setup.js.map +1 -1
  211. package/dist/commands/update.d.ts.map +1 -1
  212. package/dist/commands/update.js +2 -1
  213. package/dist/commands/update.js.map +1 -1
  214. package/dist/commands/upgrade.d.ts +5 -0
  215. package/dist/commands/upgrade.d.ts.map +1 -0
  216. package/dist/commands/upgrade.js +110 -0
  217. package/dist/commands/upgrade.js.map +1 -0
  218. package/dist/commands/verify.d.ts.map +1 -1
  219. package/dist/commands/verify.js +2 -1
  220. package/dist/commands/verify.js.map +1 -1
  221. package/dist/commands/whoami.d.ts +12 -0
  222. package/dist/commands/whoami.d.ts.map +1 -0
  223. package/dist/commands/whoami.js +70 -0
  224. package/dist/commands/whoami.js.map +1 -0
  225. package/dist/commands/whoami.test.d.ts +2 -0
  226. package/dist/commands/whoami.test.d.ts.map +1 -0
  227. package/dist/commands/whoami.test.js +50 -0
  228. package/dist/commands/whoami.test.js.map +1 -0
  229. package/dist/formatters/__tests__/orient-provenance.test.d.ts +7 -0
  230. package/dist/formatters/__tests__/orient-provenance.test.d.ts.map +1 -0
  231. package/dist/formatters/__tests__/orient-provenance.test.js +454 -0
  232. package/dist/formatters/__tests__/orient-provenance.test.js.map +1 -0
  233. package/dist/formatters/audit.d.ts +6 -0
  234. package/dist/formatters/audit.d.ts.map +1 -1
  235. package/dist/formatters/audit.js.map +1 -1
  236. package/dist/formatters/entry.d.ts +21 -0
  237. package/dist/formatters/entry.d.ts.map +1 -1
  238. package/dist/formatters/entry.js +46 -5
  239. package/dist/formatters/entry.js.map +1 -1
  240. package/dist/formatters/handshake.d.ts +19 -3
  241. package/dist/formatters/handshake.d.ts.map +1 -1
  242. package/dist/formatters/handshake.js +47 -12
  243. package/dist/formatters/handshake.js.map +1 -1
  244. package/dist/formatters/orient.d.ts +64 -4
  245. package/dist/formatters/orient.d.ts.map +1 -1
  246. package/dist/formatters/orient.js +103 -18
  247. package/dist/formatters/orient.js.map +1 -1
  248. package/dist/generators/adapters.js +4 -4
  249. package/dist/generators/context-md.js +6 -6
  250. package/dist/generators/context-md.js.map +1 -1
  251. package/dist/generators/manifest.d.ts +76 -0
  252. package/dist/generators/manifest.d.ts.map +1 -1
  253. package/dist/generators/manifest.js +125 -14
  254. package/dist/generators/manifest.js.map +1 -1
  255. package/dist/generators/portable-knowledge.d.ts +2 -2
  256. package/dist/generators/portable-knowledge.d.ts.map +1 -1
  257. package/dist/generators/region-projections.d.ts +18 -0
  258. package/dist/generators/region-projections.d.ts.map +1 -0
  259. package/dist/generators/region-projections.js +49 -0
  260. package/dist/generators/region-projections.js.map +1 -0
  261. package/dist/generators/region-projections.test.d.ts +2 -0
  262. package/dist/generators/region-projections.test.d.ts.map +1 -0
  263. package/dist/generators/region-projections.test.js +63 -0
  264. package/dist/generators/region-projections.test.js.map +1 -0
  265. package/dist/generators/region.d.ts +24 -0
  266. package/dist/generators/region.d.ts.map +1 -0
  267. package/dist/generators/region.js +87 -0
  268. package/dist/generators/region.js.map +1 -0
  269. package/dist/generators/region.test.d.ts +2 -0
  270. package/dist/generators/region.test.d.ts.map +1 -0
  271. package/dist/generators/region.test.js +126 -0
  272. package/dist/generators/region.test.js.map +1 -0
  273. package/dist/generators/surface-profiles.d.ts +1 -2
  274. package/dist/generators/surface-profiles.d.ts.map +1 -1
  275. package/dist/generators/surface-profiles.js.map +1 -1
  276. package/dist/index.js +144 -25
  277. package/dist/index.js.map +1 -1
  278. package/dist/lib/activation.js +2 -2
  279. package/dist/lib/activation.js.map +1 -1
  280. package/dist/lib/activation.test.js +3 -3
  281. package/dist/lib/activation.test.js.map +1 -1
  282. package/dist/lib/canonicalRefs.d.ts +72 -0
  283. package/dist/lib/canonicalRefs.d.ts.map +1 -1
  284. package/dist/lib/canonicalRefs.js +67 -0
  285. package/dist/lib/canonicalRefs.js.map +1 -1
  286. package/dist/lib/client.d.ts.map +1 -1
  287. package/dist/lib/client.js +13 -3
  288. package/dist/lib/client.js.map +1 -1
  289. package/dist/lib/config.d.ts +101 -4
  290. package/dist/lib/config.d.ts.map +1 -1
  291. package/dist/lib/config.js +225 -11
  292. package/dist/lib/config.js.map +1 -1
  293. package/dist/lib/constants.d.ts +2 -0
  294. package/dist/lib/constants.d.ts.map +1 -1
  295. package/dist/lib/constants.js +2 -0
  296. package/dist/lib/constants.js.map +1 -1
  297. package/dist/lib/errors.d.ts +1 -0
  298. package/dist/lib/errors.d.ts.map +1 -1
  299. package/dist/lib/errors.js +1 -0
  300. package/dist/lib/errors.js.map +1 -1
  301. package/dist/lib/notice-marker.d.ts +3 -0
  302. package/dist/lib/notice-marker.d.ts.map +1 -0
  303. package/dist/lib/notice-marker.js +53 -0
  304. package/dist/lib/notice-marker.js.map +1 -0
  305. package/dist/lib/onboarding-path-b.d.ts.map +1 -1
  306. package/dist/lib/onboarding-path-b.js +0 -1
  307. package/dist/lib/onboarding-path-b.js.map +1 -1
  308. package/dist/lib/onboarding-shared.d.ts +0 -1
  309. package/dist/lib/onboarding-shared.d.ts.map +1 -1
  310. package/dist/lib/onboarding-shared.js +1 -17
  311. package/dist/lib/onboarding-shared.js.map +1 -1
  312. package/dist/lib/profiles.d.ts +3 -1
  313. package/dist/lib/profiles.d.ts.map +1 -1
  314. package/dist/lib/profiles.js +9 -6
  315. package/dist/lib/profiles.js.map +1 -1
  316. package/dist/lib/session.d.ts +10 -0
  317. package/dist/lib/session.d.ts.map +1 -1
  318. package/dist/lib/session.js +26 -1
  319. package/dist/lib/session.js.map +1 -1
  320. package/dist/lib/update-check.d.ts +42 -7
  321. package/dist/lib/update-check.d.ts.map +1 -1
  322. package/dist/lib/update-check.js +213 -62
  323. package/dist/lib/update-check.js.map +1 -1
  324. package/dist/lib/upgrade-runner.d.ts +22 -0
  325. package/dist/lib/upgrade-runner.d.ts.map +1 -0
  326. package/dist/lib/upgrade-runner.js +110 -0
  327. package/dist/lib/upgrade-runner.js.map +1 -0
  328. package/dist/lib/workspaceVocabCache.d.ts +60 -0
  329. package/dist/lib/workspaceVocabCache.d.ts.map +1 -0
  330. package/dist/lib/workspaceVocabCache.js +98 -0
  331. package/dist/lib/workspaceVocabCache.js.map +1 -0
  332. package/dist/setup/__tests__/coach-traces.test.d.ts +2 -0
  333. package/dist/setup/__tests__/coach-traces.test.d.ts.map +1 -0
  334. package/dist/setup/__tests__/coach-traces.test.js +189 -0
  335. package/dist/setup/__tests__/coach-traces.test.js.map +1 -0
  336. package/dist/setup/__tests__/setup-commands.test.d.ts +2 -0
  337. package/dist/setup/__tests__/setup-commands.test.d.ts.map +1 -0
  338. package/dist/setup/__tests__/setup-commands.test.js +177 -0
  339. package/dist/setup/__tests__/setup-commands.test.js.map +1 -0
  340. package/dist/setup/__tests__/state-machine.test.d.ts +2 -0
  341. package/dist/setup/__tests__/state-machine.test.d.ts.map +1 -0
  342. package/dist/setup/__tests__/state-machine.test.js +341 -0
  343. package/dist/setup/__tests__/state-machine.test.js.map +1 -0
  344. package/dist/setup/detect-surfaces.d.ts +21 -0
  345. package/dist/setup/detect-surfaces.d.ts.map +1 -0
  346. package/dist/setup/detect-surfaces.js +39 -0
  347. package/dist/setup/detect-surfaces.js.map +1 -0
  348. package/dist/setup/manifest-writer.d.ts +17 -0
  349. package/dist/setup/manifest-writer.d.ts.map +1 -0
  350. package/dist/setup/manifest-writer.js +153 -0
  351. package/dist/setup/manifest-writer.js.map +1 -0
  352. package/dist/setup/perimeter.d.ts +72 -0
  353. package/dist/setup/perimeter.d.ts.map +1 -0
  354. package/dist/setup/perimeter.js +128 -0
  355. package/dist/setup/perimeter.js.map +1 -0
  356. package/dist/setup/state-machine.d.ts +67 -0
  357. package/dist/setup/state-machine.d.ts.map +1 -0
  358. package/dist/setup/state-machine.js +124 -0
  359. package/dist/setup/state-machine.js.map +1 -0
  360. package/dist/surfaces/__tests__/adapter.test.d.ts +2 -0
  361. package/dist/surfaces/__tests__/adapter.test.d.ts.map +1 -0
  362. package/dist/surfaces/__tests__/adapter.test.js +90 -0
  363. package/dist/surfaces/__tests__/adapter.test.js.map +1 -0
  364. package/dist/surfaces/__tests__/pb-setup-passthrough.test.d.ts +2 -0
  365. package/dist/surfaces/__tests__/pb-setup-passthrough.test.d.ts.map +1 -0
  366. package/dist/surfaces/__tests__/pb-setup-passthrough.test.js +132 -0
  367. package/dist/surfaces/__tests__/pb-setup-passthrough.test.js.map +1 -0
  368. package/dist/surfaces/__tests__/telemetry.test.d.ts +2 -0
  369. package/dist/surfaces/__tests__/telemetry.test.d.ts.map +1 -0
  370. package/dist/surfaces/__tests__/telemetry.test.js +55 -0
  371. package/dist/surfaces/__tests__/telemetry.test.js.map +1 -0
  372. package/dist/surfaces/adapter.d.ts +70 -0
  373. package/dist/surfaces/adapter.d.ts.map +1 -0
  374. package/dist/surfaces/adapter.js +2 -0
  375. package/dist/surfaces/adapter.js.map +1 -0
  376. package/dist/surfaces/adapters/claude.d.ts +3 -0
  377. package/dist/surfaces/adapters/claude.d.ts.map +1 -0
  378. package/dist/surfaces/adapters/claude.js +67 -0
  379. package/dist/surfaces/adapters/claude.js.map +1 -0
  380. package/dist/surfaces/adapters/codex.d.ts +3 -0
  381. package/dist/surfaces/adapters/codex.d.ts.map +1 -0
  382. package/dist/surfaces/adapters/codex.js +61 -0
  383. package/dist/surfaces/adapters/codex.js.map +1 -0
  384. package/dist/surfaces/adapters/copilot.d.ts +3 -0
  385. package/dist/surfaces/adapters/copilot.d.ts.map +1 -0
  386. package/dist/surfaces/adapters/copilot.js +59 -0
  387. package/dist/surfaces/adapters/copilot.js.map +1 -0
  388. package/dist/surfaces/adapters/cursor.d.ts +3 -0
  389. package/dist/surfaces/adapters/cursor.d.ts.map +1 -0
  390. package/dist/surfaces/adapters/cursor.js +78 -0
  391. package/dist/surfaces/adapters/cursor.js.map +1 -0
  392. package/dist/surfaces/registry.d.ts +58 -2
  393. package/dist/surfaces/registry.d.ts.map +1 -1
  394. package/dist/surfaces/registry.js +82 -7
  395. package/dist/surfaces/registry.js.map +1 -1
  396. package/dist/surfaces/telemetry.d.ts +17 -0
  397. package/dist/surfaces/telemetry.d.ts.map +1 -0
  398. package/dist/surfaces/telemetry.js +31 -0
  399. package/dist/surfaces/telemetry.js.map +1 -0
  400. package/package.json +3 -1
  401. package/dist/__tests__/setup.test.d.ts +0 -2
  402. package/dist/__tests__/setup.test.d.ts.map +0 -1
  403. package/dist/__tests__/setup.test.js +0 -141
  404. package/dist/__tests__/setup.test.js.map +0 -1
  405. package/dist/generators/__tests__/surface-profiles.test.d.ts +0 -2
  406. package/dist/generators/__tests__/surface-profiles.test.d.ts.map +0 -1
  407. package/dist/generators/__tests__/surface-profiles.test.js +0 -89
  408. package/dist/generators/__tests__/surface-profiles.test.js.map +0 -1
  409. package/dist/lib/onboarding-phases.d.ts +0 -9
  410. package/dist/lib/onboarding-phases.d.ts.map +0 -1
  411. package/dist/lib/onboarding-phases.js +0 -120
  412. package/dist/lib/onboarding-phases.js.map +0 -1
@@ -0,0 +1,130 @@
1
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
+ const mockKernelCall = vi.fn();
3
+ vi.mock('../lib/client.js', () => ({
4
+ kernelCall: (...a) => mockKernelCall(...a),
5
+ kernelCallWithSession: vi.fn(),
6
+ }));
7
+ const mockGetConfigOrGuide = vi.fn(async () => ({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' }));
8
+ const mockResolveEffectiveProfile = vi.fn(() => ({ profile: 'p', source: 'local' }));
9
+ const mockReadLocalProjectConfig = vi.fn(() => null);
10
+ vi.mock('../lib/config.js', () => ({
11
+ getConfigOrGuide: (...a) => mockGetConfigOrGuide(...a),
12
+ resolveEffectiveProfile: () => mockResolveEffectiveProfile(),
13
+ readLocalProjectConfig: () => mockReadLocalProjectConfig(),
14
+ readProjectConfig: vi.fn(() => null),
15
+ refreshPreviewApiKeyFromDisk: vi.fn(() => 'not-bound'),
16
+ }));
17
+ vi.mock('../lib/profiles.js', () => ({ getActiveProfile: vi.fn(() => 'p') }));
18
+ const mockReadSession = vi.fn();
19
+ const mockWriteSession = vi.fn();
20
+ const mockDiscardSession = vi.fn();
21
+ const mockReadClosedMarker = vi.fn(() => null);
22
+ vi.mock('../lib/session.js', () => ({
23
+ readSession: () => mockReadSession(),
24
+ writeSession: (...a) => mockWriteSession(...a),
25
+ clearSession: vi.fn(),
26
+ discardSession: () => mockDiscardSession(),
27
+ readClosedMarker: () => mockReadClosedMarker(),
28
+ sessionFileExists: vi.fn(() => false),
29
+ addCapturedEntry: vi.fn(),
30
+ }));
31
+ vi.mock('../commands/handshake.js', () => ({ runHandshake: vi.fn(async () => { }) }));
32
+ import { runSessionStart, runSessionClose } from '../commands/session.js';
33
+ describe('runSessionStart switch-backstop', () => {
34
+ beforeEach(() => {
35
+ vi.clearAllMocks();
36
+ mockGetConfigOrGuide.mockResolvedValue({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' });
37
+ mockReadClosedMarker.mockReturnValue(null);
38
+ mockReadLocalProjectConfig.mockReturnValue(null);
39
+ });
40
+ it('discards a session whose profile differs from the current effective profile, then starts fresh', async () => {
41
+ mockReadSession.mockReturnValue({
42
+ sessionId: 's-old', workspaceId: 'w-old', workspaceName: 'Old',
43
+ startedAt: '2026-01-01T00:00:00Z', entriesCaptured: [], profile: 'old',
44
+ });
45
+ mockResolveEffectiveProfile.mockReturnValue({ profile: 'new', source: 'local' });
46
+ mockKernelCall.mockImplementation(async (method) => {
47
+ if (method === 'resolveWorkspace')
48
+ return { _id: 'w-new', keyId: 'k1' };
49
+ if (method === 'agent.startSession')
50
+ return { sessionId: 's-new', workspaceName: 'New', initiatedBy: 'cli', toolsScope: 'rw' };
51
+ return {};
52
+ });
53
+ await runSessionStart({ json: true });
54
+ expect(mockDiscardSession).toHaveBeenCalled();
55
+ expect(mockWriteSession).toHaveBeenCalledWith(expect.objectContaining({ sessionId: 's-new', profile: 'new' }));
56
+ });
57
+ it('discards and starts fresh on a profile switch in pretty (non-json) mode too', async () => {
58
+ mockReadSession.mockReturnValue({
59
+ sessionId: 's-old', workspaceId: 'w-old', workspaceName: 'Old',
60
+ startedAt: '2026-01-01T00:00:00Z', entriesCaptured: [], profile: 'old',
61
+ });
62
+ mockResolveEffectiveProfile.mockReturnValue({ profile: 'new', source: 'local' });
63
+ mockKernelCall.mockImplementation(async (method) => {
64
+ if (method === 'resolveWorkspace')
65
+ return { _id: 'w-new', keyId: 'k1' };
66
+ if (method === 'agent.startSession')
67
+ return { sessionId: 's-new', workspaceName: 'New', initiatedBy: 'cli', toolsScope: 'rw' };
68
+ return {};
69
+ });
70
+ const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
71
+ try {
72
+ await runSessionStart({}); // no json → pretty mode
73
+ expect(mockDiscardSession).toHaveBeenCalled();
74
+ expect(mockKernelCall).toHaveBeenCalledWith('agent.startSession', expect.anything());
75
+ expect(mockWriteSession).toHaveBeenCalledWith(expect.objectContaining({ sessionId: 's-new', profile: 'new' }));
76
+ }
77
+ finally {
78
+ writeSpy.mockRestore();
79
+ }
80
+ });
81
+ it('preserves alreadyActive for a legacy session with no profile field (no discard)', async () => {
82
+ mockReadSession.mockReturnValue({
83
+ sessionId: 's1', workspaceId: 'w1', workspaceName: 'WS',
84
+ startedAt: '2026-01-01T00:00:00Z', entriesCaptured: [], // NOTE: no `profile`
85
+ });
86
+ mockResolveEffectiveProfile.mockReturnValue({ profile: 'new', source: 'local' });
87
+ const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
88
+ try {
89
+ await runSessionStart({ json: true });
90
+ const out = writeSpy.mock.calls.map((c) => String(c[0])).join('');
91
+ expect(out).toMatch(/alreadyActive/);
92
+ expect(mockDiscardSession).not.toHaveBeenCalled();
93
+ }
94
+ finally {
95
+ writeSpy.mockRestore();
96
+ }
97
+ });
98
+ it('keeps alreadyActive when the effective profile is unchanged', async () => {
99
+ mockReadSession.mockReturnValue({
100
+ sessionId: 's1', workspaceId: 'w1', workspaceName: 'WS',
101
+ startedAt: '2026-01-01T00:00:00Z', entriesCaptured: [], profile: 'same',
102
+ });
103
+ mockResolveEffectiveProfile.mockReturnValue({ profile: 'same', source: 'local' });
104
+ const writeSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
105
+ try {
106
+ await runSessionStart({ json: true });
107
+ const out = writeSpy.mock.calls.map((c) => String(c[0])).join('');
108
+ expect(out).toMatch(/alreadyActive/);
109
+ expect(mockDiscardSession).not.toHaveBeenCalled();
110
+ }
111
+ finally {
112
+ writeSpy.mockRestore();
113
+ }
114
+ });
115
+ });
116
+ describe('runSessionClose --force hint', () => {
117
+ beforeEach(() => {
118
+ vi.clearAllMocks();
119
+ mockGetConfigOrGuide.mockResolvedValue({ apiKey: 'pb_sk_test', siteUrl: 'https://test.convex.site' });
120
+ mockReadSession.mockReturnValue({
121
+ sessionId: 's1', workspaceId: 'w1', workspaceName: 'WS',
122
+ startedAt: '2026-01-01T00:00:00Z', entriesCaptured: [],
123
+ });
124
+ });
125
+ it('puts the --force instruction in the error message itself', async () => {
126
+ mockKernelCall.mockRejectedValue(new Error('Internal server error'));
127
+ await expect(runSessionClose({})).rejects.toThrow(/pb session close --force/);
128
+ });
129
+ });
130
+ //# sourceMappingURL=session-switch.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-switch.test.js","sourceRoot":"","sources":["../../src/__tests__/session-switch.test.ts"],"names":[],"mappings":"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"}
@@ -51,5 +51,21 @@ assetKind: bundle
51
51
  path: '/repo/skills/bundle.md',
52
52
  });
53
53
  });
54
+ it('forwards frontmatter id to setup.ingestSetupAsset', async () => {
55
+ kernelCallMock.mockResolvedValue({ action: 'created', entryId: 'SETUP-SKILL-FM' });
56
+ fileContents['/repo/.productbrain/skills/local.md'] = `---
57
+ id: SETUP-SKILL-FM
58
+ name: Local
59
+ ---
60
+ # Local
61
+ `;
62
+ await runSetupIngest('.productbrain/skills/local.md');
63
+ expect(kernelCallMock).toHaveBeenCalledWith('setup.ingestSetupAsset', expect.objectContaining({
64
+ entryId: 'SETUP-SKILL-LOCAL',
65
+ frontmatterId: 'SETUP-SKILL-FM',
66
+ name: 'Local',
67
+ assetKind: 'skill',
68
+ }));
69
+ });
54
70
  });
55
71
  //# sourceMappingURL=setup-ingest.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"setup-ingest.test.js","sourceRoot":"","sources":["../../src/__tests__/setup-ingest.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"setup-ingest.test.js","sourceRoot":"","sources":["../../src/__tests__/setup-ingest.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Skill vocabulary fixture tests — WP-436 S3.
3
+ *
4
+ * 3 skill files × 3 workspace presets = 9 fixture assertions.
5
+ *
6
+ * Each test renders a tokenized skill file content through replaceVocabTokens
7
+ * with the given workspace preset and asserts:
8
+ * 1. No un-tokenized noun-form "bet" / "Bet" / "bets" / "Bets" remains
9
+ * outside exclusions (code fences, inline code, already-tokenized lines).
10
+ * 2. No raw {{vocab:...}} token survives (resolver is exhaustive).
11
+ * 3. The rendered content contains the expected singular label for the preset.
12
+ *
13
+ * Workspace presets (methodology-neutral):
14
+ * - Shape Up: singular=Bet, plural=Bets, verb_start=shape, verb_complete=ship
15
+ * - Generic: singular=Initiative, plural=Initiatives, verb_start=start, verb_complete=complete
16
+ * - Linear: singular=Issue, plural=Issues, verb_start=begin, verb_complete=archive
17
+ *
18
+ * Chain: WP-436 S3, STD-253, DEC-1021.
19
+ */
20
+ export {};
21
+ //# sourceMappingURL=skill-vocabulary.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-vocabulary.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/skill-vocabulary.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Skill vocabulary fixture tests — WP-436 S3.
3
+ *
4
+ * 3 skill files × 3 workspace presets = 9 fixture assertions.
5
+ *
6
+ * Each test renders a tokenized skill file content through replaceVocabTokens
7
+ * with the given workspace preset and asserts:
8
+ * 1. No un-tokenized noun-form "bet" / "Bet" / "bets" / "Bets" remains
9
+ * outside exclusions (code fences, inline code, already-tokenized lines).
10
+ * 2. No raw {{vocab:...}} token survives (resolver is exhaustive).
11
+ * 3. The rendered content contains the expected singular label for the preset.
12
+ *
13
+ * Workspace presets (methodology-neutral):
14
+ * - Shape Up: singular=Bet, plural=Bets, verb_start=shape, verb_complete=ship
15
+ * - Generic: singular=Initiative, plural=Initiatives, verb_start=start, verb_complete=complete
16
+ * - Linear: singular=Issue, plural=Issues, verb_start=begin, verb_complete=archive
17
+ *
18
+ * Chain: WP-436 S3, STD-253, DEC-1021.
19
+ */
20
+ import { readFileSync } from 'fs';
21
+ import { join } from 'path';
22
+ import { describe, expect, it } from 'vitest';
23
+ import { replaceVocabTokens } from '../lib/canonicalRefs.js';
24
+ // ── Helpers ───────────────────────────────────────────────────────────────────
25
+ const PB_SKILLS_DIR = join(new URL('../../../..', import.meta.url).pathname, '.productbrain', 'skills');
26
+ function readSkill(name) {
27
+ return readFileSync(join(PB_SKILLS_DIR, `${name}.md`), 'utf8');
28
+ }
29
+ // ── Workspace presets ─────────────────────────────────────────────────────────
30
+ const PRESETS = {
31
+ 'Shape Up': {
32
+ collectionLabels: {
33
+ work_package: {
34
+ singular: 'Bet',
35
+ plural: 'Bets',
36
+ verb_start: 'shape',
37
+ verb_complete: 'ship',
38
+ verb_archive: 'archive',
39
+ },
40
+ },
41
+ },
42
+ 'Generic': {
43
+ collectionLabels: {
44
+ work_package: {
45
+ singular: 'Initiative',
46
+ plural: 'Initiatives',
47
+ verb_start: 'start',
48
+ verb_complete: 'complete',
49
+ verb_archive: 'close',
50
+ },
51
+ },
52
+ },
53
+ 'Linear': {
54
+ collectionLabels: {
55
+ work_package: {
56
+ singular: 'Issue',
57
+ plural: 'Issues',
58
+ verb_start: 'begin',
59
+ verb_complete: 'archive',
60
+ verb_archive: 'archive',
61
+ },
62
+ },
63
+ },
64
+ };
65
+ // ── Assertion helpers ─────────────────────────────────────────────────────────
66
+ /**
67
+ * Check that no raw {{vocab:...}} token survives in the rendered output.
68
+ * The resolver should replace ALL tokens.
69
+ */
70
+ function assertNoRawTokens(rendered, description) {
71
+ const rawTokens = rendered.match(/\{\{vocab:[a-z_]+\.[a-z_]+\}\}/g) ?? [];
72
+ expect(rawTokens, `${description}: found raw {{vocab:...}} tokens after render: ${rawTokens.join(', ')}`).toHaveLength(0);
73
+ }
74
+ /**
75
+ * Check that no un-tokenized noun-form "bet" remains in prose (outside code fences and inline code).
76
+ *
77
+ * This replicates the verify-no-noun-bet exclusion logic inline.
78
+ * Note: after render, what we are checking is the OUTPUT — rendered prose that should use
79
+ * the workspace label (e.g. "Bet", "Initiative", "Issue") — NOT the raw token. So we only
80
+ * need to confirm no lowercase "bet"/"bets" remain that are NOT the resolved label.
81
+ *
82
+ * For the Shape Up preset where singular="Bet", the rendered text will contain "Bet" naturally.
83
+ * For Generic/Linear, "Bet" should NOT appear (it was replaced by Initiative/Issue).
84
+ */
85
+ function assertNoUnresolved(rendered, preset, ctx) {
86
+ const singular = ctx.collectionLabels?.work_package?.singular ?? '';
87
+ const plural = ctx.collectionLabels?.work_package?.plural ?? '';
88
+ // If the preset maps to "Bet"/"Bets" (Shape Up), then rendered "Bet" is expected.
89
+ // Otherwise, we check that "bet" / "Bet" doesn't appear in prose outside inline code.
90
+ if (singular === 'Bet') {
91
+ // Shape Up: resolved labels are "Bet"/"Bets" (capital) — those are expected in prose.
92
+ // What MUST NOT appear: LOWERCASE noun-form "bet"/"bets"/possessives — that signals a
93
+ // token-rewrite miss (since resolved labels for this preset are always capital).
94
+ // Strip code fences + inline code first so legitimate `bet-XXX-short-name` etc. don't trip us.
95
+ const strippedForCheck = stripCodeSpans(stripFences(rendered));
96
+ expect(strippedForCheck, `${preset}: lowercase noun-form 'bet'/'bets' in prose = unresolved leak`)
97
+ .not.toMatch(/\bbet(s|'s|s')?\b(?!-)/);
98
+ return;
99
+ }
100
+ // For non-Shape Up presets: no "Bet" (capital) should appear in prose (it was replaced).
101
+ // Strip code fences + inline code before checking.
102
+ const strippedFences = stripFences(rendered);
103
+ const strippedAll = stripCodeSpans(strippedFences);
104
+ // Check for any remaining {{vocab:...}} already handled above.
105
+ // Check that prose noun-form "Bet" is gone (replaced by singular/plural preset label).
106
+ const betMatches = strippedAll.match(/\b[Bb]et(s|'s|s')?\b(?!-)/g) ?? [];
107
+ expect(betMatches, `${preset}: found un-resolved noun-form "bet" in prose: ${betMatches.join(', ')}`).toHaveLength(0);
108
+ }
109
+ function stripFences(text) {
110
+ // Remove code fence blocks (```...``` and ~~~~...~~~~)
111
+ return text.replace(/```[\s\S]*?```/g, ' ').replace(/~{4,}[\s\S]*?~{4,}/g, ' ');
112
+ }
113
+ function stripCodeSpans(text) {
114
+ // Remove inline backtick spans
115
+ return text.replace(/`[^`]+`/g, ' ');
116
+ }
117
+ // ── Fixture: Source file content (tokenized) loaded once ─────────────────────
118
+ const SHAPING_SRC = readSkill('shaping');
119
+ const PHASING_SRC = readSkill('phasing');
120
+ const REVIEW_SRC = readSkill('implementation-review');
121
+ // ── 3×3 tests ─────────────────────────────────────────────────────────────────
122
+ const SKILL_FIXTURES = [
123
+ { name: 'shaping', src: SHAPING_SRC },
124
+ { name: 'phasing', src: PHASING_SRC },
125
+ { name: 'implementation-review', src: REVIEW_SRC },
126
+ ];
127
+ for (const { name: skillName, src } of SKILL_FIXTURES) {
128
+ describe(`skill: ${skillName}`, () => {
129
+ for (const [presetName, ctx] of Object.entries(PRESETS)) {
130
+ it(`renders correctly under preset: ${presetName}`, () => {
131
+ const rendered = replaceVocabTokens(src, ctx);
132
+ const description = `${skillName} × ${presetName}`;
133
+ // 1. No raw {{vocab:...}} tokens survive
134
+ assertNoRawTokens(rendered, description);
135
+ // 2. Resolved content contains the workspace singular label (confirms resolution worked)
136
+ const singular = ctx.collectionLabels?.work_package?.singular ?? '';
137
+ expect(rendered, `${description}: rendered output should contain workspace singular label "${singular}"`).toContain(singular);
138
+ // 3. No un-resolved noun-form "bet" in prose (for non-Shape Up presets)
139
+ assertNoUnresolved(rendered, presetName, ctx);
140
+ });
141
+ }
142
+ });
143
+ }
144
+ // ── Additional: verify source file IS tokenized (has {{vocab:...}} tokens) ───
145
+ describe('source files are tokenized', () => {
146
+ it('shaping.md contains vocab tokens', () => {
147
+ expect(SHAPING_SRC).toContain('{{vocab:work_package.');
148
+ });
149
+ it('phasing.md contains vocab tokens', () => {
150
+ expect(PHASING_SRC).toContain('{{vocab:work_package.');
151
+ });
152
+ it('implementation-review.md contains vocab tokens', () => {
153
+ expect(REVIEW_SRC).toContain('{{vocab:work_package.');
154
+ });
155
+ });
156
+ // ── Additional: verb-form preset assertion ─────────────────────────────────────
157
+ //
158
+ // shaping.md has one verb-form token: {{vocab:work_package.verb_start}} (from "shape a bet")
159
+ // in the YAML triggers block. "ship a bet" was not literal text in any skill — so
160
+ // verb_complete tokens only appear where we explicitly test with a custom fixture.
161
+ describe('verb-form resolution across presets', () => {
162
+ it('Shape Up: verb_start resolves to "shape" (trigger line in shaping.md)', () => {
163
+ const rendered = replaceVocabTokens(SHAPING_SRC, PRESETS['Shape Up']);
164
+ // The trigger line was "- shape a bet" → "- {{vocab:work_package.verb_start}} a {{vocab:work_package.singular}}"
165
+ // After render with Shape Up: "- shape a Bet"
166
+ expect(rendered).toContain('shape a Bet');
167
+ });
168
+ it('Generic: verb_start resolves to "start" (trigger line in shaping.md)', () => {
169
+ const rendered = replaceVocabTokens(SHAPING_SRC, PRESETS['Generic']);
170
+ // After render with Generic: "- start a Initiative"
171
+ expect(rendered).toContain('start a Initiative');
172
+ });
173
+ it('Linear: verb_start resolves to "begin" (trigger line in shaping.md)', () => {
174
+ const rendered = replaceVocabTokens(SHAPING_SRC, PRESETS['Linear']);
175
+ // verb_start="begin" for Linear
176
+ // The "shape a bet" trigger → "begin a Issue"
177
+ expect(rendered).toContain('begin a Issue');
178
+ });
179
+ it('verb_complete inline fixture: each preset resolves correctly', () => {
180
+ // No "ship a bet" literal appeared in skills, so test verb_complete via an inline fixture.
181
+ const fixture = 'To {{vocab:work_package.verb_complete}} a {{vocab:work_package.singular}}, all slices must pass review.';
182
+ expect(replaceVocabTokens(fixture, PRESETS['Shape Up'])).toBe('To ship a Bet, all slices must pass review.');
183
+ expect(replaceVocabTokens(fixture, PRESETS['Generic'])).toBe('To complete a Initiative, all slices must pass review.');
184
+ expect(replaceVocabTokens(fixture, PRESETS['Linear'])).toBe('To archive a Issue, all slices must pass review.');
185
+ });
186
+ });
187
+ //# sourceMappingURL=skill-vocabulary.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-vocabulary.test.js","sourceRoot":"","sources":["../../src/__tests__/skill-vocabulary.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=update-check.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-check.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/update-check.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,215 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ const files = new Map();
3
+ // Controllable npm registry response for resolveLatestVersion's live fetch. `null` => the
4
+ // request yields an empty body (JSON.parse fails) so fetchLatestVersion resolves null.
5
+ let npmResponseVersion = null;
6
+ vi.mock('node:os', () => ({
7
+ homedir: () => '/mock-home',
8
+ }));
9
+ vi.mock('node:https', () => ({
10
+ request: (_url, _opts, cb) => {
11
+ const res = {
12
+ on: (event, handler) => {
13
+ if (event === 'data' && npmResponseVersion !== null) {
14
+ handler(Buffer.from(JSON.stringify({ version: npmResponseVersion })));
15
+ }
16
+ if (event === 'end')
17
+ handler();
18
+ return res;
19
+ },
20
+ };
21
+ cb(res);
22
+ const req = { on: () => req, setTimeout: () => req, destroy: () => { }, end: () => { } };
23
+ return req;
24
+ },
25
+ }));
26
+ vi.mock('node:fs', async () => ({
27
+ existsSync: (path) => files.has(path),
28
+ readFileSync: (path) => files.get(path) ?? '',
29
+ writeFileSync: (path, body) => { files.set(path, body); },
30
+ mkdirSync: vi.fn(),
31
+ unlinkSync: (path) => { files.delete(path); },
32
+ statSync: () => ({ mtimeMs: Date.now() }),
33
+ readdirSync: () => [...files.keys()].map((p) => p.split('/').pop()),
34
+ openSync: (path) => { if (files.has(path)) {
35
+ const e = new Error('EEXIST');
36
+ e.code = 'EEXIST';
37
+ throw e;
38
+ } files.set(path, ''); return 1; },
39
+ closeSync: vi.fn(),
40
+ }));
41
+ vi.mock('../lib/session.js', () => ({ readSession: () => ({ sessionId: 'sess-test' }) }));
42
+ import { clearPendingUpgradeCache, isNewer, recordServerLatest, readCachedLatestVersion, writeUpgradePendingSentinel, recordNpmLatest, resolveCachedLatest, resolveLatestVersion, checkForUpdate, _resetProcessGuardsForTest, } from '../lib/update-check.js';
43
+ import { setOutputMode } from '../lib/runner.js';
44
+ describe('update-check', () => {
45
+ const originalEnv = { ...process.env };
46
+ beforeEach(() => {
47
+ _resetProcessGuardsForTest();
48
+ files.clear();
49
+ npmResponseVersion = null;
50
+ process.env = { ...originalEnv };
51
+ setOutputMode('auto');
52
+ vi.clearAllMocks();
53
+ });
54
+ afterEach(() => {
55
+ process.env = { ...originalEnv };
56
+ setOutputMode('auto');
57
+ vi.restoreAllMocks();
58
+ });
59
+ it('compares prerelease channels by alpha < beta < rc < release', () => {
60
+ expect(isNewer('0.1.0-beta.32', '0.1.0-beta.108')).toBe(true);
61
+ expect(isNewer('0.1.0-beta.5', '0.1.0-rc.1')).toBe(true);
62
+ expect(isNewer('0.1.0-rc.1', '0.1.0-beta.5')).toBe(false);
63
+ expect(isNewer('0.1.0-rc.1', '0.1.0')).toBe(true);
64
+ });
65
+ it('recordServerLatest updates cache silently in JSON mode', () => {
66
+ setOutputMode('json');
67
+ const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
68
+ recordServerLatest('0.1.0-beta.109');
69
+ expect(readCachedLatestVersion()).toBe('0.1.0-beta.109');
70
+ expect(stderrSpy).not.toHaveBeenCalled();
71
+ });
72
+ it('PB_NO_VERSION_CHECK disables cache writes and output', () => {
73
+ process.env.PB_NO_VERSION_CHECK = '1';
74
+ const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
75
+ recordServerLatest('0.1.0-beta.109');
76
+ expect(readCachedLatestVersion()).toBeNull();
77
+ expect(stderrSpy).not.toHaveBeenCalled();
78
+ });
79
+ it('next startup clears upgrade sentinel and stale update cache', () => {
80
+ recordServerLatest('0.1.0-beta.109');
81
+ expect(readCachedLatestVersion()).toBe('0.1.0-beta.109');
82
+ writeUpgradePendingSentinel();
83
+ clearPendingUpgradeCache();
84
+ expect(readCachedLatestVersion()).toBeNull();
85
+ });
86
+ it('newest of fresh server/npm wins; server still wins only when it is the highest', () => {
87
+ recordNpmLatest('0.1.0-beta.140', '0.1.0-beta.109'); // (value, installed)
88
+ recordServerLatest('0.1.0-beta.130'); // fresh server, but LOWER than npm
89
+ expect(resolveCachedLatest()).toBe('0.1.0-beta.140'); // npm wins — server no longer masks a newer npm
90
+ });
91
+ it('a fresh server that LAGS npm cannot mask the true npm latest (TEN-2199 smoke-walk regression)', () => {
92
+ // The live failure mode: server header advertises the committed cliVersion.ts value (beta.108),
93
+ // which trails the run-numbered npm publish (beta.958). Newest-wins must surface 958, not 108.
94
+ recordNpmLatest('0.1.0-beta.958', '0.1.0-beta.109');
95
+ recordServerLatest('0.1.0-beta.108'); // fresh but stale-valued, < installed
96
+ expect(resolveCachedLatest()).toBe('0.1.0-beta.958');
97
+ });
98
+ it('server still wins when it is genuinely the newest source', () => {
99
+ recordNpmLatest('0.1.0-beta.140', '0.1.0-beta.109');
100
+ recordServerLatest('0.1.0-beta.145'); // fresh server, HIGHER than npm
101
+ expect(resolveCachedLatest()).toBe('0.1.0-beta.145');
102
+ });
103
+ it('npm wins when the server header is stale (>48h)', () => {
104
+ const realNow = Date.now;
105
+ recordServerLatest('0.1.0-beta.130');
106
+ Date.now = () => realNow() + 49 * 60 * 60 * 1000;
107
+ recordNpmLatest('0.1.0-beta.140', '0.1.0-beta.109');
108
+ expect(resolveCachedLatest()).toBe('0.1.0-beta.140');
109
+ Date.now = realNow;
110
+ });
111
+ it('npm fallback is isNewer-gated against installed (never records older-or-equal)', () => {
112
+ recordNpmLatest('0.1.0-beta.1', '0.1.0-beta.109'); // stale tag, older than installed
113
+ expect(resolveCachedLatest()).toBeNull();
114
+ });
115
+ it('prints an update line to stderr in JSON mode (agent), once', () => {
116
+ setOutputMode('json');
117
+ recordServerLatest('0.1.0-beta.140');
118
+ const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
119
+ checkForUpdate('0.1.0-beta.109');
120
+ checkForUpdate('0.1.0-beta.109'); // same session => silent second time
121
+ expect(stderrSpy).toHaveBeenCalledTimes(1);
122
+ expect(stderrSpy.mock.calls[0][0]).toContain('pb:');
123
+ expect(stderrSpy.mock.calls[0][0]).toContain('pb upgrade');
124
+ });
125
+ it('prints nothing to stdout (stdout stays bare JSON)', () => {
126
+ setOutputMode('json');
127
+ recordServerLatest('0.1.0-beta.140');
128
+ const stdoutSpy = vi.spyOn(process.stdout, 'write').mockImplementation(() => true);
129
+ checkForUpdate('0.1.0-beta.109');
130
+ expect(stdoutSpy).not.toHaveBeenCalled();
131
+ });
132
+ it('cold cache → no print', () => {
133
+ setOutputMode('json');
134
+ const spy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
135
+ checkForUpdate('0.1.0-beta.109');
136
+ expect(spy).not.toHaveBeenCalled();
137
+ });
138
+ it('sentinel records the installed version and suppresses re-notify for it', () => {
139
+ setOutputMode('json');
140
+ recordServerLatest('0.1.0-beta.140');
141
+ writeUpgradePendingSentinel('0.1.0-beta.140'); // just installed 140
142
+ const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true);
143
+ checkForUpdate('0.1.0-beta.140'); // running 140, latest 140 -> no notice
144
+ expect(stderrSpy).not.toHaveBeenCalled();
145
+ });
146
+ it('resolveLatestVersion serves a within-window npm fallback without refetching (P2)', async () => {
147
+ recordNpmLatest('0.1.0-beta.140', '0.1.0-beta.109'); // fresh (recordedAt = now)
148
+ npmResponseVersion = '0.1.0-beta.999'; // would win IF a fetch happened
149
+ const latest = await resolveLatestVersion('0.1.0-beta.109');
150
+ expect(latest).toBe('0.1.0-beta.140'); // fresh cache used, no network refresh
151
+ });
152
+ it('a lone fresh server header still triggers a live npm fetch — server-only cache is not trusted (P1)', async () => {
153
+ // Normal steady state: authenticated calls write a fresh server header, but the hot path never
154
+ // populates npm. If the server lags npm (108 vs 958), the live resolver must fetch npm rather
155
+ // than short-circuit on the server value, or pb doctor/upgrade would resolve the masked 108.
156
+ recordServerLatest('0.1.0-beta.108'); // fresh server only; no npm cache entry
157
+ npmResponseVersion = '0.1.0-beta.958'; // live npm is far newer
158
+ const latest = await resolveLatestVersion('0.1.0-beta.109');
159
+ expect(latest).toBe('0.1.0-beta.958'); // fetched + surfaced, not the masked server 108
160
+ });
161
+ it('resolveLatestVersion revalidates a stale npm fallback via a fresh fetch (P2)', async () => {
162
+ const realNow = Date.now;
163
+ recordNpmLatest('0.1.0-beta.140', '0.1.0-beta.109'); // recordedAt = now
164
+ Date.now = () => realNow() + 25 * 60 * 60 * 1000; // past the 24h npm window
165
+ npmResponseVersion = '0.1.0-beta.141'; // registry now serves a newer beta
166
+ try {
167
+ const latest = await resolveLatestVersion('0.1.0-beta.109');
168
+ expect(latest).toBe('0.1.0-beta.141'); // refreshed, not the stale 140
169
+ }
170
+ finally {
171
+ Date.now = realNow;
172
+ }
173
+ });
174
+ it('successful revalidation replaces a stale cache even when the live tag is not newer (P2)', async () => {
175
+ const realNow = Date.now;
176
+ recordNpmLatest('0.1.0-beta.140', '0.1.0-beta.109'); // seed npm cache at 140
177
+ Date.now = () => realNow() + 25 * 60 * 60 * 1000; // age it past the 24h window
178
+ npmResponseVersion = '0.1.0-beta.142'; // registry now points lower than installed
179
+ try {
180
+ // Installed is 145 (post-upgrade). The live tag (142) is <= installed, so recordNpmLatest
181
+ // refuses to overwrite — but the resolver must return the live truth (142), NOT the disproven
182
+ // stale 140 it would otherwise fall back to.
183
+ const latest = await resolveLatestVersion('0.1.0-beta.145');
184
+ expect(latest).toBe('0.1.0-beta.142');
185
+ }
186
+ finally {
187
+ Date.now = realNow;
188
+ }
189
+ });
190
+ it('falls back to a stale cached value only on fetch failure (offline backstop)', async () => {
191
+ const realNow = Date.now;
192
+ recordNpmLatest('0.1.0-beta.140', '0.1.0-beta.109');
193
+ Date.now = () => realNow() + 25 * 60 * 60 * 1000; // stale npm entry
194
+ npmResponseVersion = null; // registry unreachable → fetch resolves null
195
+ try {
196
+ const latest = await resolveLatestVersion('0.1.0-beta.109');
197
+ expect(latest).toBe('0.1.0-beta.140'); // offline → stale cache is better than nothing
198
+ }
199
+ finally {
200
+ Date.now = realNow;
201
+ }
202
+ });
203
+ it('hot-path resolveCachedLatest still returns a stale npm value (better than nothing)', () => {
204
+ const realNow = Date.now;
205
+ recordNpmLatest('0.1.0-beta.140', '0.1.0-beta.109');
206
+ Date.now = () => realNow() + 100 * 60 * 60 * 1000; // far past every freshness window
207
+ try {
208
+ expect(resolveCachedLatest()).toBe('0.1.0-beta.140'); // sync hot path never blocks/forgets
209
+ }
210
+ finally {
211
+ Date.now = realNow;
212
+ }
213
+ });
214
+ });
215
+ //# sourceMappingURL=update-check.test.js.map