@productbrain/cli 0.1.0-beta.9 → 0.1.0-beta.91

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 (643) hide show
  1. package/README.md +77 -92
  2. package/dist/__tests__/adapters.test.d.ts +2 -0
  3. package/dist/__tests__/adapters.test.d.ts.map +1 -0
  4. package/dist/__tests__/adapters.test.js +417 -0
  5. package/dist/__tests__/adapters.test.js.map +1 -0
  6. package/dist/__tests__/audit.test.d.ts +2 -0
  7. package/dist/__tests__/audit.test.d.ts.map +1 -0
  8. package/dist/__tests__/audit.test.js +394 -0
  9. package/dist/__tests__/audit.test.js.map +1 -0
  10. package/dist/__tests__/batch-transformations.test.d.ts +2 -0
  11. package/dist/__tests__/batch-transformations.test.d.ts.map +1 -0
  12. package/dist/__tests__/batch-transformations.test.js +263 -0
  13. package/dist/__tests__/batch-transformations.test.js.map +1 -0
  14. package/dist/__tests__/capture.test.js +309 -18
  15. package/dist/__tests__/capture.test.js.map +1 -1
  16. package/dist/__tests__/config.test.d.ts +8 -0
  17. package/dist/__tests__/config.test.d.ts.map +1 -0
  18. package/dist/__tests__/config.test.js +166 -0
  19. package/dist/__tests__/config.test.js.map +1 -0
  20. package/dist/__tests__/constants.test.d.ts +2 -0
  21. package/dist/__tests__/constants.test.d.ts.map +1 -0
  22. package/dist/__tests__/constants.test.js +141 -0
  23. package/dist/__tests__/constants.test.js.map +1 -0
  24. package/dist/__tests__/constellation.test.js +20 -26
  25. package/dist/__tests__/constellation.test.js.map +1 -1
  26. package/dist/__tests__/context-strategy.test.d.ts +2 -0
  27. package/dist/__tests__/context-strategy.test.d.ts.map +1 -0
  28. package/dist/__tests__/context-strategy.test.js +79 -0
  29. package/dist/__tests__/context-strategy.test.js.map +1 -0
  30. package/dist/__tests__/errors.test.d.ts +2 -0
  31. package/dist/__tests__/errors.test.d.ts.map +1 -0
  32. package/dist/__tests__/errors.test.js +117 -0
  33. package/dist/__tests__/errors.test.js.map +1 -0
  34. package/dist/__tests__/experiment.test.d.ts +6 -0
  35. package/dist/__tests__/experiment.test.d.ts.map +1 -0
  36. package/dist/__tests__/experiment.test.js +69 -0
  37. package/dist/__tests__/experiment.test.js.map +1 -0
  38. package/dist/__tests__/fields.test.js +68 -68
  39. package/dist/__tests__/fields.test.js.map +1 -1
  40. package/dist/__tests__/glossary.test.d.ts +2 -0
  41. package/dist/__tests__/glossary.test.d.ts.map +1 -0
  42. package/dist/__tests__/glossary.test.js +32 -0
  43. package/dist/__tests__/glossary.test.js.map +1 -0
  44. package/dist/__tests__/handshake-preview.test.d.ts +2 -0
  45. package/dist/__tests__/handshake-preview.test.d.ts.map +1 -0
  46. package/dist/__tests__/handshake-preview.test.js +156 -0
  47. package/dist/__tests__/handshake-preview.test.js.map +1 -0
  48. package/dist/__tests__/handshake.test.js +27 -18
  49. package/dist/__tests__/handshake.test.js.map +1 -1
  50. package/dist/__tests__/hook-intents.test.d.ts +2 -0
  51. package/dist/__tests__/hook-intents.test.d.ts.map +1 -0
  52. package/dist/__tests__/hook-intents.test.js +184 -0
  53. package/dist/__tests__/hook-intents.test.js.map +1 -0
  54. package/dist/__tests__/ingest.test.js +110 -12
  55. package/dist/__tests__/ingest.test.js.map +1 -1
  56. package/dist/__tests__/init.test.d.ts +7 -0
  57. package/dist/__tests__/init.test.d.ts.map +1 -0
  58. package/dist/__tests__/init.test.js +146 -0
  59. package/dist/__tests__/init.test.js.map +1 -0
  60. package/dist/__tests__/login.test.d.ts +2 -0
  61. package/dist/__tests__/login.test.d.ts.map +1 -0
  62. package/dist/__tests__/login.test.js +167 -0
  63. package/dist/__tests__/login.test.js.map +1 -0
  64. package/dist/__tests__/manifest.test.d.ts +6 -0
  65. package/dist/__tests__/manifest.test.d.ts.map +1 -0
  66. package/dist/__tests__/manifest.test.js +138 -0
  67. package/dist/__tests__/manifest.test.js.map +1 -0
  68. package/dist/__tests__/method-registry.integration.test.d.ts +6 -0
  69. package/dist/__tests__/method-registry.integration.test.d.ts.map +1 -0
  70. package/dist/__tests__/method-registry.integration.test.js +18 -0
  71. package/dist/__tests__/method-registry.integration.test.js.map +1 -0
  72. package/dist/__tests__/method-registry.test.d.ts +14 -0
  73. package/dist/__tests__/method-registry.test.d.ts.map +1 -0
  74. package/dist/__tests__/method-registry.test.js +134 -0
  75. package/dist/__tests__/method-registry.test.js.map +1 -0
  76. package/dist/__tests__/onboarding-path-b.test.d.ts +2 -0
  77. package/dist/__tests__/onboarding-path-b.test.d.ts.map +1 -0
  78. package/dist/__tests__/onboarding-path-b.test.js +46 -0
  79. package/dist/__tests__/onboarding-path-b.test.js.map +1 -0
  80. package/dist/__tests__/onboarding.test.d.ts +6 -0
  81. package/dist/__tests__/onboarding.test.d.ts.map +1 -0
  82. package/dist/__tests__/onboarding.test.js +347 -0
  83. package/dist/__tests__/onboarding.test.js.map +1 -0
  84. package/dist/__tests__/orient.test.d.ts +2 -0
  85. package/dist/__tests__/orient.test.d.ts.map +1 -0
  86. package/dist/__tests__/orient.test.js +143 -0
  87. package/dist/__tests__/orient.test.js.map +1 -0
  88. package/dist/__tests__/personal-layer.test.d.ts +12 -0
  89. package/dist/__tests__/personal-layer.test.d.ts.map +1 -0
  90. package/dist/__tests__/personal-layer.test.js +304 -0
  91. package/dist/__tests__/personal-layer.test.js.map +1 -0
  92. package/dist/__tests__/profiles.test.d.ts +2 -0
  93. package/dist/__tests__/profiles.test.d.ts.map +1 -0
  94. package/dist/__tests__/profiles.test.js +168 -0
  95. package/dist/__tests__/profiles.test.js.map +1 -0
  96. package/dist/__tests__/promote.test.d.ts +2 -0
  97. package/dist/__tests__/promote.test.d.ts.map +1 -0
  98. package/dist/__tests__/promote.test.js +161 -0
  99. package/dist/__tests__/promote.test.js.map +1 -0
  100. package/dist/__tests__/prompts.test.d.ts +6 -0
  101. package/dist/__tests__/prompts.test.d.ts.map +1 -0
  102. package/dist/__tests__/prompts.test.js +146 -0
  103. package/dist/__tests__/prompts.test.js.map +1 -0
  104. package/dist/__tests__/proposals.test.d.ts +2 -0
  105. package/dist/__tests__/proposals.test.d.ts.map +1 -0
  106. package/dist/__tests__/proposals.test.js +167 -0
  107. package/dist/__tests__/proposals.test.js.map +1 -0
  108. package/dist/__tests__/relate.test.js +57 -33
  109. package/dist/__tests__/relate.test.js.map +1 -1
  110. package/dist/__tests__/repo-detect.test.js +97 -1
  111. package/dist/__tests__/repo-detect.test.js.map +1 -1
  112. package/dist/__tests__/runner.test.js +19 -15
  113. package/dist/__tests__/runner.test.js.map +1 -1
  114. package/dist/__tests__/session-state-machine.test.d.ts +2 -0
  115. package/dist/__tests__/session-state-machine.test.d.ts.map +1 -0
  116. package/dist/__tests__/session-state-machine.test.js +154 -0
  117. package/dist/__tests__/session-state-machine.test.js.map +1 -0
  118. package/dist/__tests__/session-touch.test.js +11 -11
  119. package/dist/__tests__/session-touch.test.js.map +1 -1
  120. package/dist/__tests__/session.test.js +4 -10
  121. package/dist/__tests__/session.test.js.map +1 -1
  122. package/dist/__tests__/setup.test.d.ts +2 -0
  123. package/dist/__tests__/setup.test.d.ts.map +1 -0
  124. package/dist/__tests__/setup.test.js +141 -0
  125. package/dist/__tests__/setup.test.js.map +1 -0
  126. package/dist/__tests__/spinner-labels.test.d.ts +2 -0
  127. package/dist/__tests__/spinner-labels.test.d.ts.map +1 -0
  128. package/dist/__tests__/spinner-labels.test.js +23 -0
  129. package/dist/__tests__/spinner-labels.test.js.map +1 -0
  130. package/dist/__tests__/state.test.d.ts +6 -0
  131. package/dist/__tests__/state.test.d.ts.map +1 -0
  132. package/dist/__tests__/state.test.js +97 -0
  133. package/dist/__tests__/state.test.js.map +1 -0
  134. package/dist/__tests__/strip.test.js +2 -2
  135. package/dist/__tests__/strip.test.js.map +1 -1
  136. package/dist/__tests__/surface-profiles.test.d.ts +2 -0
  137. package/dist/__tests__/surface-profiles.test.d.ts.map +1 -0
  138. package/dist/__tests__/surface-profiles.test.js +233 -0
  139. package/dist/__tests__/surface-profiles.test.js.map +1 -0
  140. package/dist/__tests__/surfaces.test.d.ts +2 -0
  141. package/dist/__tests__/surfaces.test.d.ts.map +1 -0
  142. package/dist/__tests__/surfaces.test.js +46 -0
  143. package/dist/__tests__/surfaces.test.js.map +1 -0
  144. package/dist/__tests__/update.test.js +123 -43
  145. package/dist/__tests__/update.test.js.map +1 -1
  146. package/dist/__tests__/workspace.test.d.ts +2 -0
  147. package/dist/__tests__/workspace.test.d.ts.map +1 -0
  148. package/dist/__tests__/workspace.test.js +308 -0
  149. package/dist/__tests__/workspace.test.js.map +1 -0
  150. package/dist/commands/accept.d.ts +18 -0
  151. package/dist/commands/accept.d.ts.map +1 -0
  152. package/dist/commands/accept.js +76 -0
  153. package/dist/commands/accept.js.map +1 -0
  154. package/dist/commands/admin/cockpit.d.ts +90 -0
  155. package/dist/commands/admin/cockpit.d.ts.map +1 -0
  156. package/dist/commands/admin/cockpit.js +618 -0
  157. package/dist/commands/admin/cockpit.js.map +1 -0
  158. package/dist/commands/admin/index.d.ts +21 -0
  159. package/dist/commands/admin/index.d.ts.map +1 -0
  160. package/dist/commands/admin/index.js +256 -0
  161. package/dist/commands/admin/index.js.map +1 -0
  162. package/dist/commands/admin/inspect.d.ts +30 -0
  163. package/dist/commands/admin/inspect.d.ts.map +1 -0
  164. package/dist/commands/admin/inspect.js +555 -0
  165. package/dist/commands/admin/inspect.js.map +1 -0
  166. package/dist/commands/admin/inspect.test.d.ts +7 -0
  167. package/dist/commands/admin/inspect.test.d.ts.map +1 -0
  168. package/dist/commands/admin/inspect.test.js +90 -0
  169. package/dist/commands/admin/inspect.test.js.map +1 -0
  170. package/dist/commands/admin/manage.d.ts +8 -0
  171. package/dist/commands/admin/manage.d.ts.map +1 -0
  172. package/dist/commands/admin/manage.js +76 -0
  173. package/dist/commands/admin/manage.js.map +1 -0
  174. package/dist/commands/admin/seed.d.ts +32 -0
  175. package/dist/commands/admin/seed.d.ts.map +1 -0
  176. package/dist/commands/admin/seed.js +533 -0
  177. package/dist/commands/admin/seed.js.map +1 -0
  178. package/dist/commands/admin/seed.test.d.ts +6 -0
  179. package/dist/commands/admin/seed.test.d.ts.map +1 -0
  180. package/dist/commands/admin/seed.test.js +65 -0
  181. package/dist/commands/admin/seed.test.js.map +1 -0
  182. package/dist/commands/audit.d.ts +25 -0
  183. package/dist/commands/audit.d.ts.map +1 -0
  184. package/dist/commands/audit.js +188 -0
  185. package/dist/commands/audit.js.map +1 -0
  186. package/dist/commands/brand-pack.d.ts +2 -0
  187. package/dist/commands/brand-pack.d.ts.map +1 -0
  188. package/dist/commands/brand-pack.js +25 -0
  189. package/dist/commands/brand-pack.js.map +1 -0
  190. package/dist/commands/brief.d.ts +28 -0
  191. package/dist/commands/brief.d.ts.map +1 -0
  192. package/dist/commands/brief.js +75 -0
  193. package/dist/commands/brief.js.map +1 -0
  194. package/dist/commands/capture.d.ts +9 -0
  195. package/dist/commands/capture.d.ts.map +1 -1
  196. package/dist/commands/capture.js +256 -17
  197. package/dist/commands/capture.js.map +1 -1
  198. package/dist/commands/chain-walk.d.ts +14 -0
  199. package/dist/commands/chain-walk.d.ts.map +1 -0
  200. package/dist/commands/chain-walk.js +38 -0
  201. package/dist/commands/chain-walk.js.map +1 -0
  202. package/dist/commands/changes.d.ts +11 -0
  203. package/dist/commands/changes.d.ts.map +1 -0
  204. package/dist/commands/changes.js +46 -0
  205. package/dist/commands/changes.js.map +1 -0
  206. package/dist/commands/codex-prep.d.ts +12 -0
  207. package/dist/commands/codex-prep.d.ts.map +1 -0
  208. package/dist/commands/codex-prep.js +122 -0
  209. package/dist/commands/codex-prep.js.map +1 -0
  210. package/dist/commands/collections.d.ts +22 -0
  211. package/dist/commands/collections.d.ts.map +1 -0
  212. package/dist/commands/collections.js +77 -0
  213. package/dist/commands/collections.js.map +1 -0
  214. package/dist/commands/connect-integration.test.d.ts +7 -0
  215. package/dist/commands/connect-integration.test.d.ts.map +1 -0
  216. package/dist/commands/connect-integration.test.js +195 -0
  217. package/dist/commands/connect-integration.test.js.map +1 -0
  218. package/dist/commands/connect-screens.d.ts +21 -0
  219. package/dist/commands/connect-screens.d.ts.map +1 -0
  220. package/dist/commands/connect-screens.js +79 -0
  221. package/dist/commands/connect-screens.js.map +1 -0
  222. package/dist/commands/connect.d.ts +21 -0
  223. package/dist/commands/connect.d.ts.map +1 -0
  224. package/dist/commands/connect.js +237 -0
  225. package/dist/commands/connect.js.map +1 -0
  226. package/dist/commands/connect.test.d.ts +6 -0
  227. package/dist/commands/connect.test.d.ts.map +1 -0
  228. package/dist/commands/connect.test.js +234 -0
  229. package/dist/commands/connect.test.js.map +1 -0
  230. package/dist/commands/constellation.d.ts.map +1 -1
  231. package/dist/commands/constellation.js +8 -3
  232. package/dist/commands/constellation.js.map +1 -1
  233. package/dist/commands/context.d.ts.map +1 -1
  234. package/dist/commands/context.js +8 -3
  235. package/dist/commands/context.js.map +1 -1
  236. package/dist/commands/cross-cut.d.ts +11 -0
  237. package/dist/commands/cross-cut.d.ts.map +1 -0
  238. package/dist/commands/cross-cut.js +23 -0
  239. package/dist/commands/cross-cut.js.map +1 -0
  240. package/dist/commands/doctor.d.ts +18 -0
  241. package/dist/commands/doctor.d.ts.map +1 -0
  242. package/dist/commands/doctor.js +232 -0
  243. package/dist/commands/doctor.js.map +1 -0
  244. package/dist/commands/doctor.test.d.ts +8 -0
  245. package/dist/commands/doctor.test.d.ts.map +1 -0
  246. package/dist/commands/doctor.test.js +311 -0
  247. package/dist/commands/doctor.test.js.map +1 -0
  248. package/dist/commands/fields.d.ts.map +1 -1
  249. package/dist/commands/fields.js +8 -4
  250. package/dist/commands/fields.js.map +1 -1
  251. package/dist/commands/get.d.ts.map +1 -1
  252. package/dist/commands/get.js +14 -6
  253. package/dist/commands/get.js.map +1 -1
  254. package/dist/commands/handshake.d.ts +12 -0
  255. package/dist/commands/handshake.d.ts.map +1 -1
  256. package/dist/commands/handshake.js +422 -74
  257. package/dist/commands/handshake.js.map +1 -1
  258. package/dist/commands/ingest.d.ts +7 -2
  259. package/dist/commands/ingest.d.ts.map +1 -1
  260. package/dist/commands/ingest.js +137 -31
  261. package/dist/commands/ingest.js.map +1 -1
  262. package/dist/commands/init.d.ts +14 -0
  263. package/dist/commands/init.d.ts.map +1 -0
  264. package/dist/commands/init.js +109 -0
  265. package/dist/commands/init.js.map +1 -0
  266. package/dist/commands/login.d.ts +4 -0
  267. package/dist/commands/login.d.ts.map +1 -1
  268. package/dist/commands/login.js +101 -38
  269. package/dist/commands/login.js.map +1 -1
  270. package/dist/commands/method.d.ts +99 -0
  271. package/dist/commands/method.d.ts.map +1 -0
  272. package/dist/commands/method.js +781 -0
  273. package/dist/commands/method.js.map +1 -0
  274. package/dist/commands/orient.d.ts +106 -1
  275. package/dist/commands/orient.d.ts.map +1 -1
  276. package/dist/commands/orient.js +13 -2
  277. package/dist/commands/orient.js.map +1 -1
  278. package/dist/commands/profile.d.ts +24 -0
  279. package/dist/commands/profile.d.ts.map +1 -0
  280. package/dist/commands/profile.js +82 -0
  281. package/dist/commands/profile.js.map +1 -0
  282. package/dist/commands/promote.d.ts +12 -0
  283. package/dist/commands/promote.d.ts.map +1 -0
  284. package/dist/commands/promote.js +90 -0
  285. package/dist/commands/promote.js.map +1 -0
  286. package/dist/commands/proposals.d.ts +9 -0
  287. package/dist/commands/proposals.d.ts.map +1 -0
  288. package/dist/commands/proposals.js +24 -0
  289. package/dist/commands/proposals.js.map +1 -0
  290. package/dist/commands/reject.d.ts +14 -0
  291. package/dist/commands/reject.d.ts.map +1 -0
  292. package/dist/commands/reject.js +43 -0
  293. package/dist/commands/reject.js.map +1 -0
  294. package/dist/commands/relate.d.ts +1 -0
  295. package/dist/commands/relate.d.ts.map +1 -1
  296. package/dist/commands/relate.js +41 -15
  297. package/dist/commands/relate.js.map +1 -1
  298. package/dist/commands/search.js +2 -2
  299. package/dist/commands/search.js.map +1 -1
  300. package/dist/commands/session.d.ts.map +1 -1
  301. package/dist/commands/session.js +85 -16
  302. package/dist/commands/session.js.map +1 -1
  303. package/dist/commands/setup.d.ts +15 -0
  304. package/dist/commands/setup.d.ts.map +1 -0
  305. package/dist/commands/setup.js +148 -0
  306. package/dist/commands/setup.js.map +1 -0
  307. package/dist/commands/update.d.ts +1 -0
  308. package/dist/commands/update.d.ts.map +1 -1
  309. package/dist/commands/update.js +102 -13
  310. package/dist/commands/update.js.map +1 -1
  311. package/dist/commands/usage.d.ts +40 -0
  312. package/dist/commands/usage.d.ts.map +1 -0
  313. package/dist/commands/usage.js +232 -0
  314. package/dist/commands/usage.js.map +1 -0
  315. package/dist/commands/verify.d.ts +13 -0
  316. package/dist/commands/verify.d.ts.map +1 -0
  317. package/dist/commands/verify.js +49 -0
  318. package/dist/commands/verify.js.map +1 -0
  319. package/dist/commands/welcome.d.ts +21 -0
  320. package/dist/commands/welcome.d.ts.map +1 -0
  321. package/dist/commands/welcome.js +50 -0
  322. package/dist/commands/welcome.js.map +1 -0
  323. package/dist/commands/workspace.d.ts +41 -0
  324. package/dist/commands/workspace.d.ts.map +1 -0
  325. package/dist/commands/workspace.js +239 -0
  326. package/dist/commands/workspace.js.map +1 -0
  327. package/dist/formatters/audit.d.ts +46 -0
  328. package/dist/formatters/audit.d.ts.map +1 -0
  329. package/dist/formatters/audit.js +81 -0
  330. package/dist/formatters/audit.js.map +1 -0
  331. package/dist/formatters/brief.d.ts +112 -0
  332. package/dist/formatters/brief.d.ts.map +1 -0
  333. package/dist/formatters/brief.js +179 -0
  334. package/dist/formatters/brief.js.map +1 -0
  335. package/dist/formatters/capture.d.ts +21 -3
  336. package/dist/formatters/capture.d.ts.map +1 -1
  337. package/dist/formatters/capture.js +20 -1
  338. package/dist/formatters/capture.js.map +1 -1
  339. package/dist/formatters/chain-walk.d.ts +33 -0
  340. package/dist/formatters/chain-walk.d.ts.map +1 -0
  341. package/dist/formatters/chain-walk.js +54 -0
  342. package/dist/formatters/chain-walk.js.map +1 -0
  343. package/dist/formatters/changes.d.ts +25 -0
  344. package/dist/formatters/changes.d.ts.map +1 -0
  345. package/dist/formatters/changes.js +60 -0
  346. package/dist/formatters/changes.js.map +1 -0
  347. package/dist/formatters/collections.d.ts +40 -0
  348. package/dist/formatters/collections.d.ts.map +1 -0
  349. package/dist/formatters/collections.js +93 -0
  350. package/dist/formatters/collections.js.map +1 -0
  351. package/dist/formatters/cross-cut.d.ts +21 -0
  352. package/dist/formatters/cross-cut.d.ts.map +1 -0
  353. package/dist/formatters/cross-cut.js +32 -0
  354. package/dist/formatters/cross-cut.js.map +1 -0
  355. package/dist/formatters/entry.d.ts +11 -4
  356. package/dist/formatters/entry.d.ts.map +1 -1
  357. package/dist/formatters/entry.js +24 -8
  358. package/dist/formatters/entry.js.map +1 -1
  359. package/dist/formatters/handshake.d.ts +29 -0
  360. package/dist/formatters/handshake.d.ts.map +1 -1
  361. package/dist/formatters/handshake.js +115 -3
  362. package/dist/formatters/handshake.js.map +1 -1
  363. package/dist/formatters/orient.d.ts +104 -1
  364. package/dist/formatters/orient.d.ts.map +1 -1
  365. package/dist/formatters/orient.js +140 -17
  366. package/dist/formatters/orient.js.map +1 -1
  367. package/dist/formatters/promote.d.ts +30 -0
  368. package/dist/formatters/promote.d.ts.map +1 -0
  369. package/dist/formatters/promote.js +39 -0
  370. package/dist/formatters/promote.js.map +1 -0
  371. package/dist/formatters/proposals.d.ts +45 -0
  372. package/dist/formatters/proposals.d.ts.map +1 -0
  373. package/dist/formatters/proposals.js +62 -0
  374. package/dist/formatters/proposals.js.map +1 -0
  375. package/dist/formatters/relate.d.ts +3 -0
  376. package/dist/formatters/relate.d.ts.map +1 -1
  377. package/dist/formatters/relate.js +6 -0
  378. package/dist/formatters/relate.js.map +1 -1
  379. package/dist/formatters/search.d.ts +0 -4
  380. package/dist/formatters/search.d.ts.map +1 -1
  381. package/dist/formatters/search.js +4 -1
  382. package/dist/formatters/search.js.map +1 -1
  383. package/dist/formatters/session.d.ts +1 -1
  384. package/dist/formatters/session.d.ts.map +1 -1
  385. package/dist/formatters/session.js +3 -1
  386. package/dist/formatters/session.js.map +1 -1
  387. package/dist/formatters/update.d.ts.map +1 -1
  388. package/dist/formatters/update.js +2 -0
  389. package/dist/formatters/update.js.map +1 -1
  390. package/dist/formatters/verify.d.ts +11 -0
  391. package/dist/formatters/verify.d.ts.map +1 -0
  392. package/dist/formatters/verify.js +11 -0
  393. package/dist/formatters/verify.js.map +1 -0
  394. package/dist/generators/__tests__/surface-profiles.test.d.ts +2 -0
  395. package/dist/generators/__tests__/surface-profiles.test.d.ts.map +1 -0
  396. package/dist/generators/__tests__/surface-profiles.test.js +89 -0
  397. package/dist/generators/__tests__/surface-profiles.test.js.map +1 -0
  398. package/dist/generators/adapters.d.ts +37 -3
  399. package/dist/generators/adapters.d.ts.map +1 -1
  400. package/dist/generators/adapters.js +193 -5
  401. package/dist/generators/adapters.js.map +1 -1
  402. package/dist/generators/adapters.test.d.ts +2 -0
  403. package/dist/generators/adapters.test.d.ts.map +1 -0
  404. package/dist/generators/adapters.test.js +27 -0
  405. package/dist/generators/adapters.test.js.map +1 -0
  406. package/dist/generators/archetypes.d.ts +52 -0
  407. package/dist/generators/archetypes.d.ts.map +1 -0
  408. package/dist/generators/archetypes.js +153 -0
  409. package/dist/generators/archetypes.js.map +1 -0
  410. package/dist/generators/archetypes.test.d.ts +2 -0
  411. package/dist/generators/archetypes.test.d.ts.map +1 -0
  412. package/dist/generators/archetypes.test.js +237 -0
  413. package/dist/generators/archetypes.test.js.map +1 -0
  414. package/dist/generators/chain-classifier.d.ts +49 -0
  415. package/dist/generators/chain-classifier.d.ts.map +1 -0
  416. package/dist/generators/chain-classifier.js +180 -0
  417. package/dist/generators/chain-classifier.js.map +1 -0
  418. package/dist/generators/chain-classifier.test.d.ts +2 -0
  419. package/dist/generators/chain-classifier.test.d.ts.map +1 -0
  420. package/dist/generators/chain-classifier.test.js +257 -0
  421. package/dist/generators/chain-classifier.test.js.map +1 -0
  422. package/dist/generators/chain-rules.d.ts +42 -0
  423. package/dist/generators/chain-rules.d.ts.map +1 -0
  424. package/dist/generators/chain-rules.js +144 -0
  425. package/dist/generators/chain-rules.js.map +1 -0
  426. package/dist/generators/chain-rules.test.d.ts +2 -0
  427. package/dist/generators/chain-rules.test.d.ts.map +1 -0
  428. package/dist/generators/chain-rules.test.js +179 -0
  429. package/dist/generators/chain-rules.test.js.map +1 -0
  430. package/dist/generators/context-md.d.ts +1 -1
  431. package/dist/generators/context-md.d.ts.map +1 -1
  432. package/dist/generators/context-md.js +12 -1
  433. package/dist/generators/context-md.js.map +1 -1
  434. package/dist/generators/handshake-diff.d.ts +67 -0
  435. package/dist/generators/handshake-diff.d.ts.map +1 -0
  436. package/dist/generators/handshake-diff.js +183 -0
  437. package/dist/generators/handshake-diff.js.map +1 -0
  438. package/dist/generators/handshake-diff.test.d.ts +2 -0
  439. package/dist/generators/handshake-diff.test.d.ts.map +1 -0
  440. package/dist/generators/handshake-diff.test.js +264 -0
  441. package/dist/generators/handshake-diff.test.js.map +1 -0
  442. package/dist/generators/manifest.d.ts +37 -0
  443. package/dist/generators/manifest.d.ts.map +1 -0
  444. package/dist/generators/manifest.js +166 -0
  445. package/dist/generators/manifest.js.map +1 -0
  446. package/dist/generators/portable-knowledge.d.ts +102 -9
  447. package/dist/generators/portable-knowledge.d.ts.map +1 -1
  448. package/dist/generators/portable-knowledge.js +384 -17
  449. package/dist/generators/portable-knowledge.js.map +1 -1
  450. package/dist/generators/portable-knowledge.test.js +529 -1
  451. package/dist/generators/portable-knowledge.test.js.map +1 -1
  452. package/dist/generators/surface-profiles.d.ts +49 -0
  453. package/dist/generators/surface-profiles.d.ts.map +1 -0
  454. package/dist/generators/surface-profiles.js +98 -0
  455. package/dist/generators/surface-profiles.js.map +1 -0
  456. package/dist/index.js +618 -138
  457. package/dist/index.js.map +1 -1
  458. package/dist/lib/activation.d.ts +28 -0
  459. package/dist/lib/activation.d.ts.map +1 -0
  460. package/dist/lib/activation.js +57 -0
  461. package/dist/lib/activation.js.map +1 -0
  462. package/dist/lib/activation.test.d.ts +6 -0
  463. package/dist/lib/activation.test.d.ts.map +1 -0
  464. package/dist/lib/activation.test.js +121 -0
  465. package/dist/lib/activation.test.js.map +1 -0
  466. package/dist/lib/client.d.ts +45 -3
  467. package/dist/lib/client.d.ts.map +1 -1
  468. package/dist/lib/client.js +188 -36
  469. package/dist/lib/client.js.map +1 -1
  470. package/dist/lib/collectionRegistry.d.ts +38 -0
  471. package/dist/lib/collectionRegistry.d.ts.map +1 -0
  472. package/dist/lib/collectionRegistry.js +112 -0
  473. package/dist/lib/collectionRegistry.js.map +1 -0
  474. package/dist/lib/config.d.ts +84 -4
  475. package/dist/lib/config.d.ts.map +1 -1
  476. package/dist/lib/config.js +322 -42
  477. package/dist/lib/config.js.map +1 -1
  478. package/dist/lib/constants.d.ts +42 -0
  479. package/dist/lib/constants.d.ts.map +1 -0
  480. package/dist/lib/constants.js +76 -0
  481. package/dist/lib/constants.js.map +1 -0
  482. package/dist/lib/conversation-engine.d.ts +45 -0
  483. package/dist/lib/conversation-engine.d.ts.map +1 -0
  484. package/dist/lib/conversation-engine.js +112 -0
  485. package/dist/lib/conversation-engine.js.map +1 -0
  486. package/dist/lib/conversation-phases.d.ts +59 -0
  487. package/dist/lib/conversation-phases.d.ts.map +1 -0
  488. package/dist/lib/conversation-phases.js +11 -0
  489. package/dist/lib/conversation-phases.js.map +1 -0
  490. package/dist/lib/conversation-signals.d.ts +30 -0
  491. package/dist/lib/conversation-signals.d.ts.map +1 -0
  492. package/dist/lib/conversation-signals.js +64 -0
  493. package/dist/lib/conversation-signals.js.map +1 -0
  494. package/dist/lib/deployment.d.ts +23 -0
  495. package/dist/lib/deployment.d.ts.map +1 -0
  496. package/dist/lib/deployment.js +78 -0
  497. package/dist/lib/deployment.js.map +1 -0
  498. package/dist/lib/deployment.test.d.ts +5 -0
  499. package/dist/lib/deployment.test.d.ts.map +1 -0
  500. package/dist/lib/deployment.test.js +54 -0
  501. package/dist/lib/deployment.test.js.map +1 -0
  502. package/dist/lib/errors.d.ts +58 -0
  503. package/dist/lib/errors.d.ts.map +1 -0
  504. package/dist/lib/errors.js +67 -0
  505. package/dist/lib/errors.js.map +1 -0
  506. package/dist/lib/experiment.d.ts +18 -0
  507. package/dist/lib/experiment.d.ts.map +1 -0
  508. package/dist/lib/experiment.js +28 -0
  509. package/dist/lib/experiment.js.map +1 -0
  510. package/dist/lib/format.d.ts +10 -0
  511. package/dist/lib/format.d.ts.map +1 -0
  512. package/dist/lib/format.js +27 -0
  513. package/dist/lib/format.js.map +1 -0
  514. package/dist/lib/glossary.d.ts +19 -0
  515. package/dist/lib/glossary.d.ts.map +1 -0
  516. package/dist/lib/glossary.js +53 -0
  517. package/dist/lib/glossary.js.map +1 -0
  518. package/dist/lib/hook-intents.d.ts +51 -0
  519. package/dist/lib/hook-intents.d.ts.map +1 -0
  520. package/dist/lib/hook-intents.js +85 -0
  521. package/dist/lib/hook-intents.js.map +1 -0
  522. package/dist/lib/inferSourceDate.d.ts +12 -0
  523. package/dist/lib/inferSourceDate.d.ts.map +1 -0
  524. package/dist/lib/inferSourceDate.js +44 -0
  525. package/dist/lib/inferSourceDate.js.map +1 -0
  526. package/dist/lib/method-registry.d.ts +32 -0
  527. package/dist/lib/method-registry.d.ts.map +1 -0
  528. package/dist/lib/method-registry.js +53 -0
  529. package/dist/lib/method-registry.js.map +1 -0
  530. package/dist/lib/onboarding-path-b.d.ts +10 -0
  531. package/dist/lib/onboarding-path-b.d.ts.map +1 -0
  532. package/dist/lib/onboarding-path-b.js +214 -0
  533. package/dist/lib/onboarding-path-b.js.map +1 -0
  534. package/dist/lib/onboarding-phases.d.ts +9 -0
  535. package/dist/lib/onboarding-phases.d.ts.map +1 -0
  536. package/dist/lib/onboarding-phases.js +120 -0
  537. package/dist/lib/onboarding-phases.js.map +1 -0
  538. package/dist/lib/onboarding-shared.d.ts +81 -0
  539. package/dist/lib/onboarding-shared.d.ts.map +1 -0
  540. package/dist/lib/onboarding-shared.js +190 -0
  541. package/dist/lib/onboarding-shared.js.map +1 -0
  542. package/dist/lib/onboarding-topics.d.ts +27 -0
  543. package/dist/lib/onboarding-topics.d.ts.map +1 -0
  544. package/dist/lib/onboarding-topics.js +57 -0
  545. package/dist/lib/onboarding-topics.js.map +1 -0
  546. package/dist/lib/onboarding.d.ts +17 -0
  547. package/dist/lib/onboarding.d.ts.map +1 -0
  548. package/dist/lib/onboarding.js +350 -0
  549. package/dist/lib/onboarding.js.map +1 -0
  550. package/dist/lib/profiles.d.ts +39 -0
  551. package/dist/lib/profiles.d.ts.map +1 -0
  552. package/dist/lib/profiles.js +185 -0
  553. package/dist/lib/profiles.js.map +1 -0
  554. package/dist/lib/prompts.d.ts +65 -0
  555. package/dist/lib/prompts.d.ts.map +1 -0
  556. package/dist/lib/prompts.js +132 -0
  557. package/dist/lib/prompts.js.map +1 -0
  558. package/dist/lib/repo-detect.d.ts +19 -0
  559. package/dist/lib/repo-detect.d.ts.map +1 -1
  560. package/dist/lib/repo-detect.js +25 -0
  561. package/dist/lib/repo-detect.js.map +1 -1
  562. package/dist/lib/runner.d.ts +2 -0
  563. package/dist/lib/runner.d.ts.map +1 -1
  564. package/dist/lib/runner.js +21 -7
  565. package/dist/lib/runner.js.map +1 -1
  566. package/dist/lib/session.d.ts +25 -0
  567. package/dist/lib/session.d.ts.map +1 -1
  568. package/dist/lib/session.js +70 -4
  569. package/dist/lib/session.js.map +1 -1
  570. package/dist/lib/spinner.d.ts +27 -0
  571. package/dist/lib/spinner.d.ts.map +1 -0
  572. package/dist/lib/spinner.js +76 -0
  573. package/dist/lib/spinner.js.map +1 -0
  574. package/dist/lib/spinner.test.d.ts +2 -0
  575. package/dist/lib/spinner.test.d.ts.map +1 -0
  576. package/dist/lib/spinner.test.js +39 -0
  577. package/dist/lib/spinner.test.js.map +1 -0
  578. package/dist/lib/state.d.ts +51 -0
  579. package/dist/lib/state.d.ts.map +1 -0
  580. package/dist/lib/state.js +90 -0
  581. package/dist/lib/state.js.map +1 -0
  582. package/dist/lib/strip.d.ts +1 -0
  583. package/dist/lib/strip.d.ts.map +1 -1
  584. package/dist/lib/strip.js +15 -0
  585. package/dist/lib/strip.js.map +1 -1
  586. package/dist/lib/style.d.ts +96 -0
  587. package/dist/lib/style.d.ts.map +1 -0
  588. package/dist/lib/style.js +169 -0
  589. package/dist/lib/style.js.map +1 -0
  590. package/dist/lib/style.test.d.ts +7 -0
  591. package/dist/lib/style.test.d.ts.map +1 -0
  592. package/dist/lib/style.test.js +263 -0
  593. package/dist/lib/style.test.js.map +1 -0
  594. package/dist/lib/telemetry.d.ts +15 -0
  595. package/dist/lib/telemetry.d.ts.map +1 -0
  596. package/dist/lib/telemetry.js +47 -0
  597. package/dist/lib/telemetry.js.map +1 -0
  598. package/dist/lib/tokenConstants.d.ts +17 -0
  599. package/dist/lib/tokenConstants.d.ts.map +1 -0
  600. package/dist/lib/tokenConstants.js +17 -0
  601. package/dist/lib/tokenConstants.js.map +1 -0
  602. package/dist/lib/update-check.d.ts +21 -0
  603. package/dist/lib/update-check.d.ts.map +1 -0
  604. package/dist/lib/update-check.js +145 -0
  605. package/dist/lib/update-check.js.map +1 -0
  606. package/dist/lib/wizard-surfaces.d.ts +47 -0
  607. package/dist/lib/wizard-surfaces.d.ts.map +1 -0
  608. package/dist/lib/wizard-surfaces.js +176 -0
  609. package/dist/lib/wizard-surfaces.js.map +1 -0
  610. package/dist/lib/wizard-surfaces.test.d.ts +2 -0
  611. package/dist/lib/wizard-surfaces.test.d.ts.map +1 -0
  612. package/dist/lib/wizard-surfaces.test.js +127 -0
  613. package/dist/lib/wizard-surfaces.test.js.map +1 -0
  614. package/dist/lib/wizard-trust.d.ts +31 -0
  615. package/dist/lib/wizard-trust.d.ts.map +1 -0
  616. package/dist/lib/wizard-trust.js +66 -0
  617. package/dist/lib/wizard-trust.js.map +1 -0
  618. package/dist/lib/wizard-trust.test.d.ts +2 -0
  619. package/dist/lib/wizard-trust.test.d.ts.map +1 -0
  620. package/dist/lib/wizard-trust.test.js +32 -0
  621. package/dist/lib/wizard-trust.test.js.map +1 -0
  622. package/dist/lib/workspace-probe.d.ts +19 -0
  623. package/dist/lib/workspace-probe.d.ts.map +1 -0
  624. package/dist/lib/workspace-probe.js +27 -0
  625. package/dist/lib/workspace-probe.js.map +1 -0
  626. package/dist/surfaces/registry.d.ts +20 -0
  627. package/dist/surfaces/registry.d.ts.map +1 -0
  628. package/dist/surfaces/registry.js +42 -0
  629. package/dist/surfaces/registry.js.map +1 -0
  630. package/package.json +9 -3
  631. package/templates/archetypes/boundary.md +23 -0
  632. package/templates/archetypes/constraint.md +23 -0
  633. package/templates/archetypes/convention.md +23 -0
  634. package/templates/archetypes/policy.md +23 -0
  635. package/templates/archetypes/quality-gate.md +23 -0
  636. package/templates/archetypes/workflow.md +23 -0
  637. package/templates/general/code-integrity.md +11 -0
  638. package/templates/general/getting-started.md +12 -0
  639. package/templates/method-registry.json +16 -0
  640. package/templates/node-ts/code-integrity.md +13 -0
  641. package/templates/node-ts/testing.md +12 -0
  642. package/templates/python/code-integrity.md +13 -0
  643. package/templates/python/testing.md +12 -0
@@ -2,6 +2,12 @@
2
2
  * Portable knowledge — reads canonical skills/rules from .productbrain/
3
3
  * and generates tool-specific copies for Cursor, Claude Code, etc.
4
4
  */
5
+ import type { SurfaceProfile } from './surface-profiles.js';
6
+ export interface WhenConditions {
7
+ when_stack?: string;
8
+ when_minStage?: string;
9
+ when_minGovernance?: string;
10
+ }
5
11
  export interface CanonicalSkill {
6
12
  name: string;
7
13
  description: string;
@@ -10,6 +16,9 @@ export interface CanonicalSkill {
10
16
  sourcePath: string;
11
17
  targets?: string[];
12
18
  level?: string;
19
+ conditions?: WhenConditions;
20
+ /** 'team' = default (projected to committed adapter files); 'local' = local surface files only, never committed. */
21
+ persist?: 'local' | 'team';
13
22
  }
14
23
  export interface CanonicalRule {
15
24
  name: string;
@@ -20,22 +29,69 @@ export interface CanonicalRule {
20
29
  sourcePath: string;
21
30
  targets?: string[];
22
31
  level?: string;
32
+ conditions?: WhenConditions;
33
+ /** 'team' = default (projected to committed adapter files); 'local' = local surface files only, never committed. */
34
+ persist?: 'local' | 'team';
23
35
  }
24
- export type TargetName = 'cursor' | 'claude' | 'copilot';
36
+ export type TargetName = 'cursor' | 'claude' | 'copilot' | 'codex';
37
+ /**
38
+ * Returns true if the rule has persist: 'local'.
39
+ * Local rules are written to local surface files (.claude/rules/, .cursor/rules/)
40
+ * but must never be projected to committed adapter files (CLAUDE.md, AGENTS.md, etc.).
41
+ */
42
+ export declare function isPersistLocal(rule: CanonicalRule): boolean;
25
43
  /** Returns true if the entry should be emitted to the given target. */
26
44
  export declare function shouldEmitToTarget(entry: CanonicalRule | CanonicalSkill, target: TargetName): boolean;
27
45
  export type HandshakeLevel = 'beginner' | 'intermediate' | 'expert';
28
46
  /**
29
- * Filter items by graduated level.
30
- * - If requestedLevel is undefined/null: return ALL items (backward compat).
47
+ * Maps workspace stage to the maximum allowed HandshakeLevel.
48
+ * Stages not listed here apply no cap (fail-open for unknown stages).
49
+ * Note: 'beginner' level allows only 'core' items; 'intermediate' allows core + intermediate.
50
+ */
51
+ export declare const STAGE_TO_MAX_LEVEL: Record<string, HandshakeLevel>;
52
+ /** Level ordering used to pick the more restrictive of two levels. */
53
+ export declare const LEVEL_ORDER: HandshakeLevel[];
54
+ /**
55
+ * Filter items by graduated level, with optional workspace stage-gating.
56
+ * - If requestedLevel is undefined/null AND stage provides no cap: return ALL items (backward compat).
31
57
  * - Items with no `level` field: always included (backward compat).
32
- * - Otherwise: include items whose level is within the hierarchy for requestedLevel.
58
+ * - Stage caps the effective level: blank→beginner, seed→intermediate, grounded/connected/critical→expert.
59
+ * - If stage is unknown or null: no cap applied (fail-open).
60
+ * - The effective level is min(requestedLevel, stageCap) — most restrictive wins.
33
61
  */
34
62
  export declare function filterByLevel<T extends {
35
63
  level?: string;
36
- }>(items: T[], requestedLevel?: string): T[];
64
+ }>(items: T[], requestedLevel?: string, stage?: string): T[];
65
+ /**
66
+ * Evaluate when_* conditions against the workspace profile and repo context.
67
+ * Returns { included, reasons }.
68
+ *
69
+ * Fail-open: if profile is null and profile-dependent conditions are present,
70
+ * the item is included (preserves current behavior when Chain is unavailable).
71
+ */
72
+ export declare function evaluateConditions(conditions: WhenConditions, profile: {
73
+ stage: string;
74
+ totalRelations: number;
75
+ } | null, repoContext: {
76
+ detectedStack: string[];
77
+ }): {
78
+ included: boolean;
79
+ reasons: string[];
80
+ };
37
81
  export declare function readCanonicalSkills(productbrainDir: string): CanonicalSkill[];
38
82
  export declare function readCanonicalRules(productbrainDir: string): CanonicalRule[];
83
+ /**
84
+ * Read machine-local personal rules from .productbrain/.local/rules/.
85
+ * Returns [] when the directory is absent — no-op when personal layer is not set up.
86
+ * Every returned rule has persist: 'local' set, preventing projection to committed adapter files.
87
+ */
88
+ export declare function readPersonalLayer(productbrainDir: string): CanonicalRule[];
89
+ /**
90
+ * Read machine-local personal skills from .productbrain/.local/skills/.
91
+ * Returns [] when the directory is absent — no-op when personal layer is not set up.
92
+ * Every returned skill has persist: 'local' set, preventing projection to committed adapter files.
93
+ */
94
+ export declare function readPersonalSkillsLayer(productbrainDir: string): CanonicalSkill[];
39
95
  /**
40
96
  * Strip transport-conditional sections from a skill body.
41
97
  *
@@ -53,20 +109,57 @@ export declare function stripTransportSections(body: string, target: TargetName)
53
109
  * Generate a Cursor SKILL.md from a canonical skill.
54
110
  * Cursor expects: name, description (with triggers embedded).
55
111
  */
56
- export declare function generateCursorSkill(skill: CanonicalSkill): string;
112
+ export declare function generateCursorSkill(skill: CanonicalSkill, profile?: SurfaceProfile): string;
57
113
  /**
58
114
  * Generate a Cursor .mdc rule from a canonical rule.
59
115
  * Cursor expects: description, globs, alwaysApply.
60
116
  */
61
- export declare function generateCursorRule(rule: CanonicalRule): string;
117
+ export declare function generateCursorRule(rule: CanonicalRule, profile?: SurfaceProfile): string;
118
+ /**
119
+ * Apply batch-mode transformations to a skill body (DEC-283).
120
+ *
121
+ * Skills describe WHAT (intent). This generator produces HOW (batch-appropriate
122
+ * instructions). We transform interactive patterns without gutting the skill's
123
+ * logical structure and purpose.
124
+ *
125
+ * Transformations applied:
126
+ * 1. Strip sub-agent spawn patterns → inline steps
127
+ * 2. Strip user confirmation gates → autonomous proceed
128
+ * 3. Strip streaming/interactive references
129
+ * 4. Add batch governance header after first `#` heading
130
+ */
131
+ export declare function applyBatchTransformations(body: string): string;
132
+ /**
133
+ * Generate a Codex skill projection from a canonical skill.
134
+ * This is a repo-local markdown projection, not a separate authoring source.
135
+ *
136
+ * When profile.executionModel === 'batch', batch transformations are applied
137
+ * AFTER transport stripping and path replacement (DEC-283).
138
+ */
139
+ export declare function generateCodexSkill(skill: CanonicalSkill, profile?: SurfaceProfile): string;
140
+ /**
141
+ * Generate a Codex skill index/router file.
142
+ * AGENTS.md can point here so Codex has one obvious place to find available workflows.
143
+ */
144
+ export declare function generateCodexSkillIndex(skills: CanonicalSkill[]): string;
145
+ export interface CodexValidationWarning {
146
+ skillName: string;
147
+ pattern: string;
148
+ line: string;
149
+ }
150
+ /**
151
+ * Validate Codex-projected skills for references to capabilities Codex cannot execute.
152
+ * Scans the transport-stripped body (so claude-only blocks don't false-positive).
153
+ */
154
+ export declare function validateCodexSkills(skills: CanonicalSkill[]): CodexValidationWarning[];
62
155
  /**
63
156
  * Generate a Claude Code .md rule from a canonical rule.
64
157
  * Claude Code expects: description, optional paths (array).
65
158
  */
66
- export declare function generateClaudeRule(rule: CanonicalRule): string;
159
+ export declare function generateClaudeRule(rule: CanonicalRule, profile?: SurfaceProfile): string;
67
160
  /**
68
161
  * Generate a Claude Code skill-router.md — imperative skill activation rule.
69
162
  * Loaded automatically by Claude Code via .claude/rules/ with no paths (always active).
70
163
  */
71
- export declare function generateClaudeSkillRouter(skills: CanonicalSkill[]): string;
164
+ export declare function generateClaudeSkillRouter(skills: CanonicalSkill[], profile?: SurfaceProfile): string;
72
165
  //# sourceMappingURL=portable-knowledge.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"portable-knowledge.d.ts","sourceRoot":"","sources":["../../src/generators/portable-knowledge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEzD,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAGrG;AAID,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,cAAc,GAAG,QAAQ,CAAC;AAUpE;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,CAAC,EAAE,CASpG;AAkED,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,cAAc,EAAE,CAsB7E;AAED,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,aAAa,EAAE,CAuB3E;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAa/E;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,GAAG,MAAM,CAyBjE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAc9D;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAqB9D;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,CA4B1E"}
1
+ {"version":3,"file":"portable-knowledge.d.ts","sourceRoot":"","sources":["../../src/generators/portable-knowledge.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAI5D,MAAM,WAAW,cAAc;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,oHAAoH;IACpH,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,oHAAoH;IACpH,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAQnE;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAE3D;AAED,uEAAuE;AACvE,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAOrG;AAID,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,cAAc,GAAG,QAAQ,CAAC;AAUpE;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAM7D,CAAC;AAEF,sEAAsE;AACtE,eAAO,MAAM,WAAW,EAAE,cAAc,EAA2C,CAAC;AAepF;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EACxD,KAAK,EAAE,CAAC,EAAE,EACV,cAAc,CAAC,EAAE,MAAM,EACvB,KAAK,CAAC,EAAE,MAAM,GACb,CAAC,EAAE,CAqBL;AAMD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,cAAc,EAC1B,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EACzD,WAAW,EAAE;IAAE,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,GACvC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAqD1C;AAkED,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,cAAc,EAAE,CA+B7E;AAED,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,aAAa,EAAE,CAgC3E;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,eAAe,EAAE,MAAM,GAAG,aAAa,EAAE,CA2C1E;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,cAAc,EAAE,CAyCjF;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAa/E;AAID;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAyB3F;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAcxF;AAID;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAuB9D;AA2BD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAsB1F;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,CAsCxE;AAID,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAUD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,EAAE,GAAG,sBAAsB,EAAE,CAkBtF;AAID;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAqBxF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,cAAc,EAAE,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CA4BpG"}
@@ -5,8 +5,25 @@
5
5
  import { readdirSync, readFileSync, existsSync } from 'fs';
6
6
  import { join, basename } from 'path';
7
7
  import { MARKER } from './adapters.js';
8
+ /**
9
+ * Committed adapter targets — these correspond to files that are checked into the repo.
10
+ * Rules with persist: 'local' must never be included in arrays that feed these targets.
11
+ */
12
+ const COMMITTED_ADAPTER_TARGETS = new Set(['copilot', 'codex']);
13
+ /**
14
+ * Returns true if the rule has persist: 'local'.
15
+ * Local rules are written to local surface files (.claude/rules/, .cursor/rules/)
16
+ * but must never be projected to committed adapter files (CLAUDE.md, AGENTS.md, etc.).
17
+ */
18
+ export function isPersistLocal(rule) {
19
+ return rule.persist === 'local';
20
+ }
8
21
  /** Returns true if the entry should be emitted to the given target. */
9
22
  export function shouldEmitToTarget(entry, target) {
23
+ // Local rules must not go to committed adapter targets (copilot, codex)
24
+ if ('persist' in entry && entry.persist === 'local' && COMMITTED_ADAPTER_TARGETS.has(target)) {
25
+ return false;
26
+ }
10
27
  if (!entry.targets)
11
28
  return true;
12
29
  return entry.targets.includes(target);
@@ -18,20 +35,120 @@ const LEVEL_HIERARCHY = {
18
35
  };
19
36
  const VALID_LEVELS = new Set(Object.keys(LEVEL_HIERARCHY));
20
37
  /**
21
- * Filter items by graduated level.
22
- * - If requestedLevel is undefined/null: return ALL items (backward compat).
38
+ * Maps workspace stage to the maximum allowed HandshakeLevel.
39
+ * Stages not listed here apply no cap (fail-open for unknown stages).
40
+ * Note: 'beginner' level allows only 'core' items; 'intermediate' allows core + intermediate.
41
+ */
42
+ export const STAGE_TO_MAX_LEVEL = {
43
+ blank: 'beginner',
44
+ seed: 'intermediate',
45
+ grounded: 'expert',
46
+ connected: 'expert',
47
+ critical: 'expert',
48
+ };
49
+ /** Level ordering used to pick the more restrictive of two levels. */
50
+ export const LEVEL_ORDER = ['beginner', 'intermediate', 'expert'];
51
+ /**
52
+ * Pick the more restrictive of two levels.
53
+ * If either is undefined, returns the other (or undefined if both are).
54
+ */
55
+ function capLevel(requested, cap) {
56
+ if (!requested && !cap)
57
+ return undefined;
58
+ if (!requested)
59
+ return cap;
60
+ if (!cap)
61
+ return requested;
62
+ const requestedIdx = LEVEL_ORDER.indexOf(requested);
63
+ const capIdx = LEVEL_ORDER.indexOf(cap);
64
+ return LEVEL_ORDER[Math.min(requestedIdx, capIdx)];
65
+ }
66
+ /**
67
+ * Filter items by graduated level, with optional workspace stage-gating.
68
+ * - If requestedLevel is undefined/null AND stage provides no cap: return ALL items (backward compat).
23
69
  * - Items with no `level` field: always included (backward compat).
24
- * - Otherwise: include items whose level is within the hierarchy for requestedLevel.
70
+ * - Stage caps the effective level: blank→beginner, seed→intermediate, grounded/connected/critical→expert.
71
+ * - If stage is unknown or null: no cap applied (fail-open).
72
+ * - The effective level is min(requestedLevel, stageCap) — most restrictive wins.
25
73
  */
26
- export function filterByLevel(items, requestedLevel) {
27
- if (!requestedLevel)
28
- return items;
29
- if (!VALID_LEVELS.has(requestedLevel)) {
30
- throw new Error(`Unknown level "${requestedLevel}". Valid levels: ${[...VALID_LEVELS].join(', ')}`);
74
+ export function filterByLevel(items, requestedLevel, stage) {
75
+ // Resolve stage cap (fail-open for unknown/undefined stage)
76
+ const stageCap = stage ? STAGE_TO_MAX_LEVEL[stage] : undefined;
77
+ // Resolve requested level as typed enum (validate if provided)
78
+ let typedRequested;
79
+ if (requestedLevel) {
80
+ if (!VALID_LEVELS.has(requestedLevel)) {
81
+ throw new Error(`Unknown level "${requestedLevel}". Valid levels: ${[...VALID_LEVELS].join(', ')}`);
82
+ }
83
+ typedRequested = requestedLevel;
31
84
  }
32
- const allowedLevels = LEVEL_HIERARCHY[requestedLevel];
85
+ // Determine effective level (most restrictive)
86
+ const effectiveLevel = capLevel(typedRequested, stageCap);
87
+ // No effective level — return all items (backward compat)
88
+ if (!effectiveLevel)
89
+ return items;
90
+ const allowedLevels = LEVEL_HIERARCHY[effectiveLevel];
33
91
  return items.filter((item) => !item.level || allowedLevels.includes(item.level));
34
92
  }
93
+ // ── Stage ordering ────────────────────────────────────────────────────
94
+ const STAGE_ORDER = ['blank', 'seed', 'grounded', 'connected', 'critical'];
95
+ /**
96
+ * Evaluate when_* conditions against the workspace profile and repo context.
97
+ * Returns { included, reasons }.
98
+ *
99
+ * Fail-open: if profile is null and profile-dependent conditions are present,
100
+ * the item is included (preserves current behavior when Chain is unavailable).
101
+ */
102
+ export function evaluateConditions(conditions, profile, repoContext) {
103
+ const hasProfileConditions = conditions.when_minStage !== undefined || conditions.when_minGovernance !== undefined;
104
+ const hasStackCondition = conditions.when_stack !== undefined;
105
+ // No when_* keys at all — always include
106
+ if (!hasProfileConditions && !hasStackCondition) {
107
+ return { included: true, reasons: ['no conditions'] };
108
+ }
109
+ // Fail-open: profile unavailable but profile-dependent conditions present
110
+ if (profile === null && hasProfileConditions) {
111
+ return { included: true, reasons: ['no workspace profile — fail-open'] };
112
+ }
113
+ const reasons = [];
114
+ let included = true;
115
+ // when_stack: evaluated against repoContext (not profile)
116
+ if (conditions.when_stack !== undefined) {
117
+ const needle = conditions.when_stack.toLowerCase();
118
+ const match = repoContext.detectedStack.some((s) => s.toLowerCase() === needle);
119
+ if (!match) {
120
+ included = false;
121
+ reasons.push(`when_stack=${conditions.when_stack} not in detected stack [${repoContext.detectedStack.join(', ')}]`);
122
+ }
123
+ else {
124
+ reasons.push(`when_stack=${conditions.when_stack} matched`);
125
+ }
126
+ }
127
+ // when_minStage: profile guaranteed non-null here when this condition is present
128
+ if (conditions.when_minStage !== undefined && profile !== null) {
129
+ const profileIdx = STAGE_ORDER.indexOf(profile.stage);
130
+ const thresholdIdx = STAGE_ORDER.indexOf(conditions.when_minStage);
131
+ if (thresholdIdx === -1 || profileIdx === -1 || profileIdx < thresholdIdx) {
132
+ included = false;
133
+ reasons.push(`when_minStage=${conditions.when_minStage} but workspace stage=${profile.stage}`);
134
+ }
135
+ else {
136
+ reasons.push(`when_minStage=${conditions.when_minStage} satisfied (stage=${profile.stage})`);
137
+ }
138
+ }
139
+ // when_minGovernance: profile guaranteed non-null here when this condition is present
140
+ if (conditions.when_minGovernance !== undefined && profile !== null) {
141
+ const threshold = parseInt(conditions.when_minGovernance, 10);
142
+ if (isNaN(threshold) || profile.totalRelations < threshold) {
143
+ included = false;
144
+ reasons.push(`when_minGovernance=${conditions.when_minGovernance} but totalRelations=${profile.totalRelations}`);
145
+ }
146
+ else {
147
+ reasons.push(`when_minGovernance=${conditions.when_minGovernance} satisfied (totalRelations=${profile.totalRelations})`);
148
+ }
149
+ }
150
+ return { included, reasons };
151
+ }
35
152
  // ── Frontmatter parser ─────────────────────────────────────────────────
36
153
  function parseFrontmatter(raw) {
37
154
  const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/);
@@ -94,7 +211,18 @@ export function readCanonicalSkills(productbrainDir) {
94
211
  const triggers = arrayFields.get('triggers') ?? [];
95
212
  const targets = arrayFields.get('targets');
96
213
  const level = fields.get('level');
97
- skills.push({ name, description, triggers, body, sourcePath: filePath, targets: targets?.length ? targets : undefined, level: level || undefined });
214
+ const conditions = {};
215
+ const whenStack = fields.get('when_stack');
216
+ const whenMinStage = fields.get('when_minStage');
217
+ const whenMinGovernance = fields.get('when_minGovernance');
218
+ if (whenStack)
219
+ conditions.when_stack = whenStack;
220
+ if (whenMinStage)
221
+ conditions.when_minStage = whenMinStage;
222
+ if (whenMinGovernance)
223
+ conditions.when_minGovernance = whenMinGovernance;
224
+ const hasConditions = Object.keys(conditions).length > 0;
225
+ skills.push({ name, description, triggers, body, sourcePath: filePath, targets: targets?.length ? targets : undefined, level: level || undefined, conditions: hasConditions ? conditions : undefined });
98
226
  }
99
227
  return skills.sort((a, b) => a.name.localeCompare(b.name));
100
228
  }
@@ -114,10 +242,113 @@ export function readCanonicalRules(productbrainDir) {
114
242
  const autoApply = fields.get('autoApply') === 'true';
115
243
  const targets = arrayFields.get('targets');
116
244
  const level = fields.get('level');
117
- rules.push({ name, description, scope, autoApply, body, sourcePath: filePath, targets: targets?.length ? targets : undefined, level: level || undefined });
245
+ const conditions = {};
246
+ const whenStack = fields.get('when_stack');
247
+ const whenMinStage = fields.get('when_minStage');
248
+ const whenMinGovernance = fields.get('when_minGovernance');
249
+ if (whenStack)
250
+ conditions.when_stack = whenStack;
251
+ if (whenMinStage)
252
+ conditions.when_minStage = whenMinStage;
253
+ if (whenMinGovernance)
254
+ conditions.when_minGovernance = whenMinGovernance;
255
+ const hasConditions = Object.keys(conditions).length > 0;
256
+ rules.push({ name, description, scope, autoApply, body, sourcePath: filePath, targets: targets?.length ? targets : undefined, level: level || undefined, conditions: hasConditions ? conditions : undefined });
257
+ }
258
+ return rules.sort((a, b) => a.name.localeCompare(b.name));
259
+ }
260
+ /**
261
+ * Read machine-local personal rules from .productbrain/.local/rules/.
262
+ * Returns [] when the directory is absent — no-op when personal layer is not set up.
263
+ * Every returned rule has persist: 'local' set, preventing projection to committed adapter files.
264
+ */
265
+ export function readPersonalLayer(productbrainDir) {
266
+ const localRulesDir = join(productbrainDir, '.local', 'rules');
267
+ if (!existsSync(localRulesDir))
268
+ return [];
269
+ const files = readdirSync(localRulesDir).filter((f) => f.endsWith('.md'));
270
+ const rules = [];
271
+ for (const file of files) {
272
+ const filePath = join(localRulesDir, file);
273
+ const raw = readFileSync(filePath, 'utf8');
274
+ const { fields, arrayFields, body } = parseFrontmatter(raw);
275
+ const name = fields.get('name') ?? basename(file, '.md');
276
+ const description = fields.get('description') ?? '';
277
+ const scope = fields.get('scope');
278
+ const autoApply = fields.get('autoApply') === 'true';
279
+ const targets = arrayFields.get('targets');
280
+ const level = fields.get('level');
281
+ const conditions = {};
282
+ const whenStack = fields.get('when_stack');
283
+ const whenMinStage = fields.get('when_minStage');
284
+ const whenMinGovernance = fields.get('when_minGovernance');
285
+ if (whenStack)
286
+ conditions.when_stack = whenStack;
287
+ if (whenMinStage)
288
+ conditions.when_minStage = whenMinStage;
289
+ if (whenMinGovernance)
290
+ conditions.when_minGovernance = whenMinGovernance;
291
+ const hasConditions = Object.keys(conditions).length > 0;
292
+ rules.push({
293
+ name,
294
+ description,
295
+ scope,
296
+ autoApply,
297
+ body,
298
+ sourcePath: filePath,
299
+ targets: targets?.length ? targets : undefined,
300
+ level: level || undefined,
301
+ conditions: hasConditions ? conditions : undefined,
302
+ persist: 'local',
303
+ });
118
304
  }
119
305
  return rules.sort((a, b) => a.name.localeCompare(b.name));
120
306
  }
307
+ /**
308
+ * Read machine-local personal skills from .productbrain/.local/skills/.
309
+ * Returns [] when the directory is absent — no-op when personal layer is not set up.
310
+ * Every returned skill has persist: 'local' set, preventing projection to committed adapter files.
311
+ */
312
+ export function readPersonalSkillsLayer(productbrainDir) {
313
+ const localSkillsDir = join(productbrainDir, '.local', 'skills');
314
+ if (!existsSync(localSkillsDir))
315
+ return [];
316
+ const files = readdirSync(localSkillsDir).filter((f) => f.endsWith('.md'));
317
+ const skills = [];
318
+ for (const file of files) {
319
+ const filePath = join(localSkillsDir, file);
320
+ const raw = readFileSync(filePath, 'utf8');
321
+ const { fields, arrayFields, body } = parseFrontmatter(raw);
322
+ const name = fields.get('name') ?? basename(file, '.md');
323
+ const description = fields.get('description') ?? '';
324
+ const triggers = arrayFields.get('triggers') ?? [];
325
+ const targets = arrayFields.get('targets');
326
+ const level = fields.get('level');
327
+ const conditions = {};
328
+ const whenStack = fields.get('when_stack');
329
+ const whenMinStage = fields.get('when_minStage');
330
+ const whenMinGovernance = fields.get('when_minGovernance');
331
+ if (whenStack)
332
+ conditions.when_stack = whenStack;
333
+ if (whenMinStage)
334
+ conditions.when_minStage = whenMinStage;
335
+ if (whenMinGovernance)
336
+ conditions.when_minGovernance = whenMinGovernance;
337
+ const hasConditions = Object.keys(conditions).length > 0;
338
+ skills.push({
339
+ name,
340
+ description,
341
+ triggers,
342
+ body,
343
+ sourcePath: filePath,
344
+ targets: targets?.length ? targets : undefined,
345
+ level: level || undefined,
346
+ conditions: hasConditions ? conditions : undefined,
347
+ persist: 'local',
348
+ });
349
+ }
350
+ return skills.sort((a, b) => a.name.localeCompare(b.name));
351
+ }
121
352
  // ── Transport section stripping ───────────────────────────────────────
122
353
  /**
123
354
  * Strip transport-conditional sections from a skill body.
@@ -149,7 +380,7 @@ export function stripTransportSections(body, target) {
149
380
  * Generate a Cursor SKILL.md from a canonical skill.
150
381
  * Cursor expects: name, description (with triggers embedded).
151
382
  */
152
- export function generateCursorSkill(skill) {
383
+ export function generateCursorSkill(skill, profile) {
153
384
  // Cursor puts trigger phrases in the description field
154
385
  const triggerLine = skill.triggers.length > 0
155
386
  ? ` Use when the user says ${skill.triggers.map((t) => `"${t}"`).join(', ')}.`
@@ -174,26 +405,162 @@ ${body}`;
174
405
  * Generate a Cursor .mdc rule from a canonical rule.
175
406
  * Cursor expects: description, globs, alwaysApply.
176
407
  */
177
- export function generateCursorRule(rule) {
408
+ export function generateCursorRule(rule, profile) {
178
409
  // Replace canonical paths with Cursor paths in body
179
410
  const body = rule.body
180
411
  .replace(/\.productbrain\/rules\/(\S+)\.md/g, '.cursor/rules/$1.mdc')
181
412
  .replace(/\.productbrain\/skills\/(\S+)\.md/g, '.cursor/skills/$1/SKILL.md');
182
413
  return `---
183
414
  description: ${rule.description}
184
- globs: ${rule.scope ?? ''}
185
- alwaysApply: ${rule.autoApply}
415
+ globs: ${rule.scope || ''}
416
+ alwaysApply: ${!rule.scope && rule.autoApply}
186
417
  ---
187
418
  <!-- ${MARKER} — source: .productbrain/rules/${rule.name}.md -->
188
419
 
189
420
  ${body}`;
190
421
  }
422
+ // ── Codex generators ───────────────────────────────────────────────────
423
+ /**
424
+ * Apply batch-mode transformations to a skill body (DEC-283).
425
+ *
426
+ * Skills describe WHAT (intent). This generator produces HOW (batch-appropriate
427
+ * instructions). We transform interactive patterns without gutting the skill's
428
+ * logical structure and purpose.
429
+ *
430
+ * Transformations applied:
431
+ * 1. Strip sub-agent spawn patterns → inline steps
432
+ * 2. Strip user confirmation gates → autonomous proceed
433
+ * 3. Strip streaming/interactive references
434
+ * 4. Add batch governance header after first `#` heading
435
+ */
436
+ export function applyBatchTransformations(body) {
437
+ // Split into fenced code blocks vs prose so transforms only apply to prose.
438
+ // Fenced blocks (``` or ~~~) may contain examples of interactive patterns
439
+ // that must be preserved verbatim.
440
+ const segments = body.split(/(^```[^\n]*\n[\s\S]*?^```\s*$|^~~~[^\n]*\n[\s\S]*?^~~~\s*$)/m);
441
+ let result = segments
442
+ .map((segment, i) => {
443
+ // Odd indices are fenced code blocks — pass through unchanged
444
+ if (i % 2 === 1)
445
+ return segment;
446
+ return applyProseTransformations(segment);
447
+ })
448
+ .join('');
449
+ // 4. Add batch governance header after the first `#` heading line
450
+ const batchHeader = '> Batch execution mode: This skill runs autonomously without interactive gates. Decisions are logged, not prompted.';
451
+ result = result.replace(/^(#\s+[^\n]+)(\n)/m, `$1$2\n${batchHeader}\n`);
452
+ return result;
453
+ }
454
+ /** Apply interactive-pattern transforms to a prose segment (not inside code fences). */
455
+ function applyProseTransformations(text) {
456
+ let result = text;
457
+ // 1. Sub-agent spawn patterns — lines that dispatch to sub-agents or fresh conversations
458
+ result = result.replace(/^.*\b(spawn\s+(a\s+)?(sub-agent|build\s+sub-agent|review\s+sub-agent|judge|system\s+verification\s+agent)|Agent\s+tool\s+dispatch|fresh\s+conversation\s+handoff|open\s+a\s+(new|fresh)\s+(conversation|chat)|start\s+a\s+(new|fresh)\s+(conversation|chat))\b.*$/gim, 'Execute as inline steps within this session.');
459
+ // 2. User confirmation gates — lines that halt for human input
460
+ result = result.replace(/^.*\b(ask\s+the\s+(user|human)|wait\s+for\s+(user\s+)?input|present\s+gate\s+to\s+(the\s+)?user|stop\s+and\s+ask|pause\s+and\s+ask|get\s+user\s+confirmation|awaiting\s+your\s+feedback|wait\s+for\s+(human|user)\s+(sign-?off|approval|input))\b.*$/gim, 'Proceed autonomously. Log decision rationale.');
461
+ // 3. Streaming / persistent-connection references
462
+ result = result.replace(/^.*\b(real-time\s+feedback|streaming\s+output|interactive\s+mcp\s+tool\s+calls?\s+that\s+assume\s+a\s+persistent\s+connection)\b.*$/gim, '');
463
+ return result;
464
+ }
465
+ /**
466
+ * Generate a Codex skill projection from a canonical skill.
467
+ * This is a repo-local markdown projection, not a separate authoring source.
468
+ *
469
+ * When profile.executionModel === 'batch', batch transformations are applied
470
+ * AFTER transport stripping and path replacement (DEC-283).
471
+ */
472
+ export function generateCodexSkill(skill, profile) {
473
+ const triggerLine = skill.triggers.length > 0
474
+ ? `\n\n**Triggers:** ${skill.triggers.map((t) => `\`${t}\``).join(', ')}`
475
+ : '';
476
+ const stripped = stripTransportSections(skill.body, 'codex');
477
+ const pathReplaced = stripped
478
+ .replace(/\.productbrain\/skills\/(\S+)\.md/g, '.codex/skills/$1.md');
479
+ const body = profile?.executionModel === 'batch'
480
+ ? applyBatchTransformations(pathReplaced)
481
+ : pathReplaced;
482
+ return `<!-- ${MARKER} — source: .productbrain/skills/${skill.name}.md -->
483
+
484
+ # ${skill.name}
485
+
486
+ ${skill.description}${triggerLine}
487
+
488
+ ${body}`;
489
+ }
490
+ /**
491
+ * Generate a Codex skill index/router file.
492
+ * AGENTS.md can point here so Codex has one obvious place to find available workflows.
493
+ */
494
+ export function generateCodexSkillIndex(skills) {
495
+ const primarySkills = skills.filter((skill) => {
496
+ const lower = skill.name.toLowerCase();
497
+ return lower !== 'learnings-template' && !lower.endsWith('-learnings');
498
+ });
499
+ if (primarySkills.length === 0) {
500
+ return `<!-- ${MARKER} — source: generated from .productbrain/skills/*.md -->
501
+
502
+ # Product Brain Skills for Codex
503
+
504
+ No Product Brain skills are currently projected for Codex in this repo.
505
+ `;
506
+ }
507
+ const blocks = primarySkills.map((skill) => {
508
+ const triggerText = skill.triggers.length > 0
509
+ ? `Triggers: ${skill.triggers.map((t) => `\`${t}\``).join(', ')}`
510
+ : 'Triggers: none declared';
511
+ return `## ${skill.name}
512
+
513
+ ${skill.description}
514
+
515
+ ${triggerText}
516
+
517
+ Read: \`.codex/skills/${skill.name}.md\``;
518
+ });
519
+ return `<!-- ${MARKER} — source: generated from .productbrain/skills/*.md -->
520
+
521
+ # Product Brain Skills for Codex
522
+
523
+ When the task matches one of these workflows, read the linked skill file first and follow its protocol.
524
+ Maintenance companions like \`*-learnings\` and \`LEARNINGS-TEMPLATE\` are still projected on disk, but hidden from this index so the primary workflows stay easy to scan.
525
+
526
+ ${blocks.join('\n\n')}`;
527
+ }
528
+ const CODEX_DEAD_REFERENCE_PATTERNS = [
529
+ { pattern: /\bpb\s+(session|orient|get|capture|search|update|handshake|context|constellation)\b/, label: 'pb CLI command' },
530
+ { pattern: /\bsub-agent\b/i, label: 'sub-agent reference' },
531
+ { pattern: /\bAgent\s+tool\b/, label: 'Agent tool reference' },
532
+ { pattern: /\bkernelCall\b/, label: 'kernelCall reference' },
533
+ { pattern: /\bpb\s+session\s+(start|close)\b/, label: 'pb session lifecycle' },
534
+ ];
535
+ /**
536
+ * Validate Codex-projected skills for references to capabilities Codex cannot execute.
537
+ * Scans the transport-stripped body (so claude-only blocks don't false-positive).
538
+ */
539
+ export function validateCodexSkills(skills) {
540
+ const warnings = [];
541
+ for (const skill of skills) {
542
+ const stripped = stripTransportSections(skill.body, 'codex');
543
+ const lines = stripped.split('\n');
544
+ for (const line of lines) {
545
+ for (const { pattern, label } of CODEX_DEAD_REFERENCE_PATTERNS) {
546
+ if (pattern.test(line)) {
547
+ warnings.push({
548
+ skillName: skill.name,
549
+ pattern: label,
550
+ line: line.trim().slice(0, 80),
551
+ });
552
+ }
553
+ }
554
+ }
555
+ }
556
+ return warnings;
557
+ }
191
558
  // ── Claude Code generators ────────────────────────────────────────────
192
559
  /**
193
560
  * Generate a Claude Code .md rule from a canonical rule.
194
561
  * Claude Code expects: description, optional paths (array).
195
562
  */
196
- export function generateClaudeRule(rule) {
563
+ export function generateClaudeRule(rule, profile) {
197
564
  // Replace canonical paths with Claude Code paths in body
198
565
  const body = rule.body
199
566
  .replace(/\.productbrain\/rules\/(\S+)\.md/g, '.claude/rules/$1.md')
@@ -215,7 +582,7 @@ ${body}`;
215
582
  * Generate a Claude Code skill-router.md — imperative skill activation rule.
216
583
  * Loaded automatically by Claude Code via .claude/rules/ with no paths (always active).
217
584
  */
218
- export function generateClaudeSkillRouter(skills) {
585
+ export function generateClaudeSkillRouter(skills, profile) {
219
586
  if (skills.length === 0)
220
587
  return '';
221
588
  const triggerBlocks = skills.map((skill) => {