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
@@ -1,722 +1,47 @@
1
- import { join } from 'path';
2
- import * as semver from 'semver';
3
- import { parsePackageYml } from '../utils/package-yml.js';
4
- import { ensureRegistryDirectories, listPackageVersions } from '../core/directory.js';
5
- import { gatherGlobalVersionConstraints, gatherRootVersionConstraints } from '../core/openpackage.js';
6
- import { resolveDependencies } from '../core/dependency-resolver.js';
7
- import { registryManager } from '../core/registry.js';
8
- import { exists } from '../utils/fs.js';
9
- import { logger } from '../utils/logger.js';
10
1
  import { withErrorHandling, ValidationError } from '../utils/errors.js';
11
- import { getLocalPackageYmlPath, getLocalPackagesDir, getLocalOpenPackageDir, getInstallRootDir } from '../utils/paths.js';
12
- import { satisfiesVersion, isExactVersion, describeVersionRange } from '../utils/version-ranges.js';
13
- import { FILE_PATTERNS, DEPENDENCY_ARRAYS, } from '../constants/index.js';
14
- import { getPlatformDefinition, detectAllPlatforms } from '../core/platforms.js';
15
- import { findDirectoriesContainingFile } from '../utils/file-processing.js';
16
- import { discoverPackagesForStatus } from '../core/status/status-file-discovery.js';
17
- import { normalizePackageName } from '../utils/package-name.js';
18
- import { formatVersionLabel } from '../utils/package-versioning.js';
19
- /**
20
- * Scan local package metadata from .openpackage/packages directory
21
- * Recursively scans to handle scoped packages (e.g., @scope/name)
22
- */
23
- async function scanLocalPackageMetadata(cwd) {
24
- const packagesDir = getLocalPackagesDir(cwd);
25
- const localPackages = new Map();
26
- if (!(await exists(packagesDir))) {
27
- return localPackages;
28
- }
29
- try {
30
- // Use the generic recursive scanner to find all pkg.yml files
31
- const packageDirs = await findDirectoriesContainingFile(packagesDir, FILE_PATTERNS.PACKAGE_YML, async (filePath) => {
32
- try {
33
- return await parsePackageYml(filePath);
34
- }
35
- catch (error) {
36
- logger.warn(`Failed to parse local package metadata: ${filePath}`, { error });
37
- return null;
38
- }
39
- });
40
- // Build the map from results
41
- for (const result of packageDirs) {
42
- if (result.parsedContent) {
43
- localPackages.set(result.parsedContent.name, result.parsedContent);
44
- }
45
- }
46
- }
47
- catch (error) {
48
- logger.error('Failed to scan local package metadata', { error, packagesDir });
49
- }
50
- return localPackages;
51
- }
52
- /**
53
- * Detect platform status and configuration
54
- */
55
- async function detectPlatformStatus(cwd) {
56
- const detections = await detectAllPlatforms(cwd);
57
- const checks = detections.map(async ({ name, detected }) => {
58
- const def = getPlatformDefinition(name);
59
- const rootAbs = join(cwd, def.rootDir);
60
- const [dirExists] = await Promise.all([
61
- exists(rootAbs)
62
- ]);
63
- return {
64
- name,
65
- detected: detected && dirExists,
66
- configured: detected && dirExists,
67
- directoryExists: dirExists
68
- };
69
- });
70
- return Promise.all(checks);
71
- }
72
- /**
73
- * Check registry for available versions
74
- */
75
- async function checkRegistryVersions(packageName) {
76
- try {
77
- const [hasPackage, metadata, available] = await Promise.all([
78
- registryManager.hasPackage(packageName),
79
- registryManager.getPackageMetadata(packageName).catch(() => null),
80
- listPackageVersions(packageName).catch(() => [])
81
- ]);
82
- if (!hasPackage) {
83
- return { available: [] };
84
- }
85
- return {
86
- latest: metadata?.version,
87
- available: available || []
88
- };
89
- }
90
- catch (error) {
91
- logger.debug(`Failed to check registry for package ${packageName}`, { error });
92
- return { available: [] };
93
- }
94
- }
95
- /**
96
- * Analyze status of a single package with enhanced checks
97
- */
98
- async function analyzePackageStatus(requiredPackage, availablePackage, localMetadata, type, registryCheck = false) {
99
- const status = {
100
- name: requiredPackage.name,
101
- installedVersion: requiredPackage.version,
102
- type,
103
- status: 'missing'
104
- };
105
- // Check registry if requested
106
- if (registryCheck) {
107
- const registryInfo = await checkRegistryVersions(requiredPackage.name);
108
- status.registryVersion = registryInfo.latest;
109
- if (registryInfo.available.length === 0) {
110
- status.status = 'registry-unavailable';
111
- status.issues = [`Package '${requiredPackage.name}' not found in registry`];
112
- return status;
113
- }
114
- }
115
- // Case 1: Package not found by scanner
116
- if (!availablePackage) {
117
- if (localMetadata) {
118
- status.status = 'files-missing';
119
- status.issues = [`Package '${requiredPackage.name}' has local metadata but no files detected`];
120
- }
121
- else {
122
- status.status = 'missing';
123
- status.issues = [`Package '${requiredPackage.name}' not found`];
124
- }
125
- // Check for registry updates if available
126
- if (registryCheck && status.registryVersion && status.status === 'missing') {
127
- status.status = 'update-available';
128
- status.issues?.push(`Version ${status.registryVersion} available in registry`);
129
- }
130
- return status;
131
- }
132
- // Case 2: Package exists - compare versions
133
- status.availableVersion = localMetadata?.version || availablePackage.version;
134
- status.path = availablePackage.path;
135
- const requiredVersion = requiredPackage.version;
136
- const installedVersion = formatVersionLabel(availablePackage.version);
137
- // Ensure displayed version reflects the actual installed/detected version
138
- status.installedVersion = installedVersion;
139
- // If local metadata is missing, likely .openpackage/packages/<name>/pkg.yml is missing or misnamed
140
- if (!localMetadata) {
141
- status.status = 'files-missing';
142
- status.issues = [`'${FILE_PATTERNS.PACKAGE_YML}' is missing or misnamed`];
143
- // Avoid confusing 0.0.0 display when metadata is missing
144
- status.installedVersion = requiredVersion;
145
- return status;
146
- }
147
- if (!requiredVersion) {
148
- status.status = 'installed';
149
- return status;
150
- }
151
- // Support multiple constraints joined by ' & ' (logical AND)
152
- const requiredRanges = requiredVersion.includes('&')
153
- ? requiredVersion.split('&').map(s => s.trim()).filter(Boolean)
154
- : [requiredVersion];
155
- // Check version compatibility
156
- try {
157
- const satisfiesAll = requiredRanges.every(range => satisfiesVersion(installedVersion, range));
158
- if (satisfiesAll) {
159
- status.status = 'installed';
160
- // Check for registry updates if requested
161
- if (registryCheck &&
162
- status.registryVersion &&
163
- semver.valid(status.registryVersion) &&
164
- semver.valid(installedVersion) &&
165
- semver.gt(status.registryVersion, installedVersion)) {
166
- status.status = 'update-available';
167
- status.issues = [`Newer version ${status.registryVersion} available in registry`];
168
- }
169
- }
170
- else {
171
- // Determine version mismatch type
172
- if (requiredRanges.length === 1 &&
173
- isExactVersion(requiredRanges[0]) &&
174
- semver.valid(installedVersion) &&
175
- semver.valid(requiredRanges[0])) {
176
- status.status = semver.gt(installedVersion, requiredRanges[0]) ? 'outdated' : 'dependency-mismatch';
177
- const comparison = semver.gt(installedVersion, requiredRanges[0]) ? 'newer than' : 'older than';
178
- status.issues = [`Installed version ${installedVersion} is ${comparison} required ${requiredRanges[0]}`];
179
- }
180
- else {
181
- status.status = 'dependency-mismatch';
182
- status.issues = [
183
- `Installed version ${installedVersion} does not satisfy range ${requiredVersion} (${requiredRanges.map(describeVersionRange).join(' & ')})`
184
- ];
185
- }
186
- }
187
- }
188
- catch (error) {
189
- status.status = 'dependency-mismatch';
190
- status.issues = [`Version analysis failed: ${error}`];
191
- }
192
- // Validate local metadata consistency (only flag when exact version is required)
193
- if (localMetadata && localMetadata.version !== installedVersion && requiredVersion && isExactVersion(requiredVersion)) {
194
- status.issues = status.issues || [];
195
- status.issues.push(`Local metadata version ${localMetadata.version} differs from ai version ${installedVersion}`);
196
- if (status.status === 'installed') {
197
- status.status = 'structure-invalid';
198
- }
199
- }
200
- return status;
201
- }
202
- /**
203
- * Build dependency tree using install's dependency resolver
204
- */
205
- async function buildPackageDependencyTree(packageName, cwd, availablePackages, localMetadata, version, registryCheck = false) {
206
- try {
207
- // Use the install command's dependency resolver to get the complete tree
208
- const constraints = await gatherGlobalVersionConstraints(cwd);
209
- const rootConstraints = await gatherRootVersionConstraints(cwd);
210
- const result = await resolveDependencies(packageName, cwd, true, new Set(), new Map(), version, new Map(), constraints, rootConstraints);
211
- const resolvedPackages = result.resolvedPackages;
212
- const missingPackages = result.missingPackages;
213
- // Convert resolved packages to status info in parallel
214
- const dependencyPromises = resolvedPackages
215
- .filter(resolved => !resolved.isRoot) // Skip the root package
216
- .map(async (resolved) => {
217
- const availablePackage = availablePackages.get(resolved.name) || null;
218
- const localMeta = localMetadata.get(resolved.name) || null;
219
- const dependency = {
220
- name: resolved.name,
221
- version: resolved.requiredRange || resolved.version
222
- };
223
- const depStatus = await analyzePackageStatus(dependency, availablePackage, localMeta, 'dependency', registryCheck);
224
- if (resolved.conflictResolution) {
225
- depStatus.conflictResolution = resolved.conflictResolution;
226
- }
227
- return depStatus;
228
- });
229
- // Add status info for missing packages
230
- const missingPromises = missingPackages.map(async (missingName) => {
231
- const dependency = {
232
- name: missingName,
233
- version: 'latest'
234
- };
235
- return await analyzePackageStatus(dependency, null, // no available package
236
- null, // no local metadata
237
- 'dependency', registryCheck);
238
- });
239
- const allPromises = [...dependencyPromises, ...missingPromises];
240
- return Promise.all(allPromises);
241
- }
242
- catch (error) {
243
- logger.warn(`Failed to resolve dependencies for ${packageName}`, { error });
244
- // Fallback to basic dependency scanning
245
- const pkg = availablePackages.get(packageName);
246
- if (!pkg?.packages) {
247
- return [];
248
- }
249
- const fallbackPromises = pkg.packages.map(async (dep) => {
250
- const availableDep = availablePackages.get(dep.name) || null;
251
- const localMeta = localMetadata.get(dep.name) || null;
252
- return analyzePackageStatus(dep, availableDep, localMeta, 'dependency', registryCheck);
253
- });
254
- return Promise.all(fallbackPromises);
255
- }
256
- }
257
- /**
258
- * Perform complete status analysis with enhanced checks
259
- */
260
- async function performStatusAnalysis(cwd, options = {}) {
261
- // 1. Check basic project structure in parallel
262
- const [openpackageDir, packageYmlPath, packagesDir, aiDir] = [
263
- getLocalOpenPackageDir(cwd),
264
- getLocalPackageYmlPath(cwd),
265
- getLocalPackagesDir(cwd),
266
- getInstallRootDir(cwd)
267
- ];
268
- const [openpackageExists, packageYmlExists, packagesDirExists, aiDirExists] = await Promise.all([
269
- exists(openpackageDir),
270
- exists(packageYmlPath),
271
- exists(packagesDir),
272
- exists(aiDir)
273
- ]);
274
- if (!openpackageExists || !packageYmlExists) {
275
- throw new ValidationError(`No .openpackage/pkg.yml found in ${cwd}. This directory doesn't appear to be a package project.\n\n` +
276
- `💡 To initialize this as a package project:\n` +
277
- ` • Run 'opkg init' to create a new package project\n` +
278
- ` • Run 'opkg install' to install existing packages`);
279
- }
280
- // 2. Parse main pkg.yml and detect platforms in parallel
281
- const [cwdConfig, platformStatuses] = await Promise.all([
282
- parsePackageYml(packageYmlPath).catch(error => {
283
- throw new ValidationError(`Failed to parse pkg.yml: ${error}`);
284
- }),
285
- options.platforms ? detectPlatformStatus(cwd) : Promise.resolve([])
286
- ]);
287
- // 3. Discover installed files using same method as uninstall and read local metadata in parallel
288
- // First collect all package names including dependencies
289
- const packageNames = new Set([
290
- ...(cwdConfig.packages || []).map(f => normalizePackageName(f.name)),
291
- ...(cwdConfig[DEPENDENCY_ARRAYS.PACKAGES] || []).map(f => normalizePackageName(f.name))
292
- ]);
293
- // Resolve dependencies for each package to get their names
294
- for (const pkg of cwdConfig.packages || []) {
295
- try {
296
- const constraints = await gatherGlobalVersionConstraints(cwd);
297
- const rootConstraints = await gatherRootVersionConstraints(cwd);
298
- const result = await resolveDependencies(pkg.name, cwd, true, new Set(), new Map(), pkg.version, new Map(), constraints, rootConstraints);
299
- const resolvedPackages = result.resolvedPackages;
300
- const missingPackages = result.missingPackages;
301
- // Add all resolved dependency names to the set
302
- for (const resolved of resolvedPackages) {
303
- if (!resolved.isRoot) {
304
- packageNames.add(normalizePackageName(resolved.name));
305
- }
306
- }
307
- // Add missing package names to the set
308
- for (const missing of missingPackages) {
309
- packageNames.add(normalizePackageName(missing));
310
- }
311
- }
312
- catch (error) {
313
- logger.debug(`Failed to resolve dependencies for ${pkg.name}`, { error });
314
- }
315
- }
316
- const [detectedByFrontmatter, localMetadata] = await Promise.all([
317
- discoverPackagesForStatus(Array.from(packageNames)),
318
- scanLocalPackageMetadata(cwd)
319
- ]);
320
- // Build availability map using detection results, preferring metadata versions when present
321
- const availablePackages = new Map();
322
- for (const [name, det] of detectedByFrontmatter) {
323
- const meta = localMetadata.get(name);
324
- availablePackages.set(name, {
325
- name,
326
- version: meta?.version || '0.0.0',
327
- path: det.anyPath || join(aiDir, name)
328
- });
329
- }
330
- // 4. Analyze all packages in parallel
331
- const allPackages = [
332
- ...(cwdConfig.packages || []).map(f => ({ ...f, type: 'package' })),
333
- ...(cwdConfig[DEPENDENCY_ARRAYS.DEV_PACKAGES] || []).map(f => ({ ...f, type: 'dev-package' }))
334
- ];
335
- const analysisPromises = allPackages.map(async (pkg) => {
336
- const available = availablePackages.get(pkg.name) || null;
337
- const localMeta = localMetadata.get(pkg.name) || null;
338
- const status = await analyzePackageStatus(pkg, available, localMeta, pkg.type, options.registry);
339
- const detected = detectedByFrontmatter.get(pkg.name);
340
- if (detected) {
341
- status.fileSummary = {
342
- aiFiles: { found: detected.aiFiles.length, paths: detected.aiFiles },
343
- platformFiles: detected.platforms,
344
- rootFiles: detected.rootFiles ? { found: detected.rootFiles.length, paths: detected.rootFiles } : undefined
345
- };
346
- }
347
- // Build dependency tree if installed
348
- if (status.status === 'installed') {
349
- try {
350
- status.dependencies = await buildPackageDependencyTree(pkg.name, cwd, availablePackages, localMetadata, pkg.version, options.registry);
351
- }
352
- catch (error) {
353
- logger.warn(`Failed to build dependency tree for ${pkg.name}`, { error });
354
- status.issues = status.issues || [];
355
- status.issues.push(`Dependency analysis failed: ${error}`);
356
- }
357
- }
358
- return status;
359
- });
360
- const results = await Promise.all(analysisPromises);
361
- // 5. Build project status
362
- const projectInfo = {
363
- name: cwdConfig.name,
364
- version: cwdConfig.version,
365
- openpackageExists,
366
- packageYmlExists,
367
- packagesDirectoryExists: packagesDirExists,
368
- aiDirectoryExists: aiDirExists,
369
- platforms: platformStatuses
370
- };
371
- return {
372
- projectInfo,
373
- packages: results
374
- };
375
- }
376
- /**
377
- * Render enhanced tree view of packages with status
378
- */
379
- function renderTreeView(projectInfo, packages, options = {}) {
380
- // Project header with status indicators
381
- const statusIndicators = [
382
- !projectInfo.openpackageExists && '❌ .openpackage missing',
383
- !projectInfo.packageYmlExists && '❌ pkg.yml missing',
384
- !projectInfo.aiDirectoryExists && '⚠️ ai directory missing'
385
- ].filter(Boolean);
386
- const statusSuffix = statusIndicators.length > 0 ? ` (${statusIndicators.join(', ')})` : '';
387
- console.log(`${projectInfo.name}@${projectInfo.version}${statusSuffix}`);
388
- // Platform information if requested
389
- if (options.platforms && projectInfo.platforms.length > 0) {
390
- console.log('\n✓ Platforms:');
391
- for (const platform of projectInfo.platforms) {
392
- const status = platform.detected ? '✅' : '❌';
393
- console.log(` ${status} ${platform.name}`);
394
- }
395
- }
396
- if (packages.length === 0) {
397
- console.log('\n└── (no packages)');
398
- return;
399
- }
400
- packages.forEach((pkg, i) => {
401
- const isLast = i === packages.length - 1;
402
- renderPackageTree(pkg, '', isLast, options.depth, 1);
403
- });
404
- }
405
- /**
406
- * Status icon and suffix mapping
407
- */
408
- const STATUS_ICONS = {
409
- 'installed': '✅',
410
- 'missing': '❌',
411
- 'outdated': '⚠️',
412
- 'dependency-mismatch': '❌',
413
- 'update-available': '🔄',
414
- 'registry-unavailable': '⚠️',
415
- 'structure-invalid': '⚠️',
416
- 'platform-mismatch': '⚠️',
417
- 'files-missing': '⚠️',
418
- 'orphaned-files': '⚠️',
419
- 'frontmatter-mismatch': '⚠️'
420
- };
421
- /**
422
- * Get status suffix for display
423
- */
424
- function getStatusSuffix(pkg) {
425
- switch (pkg.status) {
426
- case 'missing':
427
- return ' (missing)';
428
- case 'outdated':
429
- return ` (outdated: ${pkg.availableVersion} available)`;
430
- case 'dependency-mismatch':
431
- return ' (version mismatch)';
432
- case 'update-available':
433
- return pkg.registryVersion ? ` (update: ${pkg.registryVersion})` : ' (update available)';
434
- case 'registry-unavailable':
435
- return ' (not in registry)';
436
- case 'structure-invalid':
437
- return ' (structure issue)';
438
- case 'platform-mismatch':
439
- return ' (platform issue)';
440
- case 'files-missing':
441
- return ' (files missing)';
442
- case 'orphaned-files':
443
- return ' (orphaned files)';
444
- case 'frontmatter-mismatch':
445
- return ' (frontmatter mismatch)';
446
- default:
447
- return '';
448
- }
449
- }
450
- /**
451
- * Render individual package in enhanced tree format
452
- */
453
- function renderPackageTree(pkg, prefix, isLast, maxDepth, currentDepth = 1) {
454
- const connector = isLast ? '└── ' : '├── ';
455
- const typePrefix = pkg.type === 'dev-package' ? '[dev] ' : '';
456
- const statusIcon = STATUS_ICONS[pkg.status] || '❓';
457
- const statusSuffix = getStatusSuffix(pkg);
458
- const conflictInfo = pkg.conflictResolution ? ` [${pkg.conflictResolution}]` : '';
459
- const installedLabel = formatVersionLabel(pkg.installedVersion);
460
- console.log(`${prefix}${connector}${statusIcon} ${typePrefix}${pkg.name}@${installedLabel}${statusSuffix}${conflictInfo}`);
461
- // Show issues if any
462
- if (pkg.issues?.length) {
463
- const issuePrefix = prefix + (isLast ? ' ' : '│ ');
464
- pkg.issues.forEach(issue => {
465
- console.log(`${issuePrefix}⚠️ ${issue}`);
466
- });
467
- }
468
- // Optional file-level summary (verbose)
469
- if (pkg.fileSummary && globalThis.__statusVerbose) {
470
- const fsPrefix = prefix + (isLast ? ' ' : '│ ');
471
- const fs = pkg.fileSummary;
472
- console.log(`${fsPrefix}📄 ai files: ${fs.aiFiles.found}`);
473
- const platforms = Object.keys(fs.platformFiles || {});
474
- if (platforms.length > 0) {
475
- console.log(`${fsPrefix}🖥️ platform files:`);
476
- for (const p of platforms) {
477
- const pf = fs.platformFiles[p] || {};
478
- const parts = [];
479
- if (pf.rules?.found)
480
- parts.push(`rules:${pf.rules.found}`);
481
- if (pf.commands?.found)
482
- parts.push(`commands:${pf.commands.found}`);
483
- if (pf.agents?.found)
484
- parts.push(`agents:${pf.agents.found}`);
485
- console.log(`${fsPrefix} - ${p} ${parts.length ? `(${parts.join(', ')})` : ''}`);
486
- }
487
- }
488
- if (fs.rootFiles && fs.rootFiles.found > 0) {
489
- console.log(`${fsPrefix}📁 root files: ${fs.rootFiles.found}`);
490
- }
491
- }
492
- // Show dependencies if within depth limit
493
- if (pkg.dependencies?.length) {
494
- if (!maxDepth || currentDepth < maxDepth) {
495
- const childPrefix = prefix + (isLast ? ' ' : '│ ');
496
- pkg.dependencies.forEach((dep, j) => {
497
- const isLastChild = j === pkg.dependencies.length - 1;
498
- renderPackageTree(dep, childPrefix, isLastChild, maxDepth, currentDepth + 1);
499
- });
500
- }
501
- else {
502
- const childPrefix = prefix + (isLast ? ' ' : '│ ');
503
- console.log(`${childPrefix}└── (${pkg.dependencies.length} dependencies - use --depth to see more)`);
504
- }
505
- }
506
- }
507
- /**
508
- * Collect all packages including dependencies recursively
509
- */
510
- function collectAllPackages(packages) {
511
- const allPackages = [];
512
- function collect(packageList) {
513
- for (const pkg of packageList) {
514
- allPackages.push(pkg);
515
- if (pkg.dependencies) {
516
- collect(pkg.dependencies);
517
- }
518
- }
519
- }
520
- collect(packages);
521
- return allPackages;
522
- }
523
- /**
524
- * Render enhanced flat table view of packages
525
- */
526
- function renderFlatView(packages, options = {}) {
527
- if (packages.length === 0) {
528
- console.log('No packages found.');
529
- return;
530
- }
531
- const allPackages = collectAllPackages(packages);
532
- // Enhanced table header
533
- const headers = ['FORMULA', 'INSTALLED', 'STATUS', 'TYPE'];
534
- const widths = [20, 12, 18, 15];
535
- if (options.registry) {
536
- headers.push('REGISTRY');
537
- widths.push(12);
538
- }
539
- headers.push('ISSUES');
540
- widths.push(30);
541
- // Print header
542
- console.log(headers.map((h, i) => h.padEnd(widths[i])).join(''));
543
- console.log(headers.map((_, i) => '-'.repeat(widths[i] - 1).padEnd(widths[i])).join(''));
544
- // Display each package
545
- allPackages.forEach(pkg => {
546
- const values = [
547
- pkg.name.padEnd(widths[0]),
548
- (pkg.installedVersion ?? '').padEnd(widths[1]),
549
- pkg.status.padEnd(widths[2]),
550
- pkg.type.padEnd(widths[3])
551
- ];
552
- if (options.registry) {
553
- values.push((pkg.registryVersion || '-').padEnd(widths[4]));
554
- }
555
- const issues = pkg.issues ? pkg.issues.slice(0, 2).join('; ') : '-';
556
- values.push(issues.length > 27 ? issues.substring(0, 24) + '...' : issues);
557
- console.log(values.join(''));
558
- });
559
- console.log('\nTotal: ${allPackages.length} packages');
560
- // Summary by status
561
- const statusCounts = new Map();
562
- allPackages.forEach(pkg => {
563
- statusCounts.set(pkg.status, (statusCounts.get(pkg.status) || 0) + 1);
564
- });
565
- console.log('\nStatus Summary:');
566
- statusCounts.forEach((count, status) => {
567
- console.log(` ${status}: ${count}`);
568
- });
569
- }
570
- /**
571
- * Calculate status counts efficiently
572
- */
573
- function calculateStatusCounts(packages) {
574
- const counts = {
575
- installed: 0,
576
- missing: 0,
577
- outdated: 0,
578
- mismatch: 0,
579
- updateAvailable: 0,
580
- registryUnavailable: 0,
581
- structureInvalid: 0
582
- };
583
- packages.forEach(pkg => {
584
- switch (pkg.status) {
585
- case 'installed':
586
- counts.installed++;
587
- break;
588
- case 'missing':
589
- counts.missing++;
590
- break;
591
- case 'outdated':
592
- counts.outdated++;
593
- break;
594
- case 'dependency-mismatch':
595
- counts.mismatch++;
596
- break;
597
- case 'update-available':
598
- counts.updateAvailable++;
599
- break;
600
- case 'registry-unavailable':
601
- counts.registryUnavailable++;
602
- break;
603
- case 'structure-invalid':
604
- counts.structureInvalid++;
605
- break;
606
- }
607
- });
608
- return counts;
609
- }
610
- /**
611
- * Display status summary and recommendations
612
- */
613
- function displayStatusSummary(packages, statusCounts) {
614
- const totalPackages = packages.length;
615
- console.log(`Summary: ${statusCounts.installed}/${totalPackages} installed`);
616
- if (statusCounts.missing > 0) {
617
- console.log(`❌ ${statusCounts.missing} packages missing from ai directory`);
618
- }
619
- if (statusCounts.mismatch > 0) {
620
- console.log(`⚠️ ${statusCounts.mismatch} packages have version mismatches`);
621
- }
622
- if (statusCounts.updateAvailable > 0) {
623
- console.log(`✓ ${statusCounts.updateAvailable} packages have updates available`);
624
- }
625
- if (statusCounts.registryUnavailable > 0) {
626
- console.log(`⚠️ ${statusCounts.registryUnavailable} packages not found in registry`);
627
- }
628
- if (statusCounts.structureInvalid > 0) {
629
- console.log(`⚠️ ${statusCounts.structureInvalid} packages have structure issues`);
630
- }
631
- // Show actionable recommendations
632
- if (totalPackages === 0) {
633
- console.log('');
634
- console.log('💡 Tips:');
635
- console.log('• Add packages to pkg.yml and run "opkg install" to install them');
636
- console.log('• Use "opkg list" to see available packages in the registry');
637
- console.log('• Run "opkg init" to initialize this as a package project');
638
- }
639
- else {
640
- const hasIssues = statusCounts.missing + statusCounts.mismatch + statusCounts.structureInvalid > 0;
641
- if (hasIssues) {
642
- console.log('');
643
- console.log('💡 Recommended actions:');
644
- if (statusCounts.missing > 0) {
645
- console.log('• Run "opkg install" to install missing packages');
646
- }
647
- if (statusCounts.updateAvailable > 0) {
648
- console.log('• Run "opkg install --force <package-name>" to update specific packages');
649
- }
650
- if (statusCounts.structureInvalid > 0) {
651
- console.log('• Run "opkg install --force" to repair structure issues');
652
- }
653
- if (statusCounts.registryUnavailable > 0) {
654
- console.log('• Check if missing packages exist in remote registry with "opkg search"');
655
- }
2
+ import { runStatusPipeline } from '../core/status/status-pipeline.js';
3
+ import { logger } from '../utils/logger.js';
4
+ function printPackageLine(pkg, verbose) {
5
+ const icon = pkg.state === 'synced' ? '✅' : pkg.state === 'missing' ? '❌' : '⚠️';
6
+ const version = pkg.version ? `@${pkg.version}` : '';
7
+ console.log(`${icon} ${pkg.name}${version} ${pkg.state} ${pkg.path}`);
8
+ if (verbose && pkg.diffs.length > 0) {
9
+ for (const diff of pkg.diffs) {
10
+ const reason = diff.reason === 'missing' ? 'missing' : 'changed';
11
+ console.log(` - ${reason}: ${diff.workspacePath || diff.sourcePath}`);
656
12
  }
657
13
  }
658
14
  }
659
- /**
660
- * Enhanced status command implementation with comprehensive analysis
661
- */
662
15
  async function statusCommand(options = {}) {
663
16
  const cwd = process.cwd();
664
- logger.info(`Checking package status for directory: ${cwd}`, { options });
665
- // Set a global verbose flag for renderer (avoids threading through many calls)
666
- globalThis.__statusVerbose = Boolean(options.verbose);
667
- // Ensure registry directories exist
668
- await ensureRegistryDirectories();
17
+ logger.info(`Checking package status for directory: ${cwd}`);
669
18
  try {
670
- const { projectInfo, packages } = await performStatusAnalysis(cwd, {
671
- registry: options.registry,
672
- platforms: options.platforms
673
- });
674
- // Display results
19
+ const result = await runStatusPipeline();
20
+ const packages = result.data?.packages ?? [];
675
21
  console.log(`✓ Package status for: ${cwd}`);
676
- if (options.flat) {
677
- renderFlatView(packages, { registry: options.registry });
22
+ if (packages.length === 0) {
23
+ console.log('(no packages in index)');
24
+ return { success: true, data: { packages: [] } };
678
25
  }
679
- else {
680
- renderTreeView(projectInfo, packages, {
681
- depth: options.depth,
682
- platforms: options.platforms
683
- });
26
+ for (const pkg of packages) {
27
+ printPackageLine(pkg, Boolean(options.verbose));
684
28
  }
685
- // Calculate and display status summary
686
- const statusCounts = calculateStatusCounts(packages);
687
- displayStatusSummary(packages, statusCounts);
688
- // Show repair suggestions if requested
689
- if (options.repair) {
690
- console.log('✓ Repair suggestions:');
691
- // TODO: Add specific repair recommendations based on issues found
692
- }
693
- return {
694
- success: true,
695
- data: {
696
- projectInfo,
697
- packages,
698
- summary: statusCounts
699
- }
700
- };
29
+ const synced = packages.filter(p => p.state === 'synced').length;
30
+ console.log(`Summary: ${synced}/${packages.length} synced`);
31
+ return { success: true, data: { packages } };
701
32
  }
702
33
  catch (error) {
703
- logger.error('Status command failed', { error, cwd });
34
+ if (error instanceof ValidationError) {
35
+ throw error;
36
+ }
704
37
  throw error;
705
38
  }
706
39
  }
707
- /**
708
- * Setup the enhanced status command
709
- */
710
40
  export function setupStatusCommand(program) {
711
41
  program
712
42
  .command('status')
713
- .description('Show comprehensive package status for the current project (ai files, platform templates, and dependencies)')
714
- .option('--flat', 'show flat table view instead of tree view')
715
- .option('--depth <number>', 'limit tree depth (default: unlimited)', parseInt)
716
- .option('--registry', 'check registry for available updates')
717
- .option('--platforms', 'show platform-specific status information')
718
- .option('--repair', 'show repair suggestions without applying them')
719
- .option('--verbose', 'show file-level details')
43
+ .description('Show package sync state')
44
+ .option('--verbose', 'show file-level differences')
720
45
  .action(withErrorHandling(async (options) => {
721
46
  await statusCommand(options);
722
47
  }));