@productbrain/cli 0.1.0-beta.95 → 0.1.0-beta.958

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 (419) 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__/authority-domains.test.js +3 -0
  4. package/dist/__tests__/authority-domains.test.js.map +1 -1
  5. package/dist/__tests__/canonicalRefs.vocab.test.d.ts +2 -0
  6. package/dist/__tests__/canonicalRefs.vocab.test.d.ts.map +1 -0
  7. package/dist/__tests__/canonicalRefs.vocab.test.js +251 -0
  8. package/dist/__tests__/canonicalRefs.vocab.test.js.map +1 -0
  9. package/dist/__tests__/config.test.js +272 -2
  10. package/dist/__tests__/config.test.js.map +1 -1
  11. package/dist/__tests__/constants.test.js +6 -1
  12. package/dist/__tests__/constants.test.js.map +1 -1
  13. package/dist/__tests__/envelope-contract.test.js +29 -3
  14. package/dist/__tests__/envelope-contract.test.js.map +1 -1
  15. package/dist/__tests__/errors.test.js +1 -0
  16. package/dist/__tests__/errors.test.js.map +1 -1
  17. package/dist/__tests__/handshake-augment.test.d.ts +2 -0
  18. package/dist/__tests__/handshake-augment.test.d.ts.map +1 -0
  19. package/dist/__tests__/handshake-augment.test.js +423 -0
  20. package/dist/__tests__/handshake-augment.test.js.map +1 -0
  21. package/dist/__tests__/handshake-dormancy.test.d.ts +2 -0
  22. package/dist/__tests__/handshake-dormancy.test.d.ts.map +1 -0
  23. package/dist/__tests__/handshake-dormancy.test.js +207 -0
  24. package/dist/__tests__/handshake-dormancy.test.js.map +1 -0
  25. package/dist/__tests__/handshake-formatter.test.d.ts +2 -0
  26. package/dist/__tests__/handshake-formatter.test.d.ts.map +1 -0
  27. package/dist/__tests__/handshake-formatter.test.js +67 -0
  28. package/dist/__tests__/handshake-formatter.test.js.map +1 -0
  29. package/dist/__tests__/handshake-preview.test.js +566 -4
  30. package/dist/__tests__/handshake-preview.test.js.map +1 -1
  31. package/dist/__tests__/handshake.e2e.test.d.ts +2 -0
  32. package/dist/__tests__/handshake.e2e.test.d.ts.map +1 -0
  33. package/dist/__tests__/handshake.e2e.test.js +1252 -0
  34. package/dist/__tests__/handshake.e2e.test.js.map +1 -0
  35. package/dist/__tests__/handshake.test.js +611 -2
  36. package/dist/__tests__/handshake.test.js.map +1 -1
  37. package/dist/__tests__/manifest.test.js +118 -1
  38. package/dist/__tests__/manifest.test.js.map +1 -1
  39. package/dist/__tests__/onboarding-path-b.test.js +4 -4
  40. package/dist/__tests__/onboarding-path-b.test.js.map +1 -1
  41. package/dist/__tests__/orient.test.js +184 -7
  42. package/dist/__tests__/orient.test.js.map +1 -1
  43. package/dist/__tests__/perimeter.test.d.ts +2 -0
  44. package/dist/__tests__/perimeter.test.d.ts.map +1 -0
  45. package/dist/__tests__/perimeter.test.js +165 -0
  46. package/dist/__tests__/perimeter.test.js.map +1 -0
  47. package/dist/__tests__/personal-layer.test.d.ts +1 -2
  48. package/dist/__tests__/personal-layer.test.d.ts.map +1 -1
  49. package/dist/__tests__/personal-layer.test.js +12 -48
  50. package/dist/__tests__/personal-layer.test.js.map +1 -1
  51. package/dist/__tests__/profiles.test.js +122 -7
  52. package/dist/__tests__/profiles.test.js.map +1 -1
  53. package/dist/__tests__/promote.test.js +71 -2
  54. package/dist/__tests__/promote.test.js.map +1 -1
  55. package/dist/__tests__/session-state-machine.test.js +45 -1
  56. package/dist/__tests__/session-state-machine.test.js.map +1 -1
  57. package/dist/__tests__/session-switch.test.d.ts +2 -0
  58. package/dist/__tests__/session-switch.test.d.ts.map +1 -0
  59. package/dist/__tests__/session-switch.test.js +129 -0
  60. package/dist/__tests__/session-switch.test.js.map +1 -0
  61. package/dist/__tests__/setup-ingest.test.js +16 -0
  62. package/dist/__tests__/setup-ingest.test.js.map +1 -1
  63. package/dist/__tests__/skill-vocabulary.test.d.ts +21 -0
  64. package/dist/__tests__/skill-vocabulary.test.d.ts.map +1 -0
  65. package/dist/__tests__/skill-vocabulary.test.js +187 -0
  66. package/dist/__tests__/skill-vocabulary.test.js.map +1 -0
  67. package/dist/__tests__/update-check.test.d.ts +2 -0
  68. package/dist/__tests__/update-check.test.d.ts.map +1 -0
  69. package/dist/__tests__/update-check.test.js +56 -0
  70. package/dist/__tests__/update-check.test.js.map +1 -0
  71. package/dist/__tests__/upgrade-runner.test.d.ts +2 -0
  72. package/dist/__tests__/upgrade-runner.test.d.ts.map +1 -0
  73. package/dist/__tests__/upgrade-runner.test.js +42 -0
  74. package/dist/__tests__/upgrade-runner.test.js.map +1 -0
  75. package/dist/__tests__/vocabulary-leak.test.d.ts +39 -0
  76. package/dist/__tests__/vocabulary-leak.test.d.ts.map +1 -0
  77. package/dist/__tests__/vocabulary-leak.test.js +534 -0
  78. package/dist/__tests__/vocabulary-leak.test.js.map +1 -0
  79. package/dist/__tests__/workspace.test.js +32 -12
  80. package/dist/__tests__/workspace.test.js.map +1 -1
  81. package/dist/commands/__tests__/connect-handoff.test.d.ts +11 -0
  82. package/dist/commands/__tests__/connect-handoff.test.d.ts.map +1 -0
  83. package/dist/commands/__tests__/connect-handoff.test.js +111 -0
  84. package/dist/commands/__tests__/connect-handoff.test.js.map +1 -0
  85. package/dist/commands/__tests__/setup-detect-surfaces.test.d.ts +15 -0
  86. package/dist/commands/__tests__/setup-detect-surfaces.test.d.ts.map +1 -0
  87. package/dist/commands/__tests__/setup-detect-surfaces.test.js +149 -0
  88. package/dist/commands/__tests__/setup-detect-surfaces.test.js.map +1 -0
  89. package/dist/commands/__tests__/setup-state.test.d.ts +2 -0
  90. package/dist/commands/__tests__/setup-state.test.d.ts.map +1 -0
  91. package/dist/commands/__tests__/setup-state.test.js +194 -0
  92. package/dist/commands/__tests__/setup-state.test.js.map +1 -0
  93. package/dist/commands/admin/seed.d.ts +46 -2
  94. package/dist/commands/admin/seed.d.ts.map +1 -1
  95. package/dist/commands/admin/seed.js +475 -33
  96. package/dist/commands/admin/seed.js.map +1 -1
  97. package/dist/commands/admin/seed.test.d.ts +5 -0
  98. package/dist/commands/admin/seed.test.d.ts.map +1 -1
  99. package/dist/commands/admin/seed.test.js +67 -2
  100. package/dist/commands/admin/seed.test.js.map +1 -1
  101. package/dist/commands/admin/seedRegistryEntries.generated.d.ts +14 -0
  102. package/dist/commands/admin/seedRegistryEntries.generated.d.ts.map +1 -0
  103. package/dist/commands/admin/seedRegistryEntries.generated.js +117 -0
  104. package/dist/commands/admin/seedRegistryEntries.generated.js.map +1 -0
  105. package/dist/commands/admin/seedRegistryEntries.test.d.ts +11 -0
  106. package/dist/commands/admin/seedRegistryEntries.test.d.ts.map +1 -0
  107. package/dist/commands/admin/seedRegistryEntries.test.js +67 -0
  108. package/dist/commands/admin/seedRegistryEntries.test.js.map +1 -0
  109. package/dist/commands/audit.d.ts.map +1 -1
  110. package/dist/commands/audit.js +30 -3
  111. package/dist/commands/audit.js.map +1 -1
  112. package/dist/commands/authority-domains.d.ts +25 -1
  113. package/dist/commands/authority-domains.d.ts.map +1 -1
  114. package/dist/commands/authority-domains.js +51 -4
  115. package/dist/commands/authority-domains.js.map +1 -1
  116. package/dist/commands/capture.d.ts.map +1 -1
  117. package/dist/commands/capture.js +3 -2
  118. package/dist/commands/capture.js.map +1 -1
  119. package/dist/commands/codex-prep.d.ts +1 -0
  120. package/dist/commands/codex-prep.d.ts.map +1 -1
  121. package/dist/commands/codex-prep.js +10 -7
  122. package/dist/commands/codex-prep.js.map +1 -1
  123. package/dist/commands/connect-config.test.d.ts +2 -0
  124. package/dist/commands/connect-config.test.d.ts.map +1 -0
  125. package/dist/commands/connect-config.test.js +44 -0
  126. package/dist/commands/connect-config.test.js.map +1 -0
  127. package/dist/commands/connect-context.d.ts +45 -0
  128. package/dist/commands/connect-context.d.ts.map +1 -0
  129. package/dist/commands/connect-context.js +64 -0
  130. package/dist/commands/connect-context.js.map +1 -0
  131. package/dist/commands/connect-context.test.d.ts +2 -0
  132. package/dist/commands/connect-context.test.d.ts.map +1 -0
  133. package/dist/commands/connect-context.test.js +110 -0
  134. package/dist/commands/connect-context.test.js.map +1 -0
  135. package/dist/commands/connect-handoff.d.ts +51 -0
  136. package/dist/commands/connect-handoff.d.ts.map +1 -0
  137. package/dist/commands/connect-handoff.js +70 -0
  138. package/dist/commands/connect-handoff.js.map +1 -0
  139. package/dist/commands/connect-integration.test.js +29 -12
  140. package/dist/commands/connect-integration.test.js.map +1 -1
  141. package/dist/commands/connect-screens.d.ts +6 -4
  142. package/dist/commands/connect-screens.d.ts.map +1 -1
  143. package/dist/commands/connect-screens.js +30 -19
  144. package/dist/commands/connect-screens.js.map +1 -1
  145. package/dist/commands/connect.d.ts +21 -6
  146. package/dist/commands/connect.d.ts.map +1 -1
  147. package/dist/commands/connect.js +65 -58
  148. package/dist/commands/connect.js.map +1 -1
  149. package/dist/commands/connect.test.js +17 -1
  150. package/dist/commands/connect.test.js.map +1 -1
  151. package/dist/commands/doctor.d.ts.map +1 -1
  152. package/dist/commands/doctor.js +68 -3
  153. package/dist/commands/doctor.js.map +1 -1
  154. package/dist/commands/doctor.test.js +131 -0
  155. package/dist/commands/doctor.test.js.map +1 -1
  156. package/dist/commands/handshake.d.ts +194 -2
  157. package/dist/commands/handshake.d.ts.map +1 -1
  158. package/dist/commands/handshake.js +1563 -54
  159. package/dist/commands/handshake.js.map +1 -1
  160. package/dist/commands/method.d.ts.map +1 -1
  161. package/dist/commands/method.js +3 -0
  162. package/dist/commands/method.js.map +1 -1
  163. package/dist/commands/orient.d.ts +52 -2
  164. package/dist/commands/orient.d.ts.map +1 -1
  165. package/dist/commands/orient.js +106 -4
  166. package/dist/commands/orient.js.map +1 -1
  167. package/dist/commands/profile.d.ts +1 -14
  168. package/dist/commands/profile.d.ts.map +1 -1
  169. package/dist/commands/profile.js +89 -72
  170. package/dist/commands/profile.js.map +1 -1
  171. package/dist/commands/promote.d.ts.map +1 -1
  172. package/dist/commands/promote.js +25 -2
  173. package/dist/commands/promote.js.map +1 -1
  174. package/dist/commands/relate.d.ts.map +1 -1
  175. package/dist/commands/relate.js +13 -0
  176. package/dist/commands/relate.js.map +1 -1
  177. package/dist/commands/session.d.ts.map +1 -1
  178. package/dist/commands/session.js +51 -14
  179. package/dist/commands/session.js.map +1 -1
  180. package/dist/commands/setup-audit.d.ts +59 -0
  181. package/dist/commands/setup-audit.d.ts.map +1 -0
  182. package/dist/commands/setup-audit.js +250 -0
  183. package/dist/commands/setup-audit.js.map +1 -0
  184. package/dist/commands/setup-detect-surfaces.d.ts +38 -0
  185. package/dist/commands/setup-detect-surfaces.d.ts.map +1 -0
  186. package/dist/commands/setup-detect-surfaces.js +76 -0
  187. package/dist/commands/setup-detect-surfaces.js.map +1 -0
  188. package/dist/commands/setup-ingest.d.ts.map +1 -1
  189. package/dist/commands/setup-ingest.js +4 -2
  190. package/dist/commands/setup-ingest.js.map +1 -1
  191. package/dist/commands/setup-state.d.ts +42 -0
  192. package/dist/commands/setup-state.d.ts.map +1 -0
  193. package/dist/commands/setup-state.js +93 -0
  194. package/dist/commands/setup-state.js.map +1 -0
  195. package/dist/commands/setup.d.ts +17 -9
  196. package/dist/commands/setup.d.ts.map +1 -1
  197. package/dist/commands/setup.js +52 -131
  198. package/dist/commands/setup.js.map +1 -1
  199. package/dist/commands/upgrade.d.ts +5 -0
  200. package/dist/commands/upgrade.d.ts.map +1 -0
  201. package/dist/commands/upgrade.js +89 -0
  202. package/dist/commands/upgrade.js.map +1 -0
  203. package/dist/commands/whoami.d.ts +12 -0
  204. package/dist/commands/whoami.d.ts.map +1 -0
  205. package/dist/commands/whoami.js +70 -0
  206. package/dist/commands/whoami.js.map +1 -0
  207. package/dist/commands/whoami.test.d.ts +2 -0
  208. package/dist/commands/whoami.test.d.ts.map +1 -0
  209. package/dist/commands/whoami.test.js +50 -0
  210. package/dist/commands/whoami.test.js.map +1 -0
  211. package/dist/commands/workspace.d.ts +23 -2
  212. package/dist/commands/workspace.d.ts.map +1 -1
  213. package/dist/commands/workspace.js +2 -2
  214. package/dist/commands/workspace.js.map +1 -1
  215. package/dist/formatters/__tests__/orient-provenance.test.d.ts +7 -0
  216. package/dist/formatters/__tests__/orient-provenance.test.d.ts.map +1 -0
  217. package/dist/formatters/__tests__/orient-provenance.test.js +227 -0
  218. package/dist/formatters/__tests__/orient-provenance.test.js.map +1 -0
  219. package/dist/formatters/audit.d.ts +6 -0
  220. package/dist/formatters/audit.d.ts.map +1 -1
  221. package/dist/formatters/audit.js.map +1 -1
  222. package/dist/formatters/entry.d.ts +6 -0
  223. package/dist/formatters/entry.d.ts.map +1 -1
  224. package/dist/formatters/entry.js +30 -5
  225. package/dist/formatters/entry.js.map +1 -1
  226. package/dist/formatters/handshake.d.ts +19 -3
  227. package/dist/formatters/handshake.d.ts.map +1 -1
  228. package/dist/formatters/handshake.js +48 -13
  229. package/dist/formatters/handshake.js.map +1 -1
  230. package/dist/formatters/orient.d.ts +68 -4
  231. package/dist/formatters/orient.d.ts.map +1 -1
  232. package/dist/formatters/orient.js +97 -17
  233. package/dist/formatters/orient.js.map +1 -1
  234. package/dist/formatters/session.js +1 -1
  235. package/dist/formatters/session.js.map +1 -1
  236. package/dist/generators/adapters.js +2 -2
  237. package/dist/generators/boundary-manifest.d.ts +29 -0
  238. package/dist/generators/boundary-manifest.d.ts.map +1 -0
  239. package/dist/generators/boundary-manifest.js +183 -0
  240. package/dist/generators/boundary-manifest.js.map +1 -0
  241. package/dist/generators/boundary-manifest.test.d.ts +2 -0
  242. package/dist/generators/boundary-manifest.test.d.ts.map +1 -0
  243. package/dist/generators/boundary-manifest.test.js +91 -0
  244. package/dist/generators/boundary-manifest.test.js.map +1 -0
  245. package/dist/generators/context-md.js +6 -6
  246. package/dist/generators/context-md.js.map +1 -1
  247. package/dist/generators/manifest.d.ts +78 -0
  248. package/dist/generators/manifest.d.ts.map +1 -1
  249. package/dist/generators/manifest.js +125 -14
  250. package/dist/generators/manifest.js.map +1 -1
  251. package/dist/generators/portable-knowledge.d.ts +6 -12
  252. package/dist/generators/portable-knowledge.d.ts.map +1 -1
  253. package/dist/generators/portable-knowledge.js +2 -19
  254. package/dist/generators/portable-knowledge.js.map +1 -1
  255. package/dist/generators/region-projections.d.ts +18 -0
  256. package/dist/generators/region-projections.d.ts.map +1 -0
  257. package/dist/generators/region-projections.js +49 -0
  258. package/dist/generators/region-projections.js.map +1 -0
  259. package/dist/generators/region-projections.test.d.ts +2 -0
  260. package/dist/generators/region-projections.test.d.ts.map +1 -0
  261. package/dist/generators/region-projections.test.js +63 -0
  262. package/dist/generators/region-projections.test.js.map +1 -0
  263. package/dist/generators/region.d.ts +24 -0
  264. package/dist/generators/region.d.ts.map +1 -0
  265. package/dist/generators/region.js +87 -0
  266. package/dist/generators/region.js.map +1 -0
  267. package/dist/generators/region.test.d.ts +2 -0
  268. package/dist/generators/region.test.d.ts.map +1 -0
  269. package/dist/generators/region.test.js +126 -0
  270. package/dist/generators/region.test.js.map +1 -0
  271. package/dist/generators/surface-profiles.d.ts +1 -2
  272. package/dist/generators/surface-profiles.d.ts.map +1 -1
  273. package/dist/generators/surface-profiles.js.map +1 -1
  274. package/dist/index.js +142 -27
  275. package/dist/index.js.map +1 -1
  276. package/dist/lib/activation.d.ts.map +1 -1
  277. package/dist/lib/activation.js +3 -3
  278. package/dist/lib/activation.js.map +1 -1
  279. package/dist/lib/activation.test.js +3 -3
  280. package/dist/lib/activation.test.js.map +1 -1
  281. package/dist/lib/canonicalRefs.d.ts +98 -0
  282. package/dist/lib/canonicalRefs.d.ts.map +1 -1
  283. package/dist/lib/canonicalRefs.js +67 -0
  284. package/dist/lib/canonicalRefs.js.map +1 -1
  285. package/dist/lib/client.d.ts.map +1 -1
  286. package/dist/lib/client.js +14 -4
  287. package/dist/lib/client.js.map +1 -1
  288. package/dist/lib/config.d.ts +70 -4
  289. package/dist/lib/config.d.ts.map +1 -1
  290. package/dist/lib/config.js +151 -11
  291. package/dist/lib/config.js.map +1 -1
  292. package/dist/lib/connectKeyLabel.d.ts +9 -0
  293. package/dist/lib/connectKeyLabel.d.ts.map +1 -0
  294. package/dist/lib/connectKeyLabel.js +12 -0
  295. package/dist/lib/connectKeyLabel.js.map +1 -0
  296. package/dist/lib/constants.d.ts +2 -0
  297. package/dist/lib/constants.d.ts.map +1 -1
  298. package/dist/lib/constants.js +2 -0
  299. package/dist/lib/constants.js.map +1 -1
  300. package/dist/lib/errors.d.ts +3 -0
  301. package/dist/lib/errors.d.ts.map +1 -1
  302. package/dist/lib/errors.js +3 -0
  303. package/dist/lib/errors.js.map +1 -1
  304. package/dist/lib/normalizeMaterializedFilename.d.ts +28 -0
  305. package/dist/lib/normalizeMaterializedFilename.d.ts.map +1 -0
  306. package/dist/lib/normalizeMaterializedFilename.js +56 -0
  307. package/dist/lib/normalizeMaterializedFilename.js.map +1 -0
  308. package/dist/lib/normalizeMaterializedFilename.test.d.ts +16 -0
  309. package/dist/lib/normalizeMaterializedFilename.test.d.ts.map +1 -0
  310. package/dist/lib/normalizeMaterializedFilename.test.js +90 -0
  311. package/dist/lib/normalizeMaterializedFilename.test.js.map +1 -0
  312. package/dist/lib/onboarding-path-b.d.ts.map +1 -1
  313. package/dist/lib/onboarding-path-b.js +0 -1
  314. package/dist/lib/onboarding-path-b.js.map +1 -1
  315. package/dist/lib/onboarding-shared.d.ts +0 -1
  316. package/dist/lib/onboarding-shared.d.ts.map +1 -1
  317. package/dist/lib/onboarding-shared.js +1 -17
  318. package/dist/lib/onboarding-shared.js.map +1 -1
  319. package/dist/lib/profiles.d.ts +3 -1
  320. package/dist/lib/profiles.d.ts.map +1 -1
  321. package/dist/lib/profiles.js +9 -6
  322. package/dist/lib/profiles.js.map +1 -1
  323. package/dist/lib/session.d.ts +10 -0
  324. package/dist/lib/session.d.ts.map +1 -1
  325. package/dist/lib/session.js +14 -0
  326. package/dist/lib/session.js.map +1 -1
  327. package/dist/lib/update-check.d.ts +20 -0
  328. package/dist/lib/update-check.d.ts.map +1 -1
  329. package/dist/lib/update-check.js +122 -21
  330. package/dist/lib/update-check.js.map +1 -1
  331. package/dist/lib/upgrade-runner.d.ts +21 -0
  332. package/dist/lib/upgrade-runner.d.ts.map +1 -0
  333. package/dist/lib/upgrade-runner.js +109 -0
  334. package/dist/lib/upgrade-runner.js.map +1 -0
  335. package/dist/lib/workspaceVocabCache.d.ts +60 -0
  336. package/dist/lib/workspaceVocabCache.d.ts.map +1 -0
  337. package/dist/lib/workspaceVocabCache.js +98 -0
  338. package/dist/lib/workspaceVocabCache.js.map +1 -0
  339. package/dist/setup/__tests__/coach-traces.test.d.ts +2 -0
  340. package/dist/setup/__tests__/coach-traces.test.d.ts.map +1 -0
  341. package/dist/setup/__tests__/coach-traces.test.js +189 -0
  342. package/dist/setup/__tests__/coach-traces.test.js.map +1 -0
  343. package/dist/setup/__tests__/setup-commands.test.d.ts +2 -0
  344. package/dist/setup/__tests__/setup-commands.test.d.ts.map +1 -0
  345. package/dist/setup/__tests__/setup-commands.test.js +177 -0
  346. package/dist/setup/__tests__/setup-commands.test.js.map +1 -0
  347. package/dist/setup/__tests__/state-machine.test.d.ts +2 -0
  348. package/dist/setup/__tests__/state-machine.test.d.ts.map +1 -0
  349. package/dist/setup/__tests__/state-machine.test.js +341 -0
  350. package/dist/setup/__tests__/state-machine.test.js.map +1 -0
  351. package/dist/setup/detect-surfaces.d.ts +21 -0
  352. package/dist/setup/detect-surfaces.d.ts.map +1 -0
  353. package/dist/setup/detect-surfaces.js +39 -0
  354. package/dist/setup/detect-surfaces.js.map +1 -0
  355. package/dist/setup/manifest-writer.d.ts +17 -0
  356. package/dist/setup/manifest-writer.d.ts.map +1 -0
  357. package/dist/setup/manifest-writer.js +153 -0
  358. package/dist/setup/manifest-writer.js.map +1 -0
  359. package/dist/setup/perimeter.d.ts +72 -0
  360. package/dist/setup/perimeter.d.ts.map +1 -0
  361. package/dist/setup/perimeter.js +128 -0
  362. package/dist/setup/perimeter.js.map +1 -0
  363. package/dist/setup/state-machine.d.ts +67 -0
  364. package/dist/setup/state-machine.d.ts.map +1 -0
  365. package/dist/setup/state-machine.js +124 -0
  366. package/dist/setup/state-machine.js.map +1 -0
  367. package/dist/surfaces/__tests__/adapter.test.d.ts +2 -0
  368. package/dist/surfaces/__tests__/adapter.test.d.ts.map +1 -0
  369. package/dist/surfaces/__tests__/adapter.test.js +90 -0
  370. package/dist/surfaces/__tests__/adapter.test.js.map +1 -0
  371. package/dist/surfaces/__tests__/pb-setup-passthrough.test.d.ts +2 -0
  372. package/dist/surfaces/__tests__/pb-setup-passthrough.test.d.ts.map +1 -0
  373. package/dist/surfaces/__tests__/pb-setup-passthrough.test.js +132 -0
  374. package/dist/surfaces/__tests__/pb-setup-passthrough.test.js.map +1 -0
  375. package/dist/surfaces/__tests__/telemetry.test.d.ts +2 -0
  376. package/dist/surfaces/__tests__/telemetry.test.d.ts.map +1 -0
  377. package/dist/surfaces/__tests__/telemetry.test.js +55 -0
  378. package/dist/surfaces/__tests__/telemetry.test.js.map +1 -0
  379. package/dist/surfaces/adapter.d.ts +70 -0
  380. package/dist/surfaces/adapter.d.ts.map +1 -0
  381. package/dist/surfaces/adapter.js +2 -0
  382. package/dist/surfaces/adapter.js.map +1 -0
  383. package/dist/surfaces/adapters/claude.d.ts +3 -0
  384. package/dist/surfaces/adapters/claude.d.ts.map +1 -0
  385. package/dist/surfaces/adapters/claude.js +67 -0
  386. package/dist/surfaces/adapters/claude.js.map +1 -0
  387. package/dist/surfaces/adapters/codex.d.ts +3 -0
  388. package/dist/surfaces/adapters/codex.d.ts.map +1 -0
  389. package/dist/surfaces/adapters/codex.js +61 -0
  390. package/dist/surfaces/adapters/codex.js.map +1 -0
  391. package/dist/surfaces/adapters/copilot.d.ts +3 -0
  392. package/dist/surfaces/adapters/copilot.d.ts.map +1 -0
  393. package/dist/surfaces/adapters/copilot.js +59 -0
  394. package/dist/surfaces/adapters/copilot.js.map +1 -0
  395. package/dist/surfaces/adapters/cursor.d.ts +3 -0
  396. package/dist/surfaces/adapters/cursor.d.ts.map +1 -0
  397. package/dist/surfaces/adapters/cursor.js +78 -0
  398. package/dist/surfaces/adapters/cursor.js.map +1 -0
  399. package/dist/surfaces/registry.d.ts +58 -2
  400. package/dist/surfaces/registry.d.ts.map +1 -1
  401. package/dist/surfaces/registry.js +82 -7
  402. package/dist/surfaces/registry.js.map +1 -1
  403. package/dist/surfaces/telemetry.d.ts +17 -0
  404. package/dist/surfaces/telemetry.d.ts.map +1 -0
  405. package/dist/surfaces/telemetry.js +31 -0
  406. package/dist/surfaces/telemetry.js.map +1 -0
  407. package/package.json +3 -1
  408. package/dist/__tests__/setup.test.d.ts +0 -2
  409. package/dist/__tests__/setup.test.d.ts.map +0 -1
  410. package/dist/__tests__/setup.test.js +0 -141
  411. package/dist/__tests__/setup.test.js.map +0 -1
  412. package/dist/generators/__tests__/surface-profiles.test.d.ts +0 -2
  413. package/dist/generators/__tests__/surface-profiles.test.d.ts.map +0 -1
  414. package/dist/generators/__tests__/surface-profiles.test.js +0 -89
  415. package/dist/generators/__tests__/surface-profiles.test.js.map +0 -1
  416. package/dist/lib/onboarding-phases.d.ts +0 -9
  417. package/dist/lib/onboarding-phases.d.ts.map +0 -1
  418. package/dist/lib/onboarding-phases.js +0 -120
  419. package/dist/lib/onboarding-phases.js.map +0 -1
@@ -3,6 +3,7 @@
3
3
  * STD-197: preview is the new default (no --apply flag = no writes).
4
4
  */
5
5
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
6
+ import { createHash } from 'crypto';
6
7
  const { vfs, MOCK_MARKER, MOCK_CWD, MOCK_HOME } = vi.hoisted(() => ({
7
8
  vfs: {},
8
9
  MOCK_MARKER: 'auto-generated by pb handshake',
@@ -22,6 +23,7 @@ vi.mock('fs', () => ({
22
23
  }),
23
24
  readdirSync: vi.fn(() => []),
24
25
  copyFileSync: vi.fn(),
26
+ realpathSync: vi.fn((path) => path),
25
27
  }));
26
28
  vi.mock('os', () => ({ homedir: vi.fn(() => MOCK_HOME) }));
27
29
  vi.mock('../lib/prompts.js', () => ({
@@ -33,6 +35,14 @@ vi.mock('../lib/prompts.js', () => ({
33
35
  }));
34
36
  vi.mock('../lib/client.js', () => ({
35
37
  kernelCall: vi.fn().mockResolvedValue([]),
38
+ kernelCallWithSession: vi.fn().mockResolvedValue(undefined),
39
+ }));
40
+ vi.mock('../lib/session.js', () => ({
41
+ readSession: vi.fn(() => null),
42
+ writeSession: vi.fn(),
43
+ clearSession: vi.fn(),
44
+ readClosedMarker: vi.fn(() => null),
45
+ addCapturedEntry: vi.fn(),
36
46
  }));
37
47
  vi.mock('../lib/config.js', () => ({
38
48
  getConfigOrGuide: vi.fn().mockResolvedValue({
@@ -90,6 +100,13 @@ vi.mock('../generators/surface-profiles.js', () => ({
90
100
  }));
91
101
  vi.mock('../generators/manifest.js', () => ({
92
102
  readManifest: vi.fn().mockReturnValue(null),
103
+ readManifestStatus: vi.fn().mockReturnValue({
104
+ mode: 'project',
105
+ surfaces: ['.cursor', '.claude', '.codex', '.github'],
106
+ lock: {},
107
+ parseStatus: 'ok',
108
+ manifest: null,
109
+ }),
93
110
  filterByAdoptionState: vi.fn().mockImplementation((items) => items),
94
111
  }));
95
112
  vi.mock('../formatters/handshake.js', () => ({
@@ -102,15 +119,29 @@ vi.mock('../lib/hook-intents.js', () => ({
102
119
  vi.mock('../lib/method-registry.js', () => ({
103
120
  loadMethodRegistry: vi.fn().mockResolvedValue({ methods: [] }),
104
121
  }));
105
- import { writeFileSync } from 'fs';
122
+ import { readdirSync, writeFileSync } from 'fs';
106
123
  import { formatHandshakeReport } from '../formatters/handshake.js';
107
- import { kernelCall } from '../lib/client.js';
124
+ import { kernelCall, kernelCallWithSession } from '../lib/client.js';
125
+ import { readSession } from '../lib/session.js';
126
+ import { readManifestStatus } from '../generators/manifest.js';
108
127
  import { generateCursorSkill, shouldEmitToTarget } from '../generators/portable-knowledge.js';
109
128
  import { runHandshake } from '../commands/handshake.js';
110
129
  function capturedReport() {
111
130
  const calls = vi.mocked(formatHandshakeReport).mock.calls;
112
131
  return calls.length > 0 ? calls[calls.length - 1][0] : null;
113
132
  }
133
+ function setupAuthoringTestHash(asset) {
134
+ const canonical = {
135
+ entryId: asset.entryId,
136
+ name: asset.name,
137
+ description: asset.description,
138
+ assetKind: asset.assetKind,
139
+ triggers: asset.triggers ?? [],
140
+ semanticRefs: asset.semanticRefs ?? [],
141
+ body: asset.body.replace(/\r\n/g, '\n').replace(/\r/g, '\n').trimEnd(),
142
+ };
143
+ return `sha256:${createHash('sha256').update(JSON.stringify(canonical), 'utf8').digest('hex')}`;
144
+ }
114
145
  describe('runHandshake — preview/apply/dryRun invariants (WP-332 S1)', () => {
115
146
  let cwdSpy;
116
147
  beforeEach(() => {
@@ -120,6 +151,14 @@ describe('runHandshake — preview/apply/dryRun invariants (WP-332 S1)', () => {
120
151
  vi.spyOn(console, 'log').mockImplementation(() => { });
121
152
  vi.spyOn(console, 'error').mockImplementation(() => { });
122
153
  vi.spyOn(console, 'warn').mockImplementation(() => { });
154
+ vi.mocked(readdirSync).mockReturnValue([]);
155
+ vi.mocked(readManifestStatus).mockReturnValue({
156
+ mode: 'project',
157
+ surfaces: ['.cursor', '.claude', '.codex', '.github'],
158
+ lock: {},
159
+ parseStatus: 'ok',
160
+ manifest: null,
161
+ });
123
162
  });
124
163
  afterEach(() => {
125
164
  cwdSpy.mockRestore();
@@ -136,6 +175,161 @@ describe('runHandshake — preview/apply/dryRun invariants (WP-332 S1)', () => {
136
175
  await runHandshake({ dryRun: true });
137
176
  expect(writeFileSync).not.toHaveBeenCalled();
138
177
  });
178
+ it('apply + observe authority is preview-only and writes nothing', async () => {
179
+ vi.mocked(readManifestStatus).mockReturnValue({
180
+ mode: 'observe',
181
+ surfaces: ['.cursor'],
182
+ lock: {},
183
+ parseStatus: 'ok',
184
+ manifest: null,
185
+ });
186
+ await runHandshake({ apply: true, surfaces: ['cursor'] });
187
+ expect(writeFileSync).not.toHaveBeenCalled();
188
+ expect(vi.mocked(kernelCall).mock.calls.some(([tool]) => tool === 'setup.materializeSetup')).toBe(false);
189
+ expect(capturedReport()?.filesWritten).toEqual([]);
190
+ expect(capturedReport()?.filesSkipped?.some((f) => f.reason === 'preview-only (materialize: observe)')).toBe(true);
191
+ });
192
+ it('apply + govern authority writes files and invokes materializeSetup (KEY-24 complement to observe)', async () => {
193
+ vi.mocked(readManifestStatus).mockReturnValue({
194
+ mode: 'govern',
195
+ surfaces: ['.cursor'],
196
+ lock: {},
197
+ parseStatus: 'ok',
198
+ manifest: null,
199
+ });
200
+ await runHandshake({ apply: true, surfaces: ['cursor'] });
201
+ expect(writeFileSync).toHaveBeenCalled();
202
+ expect(vi.mocked(kernelCall).mock.calls.some(([tool]) => tool === 'setup.materializeSetup')).toBe(true);
203
+ expect(capturedReport()?.filesSkipped?.some((f) => f.reason === 'preview-only (materialize: observe)')).toBeFalsy();
204
+ });
205
+ it('--surfaces is an intersection with manifest.surfaces, not a superset', async () => {
206
+ vi.mocked(readManifestStatus).mockReturnValue({
207
+ mode: 'project',
208
+ surfaces: ['.cursor'],
209
+ lock: {},
210
+ parseStatus: 'ok',
211
+ manifest: null,
212
+ });
213
+ vi.mocked(shouldEmitToTarget).mockImplementation((_entry, target) => target === 'cursor');
214
+ vi.mocked(generateCursorSkill).mockImplementation((skill) => skill.body);
215
+ vi.mocked(kernelCall).mockImplementation(async (tool) => {
216
+ if (tool === 'chain.workspaceReadiness')
217
+ return null;
218
+ if (tool === 'chain.getOrientView')
219
+ return null;
220
+ if (tool === 'chain.searchEntries')
221
+ return [];
222
+ if (tool === 'setup.listAssetsForUser') {
223
+ return [{
224
+ entryId: 'SETUP-SKILL-INTERSECTION',
225
+ name: 'Intersection',
226
+ description: 'Intersection',
227
+ body: '# Intersection',
228
+ triggers: [],
229
+ assetKind: 'skill',
230
+ semanticRefs: [],
231
+ disabledByOwner: false,
232
+ lastProjectedHash: null,
233
+ }];
234
+ }
235
+ if (tool === 'setup.getCurrentSetupState')
236
+ return { effectiveMode: 'observe' };
237
+ if (tool === 'setup.recordTransition')
238
+ return { ok: true, receiptId: 'r1', deduped: false };
239
+ return [];
240
+ });
241
+ await runHandshake({ apply: true, surfaces: ['claude'] });
242
+ expect(writeFileSync).not.toHaveBeenCalledWith(expect.stringContaining('/.cursor/skills/Intersection/SKILL.md'), expect.any(String));
243
+ });
244
+ it('apply records a mode-change transition when manifest mode differs from current setup state', async () => {
245
+ vi.mocked(readManifestStatus).mockReturnValue({
246
+ mode: 'project',
247
+ surfaces: ['.cursor'],
248
+ lock: { 'SETUP-SKILL-TRANSITION': 'workspace' },
249
+ parseStatus: 'ok',
250
+ manifest: null,
251
+ });
252
+ vi.mocked(kernelCall).mockImplementation(async (tool) => {
253
+ if (tool === 'chain.workspaceReadiness')
254
+ return null;
255
+ if (tool === 'chain.getOrientView')
256
+ return null;
257
+ if (tool === 'chain.searchEntries')
258
+ return [];
259
+ if (tool === 'setup.listAssetsForUser')
260
+ return [];
261
+ if (tool === 'setup.getCurrentSetupState')
262
+ return { effectiveMode: 'observe' };
263
+ if (tool === 'setup.recordTransition')
264
+ return { ok: true, receiptId: 'r1', deduped: false };
265
+ return [];
266
+ });
267
+ await runHandshake({ apply: true });
268
+ expect(kernelCall).toHaveBeenCalledWith('setup.recordTransition', {
269
+ fromMode: 'observe',
270
+ toMode: 'project',
271
+ parseStatus: 'ok',
272
+ surfaces: ['.cursor'],
273
+ lock: { 'SETUP-SKILL-TRANSITION': 'workspace' },
274
+ });
275
+ });
276
+ it('apply bulk-imports .productbrain authoring files with frontmatter id before DB projection', async () => {
277
+ vi.mocked(readManifestStatus).mockReturnValue({
278
+ mode: 'project',
279
+ surfaces: ['.cursor'],
280
+ lock: {},
281
+ parseStatus: 'ok',
282
+ manifest: null,
283
+ });
284
+ const skillPath = `${MOCK_CWD}/.productbrain/skills/local.md`;
285
+ vfs[`${MOCK_CWD}/.productbrain/skills`] = '';
286
+ vfs[skillPath] = [
287
+ '---',
288
+ 'id: SETUP-SKILL-FRONTMATTER',
289
+ 'name: Local Skill',
290
+ 'description: Local description',
291
+ 'triggers:',
292
+ ' - local',
293
+ 'semanticRefs:',
294
+ ' - entry:WP-423',
295
+ '---',
296
+ '# Local Skill',
297
+ '',
298
+ 'Body.',
299
+ ].join('\n');
300
+ vi.mocked(readdirSync).mockImplementation((path) => {
301
+ if (String(path).endsWith('/.productbrain/skills'))
302
+ return ['local.md'];
303
+ return [];
304
+ });
305
+ vi.mocked(kernelCall).mockImplementation(async (tool) => {
306
+ if (tool === 'chain.workspaceReadiness')
307
+ return null;
308
+ if (tool === 'chain.getOrientView')
309
+ return null;
310
+ if (tool === 'chain.searchEntries')
311
+ return [];
312
+ // WP-428 S2 (Critical #1): CLI now calls ingestSetupAssetWithBody per-asset.
313
+ if (tool === 'setup.ingestSetupAssetWithBody')
314
+ return { action: 'created', entryId: 'SETUP-SKILL-FRONTMATTER' };
315
+ if (tool === 'setup.listAssetsForUser')
316
+ return [];
317
+ if (tool === 'setup.getCurrentSetupState')
318
+ return { effectiveMode: 'project' };
319
+ return [];
320
+ });
321
+ await runHandshake({ apply: true });
322
+ // WP-428 S2: CLI now calls ingestSetupAssetWithBody per-asset (not ingestSetupAssetsBatch).
323
+ expect(kernelCall).toHaveBeenCalledWith('setup.ingestSetupAssetWithBody', expect.objectContaining({
324
+ entryId: 'SETUP-SKILL-LOCAL',
325
+ frontmatterId: 'SETUP-SKILL-FRONTMATTER',
326
+ name: 'Local Skill',
327
+ description: 'Local description',
328
+ assetKind: 'skill',
329
+ triggers: ['local'],
330
+ semanticRefs: ['entry:WP-423'],
331
+ }));
332
+ });
139
333
  it('preview mode reports unchanged for files with identical content', async () => {
140
334
  const agentsPath = `${MOCK_CWD}/AGENTS.md`;
141
335
  vfs[agentsPath] = `<!-- ${MOCK_MARKER} -->\nagents content`;
@@ -145,14 +339,66 @@ describe('runHandshake — preview/apply/dryRun invariants (WP-332 S1)', () => {
145
339
  const entry = report?.previewPlan?.find((e) => e.path.includes('AGENTS.md') && e.status === 'unchanged');
146
340
  expect(entry).toBeDefined();
147
341
  });
148
- it('forked adapter (file exists without MARKER) = forked in previewPlan, no write', async () => {
342
+ it('user-owned adapter (file exists without MARKER) = would-augment in previewPlan, no write (TEN-2155)', async () => {
343
+ // TEN-2155: user-owned CLAUDE.md/AGENTS.md (no MARKER) are now AUGMENTED with a PB
344
+ // region rather than left fully untouched. In preview mode this shows as 'would-augment'
345
+ // in the previewPlan. No bytes are written to disk in preview mode.
149
346
  const agentsPath = `${MOCK_CWD}/AGENTS.md`;
150
347
  vfs[agentsPath] = '# Custom AGENTS\nNo auto-generated marker here.';
151
348
  await runHandshake({});
152
349
  expect(writeFileSync).not.toHaveBeenCalled();
153
350
  const report = capturedReport();
154
- const entry = report?.previewPlan?.find((e) => e.path.includes('AGENTS.md') && e.status === 'forked');
351
+ const entry = report?.previewPlan?.find((e) => e.path.includes('AGENTS.md') && e.status === 'would-augment');
155
352
  expect(entry).toBeDefined();
353
+ // Never labelled as a "forked" conflict the user must --force away.
354
+ const forkedEntry = report?.previewPlan?.find((e) => e.status === 'forked');
355
+ expect(forkedEntry).toBeUndefined();
356
+ });
357
+ it('apply: user-owned files (no MARKER) are augmented with a PB region, not skipped (TEN-2155)', async () => {
358
+ // TEN-2155: user-owned CLAUDE.md/AGENTS.md get a pb:region spliced in — they are
359
+ // NOT added to userOwnedSkipped. Their original content is preserved; only the PB
360
+ // region block is appended. They must appear in filesWritten, not filesSkipped.
361
+ const claudePath = `${MOCK_CWD}/CLAUDE.md`;
362
+ const agentsPath = `${MOCK_CWD}/AGENTS.md`;
363
+ const userClaude = '# My own CLAUDE.md\nNo auto-generated marker.';
364
+ const userAgents = '# My own AGENTS.md\nNo auto-generated marker.';
365
+ vfs[claudePath] = userClaude;
366
+ vfs[agentsPath] = userAgents;
367
+ const report = await runHandshake({ apply: true });
368
+ // Augmented files appear in filesWritten, not userOwnedSkipped.
369
+ expect(report?.filesWritten).toEqual(expect.arrayContaining(['CLAUDE.md', 'AGENTS.md']));
370
+ expect(report?.userOwnedSkipped ?? []).not.toEqual(expect.arrayContaining(['CLAUDE.md']));
371
+ expect(report?.userOwnedSkipped ?? []).not.toEqual(expect.arrayContaining(['AGENTS.md']));
372
+ // The augmented content on disk must contain the original user content.
373
+ expect(vfs[claudePath]).toContain(userClaude);
374
+ expect(vfs[agentsPath]).toContain(userAgents);
375
+ // And the PB region sentinel must be present (the full sentinel includes a comment suffix).
376
+ expect(vfs[claudePath]).toContain('<!-- pb:region:start');
377
+ expect(vfs[agentsPath]).toContain('<!-- pb:region:start');
378
+ });
379
+ it('apply: user-owned files never trigger a chain.createEntry drift TEN, even with an active session + receipts (TEN-2150)', async () => {
380
+ vfs[`${MOCK_CWD}/CLAUDE.md`] = '# My own CLAUDE.md\nNo auto-generated marker.';
381
+ vfs[`${MOCK_CWD}/AGENTS.md`] = '# My own AGENTS.md\nNo auto-generated marker.';
382
+ // Force the EXACT conditions under which the old code logged the spurious draft
383
+ // TEN: an active write session + a workspace that already has setup receipts
384
+ // (non-first-run). hasAnyReceipt is ignored post-fix but proves this is a real
385
+ // RED guard against the removed forked-adapter drift-logging block.
386
+ vi.mocked(readSession).mockReturnValue({ sessionId: 'test-session' });
387
+ vi.mocked(kernelCall).mockImplementation(async (tool) => tool === 'setup.listAssetsForUser'
388
+ ? { activeAssets: [], dormantAssets: [], hasAnyReceipt: true }
389
+ : []);
390
+ try {
391
+ await runHandshake({ apply: true });
392
+ // The session-bound path is genuinely exercised (materializeSetup runs through it)…
393
+ expect(kernelCallWithSession).toHaveBeenCalled();
394
+ // …but NO draft TEN is ever logged about the user's own files.
395
+ expect(kernelCallWithSession).not.toHaveBeenCalledWith('chain.createEntry', expect.anything());
396
+ }
397
+ finally {
398
+ // Restore defaults — beforeEach clears call history but not implementations.
399
+ vi.mocked(readSession).mockReturnValue(null);
400
+ vi.mocked(kernelCall).mockResolvedValue([]);
401
+ }
156
402
  });
157
403
  it('apply mode projects DB setup assets with body-derived refs, disabled filtering, and hash trailers', async () => {
158
404
  vi.mocked(shouldEmitToTarget).mockImplementation((_entry, target) => target === 'cursor');
@@ -275,5 +521,321 @@ describe('runHandshake — preview/apply/dryRun invariants (WP-332 S1)', () => {
275
521
  await runHandshake({ apply: true, surfaces: ['cursor'] });
276
522
  expect(vi.mocked(kernelCall).mock.calls.some(([tool]) => tool === 'setup.updateLastProjectedHash')).toBe(false);
277
523
  });
524
+ it('writes missing caller-owned personal DB assets back to .productbrain authoring files', async () => {
525
+ vi.mocked(kernelCall).mockImplementation(async (tool) => {
526
+ if (tool === 'chain.workspaceReadiness')
527
+ return null;
528
+ if (tool === 'chain.getOrientView')
529
+ return null;
530
+ if (tool === 'chain.searchEntries')
531
+ return [];
532
+ if (tool === 'setup.listAssetsForUser') {
533
+ return {
534
+ activeAssets: [
535
+ {
536
+ entryId: 'SETUP-SKILL-PERSONAL',
537
+ name: 'Personal Skill',
538
+ description: 'Personal authoring row.',
539
+ body: '# Personal Skill\nBody.',
540
+ triggers: ['personal'],
541
+ assetKind: 'skill',
542
+ semanticRefs: ['entry:WP-423'],
543
+ disabledByOwner: false,
544
+ lastProjectedHash: null,
545
+ scope: 'personal',
546
+ },
547
+ ],
548
+ dormantAssets: [],
549
+ hasAnyReceipt: true,
550
+ };
551
+ }
552
+ if (tool === 'setup.updateLastProjectedHash')
553
+ return { ok: true };
554
+ if (tool === 'setup.materializeSetup')
555
+ return { ok: true, assetCount: 1, receiptWritten: true };
556
+ return [];
557
+ });
558
+ await runHandshake({ apply: true });
559
+ const path = `${MOCK_CWD}/.productbrain/skills/Personal Skill.md`;
560
+ expect(vfs[path]).toContain('id: SETUP-SKILL-PERSONAL');
561
+ expect(vfs[path]).toContain('# Personal Skill\nBody.');
562
+ expect(vi.mocked(kernelCall).mock.calls.some(([tool]) => tool === 'setup.updateLastProjectedHash')).toBe(true);
563
+ });
564
+ it('writes newer DB edits over a tracked authoring file unchanged from baseline', async () => {
565
+ const baselineHash = setupAuthoringTestHash({
566
+ entryId: 'SETUP-SKILL-DB-WINS',
567
+ name: 'DB Wins',
568
+ description: 'DB should win.',
569
+ assetKind: 'skill',
570
+ body: '# Original',
571
+ });
572
+ vfs[`${MOCK_CWD}/.productbrain/skills`] = '';
573
+ vfs[`${MOCK_CWD}/.productbrain/skills/DB Wins.md`] = [
574
+ '---',
575
+ 'id: SETUP-SKILL-DB-WINS',
576
+ 'name: "DB Wins"',
577
+ 'description: "DB should win."',
578
+ 'assetKind: skill',
579
+ '---',
580
+ '# Original',
581
+ '',
582
+ ].join('\n');
583
+ vfs[`${MOCK_CWD}/.productbrain/.authoring-sync.json`] = JSON.stringify({
584
+ version: 1,
585
+ assets: {
586
+ 'SETUP-SKILL-DB-WINS': {
587
+ path: '.productbrain/skills/DB Wins.md',
588
+ hash: baselineHash,
589
+ },
590
+ },
591
+ });
592
+ vi.mocked(readdirSync).mockImplementation((path) => {
593
+ if (String(path).endsWith('/.productbrain/skills'))
594
+ return ['DB Wins.md'];
595
+ return [];
596
+ });
597
+ vi.mocked(kernelCall).mockImplementation(async (tool) => {
598
+ if (tool === 'chain.workspaceReadiness')
599
+ return null;
600
+ if (tool === 'chain.getOrientView')
601
+ return null;
602
+ if (tool === 'chain.searchEntries')
603
+ return [];
604
+ // WP-428 S2 (Critical #1): CLI now calls ingestSetupAssetWithBody per-asset.
605
+ if (tool === 'setup.ingestSetupAssetWithBody') {
606
+ return { action: 'unchanged', entryId: 'SETUP-SKILL-DB-WINS' };
607
+ }
608
+ if (tool === 'setup.listAssetsForUser') {
609
+ return {
610
+ activeAssets: [
611
+ {
612
+ entryId: 'SETUP-SKILL-DB-WINS',
613
+ name: 'DB Wins',
614
+ description: 'DB should win.',
615
+ body: '# DB edit',
616
+ triggers: [],
617
+ assetKind: 'skill',
618
+ semanticRefs: [],
619
+ disabledByOwner: false,
620
+ lastProjectedHash: baselineHash,
621
+ scope: 'personal',
622
+ },
623
+ ],
624
+ dormantAssets: [],
625
+ hasAnyReceipt: true,
626
+ };
627
+ }
628
+ if (tool === 'setup.updateLastProjectedHash')
629
+ return { ok: true };
630
+ if (tool === 'setup.materializeSetup')
631
+ return { ok: true, assetCount: 1, receiptWritten: true };
632
+ return [];
633
+ });
634
+ await runHandshake({ apply: true });
635
+ expect(vfs[`${MOCK_CWD}/.productbrain/skills/DB Wins.md`]).toContain('# DB edit');
636
+ expect(vi.mocked(kernelCall).mock.calls.some(([tool]) => tool === 'setup.updateLastProjectedHash')).toBe(true);
637
+ });
638
+ it('marks personal DB assets dormant when their tracked authoring file is deleted', async () => {
639
+ const syncedHash = setupAuthoringTestHash({
640
+ entryId: 'SETUP-SKILL-DELETED',
641
+ name: 'Deleted Skill',
642
+ description: 'Deleted authoring row.',
643
+ assetKind: 'skill',
644
+ body: '# Deleted Skill\nBody.',
645
+ });
646
+ vfs[`${MOCK_CWD}/.productbrain/.authoring-sync.json`] = JSON.stringify({
647
+ version: 1,
648
+ assets: {
649
+ 'SETUP-SKILL-DELETED': {
650
+ path: '.productbrain/skills/Deleted Skill.md',
651
+ hash: syncedHash,
652
+ },
653
+ },
654
+ });
655
+ vi.mocked(kernelCall).mockImplementation(async (tool) => {
656
+ if (tool === 'chain.workspaceReadiness')
657
+ return null;
658
+ if (tool === 'chain.getOrientView')
659
+ return null;
660
+ if (tool === 'chain.searchEntries')
661
+ return [];
662
+ if (tool === 'setup.listAssetsForUser') {
663
+ return {
664
+ activeAssets: [
665
+ {
666
+ entryId: 'SETUP-SKILL-DELETED',
667
+ name: 'Deleted Skill',
668
+ description: 'Deleted authoring row.',
669
+ body: '# Deleted Skill\nBody.',
670
+ triggers: [],
671
+ assetKind: 'skill',
672
+ semanticRefs: [],
673
+ disabledByOwner: false,
674
+ lastProjectedHash: syncedHash,
675
+ scope: 'personal',
676
+ },
677
+ ],
678
+ dormantAssets: [],
679
+ hasAnyReceipt: true,
680
+ };
681
+ }
682
+ if (tool === 'setup.markPersonalSetupAssetDormantFromSync')
683
+ return { action: 'dormant', entryId: 'SETUP-SKILL-DELETED' };
684
+ if (tool === 'setup.materializeSetup')
685
+ return { ok: true, assetCount: 0, receiptWritten: true };
686
+ return [];
687
+ });
688
+ await runHandshake({ apply: true });
689
+ expect(vi.mocked(kernelCall).mock.calls).toContainEqual([
690
+ 'setup.markPersonalSetupAssetDormantFromSync',
691
+ { entryId: 'SETUP-SKILL-DELETED', expectedLastProjectedHash: syncedHash },
692
+ ]);
693
+ });
694
+ it('does not mark a stale tracked deletion dormant when the DB baseline changed', async () => {
695
+ vfs[`${MOCK_CWD}/.productbrain/.authoring-sync.json`] = JSON.stringify({
696
+ version: 1,
697
+ assets: {
698
+ 'SETUP-SKILL-STALE': {
699
+ path: '.productbrain/skills/Stale Skill.md',
700
+ hash: 'sha256:old-baseline',
701
+ },
702
+ },
703
+ });
704
+ vi.mocked(kernelCall).mockImplementation(async (tool) => {
705
+ if (tool === 'chain.workspaceReadiness')
706
+ return null;
707
+ if (tool === 'chain.getOrientView')
708
+ return null;
709
+ if (tool === 'chain.searchEntries')
710
+ return [];
711
+ if (tool === 'setup.listAssetsForUser') {
712
+ return {
713
+ activeAssets: [
714
+ {
715
+ entryId: 'SETUP-SKILL-STALE',
716
+ name: 'Stale Skill',
717
+ description: 'DB changed after local sync.',
718
+ body: '# Stale Skill\nUpdated DB body.',
719
+ triggers: [],
720
+ assetKind: 'skill',
721
+ semanticRefs: [],
722
+ disabledByOwner: false,
723
+ lastProjectedHash: 'sha256:new-baseline',
724
+ scope: 'personal',
725
+ },
726
+ ],
727
+ dormantAssets: [],
728
+ hasAnyReceipt: true,
729
+ };
730
+ }
731
+ if (tool === 'setup.updateLastProjectedHash')
732
+ return { ok: true };
733
+ if (tool === 'setup.materializeSetup')
734
+ return { ok: true, assetCount: 1, receiptWritten: true };
735
+ return [];
736
+ });
737
+ await runHandshake({ apply: true });
738
+ expect(vi.mocked(kernelCall).mock.calls.some(([tool]) => tool === 'setup.markPersonalSetupAssetDormantFromSync')).toBe(false);
739
+ expect(vfs[`${MOCK_CWD}/.productbrain/skills/Stale Skill.md`]).toContain('Updated DB body.');
740
+ });
741
+ it('does not write a stale snapshot back when dormant sync returns a server-side conflict', async () => {
742
+ const listedHash = setupAuthoringTestHash({
743
+ entryId: 'SETUP-SKILL-RACE',
744
+ name: 'Race Skill',
745
+ description: 'Race during sync.',
746
+ assetKind: 'skill',
747
+ body: '# Race Skill\nDB body.',
748
+ });
749
+ vfs[`${MOCK_CWD}/.productbrain/.authoring-sync.json`] = JSON.stringify({
750
+ version: 1,
751
+ assets: {
752
+ 'SETUP-SKILL-RACE': {
753
+ path: '.productbrain/skills/Race Skill.md',
754
+ hash: listedHash,
755
+ },
756
+ },
757
+ });
758
+ vi.mocked(kernelCall).mockImplementation(async (tool) => {
759
+ if (tool === 'chain.workspaceReadiness')
760
+ return null;
761
+ if (tool === 'chain.getOrientView')
762
+ return null;
763
+ if (tool === 'chain.searchEntries')
764
+ return [];
765
+ if (tool === 'setup.listAssetsForUser') {
766
+ return {
767
+ activeAssets: [
768
+ {
769
+ entryId: 'SETUP-SKILL-RACE',
770
+ name: 'Race Skill',
771
+ description: 'Race during sync.',
772
+ body: '# Race Skill\nDB body.',
773
+ triggers: [],
774
+ assetKind: 'skill',
775
+ semanticRefs: [],
776
+ disabledByOwner: false,
777
+ lastProjectedHash: listedHash,
778
+ scope: 'personal',
779
+ },
780
+ ],
781
+ dormantAssets: [],
782
+ hasAnyReceipt: true,
783
+ };
784
+ }
785
+ if (tool === 'setup.markPersonalSetupAssetDormantFromSync')
786
+ return { action: 'conflict', entryId: 'SETUP-SKILL-RACE' };
787
+ if (tool === 'setup.updateLastProjectedHash')
788
+ return { ok: true };
789
+ if (tool === 'setup.materializeSetup')
790
+ return { ok: true, assetCount: 1, receiptWritten: true };
791
+ return [];
792
+ });
793
+ await runHandshake({ apply: true });
794
+ expect(vi.mocked(kernelCall).mock.calls).toContainEqual([
795
+ 'setup.markPersonalSetupAssetDormantFromSync',
796
+ { entryId: 'SETUP-SKILL-RACE', expectedLastProjectedHash: listedHash },
797
+ ]);
798
+ expect(vfs[`${MOCK_CWD}/.productbrain/skills/Race Skill.md`]).toBeUndefined();
799
+ expect(vi.mocked(kernelCall).mock.calls.some(([tool, args]) => tool === 'setup.updateLastProjectedHash' &&
800
+ args?.entryId === 'SETUP-SKILL-RACE')).toBe(false);
801
+ });
802
+ it('does not mark a missing personal authoring file dormant on a fresh clone without local tracking state', async () => {
803
+ vi.mocked(kernelCall).mockImplementation(async (tool) => {
804
+ if (tool === 'chain.workspaceReadiness')
805
+ return null;
806
+ if (tool === 'chain.getOrientView')
807
+ return null;
808
+ if (tool === 'chain.searchEntries')
809
+ return [];
810
+ if (tool === 'setup.listAssetsForUser') {
811
+ return {
812
+ activeAssets: [
813
+ {
814
+ entryId: 'SETUP-SKILL-FRESH',
815
+ name: 'Fresh Skill',
816
+ description: 'Fresh clone row.',
817
+ body: '# Fresh Skill\nBody.',
818
+ triggers: [],
819
+ assetKind: 'skill',
820
+ semanticRefs: [],
821
+ disabledByOwner: false,
822
+ lastProjectedHash: 'sha256:previous',
823
+ scope: 'personal',
824
+ },
825
+ ],
826
+ dormantAssets: [],
827
+ hasAnyReceipt: true,
828
+ };
829
+ }
830
+ if (tool === 'setup.updateLastProjectedHash')
831
+ return { ok: true };
832
+ if (tool === 'setup.materializeSetup')
833
+ return { ok: true, assetCount: 1, receiptWritten: true };
834
+ return [];
835
+ });
836
+ await runHandshake({ apply: true });
837
+ expect(vi.mocked(kernelCall).mock.calls.some(([tool]) => tool === 'setup.markPersonalSetupAssetDormantFromSync')).toBe(false);
838
+ expect(vfs[`${MOCK_CWD}/.productbrain/skills/Fresh Skill.md`]).toContain('id: SETUP-SKILL-FRESH');
839
+ });
278
840
  });
279
841
  //# sourceMappingURL=handshake-preview.test.js.map