opkg 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (487) hide show
  1. package/README.md +109 -186
  2. package/assets/openpackage_ascii_dark.png +0 -0
  3. package/assets/openpackage_ascii_light.png +0 -0
  4. package/dist/commands/add.js +34 -10
  5. package/dist/commands/add.js.map +1 -1
  6. package/dist/commands/apply.js +16 -0
  7. package/dist/commands/apply.js.map +1 -0
  8. package/dist/commands/delete.js +1 -1
  9. package/dist/commands/delete.js.map +1 -1
  10. package/dist/commands/install.js +177 -8
  11. package/dist/commands/install.js.map +1 -1
  12. package/dist/commands/list.js +2 -2
  13. package/dist/commands/list.js.map +1 -1
  14. package/dist/commands/login.js +1 -1
  15. package/dist/commands/login.js.map +1 -1
  16. package/dist/commands/logout.js +1 -1
  17. package/dist/commands/logout.js.map +1 -1
  18. package/dist/commands/new.js +125 -0
  19. package/dist/commands/new.js.map +1 -0
  20. package/dist/commands/pack.js +7 -13
  21. package/dist/commands/pack.js.map +1 -1
  22. package/dist/commands/pull.js +1 -1
  23. package/dist/commands/pull.js.map +1 -1
  24. package/dist/commands/push.js +1 -1
  25. package/dist/commands/push.js.map +1 -1
  26. package/dist/commands/remove.js +63 -0
  27. package/dist/commands/remove.js.map +1 -0
  28. package/dist/commands/save.js +11 -17
  29. package/dist/commands/save.js.map +1 -1
  30. package/dist/commands/set.js +33 -0
  31. package/dist/commands/set.js.map +1 -0
  32. package/dist/commands/show.js +16 -94
  33. package/dist/commands/show.js.map +1 -1
  34. package/dist/commands/status.js +26 -701
  35. package/dist/commands/status.js.map +1 -1
  36. package/dist/commands/uninstall.js +14 -427
  37. package/dist/commands/uninstall.js.map +1 -1
  38. package/dist/constants/index.js +72 -16
  39. package/dist/constants/index.js.map +1 -1
  40. package/dist/core/add/add-conflict-handler.js +1 -8
  41. package/dist/core/add/add-conflict-handler.js.map +1 -1
  42. package/dist/core/add/add-pipeline.js +12 -10
  43. package/dist/core/add/add-pipeline.js.map +1 -1
  44. package/dist/core/add/add-to-source-pipeline.js +123 -0
  45. package/dist/core/add/add-to-source-pipeline.js.map +1 -0
  46. package/dist/core/add/package-index-updater.js +77 -78
  47. package/dist/core/add/package-index-updater.js.map +1 -1
  48. package/dist/core/add/platform-path-transformer.js +6 -4
  49. package/dist/core/add/platform-path-transformer.js.map +1 -1
  50. package/dist/core/add/source-collector.js +2 -3
  51. package/dist/core/add/source-collector.js.map +1 -1
  52. package/dist/core/apply/apply-pipeline.js +110 -0
  53. package/dist/core/apply/apply-pipeline.js.map +1 -0
  54. package/dist/core/dependency-resolver.js +263 -21
  55. package/dist/core/dependency-resolver.js.map +1 -1
  56. package/dist/core/discovery/file-discovery.js +1 -2
  57. package/dist/core/discovery/file-discovery.js.map +1 -1
  58. package/dist/core/discovery/platform-files-discovery.js +33 -18
  59. package/dist/core/discovery/platform-files-discovery.js.map +1 -1
  60. package/dist/core/flows/flow-executor.js +974 -0
  61. package/dist/core/flows/flow-executor.js.map +1 -0
  62. package/dist/core/flows/flow-inverter.js +442 -0
  63. package/dist/core/flows/flow-inverter.js.map +1 -0
  64. package/dist/core/flows/flow-key-extractor.js +101 -0
  65. package/dist/core/flows/flow-key-extractor.js.map +1 -0
  66. package/dist/core/flows/flow-key-mapper.js +382 -0
  67. package/dist/core/flows/flow-key-mapper.js.map +1 -0
  68. package/dist/core/flows/flow-transforms.js +632 -0
  69. package/dist/core/flows/flow-transforms.js.map +1 -0
  70. package/dist/core/flows/map-pipeline/context.js +73 -0
  71. package/dist/core/flows/map-pipeline/context.js.map +1 -0
  72. package/dist/core/flows/map-pipeline/index.js +156 -0
  73. package/dist/core/flows/map-pipeline/index.js.map +1 -0
  74. package/dist/core/flows/map-pipeline/operations/copy.js +104 -0
  75. package/dist/core/flows/map-pipeline/operations/copy.js.map +1 -0
  76. package/dist/core/flows/map-pipeline/operations/pipe.js +70 -0
  77. package/dist/core/flows/map-pipeline/operations/pipe.js.map +1 -0
  78. package/dist/core/flows/map-pipeline/operations/rename.js +102 -0
  79. package/dist/core/flows/map-pipeline/operations/rename.js.map +1 -0
  80. package/dist/core/flows/map-pipeline/operations/set.js +50 -0
  81. package/dist/core/flows/map-pipeline/operations/set.js.map +1 -0
  82. package/dist/core/flows/map-pipeline/operations/switch.js +79 -0
  83. package/dist/core/flows/map-pipeline/operations/switch.js.map +1 -0
  84. package/dist/core/flows/map-pipeline/operations/transform.js +543 -0
  85. package/dist/core/flows/map-pipeline/operations/transform.js.map +1 -0
  86. package/dist/core/flows/map-pipeline/operations/unset.js +65 -0
  87. package/dist/core/flows/map-pipeline/operations/unset.js.map +1 -0
  88. package/dist/core/flows/map-pipeline/types.js +8 -0
  89. package/dist/core/flows/map-pipeline/types.js.map +1 -0
  90. package/dist/core/flows/map-pipeline/utils.js +278 -0
  91. package/dist/core/flows/map-pipeline/utils.js.map +1 -0
  92. package/dist/core/flows/platform-converter.js +328 -0
  93. package/dist/core/flows/platform-converter.js.map +1 -0
  94. package/dist/core/flows/source-resolver.js +192 -0
  95. package/dist/core/flows/source-resolver.js.map +1 -0
  96. package/dist/core/flows/toml-domain-transforms.js +23 -0
  97. package/dist/core/flows/toml-domain-transforms.js.map +1 -0
  98. package/dist/core/install/bulk-install-pipeline.js +68 -7
  99. package/dist/core/install/bulk-install-pipeline.js.map +1 -1
  100. package/dist/core/install/canonical-plan.js +3 -3
  101. package/dist/core/install/canonical-plan.js.map +1 -1
  102. package/dist/core/install/dry-run.js +3 -3
  103. package/dist/core/install/dry-run.js.map +1 -1
  104. package/dist/core/install/flow-based-installer.js +1158 -0
  105. package/dist/core/install/flow-based-installer.js.map +1 -0
  106. package/dist/core/install/flow-workspace-tracker.js +111 -0
  107. package/dist/core/install/flow-workspace-tracker.js.map +1 -0
  108. package/dist/core/install/format-detector.js +228 -0
  109. package/dist/core/install/format-detector.js.map +1 -0
  110. package/dist/core/install/git-package-loader.js +20 -0
  111. package/dist/core/install/git-package-loader.js.map +1 -0
  112. package/dist/core/install/install-errors.js +1 -1
  113. package/dist/core/install/install-errors.js.map +1 -1
  114. package/dist/core/install/install-flow.js +34 -14
  115. package/dist/core/install/install-flow.js.map +1 -1
  116. package/dist/core/install/install-pipeline.js +52 -17
  117. package/dist/core/install/install-pipeline.js.map +1 -1
  118. package/dist/core/install/install-reporting.js +26 -8
  119. package/dist/core/install/install-reporting.js.map +1 -1
  120. package/dist/core/install/local-source-resolution.js +103 -0
  121. package/dist/core/install/local-source-resolution.js.map +1 -0
  122. package/dist/core/install/marketplace-handler.js +221 -0
  123. package/dist/core/install/marketplace-handler.js.map +1 -0
  124. package/dist/core/install/path-install-pipeline.js +241 -0
  125. package/dist/core/install/path-install-pipeline.js.map +1 -0
  126. package/dist/core/install/path-package-loader.js +116 -0
  127. package/dist/core/install/path-package-loader.js.map +1 -0
  128. package/dist/core/install/plugin-detector.js +72 -0
  129. package/dist/core/install/plugin-detector.js.map +1 -0
  130. package/dist/core/install/plugin-to-universal-converter.js +218 -0
  131. package/dist/core/install/plugin-to-universal-converter.js.map +1 -0
  132. package/dist/core/install/plugin-transformer.js +191 -0
  133. package/dist/core/install/plugin-transformer.js.map +1 -0
  134. package/dist/core/install/version-selection.js +1 -1
  135. package/dist/core/install/version-selection.js.map +1 -1
  136. package/dist/core/openpackage.js +40 -22
  137. package/dist/core/openpackage.js.map +1 -1
  138. package/dist/core/pack/pack-output.js +62 -0
  139. package/dist/core/pack/pack-output.js.map +1 -0
  140. package/dist/core/pack/pack-pipeline.js +186 -0
  141. package/dist/core/pack/pack-pipeline.js.map +1 -0
  142. package/dist/core/package-context.js +45 -70
  143. package/dist/core/package-context.js.map +1 -1
  144. package/dist/core/package-creation.js +203 -0
  145. package/dist/core/package-creation.js.map +1 -0
  146. package/dist/core/package.js +20 -6
  147. package/dist/core/package.js.map +1 -1
  148. package/dist/core/platforms.js +665 -209
  149. package/dist/core/platforms.js.map +1 -1
  150. package/dist/core/push/push-context.js +1 -1
  151. package/dist/core/push/push-context.js.map +1 -1
  152. package/dist/core/push/push-upload.js +2 -2
  153. package/dist/core/push/push-upload.js.map +1 -1
  154. package/dist/core/registry.js +6 -6
  155. package/dist/core/registry.js.map +1 -1
  156. package/dist/core/remote-pull.js +2 -2
  157. package/dist/core/remote-pull.js.map +1 -1
  158. package/dist/core/remove/removal-collector.js +52 -0
  159. package/dist/core/remove/removal-collector.js.map +1 -0
  160. package/dist/core/remove/removal-confirmation.js +39 -0
  161. package/dist/core/remove/removal-confirmation.js.map +1 -0
  162. package/dist/core/remove/remove-from-source-pipeline.js +173 -0
  163. package/dist/core/remove/remove-from-source-pipeline.js.map +1 -0
  164. package/dist/core/save/constants.js +3 -3
  165. package/dist/core/save/constants.js.map +1 -1
  166. package/dist/core/save/flow-based-saver.js +270 -0
  167. package/dist/core/save/flow-based-saver.js.map +1 -0
  168. package/dist/core/save/name-resolution.js +1 -1
  169. package/dist/core/save/name-resolution.js.map +1 -1
  170. package/dist/core/save/package-yml-generator.js +4 -5
  171. package/dist/core/save/package-yml-generator.js.map +1 -1
  172. package/dist/core/save/save-candidate-builder.js +215 -0
  173. package/dist/core/save/save-candidate-builder.js.map +1 -0
  174. package/dist/core/save/save-candidate-loader.js +12 -11
  175. package/dist/core/save/save-candidate-loader.js.map +1 -1
  176. package/dist/core/save/save-conflict-analyzer.js +150 -0
  177. package/dist/core/save/save-conflict-analyzer.js.map +1 -0
  178. package/dist/core/save/save-conflict-resolution.js +28 -14
  179. package/dist/core/save/save-conflict-resolution.js.map +1 -1
  180. package/dist/core/save/save-conflict-resolver.js +31 -275
  181. package/dist/core/save/save-conflict-resolver.js.map +1 -1
  182. package/dist/core/save/save-group-builder.js +52 -0
  183. package/dist/core/save/save-group-builder.js.map +1 -0
  184. package/dist/core/save/save-interactive-resolver.js +190 -0
  185. package/dist/core/save/save-interactive-resolver.js.map +1 -0
  186. package/dist/core/save/save-pipeline.js +58 -34
  187. package/dist/core/save/save-pipeline.js.map +1 -1
  188. package/dist/core/save/save-platform-handler.js +53 -0
  189. package/dist/core/save/save-platform-handler.js.map +1 -0
  190. package/dist/core/save/save-resolution-executor.js +145 -0
  191. package/dist/core/save/save-resolution-executor.js.map +1 -0
  192. package/dist/core/save/save-result-reporter.js +167 -0
  193. package/dist/core/save/save-result-reporter.js.map +1 -0
  194. package/dist/core/save/save-to-source-pipeline.js +154 -0
  195. package/dist/core/save/save-to-source-pipeline.js.map +1 -0
  196. package/dist/core/save/save-versioning.js +4 -4
  197. package/dist/core/save/save-versioning.js.map +1 -1
  198. package/dist/core/save/save-write-coordinator.js +204 -0
  199. package/dist/core/save/save-write-coordinator.js.map +1 -0
  200. package/dist/core/save/save-yml-resolution.js +28 -216
  201. package/dist/core/save/save-yml-resolution.js.map +1 -1
  202. package/dist/core/save/workspace-rename.js +7 -8
  203. package/dist/core/save/workspace-rename.js.map +1 -1
  204. package/dist/core/set/set-output.js +72 -0
  205. package/dist/core/set/set-output.js.map +1 -0
  206. package/dist/core/set/set-pipeline.js +361 -0
  207. package/dist/core/set/set-pipeline.js.map +1 -0
  208. package/dist/core/set/set-types.js +5 -0
  209. package/dist/core/set/set-types.js.map +1 -0
  210. package/dist/core/show/package-resolver.js +257 -0
  211. package/dist/core/show/package-resolver.js.map +1 -0
  212. package/dist/core/show/scope-discovery.js +165 -0
  213. package/dist/core/show/scope-discovery.js.map +1 -0
  214. package/dist/core/show/show-output.js +168 -0
  215. package/dist/core/show/show-output.js.map +1 -0
  216. package/dist/core/show/show-pipeline.js +113 -0
  217. package/dist/core/show/show-pipeline.js.map +1 -0
  218. package/dist/core/show/show-types.js +5 -0
  219. package/dist/core/show/show-types.js.map +1 -0
  220. package/dist/core/source-resolution/dependency-graph.js +104 -0
  221. package/dist/core/source-resolution/dependency-graph.js.map +1 -0
  222. package/dist/core/source-resolution/resolve-mutable-source.js +109 -0
  223. package/dist/core/source-resolution/resolve-mutable-source.js.map +1 -0
  224. package/dist/core/source-resolution/resolve-package-source.js +29 -0
  225. package/dist/core/source-resolution/resolve-package-source.js.map +1 -0
  226. package/dist/core/source-resolution/resolve-registry-version.js +35 -0
  227. package/dist/core/source-resolution/resolve-registry-version.js.map +1 -0
  228. package/dist/core/source-resolution/types.js.map +1 -0
  229. package/dist/core/status/status-file-discovery.js +23 -12
  230. package/dist/core/status/status-file-discovery.js.map +1 -1
  231. package/dist/core/status/status-pipeline.js +134 -0
  232. package/dist/core/status/status-pipeline.js.map +1 -0
  233. package/dist/core/sync/platform-sync-summary.js +27 -0
  234. package/dist/core/sync/platform-sync-summary.js.map +1 -0
  235. package/dist/core/uninstall/flow-aware-uninstaller.js +189 -0
  236. package/dist/core/uninstall/flow-aware-uninstaller.js.map +1 -0
  237. package/dist/core/uninstall/uninstall-file-discovery.js +11 -6
  238. package/dist/core/uninstall/uninstall-file-discovery.js.map +1 -1
  239. package/dist/core/uninstall/uninstall-pipeline.js +141 -0
  240. package/dist/core/uninstall/uninstall-pipeline.js.map +1 -0
  241. package/dist/core/universal-patterns.js +64 -0
  242. package/dist/core/universal-patterns.js.map +1 -0
  243. package/dist/index.js +99 -6
  244. package/dist/index.js.map +1 -1
  245. package/dist/types/flows.js +8 -0
  246. package/dist/types/flows.js.map +1 -0
  247. package/dist/types/index.js +3 -0
  248. package/dist/types/index.js.map +1 -1
  249. package/dist/types/platform-flows.js +8 -0
  250. package/dist/types/platform-flows.js.map +1 -0
  251. package/dist/types/workspace-index.js +6 -0
  252. package/dist/types/workspace-index.js.map +1 -0
  253. package/dist/utils/custom-path-resolution.js +160 -0
  254. package/dist/utils/custom-path-resolution.js.map +1 -0
  255. package/dist/utils/dependency-coverage.js +1 -1
  256. package/dist/utils/dependency-coverage.js.map +1 -1
  257. package/dist/utils/file-processing.js +1 -1
  258. package/dist/utils/flow-index-installer.js +209 -0
  259. package/dist/utils/flow-index-installer.js.map +1 -0
  260. package/dist/utils/formatters.js +47 -1
  261. package/dist/utils/formatters.js.map +1 -1
  262. package/dist/utils/fs.js +17 -0
  263. package/dist/utils/fs.js.map +1 -1
  264. package/dist/utils/git-clone-registry.js +88 -0
  265. package/dist/utils/git-clone-registry.js.map +1 -0
  266. package/dist/utils/git-clone.js +69 -0
  267. package/dist/utils/git-clone.js.map +1 -0
  268. package/dist/utils/git-spec.js +96 -0
  269. package/dist/utils/git-spec.js.map +1 -0
  270. package/dist/utils/http-client.js +7 -0
  271. package/dist/utils/http-client.js.map +1 -1
  272. package/dist/utils/index-based-installer.js +356 -163
  273. package/dist/utils/index-based-installer.js.map +1 -1
  274. package/dist/utils/install-conflict-handler.js +2 -2
  275. package/dist/utils/install-conflict-handler.js.map +1 -1
  276. package/dist/utils/install-file-discovery.js +18 -13
  277. package/dist/utils/install-file-discovery.js.map +1 -1
  278. package/dist/utils/install-helpers.js +43 -20
  279. package/dist/utils/install-helpers.js.map +1 -1
  280. package/dist/utils/jsonc.js +23 -1
  281. package/dist/utils/jsonc.js.map +1 -1
  282. package/dist/utils/manifest-paths.js +1 -1
  283. package/dist/utils/manifest-paths.js.map +1 -1
  284. package/dist/utils/markdown-frontmatter.js +46 -0
  285. package/dist/utils/markdown-frontmatter.js.map +1 -1
  286. package/dist/utils/package-copy.js +5 -103
  287. package/dist/utils/package-copy.js.map +1 -1
  288. package/dist/utils/package-filters.js +9 -105
  289. package/dist/utils/package-filters.js.map +1 -1
  290. package/dist/utils/package-index-yml.js +27 -6
  291. package/dist/utils/package-index-yml.js.map +1 -1
  292. package/dist/utils/package-input.js +98 -0
  293. package/dist/utils/package-input.js.map +1 -0
  294. package/dist/utils/package-management.js +80 -28
  295. package/dist/utils/package-management.js.map +1 -1
  296. package/dist/utils/package-name-resolution.js +327 -0
  297. package/dist/utils/package-name-resolution.js.map +1 -0
  298. package/dist/utils/package-name.js +18 -16
  299. package/dist/utils/package-name.js.map +1 -1
  300. package/dist/utils/package-versioning.js +2 -33
  301. package/dist/utils/package-versioning.js.map +1 -1
  302. package/dist/utils/package-yml.js +19 -28
  303. package/dist/utils/package-yml.js.map +1 -1
  304. package/dist/utils/path-resolution.js +102 -0
  305. package/dist/utils/path-resolution.js.map +1 -0
  306. package/dist/utils/paths.js +6 -6
  307. package/dist/utils/paths.js.map +1 -1
  308. package/dist/utils/platform-file.js +36 -24
  309. package/dist/utils/platform-file.js.map +1 -1
  310. package/dist/utils/platform-mapper.js +222 -68
  311. package/dist/utils/platform-mapper.js.map +1 -1
  312. package/dist/utils/platform-root-files.js +44 -0
  313. package/dist/utils/platform-root-files.js.map +1 -0
  314. package/dist/utils/platform-utils.js +35 -54
  315. package/dist/utils/platform-utils.js.map +1 -1
  316. package/dist/utils/platform-yaml-merge.js +20 -140
  317. package/dist/utils/platform-yaml-merge.js.map +1 -1
  318. package/dist/utils/prompts.js +92 -7
  319. package/dist/utils/prompts.js.map +1 -1
  320. package/dist/utils/registry-entry-filter.js +50 -27
  321. package/dist/utils/registry-entry-filter.js.map +1 -1
  322. package/dist/utils/registry-paths.js +5 -4
  323. package/dist/utils/registry-paths.js.map +1 -1
  324. package/dist/utils/scope-resolution.js +156 -0
  325. package/dist/utils/scope-resolution.js.map +1 -0
  326. package/dist/utils/source-mutability.js +15 -0
  327. package/dist/utils/source-mutability.js.map +1 -0
  328. package/dist/utils/tarball.js +29 -4
  329. package/dist/utils/tarball.js.map +1 -1
  330. package/dist/utils/version-ranges.js +1 -32
  331. package/dist/utils/version-ranges.js.map +1 -1
  332. package/dist/utils/workspace-index-helpers.js +28 -0
  333. package/dist/utils/workspace-index-helpers.js.map +1 -0
  334. package/dist/utils/workspace-index-ownership.js +100 -0
  335. package/dist/utils/workspace-index-ownership.js.map +1 -0
  336. package/dist/utils/workspace-index-yml.js +173 -0
  337. package/dist/utils/workspace-index-yml.js.map +1 -0
  338. package/examples/custom-subdirs-platform.jsonc +157 -0
  339. package/package.json +7 -2
  340. package/platforms.jsonc +531 -84
  341. package/schemas/map-pipeline-v1.json +256 -0
  342. package/schemas/platforms-v1.json +400 -0
  343. package/specs/README.md +88 -0
  344. package/specs/add/README.md +166 -0
  345. package/specs/agents-claude.md +570 -0
  346. package/specs/agents-opencode.md +622 -0
  347. package/specs/apply/README.md +21 -0
  348. package/specs/apply/apply-behavior.md +58 -0
  349. package/specs/apply/apply-command.md +51 -0
  350. package/specs/apply/conflicts.md +41 -0
  351. package/specs/apply/index-effects.md +81 -0
  352. package/specs/architecture.md +107 -0
  353. package/specs/auth/README.md +17 -0
  354. package/specs/auth/auth-http-contract.md +25 -0
  355. package/specs/auth/cli/credentials.md +39 -0
  356. package/specs/auth/cli/login.md +32 -0
  357. package/specs/auth/cli/logout.md +16 -0
  358. package/specs/claude-mcp.md +1065 -0
  359. package/specs/claude-plugins-marketplace.md +363 -0
  360. package/specs/claude-plugins.md +413 -0
  361. package/specs/cli-options.md +52 -0
  362. package/specs/codex-mcp.md +114 -0
  363. package/specs/commands-overview.md +175 -0
  364. package/specs/directory-layout.md +95 -0
  365. package/specs/install/README.md +12 -4
  366. package/specs/install/git-sources.md +230 -0
  367. package/specs/install/install-behavior.md +483 -73
  368. package/specs/install/package-yml-canonical.md +67 -35
  369. package/specs/install/version-resolution.md +69 -115
  370. package/specs/new/README.md +769 -0
  371. package/specs/new/SUMMARY.md +310 -0
  372. package/specs/new/scope-behavior.md +793 -0
  373. package/specs/pack/README.md +77 -0
  374. package/specs/pack/package-name-resolution.md +330 -0
  375. package/specs/package/README.md +18 -17
  376. package/specs/package/nested-packages-and-parent-packages.md +32 -31
  377. package/specs/package/package-index-yml.md +95 -101
  378. package/specs/package/package-root-layout.md +64 -46
  379. package/specs/package/registry-payload-and-copy.md +50 -44
  380. package/specs/package/universal-content.md +33 -56
  381. package/specs/package-sources.md +248 -0
  382. package/specs/platforms/README.md +52 -0
  383. package/specs/platforms/configuration.md +571 -0
  384. package/specs/platforms/detection.md +552 -0
  385. package/specs/platforms/directory-layout.md +599 -0
  386. package/specs/platforms/examples.md +1146 -0
  387. package/specs/platforms/flow-reference.md +1240 -0
  388. package/specs/platforms/flows.md +1488 -0
  389. package/specs/platforms/map-pipeline.md +801 -0
  390. package/specs/platforms/overview.md +349 -0
  391. package/specs/platforms/specification.md +700 -0
  392. package/specs/platforms/troubleshooting.md +697 -0
  393. package/specs/platforms/universal-converter.md +520 -0
  394. package/specs/push/README.md +1 -0
  395. package/specs/push/push-behavior.md +11 -3
  396. package/specs/push/push-remote-upload.md +1 -1
  397. package/specs/push/push-scoping.md +1 -1
  398. package/specs/push/push-version-selection.md +1 -1
  399. package/specs/registry.md +111 -0
  400. package/specs/remove/README.md +257 -0
  401. package/specs/save/README.md +21 -17
  402. package/specs/save/save-conflict-resolution.md +205 -83
  403. package/specs/save/save-file-discovery.md +6 -4
  404. package/specs/save/save-frontmatter-overrides.md +11 -15
  405. package/specs/save/save-modes-inputs.md +9 -39
  406. package/specs/save/save-naming-scoping.md +4 -4
  407. package/specs/save/save-package-detection.md +13 -13
  408. package/specs/save/save-registry-sync.md +16 -106
  409. package/specs/save/save-versioning.md +80 -0
  410. package/specs/scope-management.md +92 -0
  411. package/specs/set/README.md +520 -0
  412. package/specs/set/set-behavior.md +563 -0
  413. package/specs/show/README.md +483 -0
  414. package/specs/show/show-remote.md +494 -0
  415. package/specs/status/README.md +38 -0
  416. package/specs/uninstall/README.md +231 -0
  417. package/dist/commands/duplicate.js +0 -69
  418. package/dist/commands/duplicate.js.map +0 -1
  419. package/dist/commands/init.js +0 -117
  420. package/dist/commands/init.js.map +0 -1
  421. package/dist/commands/prune.js +0 -357
  422. package/dist/commands/prune.js.map +0 -1
  423. package/dist/commands/tui.js +0 -61
  424. package/dist/commands/tui.js.map +0 -1
  425. package/dist/core/install/index.js +0 -3
  426. package/dist/core/install/index.js.map +0 -1
  427. package/dist/core/push/push-single-file.js +0 -56
  428. package/dist/core/push/push-single-file.js.map +0 -1
  429. package/dist/core/save/package-detection.js +0 -147
  430. package/dist/core/save/package-detection.js.map +0 -1
  431. package/dist/core/save/save-single-file.js +0 -124
  432. package/dist/core/save/save-single-file.js.map +0 -1
  433. package/dist/core/token-store.js +0 -73
  434. package/dist/core/token-store.js.map +0 -1
  435. package/dist/tui/app.js +0 -95
  436. package/dist/tui/app.js.map +0 -1
  437. package/dist/tui/components/package-list.js +0 -73
  438. package/dist/tui/components/package-list.js.map +0 -1
  439. package/dist/tui/controller.js +0 -365
  440. package/dist/tui/controller.js.map +0 -1
  441. package/dist/tui/index.js +0 -12
  442. package/dist/tui/index.js.map +0 -1
  443. package/dist/tui/services/file-index.js +0 -64
  444. package/dist/tui/services/file-index.js.map +0 -1
  445. package/dist/tui/services/packages.js +0 -18
  446. package/dist/tui/services/packages.js.map +0 -1
  447. package/dist/tui/services/save.js +0 -21
  448. package/dist/tui/services/save.js.map +0 -1
  449. package/dist/tui/state/app-state.js +0 -15
  450. package/dist/tui/state/app-state.js.map +0 -1
  451. package/dist/tui/state.js +0 -17
  452. package/dist/tui/state.js.map +0 -1
  453. package/dist/tui/types.js.map +0 -1
  454. package/dist/tui/views/add-file-modal.js +0 -129
  455. package/dist/tui/views/add-file-modal.js.map +0 -1
  456. package/dist/tui/views/file-preview.js +0 -44
  457. package/dist/tui/views/file-preview.js.map +0 -1
  458. package/dist/tui/views/list-packages.js +0 -73
  459. package/dist/tui/views/list-packages.js.map +0 -1
  460. package/dist/tui/views/main-menu.js +0 -29
  461. package/dist/tui/views/main-menu.js.map +0 -1
  462. package/dist/tui/views/manage-view.js +0 -81
  463. package/dist/tui/views/manage-view.js.map +0 -1
  464. package/dist/tui/views/package-hub.js +0 -120
  465. package/dist/tui/views/package-hub.js.map +0 -1
  466. package/dist/tui/views/placeholder.js +0 -24
  467. package/dist/tui/views/placeholder.js.map +0 -1
  468. package/dist/utils/bun-bootstrap.js +0 -72
  469. package/dist/utils/bun-bootstrap.js.map +0 -1
  470. package/dist/utils/entity-id.js +0 -19
  471. package/dist/utils/entity-id.js.map +0 -1
  472. package/dist/utils/package-local-files.js +0 -5
  473. package/dist/utils/package-local-files.js.map +0 -1
  474. package/dist/utils/path-matching.js +0 -74
  475. package/dist/utils/path-matching.js.map +0 -1
  476. package/dist/utils/root-file-operations.js +0 -39
  477. package/dist/utils/root-file-operations.js.map +0 -1
  478. package/dist/utils/root-file-transformer.js +0 -27
  479. package/dist/utils/root-file-transformer.js.map +0 -1
  480. package/dist/utils/yaml-frontmatter.js +0 -25
  481. package/dist/utils/yaml-frontmatter.js.map +0 -1
  482. package/specs/auth/auth-device-flow.md +0 -70
  483. package/specs/login/login-device-flow.md +0 -70
  484. package/specs/platforms.md +0 -193
  485. package/specs/save-pack-versioning.md +0 -224
  486. package/specs/save-pack.md +0 -68
  487. /package/dist/{tui → core/source-resolution}/types.js +0 -0
@@ -0,0 +1,700 @@
1
+ # Platform Specification
2
+
3
+ Technical requirements and contracts for the platform system. This document uses SHALL/MUST for normative requirements with scenario-based specifications.
4
+
5
+ ## Platform Configuration Requirements
6
+
7
+ ### Requirement: Platform Configuration Schema
8
+
9
+ Each platform entry in `platforms.jsonc` SHALL have the following structure:
10
+
11
+ - `name` (string): Human-readable display name
12
+ - `rootDir` (string): Platform root directory (e.g., `.cursor`, `.claude`)
13
+ - `rootFile?` (string): Optional root file at project root (e.g., `CLAUDE.md`, `QWEN.md`)
14
+ - `aliases?` (string[]): Optional CLI aliases
15
+ - `enabled?` (boolean): Whether platform is enabled (default: `true`)
16
+ - `export?` (Flow[]): Export flows (package → workspace, used by install/apply)
17
+ - `import?` (Flow[]): Import flows (workspace → package, used by save)
18
+
19
+ #### Scenario: Load platform with valid configuration
20
+
21
+ - **WHEN** platform config defines all required fields with valid types
22
+ - **THEN** platform is loaded successfully and available for use
23
+
24
+ #### Scenario: Load platform with export/import flows configuration
25
+
26
+ - **WHEN** platform config defines `export` and/or `import` arrays with valid flow objects
27
+ - **THEN** flows are loaded and validated according to flow schema
28
+
29
+ #### Scenario: Invalid platform configuration missing required field
30
+
31
+ - **WHEN** platform config is missing `name`, `rootDir`, or both `export`/`import`/`rootFile` fields
32
+ - **THEN** configuration load fails with error: "Platform 'id': Must define at least one of 'export', 'import', or 'rootFile'"
33
+
34
+ #### Scenario: Invalid platform configuration with wrong types
35
+
36
+ - **WHEN** platform config has field with incorrect type (e.g., `name` as number)
37
+ - **THEN** configuration load fails with type error and expected type
38
+
39
+ ### Requirement: Configuration Merge Hierarchy
40
+
41
+ Platform configurations SHALL be loaded and merged from three sources in priority order:
42
+
43
+ 1. **Built-in**: Default configurations shipped with CLI
44
+ 2. **Global**: User overrides in `~/.openpackage/platforms.jsonc`
45
+ 3. **Workspace**: Project-specific overrides in `<workspace>/.openpackage/platforms.jsonc`
46
+
47
+ Merge order: workspace > global > built-in (last writer wins)
48
+
49
+ #### Scenario: Global override of platform flows
50
+
51
+ - **WHEN** global config defines export/import flows for existing built-in platform
52
+ - **THEN** global export/import arrays completely replace built-in flows for that platform (per array)
53
+
54
+ #### Scenario: Workspace adds custom platform
55
+
56
+ - **WHEN** workspace config defines new platform not in built-in or global
57
+ - **THEN** custom platform is added and available for detection and flow execution
58
+
59
+ #### Scenario: Workspace disables built-in platform
60
+
61
+ - **WHEN** workspace config sets `enabled: false` for built-in platform
62
+ - **THEN** platform is skipped during detection and flow execution
63
+
64
+ #### Scenario: Invalid merged configuration
65
+
66
+ - **WHEN** merged configuration results in invalid platform definition
67
+ - **THEN** configuration load fails with error indicating which source/platform caused issue
68
+
69
+ #### Scenario: Field-level merge behavior
70
+
71
+ - **WHEN** platform field is defined in multiple configs
72
+ - **THEN** last writer wins (workspace > global > built-in)
73
+ - **AND** export/import arrays are replaced entirely, not merged at element level
74
+
75
+ ### Requirement: Platform Detection
76
+
77
+ Platform detection SHALL use following logic:
78
+
79
+ - **Directory detection**: Check if platform `rootDir` exists in workspace
80
+ - **Root file detection**: Check if platform `rootFile` exists at project root
81
+ - **Enabled flag**: Only detect platforms where `enabled` is `true` or omitted
82
+ - **Detection signal**: Platform detected if rootDir OR rootFile exists
83
+
84
+ #### Scenario: Detect platform by root directory
85
+
86
+ - **WHEN** platform's `rootDir` exists in workspace
87
+ - **THEN** platform is marked as detected and flows can execute
88
+
89
+ #### Scenario: Detect platform by root file
90
+
91
+ - **WHEN** platform's `rootFile` exists at project root
92
+ - **THEN** platform is marked as detected even without directory structure
93
+
94
+ #### Scenario: Skip disabled platform during detection
95
+
96
+ - **WHEN** platform has `enabled: false` in configuration
97
+ - **THEN** platform is not detected regardless of directory/file presence
98
+
99
+ #### Scenario: Platform detection with both signals
100
+
101
+ - **WHEN** both `rootDir` and `rootFile` exist
102
+ - **THEN** platform is detected (redundant but valid)
103
+
104
+ ## Flow Configuration Requirements
105
+
106
+ ### Requirement: Flow Schema Validation
107
+
108
+ The system SHALL support declarative flow configurations with following structure:
109
+
110
+ - **Required fields**: `from` (source pattern), `to` (target path or multi-target object)
111
+ - **Optional transforms**: `pipe`, `map`, `pick`, `omit`, `path`, `embed`, `section`, `when`, `merge`, `namespace`, `handler`
112
+ - **Multi-target support**: `to` can be object mapping target paths to transform options
113
+ - **Validation**: Validate all flows on configuration load
114
+
115
+ #### Scenario: Simple file mapping flow loads successfully
116
+
117
+ - **WHEN** flow defines `{ "from": "rules/**/*.md", "to": ".cursor/rules/**/*.mdc" }`
118
+ - **THEN** flow is validated and ready for execution
119
+
120
+ #### Scenario: Recursive glob pattern flow loads successfully
121
+
122
+ - **WHEN** flow defines `{ "from": "skills/**/*", "to": ".platform/skills/**/*" }`
123
+ - **THEN** flow is validated and supports recursive directory traversal
124
+
125
+ #### Scenario: Multi-target flow with different transforms loads successfully
126
+
127
+ - **WHEN** flow defines `to` as object with multiple target paths
128
+ - **THEN** each target configuration is validated independently
129
+
130
+ #### Scenario: Invalid flow missing required field
131
+
132
+ - **WHEN** flow is missing `from` or `to` field
133
+ - **THEN** validation fails with error: "Flow missing required field 'from'/'to'"
134
+
135
+ #### Scenario: Invalid flow with wrong field types
136
+
137
+ - **WHEN** flow has field with incorrect type (e.g., `merge` as number)
138
+ - **THEN** validation fails with type error
139
+
140
+ ### Requirement: Flow Execution Pipeline
141
+
142
+ The system SHALL execute flows through multi-stage pipeline:
143
+
144
+ 1. **Load**: Read source file, auto-detect format (YAML/JSON/JSONC/TOML/Markdown)
145
+ 2. **Extract**: Apply JSONPath extraction if `path` specified
146
+ 3. **Filter**: Apply `pick` (whitelist) or `omit` (blacklist) key filters
147
+ 4. **Map**: Transform keys and values using `map` configuration
148
+ 5. **Transform**: Apply pipe transforms in order
149
+ 6. **Namespace**: Wrap content if `namespace` enabled
150
+ 7. **Embed**: Wrap under key/section if `embed` or `section` specified
151
+ 8. **Merge**: Merge with existing target using strategy
152
+ 9. **Write**: Serialize to target format and write atomically
153
+
154
+ #### Scenario: Simple format conversion through pipeline
155
+
156
+ - **WHEN** YAML file flows to JSON target with no additional transforms
157
+ - **THEN** content is parsed as YAML, converted to JSON object, serialized as JSON
158
+
159
+ #### Scenario: Complex transformation pipeline with multiple stages
160
+
161
+ - **WHEN** flow defines `path`, `map`, `pipe`, `embed`, and `merge` options
162
+ - **THEN** transformations are applied in defined pipeline order
163
+
164
+ #### Scenario: Pipeline stage failure stops execution
165
+
166
+ - **WHEN** any pipeline stage fails (parse error, transform error, write error)
167
+ - **THEN** execution stops immediately and error is reported with context (stage, file, reason)
168
+
169
+ #### Scenario: Simple file copy bypasses pipeline
170
+
171
+ - **WHEN** flow has no transform options (only `from` and `to`)
172
+ - **THEN** file is copied directly without parsing for performance optimization
173
+
174
+ ### Requirement: Glob Pattern Support
175
+
176
+ The system SHALL support glob patterns for file matching:
177
+
178
+ - **Single-level glob** (`*`): Matches files in a single directory level
179
+ - **Recursive glob** (`**`): Matches files in all subdirectories recursively
180
+ - **Extension mapping**: Target patterns can specify different extensions
181
+ - **Directory structure preservation**: Recursive globs maintain nested directory structure
182
+
183
+ #### Scenario: Single-level glob matches files in directory
184
+
185
+ - **WHEN** flow uses pattern `rules/*.md`
186
+ - **THEN** all `.md` files in `rules/` directory are matched (not subdirectories)
187
+
188
+ #### Scenario: Recursive glob matches nested files
189
+
190
+ - **WHEN** flow uses pattern `rules/**/*.md`
191
+ - **THEN** all `.md` files in `rules/` and all subdirectories are matched
192
+ - **AND** directory structure is preserved in target
193
+
194
+ #### Scenario: Recursive glob with all file types
195
+
196
+ - **WHEN** flow uses pattern `skills/**/*`
197
+ - **THEN** all files of any type in `skills/` and subdirectories are matched
198
+ - **AND** complete directory tree is replicated in target
199
+
200
+ #### Scenario: Extension mapping in recursive glob
201
+
202
+ - **WHEN** flow defines `from: "rules/**/*.md", to: ".cursor/rules/**/*.mdc"`
203
+ - **THEN** all `.md` files are copied with `.mdc` extension
204
+ - **AND** directory structure `rules/advanced/types.md` → `.cursor/rules/advanced/types.mdc`
205
+
206
+ #### Scenario: Empty glob match returns no error
207
+
208
+ - **WHEN** glob pattern matches no files
209
+ - **THEN** flow succeeds with warning "No files matched pattern"
210
+ - **AND** no error is raised
211
+
212
+ #### Scenario: Glob pattern preserves directory structure
213
+
214
+ - **WHEN** source has `rules/typescript/advanced/generics.md`
215
+ - **AND** flow uses `rules/**/*.md` → `.cursor/rules/**/*.md`
216
+ - **THEN** target is `.cursor/rules/typescript/advanced/generics.md`
217
+
218
+ ## Format Conversion Requirements
219
+
220
+ ### Requirement: Automatic Format Conversion
221
+
222
+ The system SHALL support bidirectional format conversion:
223
+
224
+ - **JSONC**: Parse JSON with comments, strip comments when converting to strict JSON
225
+ - **YAML**: Convert between YAML and JSON object representations
226
+ - **TOML**: Convert between TOML and JSON object representations
227
+ - **Markdown**: Parse frontmatter as YAML, transform frontmatter, preserve body
228
+ - **Auto-detection**: Detect format from file extension or content analysis
229
+
230
+ #### Scenario: YAML to JSON conversion
231
+
232
+ - **WHEN** source is YAML and target is JSON
233
+ - **THEN** content is parsed as YAML object and serialized as JSON
234
+
235
+ #### Scenario: JSONC to JSON conversion strips comments
236
+
237
+ - **WHEN** source is JSONC and target is JSON
238
+ - **THEN** comments are stripped during conversion, content preserved
239
+
240
+ #### Scenario: Format auto-detection from extension
241
+
242
+ - **WHEN** file extension is `.yaml`, `.json`, `.toml`, or `.md`
243
+ - **THEN** format is detected from extension and appropriate parser used
244
+
245
+ #### Scenario: Format auto-detection from content
246
+
247
+ - **WHEN** file extension is ambiguous or missing
248
+ - **THEN** format is detected by attempting to parse with multiple parsers
249
+
250
+ ## Merge Strategy Requirements
251
+
252
+ ### Requirement: Configurable Merge Strategies
253
+
254
+ The system SHALL support multiple merge strategies:
255
+
256
+ - **Deep merge** (`merge: "deep"`): Recursively merge nested objects and arrays
257
+ - **Shallow merge** (`merge: "shallow"`): Merge only top-level keys
258
+ - **Replace** (default): Completely replace target content with source
259
+ - **Composite** (`merge: "composite"`): Compose multiple package contributions using delimiters
260
+ - **Priority-based**: Workspace > direct deps > nested deps (shallower = higher priority)
261
+
262
+ #### Scenario: Deep merge of nested objects
263
+
264
+ - **WHEN** two JSON files are merged with `merge: "deep"`
265
+ - **THEN** nested objects are recursively merged, preserving non-overlapping keys at all levels
266
+
267
+ #### Scenario: Shallow merge of top-level keys only
268
+
269
+ - **WHEN** two JSON files are merged with `merge: "shallow"`
270
+ - **THEN** only top-level keys are merged, nested objects are replaced entirely
271
+
272
+ #### Scenario: Replace strategy overwrites target
273
+
274
+ - **WHEN** no merge strategy is specified
275
+ - **THEN** target file is completely replaced with source content
276
+
277
+ #### Scenario: Composite merge with multiple packages
278
+
279
+ - **WHEN** multiple packages define flows to same target with `merge: "composite"`
280
+ - **THEN** each package's content is wrapped in HTML comment delimiters with package name
281
+ - **AND** updates replace only that package's section
282
+ - **AND** all other packages' sections are preserved
283
+
284
+ #### Scenario: Composite merge preserves manual edits
285
+
286
+ - **WHEN** target file has manual edits outside package markers
287
+ - **AND** package content is merged with `merge: "composite"`
288
+ - **THEN** manual edits are preserved
289
+ - **AND** only the package's marked section is updated
290
+
291
+ #### Scenario: Composite merge format
292
+
293
+ - **WHEN** composite merge is used
294
+ - **THEN** content is wrapped in markers: `<!-- package: @scope/name -->` content `<!-- -->`
295
+ - **AND** each package gets its own section
296
+ - **AND** sections can be independently updated or removed
297
+
298
+ #### Scenario: Priority-based merge with multiple packages
299
+
300
+ - **WHEN** multiple packages define flows to same target with merge strategy
301
+ - **THEN** content is merged according to priority order (workspace > direct > nested)
302
+ - **AND** conflicts at leaf nodes resolved by last-writer-wins using priority
303
+
304
+ #### Scenario: Conflict warning logged during merge
305
+
306
+ - **WHEN** multiple packages write to same file and content conflicts
307
+ - **THEN** warning is logged: "Package @scope/b overwrites content from @scope/a in path"
308
+
309
+ ## Key Mapping Requirements
310
+
311
+ ### Requirement: Sophisticated Key Transformations
312
+
313
+ The system SHALL support key mapping with:
314
+
315
+ - **Dot notation**: Map to nested paths (`theme` → `workbench.colorTheme`)
316
+ - **Wildcard patterns**: Map multiple keys (`ai.*` → `cursor.*`)
317
+ - **Value transforms**: Apply type/string transforms during mapping
318
+ - **Value lookup tables**: Map values to platform-specific equivalents
319
+ - **Default values**: Provide fallback for missing keys
320
+
321
+ #### Scenario: Simple key rename with dot notation
322
+
323
+ - **WHEN** map defines `{ "theme": "workbench.colorTheme" }`
324
+ - **THEN** key `theme` is moved to nested path `workbench.colorTheme`
325
+
326
+ #### Scenario: Wildcard key mapping
327
+
328
+ - **WHEN** map defines `{ "ai.*": "cursor.*" }`
329
+ - **THEN** all keys under `ai` namespace are moved under `cursor` namespace
330
+
331
+ #### Scenario: Value transformation during mapping
332
+
333
+ - **WHEN** map defines `{ "fontSize": { "to": "editor.fontSize", "transform": "number" } }`
334
+ - **THEN** value is converted to number type and moved to target key
335
+
336
+ #### Scenario: Value lookup table mapping
337
+
338
+ - **WHEN** map defines `values` object with source-to-target mapping
339
+ - **THEN** source values are replaced with corresponding target values from table
340
+
341
+ #### Scenario: Default value for missing key
342
+
343
+ - **WHEN** map defines `default` value and source key is missing
344
+ - **THEN** default value is used in target
345
+
346
+ ## Markdown Frontmatter Requirements
347
+
348
+ ### Requirement: Frontmatter Transformation
349
+
350
+ The system SHALL support transforming YAML frontmatter in Markdown files:
351
+
352
+ - **Parse frontmatter**: Extract YAML frontmatter from Markdown
353
+ - **Transform frontmatter**: Apply key mapping and transforms to frontmatter only
354
+ - **Preserve body**: Keep Markdown body content unchanged
355
+ - **Serialize**: Reconstruct file with transformed frontmatter and original body
356
+
357
+ #### Scenario: Transform agent frontmatter with key mapping
358
+
359
+ - **WHEN** agent Markdown file has frontmatter with keys defined in map
360
+ - **THEN** frontmatter keys/values are transformed according to map
361
+ - **AND** markdown body content is preserved byte-for-byte
362
+
363
+ #### Scenario: Add frontmatter keys with defaults
364
+
365
+ - **WHEN** map defines new keys with default values
366
+ - **THEN** new keys are added to frontmatter without affecting body
367
+
368
+ #### Scenario: Remove frontmatter keys with omit
369
+
370
+ - **WHEN** omit list includes frontmatter keys
371
+ - **THEN** specified keys are removed from frontmatter without affecting body
372
+
373
+ ## Multi-Package Composition Requirements
374
+
375
+ ### Requirement: Priority-Based Multi-Package Merging
376
+
377
+ The system SHALL support composition from multiple packages using priority-based conflict resolution:
378
+
379
+ - **Priority order**: Workspace content > direct dependencies > nested dependencies (shallower = higher)
380
+ - **Conflict detection**: Detect when multiple packages write to same file paths
381
+ - **Conflict warnings**: Log warnings when conflicts occur with package information
382
+ - **Last-writer-wins**: Package with highest priority overwrites conflicting content at leaf nodes
383
+ - **Merge strategies**: Apply deep/shallow/replace merge based on flow configuration
384
+
385
+ #### Scenario: Direct dependency wins over nested dependency
386
+
387
+ - **WHEN** direct dependency and its nested dependency target same file
388
+ - **THEN** direct dependency content takes precedence (shallower = higher priority)
389
+ - **AND** warning logged: "Package @scope/direct overwrites @scope/nested in path"
390
+
391
+ #### Scenario: Later direct dependency wins over earlier
392
+
393
+ - **WHEN** two direct dependencies define conflicting content for same target
394
+ - **THEN** package listed later in dependency order wins (higher priority)
395
+ - **AND** warning logged with package information
396
+
397
+ #### Scenario: Workspace content preserved with highest priority
398
+
399
+ - **WHEN** workspace has manually-edited content in target file
400
+ - **THEN** workspace content is preserved (highest priority)
401
+ - **AND** package content does not overwrite manual edits
402
+
403
+ #### Scenario: Multi-package deep merge with priority resolution
404
+
405
+ - **WHEN** multiple packages define flows to same target with `merge: "deep"`
406
+ - **THEN** content is deeply merged according to priority order
407
+ - **AND** conflicts at leaf nodes resolved by priority (last-writer-wins)
408
+
409
+ ## Conditional Execution Requirements
410
+
411
+ ### Requirement: Context-Based Conditional Flows
412
+
413
+ The system SHALL support conditional flow execution:
414
+
415
+ - **Platform checks**: Execute only if specific platform detected (`platform: "cursor"`)
416
+ - **Existence checks**: Execute only if file/directory exists (`exists: ".cursor"`)
417
+ - **Key checks**: Execute only if source key exists (`key: "servers"`)
418
+ - **Value checks**: Execute only if key equals value (`equals: "production"`)
419
+ - **Composite conditions**: Support `and` and `or` operators for complex logic
420
+
421
+ #### Scenario: Platform-conditional flow execution
422
+
423
+ - **WHEN** flow has `when: { "platform": "cursor" }` condition
424
+ - **THEN** flow executes only when Cursor platform is detected in workspace
425
+
426
+ #### Scenario: File existence check before execution
427
+
428
+ - **WHEN** flow has `when: { "exists": ".cursor" }` condition
429
+ - **THEN** flow executes only if `.cursor` directory exists
430
+
431
+ #### Scenario: Composite AND condition requires all true
432
+
433
+ - **WHEN** flow has `when: { "and": [{ "platform": "cursor" }, { "exists": "mcp.jsonc" }] }`
434
+ - **THEN** flow executes only if both Cursor detected AND mcp.jsonc exists
435
+
436
+ #### Scenario: Composite OR condition requires any true
437
+
438
+ - **WHEN** flow has `when: { "or": [{ "platform": "cursor" }, { "platform": "claude" }] }`
439
+ - **THEN** flow executes if either Cursor OR Claude platform is detected
440
+
441
+ ## Content Embedding Requirements
442
+
443
+ ### Requirement: Content Embedding in Target Structures
444
+
445
+ The system SHALL support embedding content within target structures:
446
+
447
+ - **JSON embedding**: Wrap content under specified key with `embed: "key"`
448
+ - **TOML sections**: Place content in TOML section with `section: "section_name"`
449
+ - **Merge with embedding**: Combine embedding with merge strategies
450
+
451
+ #### Scenario: Embed content in JSON structure
452
+
453
+ - **WHEN** flow defines `embed: "mcp"` for JSON target
454
+ - **THEN** source content is wrapped under `{ "mcp": <content> }` in target
455
+
456
+ #### Scenario: TOML section embedding
457
+
458
+ - **WHEN** flow defines `section: "mcp_servers"` for TOML target
459
+ - **THEN** content is placed under `[mcp_servers]` section in TOML file
460
+
461
+ #### Scenario: Embed and deep merge together
462
+
463
+ - **WHEN** flow defines both `embed: "mcp"` and `merge: "deep"`
464
+ - **THEN** embedded content is deep merged with existing embedded section in target
465
+
466
+ ## Built-in Transform Requirements
467
+
468
+ ### Requirement: Comprehensive Built-in Value Transforms
469
+
470
+ The system SHALL provide built-in value transforms:
471
+
472
+ **Type Converters:** `number`, `string`, `boolean`, `json`, `date`
473
+ **String Transforms:** `uppercase`, `lowercase`, `title-case`, `camel-case`, `kebab-case`, `snake-case`, `trim`, `slugify`
474
+ **Array Transforms:** `array-append`, `array-unique`, `array-flatten`
475
+ **Object Transforms:** `flatten`, `unflatten`, `pick-keys`, `omit-keys`
476
+
477
+ #### Scenario: Type conversion transform
478
+
479
+ - **WHEN** transform is `number` and value is string "42"
480
+ - **THEN** value is converted to number 42
481
+
482
+ #### Scenario: String case transform
483
+
484
+ - **WHEN** transform is `kebab-case` and value is "helloWorld"
485
+ - **THEN** value is converted to "hello-world"
486
+
487
+ #### Scenario: Array deduplication transform
488
+
489
+ - **WHEN** transform is `array-unique` and value is `[1, 2, 2, 3]`
490
+ - **THEN** value is converted to `[1, 2, 3]`
491
+
492
+ #### Scenario: Object flattening transform
493
+
494
+ - **WHEN** transform is `flatten` and value is `{ "a": { "b": 1 } }`
495
+ - **THEN** value is converted to `{ "a.b": 1 }`
496
+
497
+ ## Namespace Isolation Requirements
498
+
499
+ ### Requirement: Package Namespace Isolation
500
+
501
+ The system SHALL support namespace isolation to prevent package collisions:
502
+
503
+ - **Automatic wrapping**: Wrap content under `packages.{packageName}` when `namespace: true`
504
+ - **Custom namespace key**: Support custom key via `namespace: "customKey"`
505
+ - **Merge with namespacing**: Combine namespacing with merge strategies
506
+ - **Per-package isolation**: Each package gets separate namespace
507
+
508
+ #### Scenario: Automatic namespace wrapping
509
+
510
+ - **WHEN** flow has `namespace: true`
511
+ - **THEN** content is wrapped under `packages[@scope/package-name]` key in target
512
+
513
+ #### Scenario: Custom namespace key
514
+
515
+ - **WHEN** flow has `namespace: "extensions"`
516
+ - **THEN** content is wrapped under `extensions[@scope/package-name]` key in target
517
+
518
+ #### Scenario: Namespace isolation prevents conflicts
519
+
520
+ - **WHEN** multiple packages use namespacing for same target
521
+ - **THEN** each package's content is isolated under its own namespace
522
+ - **AND** no conflicts occur between packages
523
+
524
+ ## Validation Requirements
525
+
526
+ ### Requirement: Configuration Validation
527
+
528
+ The system SHALL validate configurations with clear error reporting:
529
+
530
+ - **Schema validation**: Validate required fields and types
531
+ - **Transform validation**: Verify transform names exist in built-ins
532
+ - **JSONPath validation**: Validate JSONPath expression syntax
533
+ - **Circular dependency detection**: Detect and report circular flow dependencies
534
+ - **Context-rich errors**: Include file path, platform, flow index, and fix suggestions
535
+
536
+ #### Scenario: Missing required field validation
537
+
538
+ - **WHEN** flow is missing `from` or `to` field
539
+ - **THEN** validation fails with error: "Platform 'id' flow N: missing required field 'from'/'to'"
540
+
541
+ #### Scenario: Invalid transform name validation
542
+
543
+ - **WHEN** flow references non-existent transform in `pipe`
544
+ - **THEN** validation fails with error: "Unknown transform 'xyz'. Available: [list]"
545
+
546
+ #### Scenario: Invalid JSONPath expression validation
547
+
548
+ - **WHEN** flow defines invalid JSONPath in `path` field
549
+ - **THEN** validation fails with error: "Invalid JSONPath expression: <expr>. <reason>"
550
+
551
+ #### Scenario: Circular dependency detection
552
+
553
+ - **WHEN** flows create circular transformation dependency
554
+ - **THEN** validation fails with error: "Circular dependency detected: A → B → A"
555
+
556
+ ## Performance Requirements
557
+
558
+ ### Requirement: Performance Optimization
559
+
560
+ The system SHALL optimize flow execution:
561
+
562
+ - **Simple file copy bypass**: Skip pipeline for flows with no transforms
563
+ - **Parser caching**: Cache format parsers per file type within execution context
564
+ - **Single source parse**: Parse source once for multi-target flows
565
+ - **Lazy evaluation**: Evaluate conditional flows only when conditions might be true
566
+ - **Structural sharing**: Share unchanged object structures during merges
567
+
568
+ #### Scenario: Simple file copy optimization
569
+
570
+ - **WHEN** flow has no transforms (just `from` and `to` with extension change)
571
+ - **THEN** file is copied directly without parsing pipeline
572
+
573
+ #### Scenario: Multi-target source caching
574
+
575
+ - **WHEN** flow has multiple targets from same source
576
+ - **THEN** source is parsed once and AST/object is reused for all targets
577
+
578
+ #### Scenario: Conditional flow lazy evaluation
579
+
580
+ - **WHEN** flow has `when` condition that evaluates to false
581
+ - **THEN** flow is skipped without loading or parsing source file
582
+
583
+ ## Bidirectional Flow Requirements
584
+
585
+ ### Requirement: Explicit Bidirectional Flow Configuration
586
+
587
+ The system SHALL define flows as explicit bidirectional transformations using separate export and import flows:
588
+
589
+ - **Export flows**: Transform from universal package format to platform-specific workspace format (package → workspace)
590
+ - **Import flows**: Transform from platform-specific workspace format to universal package format (workspace → package)
591
+ - **Export `from`**: Always relative to package root (universal format)
592
+ - **Export `to`**: Always relative to workspace root (platform-specific format)
593
+ - **Import `from`**: Always relative to workspace root (platform-specific format)
594
+ - **Import `to`**: Always relative to package root (universal format)
595
+ - **No automatic inversion**: Import flows must be explicitly defined, no automatic reversal of export flows
596
+ - **Independent flows**: Export and import flows are independent; no pairing or coupling required
597
+
598
+ #### Scenario: Install executes export flows (package → workspace)
599
+
600
+ - **WHEN** installing a package with export flows
601
+ - **THEN** export flows execute transforming package files to workspace files
602
+ - **AND** source files are in universal package format
603
+ - **AND** target files are in platform-specific format
604
+
605
+ #### Scenario: Apply re-executes export flows (package → workspace)
606
+
607
+ - **WHEN** applying a package with export flows
608
+ - **THEN** export flows execute again transforming package files to workspace files
609
+ - **AND** existing workspace files may be overwritten based on merge strategy
610
+
611
+ #### Scenario: Save executes import flows (workspace → package)
612
+
613
+ - **WHEN** saving workspace files to package
614
+ - **THEN** system matches workspace files against import flow `from` patterns
615
+ - **AND** executes import flows to transform workspace format to universal format
616
+ - **AND** only processes files tracked in workspace index
617
+
618
+ #### Scenario: Save with no matching import flow
619
+
620
+ - **WHEN** workspace file is tracked in index but no import flow matches
621
+ - **THEN** file is silently skipped (no error)
622
+ - **AND** package is not updated for that file
623
+
624
+ #### Scenario: Save only processes indexed files
625
+
626
+ - **WHEN** workspace contains files not in workspace index
627
+ - **THEN** import flows do not process untracked files
628
+ - **AND** only files previously exported are candidates for import
629
+
630
+ #### Scenario: Independent export and import flows
631
+
632
+ - **WHEN** platform defines export flows without corresponding import flows
633
+ - **THEN** install/apply work normally but save cannot update package
634
+ - **WHEN** platform defines import flows without corresponding export flows
635
+ - **THEN** save works normally but install/apply do nothing
636
+
637
+ #### Scenario: Array pattern support in both directions
638
+
639
+ - **WHEN** export flow uses array pattern `from: ["file1.jsonc", "file1.json"]`
640
+ - **THEN** first matching file is used (priority order)
641
+ - **WHEN** import flow uses array pattern `from: [".platform/file1.json", ".platform/file1.jsonc"]`
642
+ - **THEN** first matching file is used (priority order)
643
+
644
+ ## Schema Versioning Requirements
645
+
646
+ ### Requirement: Local JSON Schema Support
647
+
648
+ The system SHALL support schema versioning using local JSON schema files:
649
+
650
+ - **Schema field**: Optional `$schema` field in platforms.jsonc referencing local schema
651
+ - **Local schema path**: Resolve relative to workspace or node_modules
652
+ - **IDE support**: Enable validation and autocomplete via JSON schema
653
+ - **Version detection**: Infer version from schema path or default to CLI version
654
+ - **Validation**: Validate config against specified schema version
655
+
656
+ #### Scenario: Explicit schema version reference
657
+
658
+ - **WHEN** platforms.jsonc includes `$schema: "./node_modules/opkg-cli/schemas/platforms-v1.json"`
659
+ - **THEN** config is validated against v1 schema
660
+ - **AND** IDE provides v1-specific autocomplete and validation
661
+
662
+ #### Scenario: Missing schema field defaults to current
663
+
664
+ - **WHEN** platforms.jsonc has no `$schema` field
665
+ - **THEN** config defaults to current CLI version schema
666
+ - **AND** validation uses latest schema rules
667
+
668
+ #### Scenario: Schema path resolution
669
+
670
+ - **WHEN** schema path is relative (e.g., `./node_modules/...` or `./schemas/...`)
671
+ - **THEN** system resolves path relative to config file location
672
+ - **AND** loads schema for IDE and CLI validation
673
+
674
+ ## Custom Handler Requirements
675
+
676
+ ### Requirement: Custom Handler Escape Hatch
677
+
678
+ The system SHALL support custom handlers for edge cases not expressible via declarative options:
679
+
680
+ - **Handler registration**: Register handler functions in CLI code
681
+ - **Handler invocation**: Invoke handler when `handler: "name"` specified in flow
682
+ - **Handler context**: Provide full flow context (source, target, package info) to handlers
683
+ - **Handler errors**: Report handler errors clearly with handler name and context
684
+ - **Not user-configurable**: Handlers require CLI code changes, not available in user configs
685
+
686
+ #### Scenario: Custom handler for complex transformation
687
+
688
+ - **WHEN** flow defines `handler: "custom-mcp-transform"`
689
+ - **AND** handler is registered in CLI code
690
+ - **THEN** handler function is invoked with source content and full context
691
+
692
+ #### Scenario: Handler not found error
693
+
694
+ - **WHEN** flow references unregistered handler name
695
+ - **THEN** execution fails with error: "Handler 'xyz' not found. Available: [list]"
696
+
697
+ #### Scenario: Handler error with context
698
+
699
+ - **WHEN** custom handler throws error during execution
700
+ - **THEN** error is caught and reported with handler name, source file, and error details