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,520 @@
1
+ # Universal Platform Converter
2
+
3
+ ## Overview
4
+
5
+ The **Universal Platform Converter** enables OpenPackage to install platform-specific packages (like Claude Code plugins) across different platforms by automatically converting between formats.
6
+
7
+ **Key capability:** Install a Claude Code plugin directly into Cursor, OpenCode, or any other platform without manual conversion.
8
+
9
+ ## Problem Statement
10
+
11
+ Previously, OpenPackage expected all packages to be in **universal format** (with `commands/`, `agents/`, `rules/` subdirectories). Platform-specific packages like Claude Code plugins use a different structure (`.claude/commands/`, `.claude/agents/`, etc.).
12
+
13
+ **The challenge:**
14
+ - Claude Code plugins are already in Claude format
15
+ - Installing to Claude platform: Should copy files AS-IS (no transformation)
16
+ - Installing to other platforms: Need to convert Claude → Universal → Target Platform
17
+
18
+ ## Solution Architecture
19
+
20
+ ### Three-Phase Approach
21
+
22
+ ```
23
+ ┌─────────────────────────────────────────────────────────┐
24
+ │ Phase 1: Format Detection │
25
+ │ - Analyze package file structure │
26
+ │ - Determine: universal or platform-specific │
27
+ │ - Calculate confidence score │
28
+ └─────────────────────────────────────────────────────────┘
29
+
30
+ ┌─────────────────────────────────────────────────────────┐
31
+ │ Phase 2: Strategy Selection │
32
+ │ • Source = Target Platform → Install AS-IS │
33
+ │ • Source ≠ Target Platform → Convert │
34
+ │ • Universal Format → Standard Flow Installation │
35
+ └─────────────────────────────────────────────────────────┘
36
+
37
+ ┌─────────────────────────────────────────────────────────┐
38
+ │ Phase 3: Execution │
39
+ │ - Direct copy (AS-IS) │
40
+ │ - OR: Bidirectional flow conversion │
41
+ │ - OR: Standard flow-based installation │
42
+ └─────────────────────────────────────────────────────────┘
43
+ ```
44
+
45
+ ## Core Components
46
+
47
+ ### 1. Format Detector (`format-detector.ts`)
48
+
49
+ **Purpose:** Identify package format by analyzing file paths.
50
+
51
+ **Detection heuristics:**
52
+ - Universal subdirs: `commands/`, `agents/`, `rules/`, `skills/`, `hooks/`
53
+ - Platform-specific dirs: `.claude/`, `.cursor/`, `.opencode/`, etc.
54
+ - Platform suffixes in filenames: `mcp.claude.jsonc`, `config.cursor.yaml`
55
+ - Confidence scoring based on file distribution
56
+
57
+ **Example:**
58
+ ```typescript
59
+ import { detectPackageFormat } from './format-detector.js';
60
+
61
+ const files = [
62
+ { path: '.claude/commands/review.md', content: '...' },
63
+ { path: '.claude/agents/helper.md', content: '...' }
64
+ ];
65
+
66
+ const format = detectPackageFormat(files);
67
+ // Result:
68
+ // {
69
+ // type: 'platform-specific',
70
+ // platform: 'claude',
71
+ // confidence: 0.95,
72
+ // analysis: { ... }
73
+ // }
74
+ ```
75
+
76
+ **Format types:**
77
+ - `'universal'`: OpenPackage universal format
78
+ - `'platform-specific'`: Claude, Cursor, OpenCode, etc.
79
+
80
+ ### 2. Flow Inverter (`flow-inverter.ts`)
81
+
82
+ **Purpose:** Reverse flow transformations to convert platform-specific → universal.
83
+
84
+ **Key insight:** The `platforms.jsonc` flows already define universal → platform transformations. We can **invert** these flows to go in reverse.
85
+
86
+ **Inversion rules:**
87
+ - **Paths:** Swap `from` ↔ `to`
88
+ ```typescript
89
+ // Original
90
+ { from: "commands/**/*.md", to: ".claude/commands/**/*.md" }
91
+
92
+ // Inverted
93
+ { from: ".claude/commands/**/*.md", to: "commands/**/*.md" }
94
+ ```
95
+
96
+ - **Map `$rename`:** Swap key pairs
97
+ ```typescript
98
+ // Original
99
+ { $rename: { "mcp": "mcpServers" } }
100
+
101
+ // Inverted
102
+ { $rename: { "mcpServers": "mcp" } }
103
+ ```
104
+
105
+ - **Operations processed in reverse order**
106
+ - **Non-reversible operations skipped** (`$set`, `$unset`, `$pipeline` with lossy transforms)
107
+ - **Format converters preserved** (`yaml`, `jsonc`, `toml`)
108
+ - **Filters skipped** (`filter-empty`, `filter-null`)
109
+
110
+ ### 3. Platform Converter (`platform-converter.ts`)
111
+
112
+ **Purpose:** High-level orchestration of format conversions.
113
+
114
+ **Conversion pipeline stages:**
115
+ 1. **Platform → Universal:** Invert source platform flows
116
+ 2. **Universal → Target:** Apply target platform flows (handled by installer)
117
+
118
+ **Example usage:**
119
+ ```typescript
120
+ import { createPlatformConverter } from './platform-converter.js';
121
+
122
+ const converter = createPlatformConverter(workspaceRoot);
123
+
124
+ const result = await converter.convert(
125
+ package,
126
+ targetPlatform,
127
+ { dryRun: false }
128
+ );
129
+
130
+ if (result.success) {
131
+ console.log(`Converted ${result.stages.length} stages`);
132
+ }
133
+ ```
134
+
135
+ ### 4. Enhanced Flow-Based Installer
136
+
137
+ **Purpose:** Integrate converter into installation pipeline.
138
+
139
+ **Installation strategies:**
140
+
141
+ #### Strategy 1: Direct Installation (AS-IS)
142
+ ```
143
+ Source: Claude plugin
144
+ Target: claude platform
145
+ Action: Copy files directly, skip all transformations
146
+ ```
147
+
148
+ #### Strategy 2: Convert via Universal
149
+ ```
150
+ Source: Claude plugin
151
+ Target: cursor platform
152
+ Pipeline:
153
+ 1. Detect format (claude platform-specific)
154
+ 2. Invert claude flows (.claude/commands/*.md → commands/*.md)
155
+ 3. Apply cursor flows (commands/*.md → .cursor/commands/*.md)
156
+ ```
157
+
158
+ #### Strategy 3: Standard Flow Installation
159
+ ```
160
+ Source: Universal package
161
+ Target: Any platform
162
+ Action: Apply platform flows (existing behavior)
163
+ ```
164
+
165
+ ## Installation Flow
166
+
167
+ ### Full Installation Pipeline
168
+
169
+ ```typescript
170
+ async function installPackageWithFlows(context) {
171
+ // 1. Detect package format
172
+ const format = await detectPackageFormat(packageRoot);
173
+
174
+ // 2. Check for direct installation
175
+ if (shouldInstallDirectly(format, targetPlatform)) {
176
+ return await installDirectly(context, format);
177
+ }
178
+
179
+ // 3. Check for conversion
180
+ if (needsConversion(format, targetPlatform)) {
181
+ return await installWithConversion(context, format);
182
+ }
183
+
184
+ // 4. Standard flow-based installation
185
+ return await executeStandardFlows(context);
186
+ }
187
+ ```
188
+
189
+ ### Decision Tree
190
+
191
+ ```
192
+ Package Format Detection
193
+ ├─ Universal Format
194
+ │ └─→ Standard flow-based installation
195
+
196
+ ├─ Platform-Specific (matches target)
197
+ │ └─→ Direct installation (AS-IS)
198
+
199
+ └─ Platform-Specific (different from target)
200
+ └─→ Convert via universal
201
+ ├─ Stage 1: Invert source platform flows
202
+ └─ Stage 2: Apply target platform flows
203
+ ```
204
+
205
+ ## Usage Examples
206
+
207
+ ### Example 1: Claude Plugin → Claude Platform
208
+
209
+ ```bash
210
+ # Install Claude plugin to Claude platform
211
+ opkg install path/to/claude-plugin --platforms claude
212
+ ```
213
+
214
+ **Behavior:**
215
+ - Detects: Claude platform-specific format
216
+ - Target: claude platform
217
+ - Action: **Direct installation (AS-IS)**
218
+ - Result: Files copied to `.claude/` without any transformation
219
+
220
+ **Console output:**
221
+ ```
222
+ 🔌 Detected Claude Code plugin
223
+ 📦 Installing plugin: my-plugin@1.0.0
224
+ ✓ Installing my-plugin AS-IS for claude platform (matching format)
225
+ ✓ Added files: 5
226
+ ├── .claude/commands/review.md
227
+ ├── .claude/commands/test.md
228
+ ├── .claude/agents/helper.md
229
+ └── ...
230
+ ```
231
+
232
+ ### Example 2: Claude Plugin → Cursor Platform
233
+
234
+ ```bash
235
+ # Install Claude plugin to Cursor platform
236
+ opkg install path/to/claude-plugin --platforms cursor
237
+ ```
238
+
239
+ **Behavior:**
240
+ - Detects: Claude platform-specific format
241
+ - Target: cursor platform
242
+ - Action: **Convert via universal**
243
+ 1. Invert claude flows (`.claude/commands/*.md` → `commands/*.md`)
244
+ 2. Apply cursor flows (`commands/*.md` → `.cursor/commands/*.md`)
245
+
246
+ **Console output:**
247
+ ```
248
+ 🔌 Detected Claude Code plugin
249
+ 📦 Installing plugin: my-plugin@1.0.0
250
+ 🔄 Converting my-plugin from claude to cursor format
251
+ ✓ Conversion stage: platform-to-universal (5 files)
252
+ ✓ Applying cursor platform flows
253
+ ✓ Added files: 5
254
+ ├── .cursor/commands/review.md
255
+ ├── .cursor/commands/test.md
256
+ └── ...
257
+ ```
258
+
259
+ ### Example 3: Claude Plugin → Multiple Platforms
260
+
261
+ ```bash
262
+ # Install to both Claude and Cursor
263
+ opkg install path/to/claude-plugin --platforms claude,cursor
264
+ ```
265
+
266
+ **Behavior:**
267
+ - For `claude`: Direct installation (AS-IS)
268
+ - For `cursor`: Convert via universal
269
+ - Efficient: Conversion happens once, applied to cursor only
270
+
271
+ ### Example 4: Universal Package (Existing Behavior)
272
+
273
+ ```bash
274
+ # Standard universal package installation
275
+ opkg install @user/package --platforms claude,cursor
276
+ ```
277
+
278
+ **Behavior:**
279
+ - Detects: Universal format
280
+ - Action: **Standard flow-based installation** (no changes)
281
+ - Claude: Apply claude flows
282
+ - Cursor: Apply cursor flows
283
+
284
+ ## Configuration
285
+
286
+ **No configuration needed!** The system works automatically by:
287
+ 1. Analyzing file structure
288
+ 2. Reading existing `platforms.jsonc` flows
289
+ 3. Inverting flows as needed
290
+
291
+ ## API Reference
292
+
293
+ ### Format Detector
294
+
295
+ ```typescript
296
+ /**
297
+ * Detect package format from file list
298
+ */
299
+ function detectPackageFormat(files: PackageFile[]): PackageFormat
300
+
301
+ /**
302
+ * Check if format is platform-specific
303
+ */
304
+ function isPlatformSpecific(format: PackageFormat): boolean
305
+
306
+ /**
307
+ * Check if conversion is needed
308
+ */
309
+ function needsConversion(
310
+ format: PackageFormat,
311
+ targetPlatform: Platform
312
+ ): boolean
313
+
314
+ /**
315
+ * Check if should install AS-IS
316
+ */
317
+ function shouldInstallDirectly(
318
+ format: PackageFormat,
319
+ targetPlatform: Platform
320
+ ): boolean
321
+ ```
322
+
323
+ ### Flow Inverter
324
+
325
+ ```typescript
326
+ /**
327
+ * Invert a single flow
328
+ */
329
+ function invertFlow(flow: Flow, sourcePlatform: Platform): InvertedFlow
330
+
331
+ /**
332
+ * Invert multiple flows
333
+ */
334
+ function invertFlows(flows: Flow[], sourcePlatform: Platform): InvertedFlow[]
335
+
336
+ /**
337
+ * Check if flow is inverted
338
+ */
339
+ function isInvertedFlow(flow: Flow): boolean
340
+ ```
341
+
342
+ ### Platform Converter
343
+
344
+ ```typescript
345
+ /**
346
+ * Convert package to target platform
347
+ */
348
+ class PlatformConverter {
349
+ async convert(
350
+ pkg: Package,
351
+ targetPlatform: Platform,
352
+ options?: { dryRun?: boolean }
353
+ ): Promise<ConversionResult>
354
+
355
+ buildPipeline(
356
+ sourceFormat: PackageFormat,
357
+ targetPlatform: Platform
358
+ ): ConversionPipeline
359
+ }
360
+
361
+ /**
362
+ * Create converter instance
363
+ */
364
+ function createPlatformConverter(workspaceRoot: string): PlatformConverter
365
+ ```
366
+
367
+ ## Implementation Details
368
+
369
+ ### Format Detection Algorithm
370
+
371
+ ```typescript
372
+ 1. Scan all package files
373
+ 2. For each file:
374
+ a. Check if path starts with platform dir (.claude/, .cursor/, etc.)
375
+ b. Check if path starts with universal subdir (commands/, agents/, etc.)
376
+ c. Check for platform suffix in filename (mcp.claude.jsonc)
377
+ 3. Calculate ratios:
378
+ - universalRatio = universalFiles / totalFiles
379
+ - platformRatio = platformSpecificFiles / totalFiles
380
+ 4. Determine format:
381
+ - If universalRatio > 0.7 → universal
382
+ - If platformRatio > 0.7 → platform-specific (dominant platform)
383
+ - Else → universal (default, low confidence)
384
+ ```
385
+
386
+ ### Flow Inversion Algorithm
387
+
388
+ ```typescript
389
+ 1. Swap from ↔ to paths
390
+ 2. Process map operations in reverse order:
391
+ For each operation:
392
+ - $rename: Swap key pairs
393
+ - $copy: Swap from/to
394
+ - $set/$unset: Skip (not reversible)
395
+ - $switch: Reverse pattern/value pairs
396
+ - $pipeline: Invert operations if possible (see below)
397
+ 3. Filter pipe transforms:
398
+ - Keep: Format converters (yaml, jsonc, toml)
399
+ - Keep: Merge strategies
400
+ - Skip: Filters (filter-empty, filter-null)
401
+ - Skip: Validation (validate-*)
402
+ 4. Preserve: merge, when, namespace
403
+ 5. Remove: embed, section
404
+ ```
405
+
406
+ ## Testing
407
+
408
+ ### Unit Tests
409
+
410
+ **Format Detection:**
411
+ ```typescript
412
+ // tests/format-detector.test.ts
413
+ - Detect universal format
414
+ - Detect Claude platform-specific
415
+ - Detect Cursor platform-specific
416
+ - Detect platform suffix in filenames
417
+ - Handle mixed files
418
+ - Provide detailed analysis
419
+ ```
420
+
421
+ **Flow Inversion:**
422
+ ```typescript
423
+ // tests/flow-inverter.test.ts
424
+ - Swap from/to paths
425
+ - Invert $rename operations
426
+ - Skip non-reversible operations
427
+ - Preserve merge strategy
428
+ - Handle pipe transforms
429
+ - Invert $copy operations
430
+ ```
431
+
432
+ **Platform Converter:**
433
+ ```typescript
434
+ // tests/platform-converter.test.ts
435
+ - Build conversion pipeline
436
+ - Convert between formats
437
+ - Handle matching formats (no conversion)
438
+ - Integration scenarios
439
+ ```
440
+
441
+ ### Integration Tests
442
+
443
+ ```typescript
444
+ // tests/install-claude-plugin.test.ts
445
+ - Install Claude plugin to claude platform (AS-IS)
446
+ - Install Claude plugin to cursor platform (convert)
447
+ - Multi-platform installation
448
+ - Git-based plugin installation
449
+ ```
450
+
451
+ ## Performance Considerations
452
+
453
+ 1. **Format Detection:** Fast - only analyzes file paths, no content parsing
454
+ 2. **Direct Installation:** Fastest - simple file copy, no transformations
455
+ 3. **Conversion:** Moderate - one conversion to universal, then standard flows
456
+ 4. **Caching:** Package format cached after first detection
457
+
458
+ ## Limitations
459
+
460
+ ### Non-Reversible Operations
461
+
462
+ Some flow operations cannot be reliably inverted:
463
+
464
+ - **`$set`:** Cannot determine original value
465
+ - **`$unset`:** Cannot restore removed fields
466
+ - **`$pipeline`:** Complex multi-step transformations with lossy operations (e.g., `$map` with case changes)
467
+ - **Filters:** Cannot "un-filter" removed content
468
+
469
+ **Impact:** Conversion may not be 100% lossless for packages with complex transformations.
470
+
471
+ **Mitigation:** Most platform flows use simple path mappings and basic $rename operations, which invert perfectly.
472
+
473
+ ### Round-Trip Accuracy
474
+
475
+ Converting `Platform A → Universal → Platform B` may not always equal converting `Platform B → Universal → Platform A` in reverse, due to:
476
+ - Non-reversible operations
477
+ - Lossy transformations (e.g., filtering, complex string manipulations)
478
+
479
+ **Best practice:** Keep flows simple and bidirectional-friendly.
480
+
481
+ ## Future Enhancements
482
+
483
+ 1. **Direct Platform-to-Platform:** Skip universal intermediate step for known conversions
484
+ 2. **Conversion Validation:** Round-trip testing to verify accuracy
485
+ 3. **Custom Converters:** Plugin system for complex conversions
486
+ 4. **Conversion Cache:** Store converted packages for faster reinstalls
487
+ 5. **Partial Conversion:** Convert only specific files/flows
488
+
489
+ ## FAQ
490
+
491
+ ### Q: Will this break existing packages?
492
+ **A:** No. Universal packages continue to work exactly as before. The converter only activates for platform-specific packages.
493
+
494
+ ### Q: Can I force AS-IS installation?
495
+ **A:** Yes, by targeting the same platform as the source:
496
+ ```bash
497
+ opkg install claude-plugin --platforms claude
498
+ ```
499
+
500
+ ### Q: What if conversion fails?
501
+ **A:** The installer will report errors and fall back gracefully. You can inspect conversion errors with `--dry-run` flag.
502
+
503
+ ### Q: How accurate is format detection?
504
+ **A:** Very accurate for typical packages. Confidence scores indicate certainty. Mixed-format packages default to universal (safest).
505
+
506
+ ### Q: Can I convert between any two platforms?
507
+ **A:** Yes! The system converts through universal format:
508
+ ```
509
+ Platform A → Universal → Platform B
510
+ ```
511
+
512
+ ### Q: Does this work with git sources?
513
+ **A:** Yes! Format detection and conversion work for all package sources (path, git, registry).
514
+
515
+ ## See Also
516
+
517
+ - [Platform Flows](./flows.md) - Declarative transformation system
518
+ - [Flow Reference](./flow-reference.md) - Complete flow syntax
519
+ - [Platform Detection](./detection.md) - Platform identification
520
+ - [Installation Behavior](../install/install-behavior.md) - Install semantics
@@ -3,6 +3,7 @@
3
3
  This directory contains specifications for the `push` command, with a focus on:
4
4
 
5
5
  - **Stable-only pushes (no prereleases)**
6
+ - **Source package detection**: At effective cwd (shell or --cwd; see [../../cli-options.md])
6
7
  - **Local-version selection and scoping behavior**
7
8
  - **Consistent, helpful CLI UX and error messaging**
8
9
 
@@ -1,11 +1,19 @@
1
1
  ## Push command behavior
2
2
 
3
+ ### Effective Working Directory
4
+ The command determines the source package via the **effective cwd** (shell `cwd` or global `--cwd <dir>` override; see [../../cli-options.md]):
5
+ - Detects package context at effective cwd (root `openpackage.yml` or nested `.openpackage/packages/<name>/`).
6
+ - Packs from that dir's content/layout.
7
+ - Enables monorepo pushes: `opkg push --cwd ./sub-pkg` targets sub-dir package without `cd`.
8
+
9
+ If no valid package detected, errors early ("No package project at <dir>").
10
+
3
11
  ### Overview
4
12
 
5
13
  The `opkg push` command uploads a local package version from the **local registry** to the **remote registry**.
6
14
  It allows:
7
15
  - **Stable versions** (`x.y.z`).
8
- - **Unversioned packages** (when `package.yml` omits `version`, represented as `0.0.0`).
16
+ - **Unversioned packages** (when `openpackage.yml` omits `version`, represented as `0.0.0`).
9
17
  It still rejects prerelease versions like `1.2.3-dev.abc`.
10
18
 
11
19
  This document focuses on user-facing behavior:
@@ -111,12 +119,12 @@ High-level flow:
111
119
  - Missing paths fail the push with a clear missing-path message.
112
120
  3. Tarball is narrowed to:
113
121
  - The requested file set.
114
- - `.openpackage/package.yml`.
122
+ - `openpackage.yml`.
115
123
  4. Upload uses the standard `/packages/push` endpoint.
116
124
 
117
125
  Notes:
118
126
  - This replaces the previous single-file `f` flow; single-file pushes are just partial pushes with one path.
119
- - Manifest is required; if `.openpackage/package.yml` is missing locally, the CLI errors.
127
+ - Manifest is required; if `openpackage.yml` is missing locally, the CLI errors.
120
128
 
121
129
 
122
130
  ## Stable-only guarantees (behavioral view)
@@ -42,7 +42,7 @@ Assuming a valid stable package `pkg` and `versionToPush` have been selected:
42
42
 
43
43
  - `createTarballFromPackage(pkg)` builds a tarball from the package files.
44
44
  - For **partial pushes** (paths provided via spec or `--paths`):
45
- - The tarball is narrowed to only the requested registry paths plus `.openpackage/package.yml`.
45
+ - The tarball is narrowed to only the requested registry paths plus `openpackage.yml`.
46
46
  - File count reflects only the selected files.
47
47
  - The CLI prints:
48
48
  - `✓ Creating tarball...`
@@ -18,7 +18,7 @@ This document describes how `push` handles scoping for upload. Scoping is applie
18
18
  - A scoped upload name is computed (e.g. `@user/test`) via the existing prompt/default-scope flow.
19
19
  - No local rename occurs; the local registry and workspace remain on the unscoped name.
20
20
  3. Before tarball creation:
21
- - The package is cloned in-memory and its `.openpackage/package.yml` `name` field is rewritten to the scoped upload name.
21
+ - The package is cloned in-memory and its `openpackage.yml` `name` field is rewritten to the scoped upload name.
22
22
  - The upload payload (full or partial) uses this in-memory manifest, so the remote receives the scoped identity.
23
23
  4. Version selection and path validation still operate on the local name and local files.
24
24
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  - **Stable version**: A semver-valid version with no prerelease segment, e.g. `1.2.3`.
6
6
  - **Prerelease version**: A semver-valid version with a prerelease segment, e.g. `1.2.3-dev.abc123`.
7
- - **Unversioned package**: A package whose `package.yml` omits `version`; represented and stored as semver `0.0.0` locally (one per package) and can be pushed like any other stable version.
7
+ - **Unversioned package**: A package whose `openpackage.yml` omits `version`; represented and stored as semver `0.0.0` locally (one per package) and can be pushed like any other stable version.
8
8
  - **Local registry**: The on-disk package store used by `opkg` (managed via `packageManager`).
9
9
 
10
10
  This document defines the rules `opkg push` uses to decide **which local version** is eligible to be pushed to the remote registry.
@@ -0,0 +1,111 @@
1
+ # Registry
2
+
3
+ The local registry stores **immutable, versioned package snapshots** for offline use, distribution, and caching. It uses directory-based storage for simplicity, analogous to a local npm or Docker registry (file-system only currently; remotes deferred).
4
+
5
+ ## Structure
6
+
7
+ Scoped, nested directories:
8
+
9
+ ```
10
+ ~/.openpackage/registry/
11
+ ├── <name>/ # Unscoped package
12
+ │ ├── <version>/ # e.g., 1.0.0 or WIP prerelease
13
+ │ │ ├── openpackage.yml # Manifest (version, deps)
14
+ │ │ ├── commands/ # Universal subdirs
15
+ │ │ ├── rules/
16
+ │ │ ├── AGENTS.md # Root files
17
+ │ │ └── root/ # Direct copy content
18
+ │ └── <version>/
19
+
20
+ └── @<scope>/ # Scoped
21
+ └── <name>/
22
+ └── <version>/
23
+ └── ...
24
+ ```
25
+
26
+ Each `<version>/` is a full, self-contained package copy (no links/extraction).
27
+
28
+ ## Why Directory-Based (vs. Tarballs)?
29
+
30
+ | Aspect | Directories | Tarballs |
31
+ |--------|-------------|----------|
32
+ | Simplicity | ✅ No extraction | ❌ Pack/unpack steps |
33
+ | Path Refs | ✅ Direct `path:` works | ❌ Cache + extract |
34
+ | Debugging | ✅ Browse files | ❌ Must unpack to inspect |
35
+ | Code Reuse | ✅ Same read logic as sources | ❌ Special handling |
36
+ | Storage | ⚠️ Uncompressed (text pkgs small) | ✅ Compressed |
37
+
38
+ The architecture prioritizes dev ergonomics over size.
39
+
40
+ ## Version Directory Contents (Payload)
41
+
42
+ Full package root; structural rules—no YAML filters.
43
+
44
+ - **Always**: `openpackage.yml`.
45
+ - **Universal Subdirs**: `commands/`, `rules/`, etc. (from platforms.jsonc).
46
+ - **Root Files**: `AGENTS.md`, platform variants (e.g., `CLAUDE.md` overrides).
47
+ - **root/**: 1:1 copy to workspace root (prefix stripped on install).
48
+ - **Other**: Docs (`README.md`), licenses, arbitrary files/dirs.
49
+
50
+ **Excludes**:
51
+ - `.openpackage/**` (metadata).
52
+ - `openpackage.index.yml` (workspace-local).
53
+ - `packages/**` (reserved).
54
+
55
+ Details: [Registry Payload and Copy](package/registry-payload-and-copy.md).
56
+
57
+ ## Operations
58
+
59
+ ### Creation (pack)
60
+ From mutable source to registry snapshot.
61
+
62
+ ```bash
63
+ opkg pack <name> # Copies source to registry/<name>/<version>/
64
+ ```
65
+
66
+ - Version from `openpackage.yml` or computed stable/WIP.
67
+ - Full dir copy; marks immutable.
68
+ - Options: `--output <path>` (direct copy, no <name>/<ver>); `--dry-run`.
69
+ - See [Pack](pack/).
70
+
71
+ ### Consumption (install, apply)
72
+ ```bash
73
+ opkg install <name>@<ver> # Resolves, copies from registry/<name>/<ver>/ to workspace
74
+ opkg apply <name> # Syncs from inferred path
75
+ ```
76
+
77
+ - Direct file access.
78
+ - Updates index/yml.
79
+ - See [Install](install/), [Apply](apply/).
80
+
81
+ ### Listing
82
+ ```bash
83
+ opkg list <name> # Versions from dir names
84
+ ```
85
+
86
+ ### Git Clones in Registry
87
+ Git deps cloned here → treated immutable (current behavior).
88
+
89
+ ## Immutability
90
+
91
+ - Registry dirs read-only: `save`/`add` detect and error.
92
+ - Re-pack overwrites entire dir (idempotent).
93
+ - No partial updates.
94
+
95
+ Error example:
96
+ ```
97
+ Error: Cannot save – source in registry (immutable).
98
+ Path: ~/.openpackage/registry/my-pkg/1.0.0/
99
+ Fix: Copy to packages/, update path.
100
+ ```
101
+
102
+ ## Scoping
103
+
104
+ Scoped: `registry/@org/my-pkg/<ver>/`; yml uses `@org/my-pkg`.
105
+
106
+ ## Remote Registries (Deferred)
107
+
108
+ Future: Push/pull tarballs for transfer; extract to local dir.
109
+ See [Push](push/) for upload prep; [Self-Hosted](self-hosted-registries.md) if created.
110
+
111
+ Cross-links: [Package Sources](package-sources.md) for resolution; [Directory Layout](directory-layout.md).