opkg 0.5.0 → 0.6.1

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 (397) hide show
  1. package/README.md +82 -21
  2. package/dist/commands/add.js +11 -276
  3. package/dist/commands/add.js.map +1 -1
  4. package/dist/commands/duplicate.js +5 -2
  5. package/dist/commands/duplicate.js.map +1 -1
  6. package/dist/commands/init.js +76 -145
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/install.js +30 -671
  9. package/dist/commands/install.js.map +1 -1
  10. package/dist/commands/list.js +9 -3
  11. package/dist/commands/list.js.map +1 -1
  12. package/dist/commands/login.js +58 -0
  13. package/dist/commands/login.js.map +1 -0
  14. package/dist/commands/logout.js +28 -0
  15. package/dist/commands/logout.js.map +1 -0
  16. package/dist/commands/pack.js +10 -137
  17. package/dist/commands/pack.js.map +1 -1
  18. package/dist/commands/pull.js +5 -299
  19. package/dist/commands/pull.js.map +1 -1
  20. package/dist/commands/push.js +5 -239
  21. package/dist/commands/push.js.map +1 -1
  22. package/dist/commands/save.js +29 -168
  23. package/dist/commands/save.js.map +1 -1
  24. package/dist/commands/show.js +18 -5
  25. package/dist/commands/show.js.map +1 -1
  26. package/dist/commands/status.js +21 -8
  27. package/dist/commands/status.js.map +1 -1
  28. package/dist/commands/tui.js +61 -0
  29. package/dist/commands/tui.js.map +1 -0
  30. package/dist/commands/uninstall.js +5 -5
  31. package/dist/commands/uninstall.js.map +1 -1
  32. package/dist/constants/index.js +19 -45
  33. package/dist/constants/index.js.map +1 -1
  34. package/dist/constants/workspace.js +9 -0
  35. package/dist/constants/workspace.js.map +1 -0
  36. package/dist/core/add/add-conflict-handler.js +68 -0
  37. package/dist/core/add/add-conflict-handler.js.map +1 -0
  38. package/dist/core/add/add-pipeline.js +137 -0
  39. package/dist/core/add/add-pipeline.js.map +1 -0
  40. package/dist/core/add/package-index-updater.js +66 -36
  41. package/dist/core/add/package-index-updater.js.map +1 -1
  42. package/dist/core/add/platform-path-transformer.js +47 -0
  43. package/dist/core/add/platform-path-transformer.js.map +1 -0
  44. package/dist/core/add/source-collector.js +57 -0
  45. package/dist/core/add/source-collector.js.map +1 -0
  46. package/dist/core/api-keys.js +6 -2
  47. package/dist/core/api-keys.js.map +1 -1
  48. package/dist/core/auth.js +25 -40
  49. package/dist/core/auth.js.map +1 -1
  50. package/dist/core/config.js +11 -3
  51. package/dist/core/config.js.map +1 -1
  52. package/dist/core/dependency-resolver.js +24 -11
  53. package/dist/core/dependency-resolver.js.map +1 -1
  54. package/dist/core/device-auth.js +81 -0
  55. package/dist/core/device-auth.js.map +1 -0
  56. package/dist/core/directory.js +15 -9
  57. package/dist/core/directory.js.map +1 -1
  58. package/dist/core/discovery/file-discovery.js +55 -54
  59. package/dist/core/discovery/file-discovery.js.map +1 -1
  60. package/dist/core/discovery/platform-files-discovery.js +32 -17
  61. package/dist/core/discovery/platform-files-discovery.js.map +1 -1
  62. package/dist/core/install/bulk-install-pipeline.js +200 -0
  63. package/dist/core/install/bulk-install-pipeline.js.map +1 -0
  64. package/dist/core/install/canonical-plan.js +129 -0
  65. package/dist/core/install/canonical-plan.js.map +1 -0
  66. package/dist/core/install/download-keys.js +2 -2
  67. package/dist/core/install/download-keys.js.map +1 -1
  68. package/dist/core/install/dry-run.js +2 -2
  69. package/dist/core/install/dry-run.js.map +1 -1
  70. package/dist/core/install/index.js +3 -0
  71. package/dist/core/install/index.js.map +1 -0
  72. package/dist/core/install/install-errors.js +41 -0
  73. package/dist/core/install/install-errors.js.map +1 -0
  74. package/dist/core/install/install-flow.js +8 -9
  75. package/dist/core/install/install-flow.js.map +1 -1
  76. package/dist/core/install/install-pipeline.js +296 -0
  77. package/dist/core/install/install-pipeline.js.map +1 -0
  78. package/dist/core/install/install-reporting.js +99 -0
  79. package/dist/core/install/install-reporting.js.map +1 -0
  80. package/dist/core/install/platform-resolution.js +6 -6
  81. package/dist/core/install/platform-resolution.js.map +1 -1
  82. package/dist/core/install/remote-flow.js +84 -7
  83. package/dist/core/install/remote-flow.js.map +1 -1
  84. package/dist/core/install/version-selection.js +25 -8
  85. package/dist/core/install/version-selection.js.map +1 -1
  86. package/dist/core/openpackage.js +22 -14
  87. package/dist/core/openpackage.js.map +1 -1
  88. package/dist/core/package-context.js +246 -0
  89. package/dist/core/package-context.js.map +1 -0
  90. package/dist/core/package.js +73 -9
  91. package/dist/core/package.js.map +1 -1
  92. package/dist/core/platforms.js +126 -217
  93. package/dist/core/platforms.js.map +1 -1
  94. package/dist/core/profiles.js +60 -3
  95. package/dist/core/profiles.js.map +1 -1
  96. package/dist/core/pull/pull-errors.js +62 -0
  97. package/dist/core/pull/pull-errors.js.map +1 -0
  98. package/dist/core/pull/pull-options.js +2 -0
  99. package/dist/core/pull/pull-options.js.map +1 -0
  100. package/dist/core/pull/pull-output.js +50 -0
  101. package/dist/core/pull/pull-output.js.map +1 -0
  102. package/dist/core/pull/pull-pipeline.js +141 -0
  103. package/dist/core/pull/pull-pipeline.js.map +1 -0
  104. package/dist/core/pull/pull-strategies.js +103 -0
  105. package/dist/core/pull/pull-strategies.js.map +1 -0
  106. package/dist/core/pull/pull-types.js +2 -0
  107. package/dist/core/pull/pull-types.js.map +1 -0
  108. package/dist/core/push/push-context.js +95 -0
  109. package/dist/core/push/push-context.js.map +1 -0
  110. package/dist/core/push/push-errors.js +133 -0
  111. package/dist/core/push/push-errors.js.map +1 -0
  112. package/dist/core/push/push-output.js +44 -0
  113. package/dist/core/push/push-output.js.map +1 -0
  114. package/dist/core/push/push-pipeline.js +74 -0
  115. package/dist/core/push/push-pipeline.js.map +1 -0
  116. package/dist/core/push/push-single-file.js +56 -0
  117. package/dist/core/push/push-single-file.js.map +1 -0
  118. package/dist/core/push/push-types.js +2 -0
  119. package/dist/core/push/push-types.js.map +1 -0
  120. package/dist/core/push/push-upload.js +68 -0
  121. package/dist/core/push/push-upload.js.map +1 -0
  122. package/dist/core/registry/registry-rename.js +2 -1
  123. package/dist/core/registry/registry-rename.js.map +1 -1
  124. package/dist/core/registry.js +14 -5
  125. package/dist/core/registry.js.map +1 -1
  126. package/dist/core/remote-pull.js +165 -36
  127. package/dist/core/remote-pull.js.map +1 -1
  128. package/dist/core/save/constants.js +4 -0
  129. package/dist/core/save/constants.js.map +1 -1
  130. package/dist/core/save/name-resolution.js +31 -0
  131. package/dist/core/save/name-resolution.js.map +1 -0
  132. package/dist/core/save/package-detection.js +147 -0
  133. package/dist/core/save/package-detection.js.map +1 -0
  134. package/dist/core/save/package-saver.js +82 -43
  135. package/dist/core/save/package-saver.js.map +1 -1
  136. package/dist/core/save/package-yml-generator.js +51 -71
  137. package/dist/core/save/package-yml-generator.js.map +1 -1
  138. package/dist/core/save/root-save-candidates.js.map +1 -1
  139. package/dist/core/save/save-candidate-loader.js +89 -0
  140. package/dist/core/save/save-candidate-loader.js.map +1 -0
  141. package/dist/core/save/save-conflict-resolution.js +72 -410
  142. package/dist/core/save/save-conflict-resolution.js.map +1 -1
  143. package/dist/core/save/save-conflict-resolver.js +277 -0
  144. package/dist/core/save/save-conflict-resolver.js.map +1 -0
  145. package/dist/core/save/save-pipeline.js +162 -0
  146. package/dist/core/save/save-pipeline.js.map +1 -0
  147. package/dist/core/save/save-single-file.js +124 -0
  148. package/dist/core/save/save-single-file.js.map +1 -0
  149. package/dist/core/save/save-types.js +2 -0
  150. package/dist/core/save/save-types.js.map +1 -0
  151. package/dist/core/save/save-yml-resolution.js +77 -39
  152. package/dist/core/save/save-yml-resolution.js.map +1 -1
  153. package/dist/core/save/workspace-rename.js +6 -6
  154. package/dist/core/save/workspace-rename.js.map +1 -1
  155. package/dist/core/scoping/package-scoping.js +14 -2
  156. package/dist/core/scoping/package-scoping.js.map +1 -1
  157. package/dist/core/status/status-file-discovery.js +12 -30
  158. package/dist/core/status/status-file-discovery.js.map +1 -1
  159. package/dist/core/sync/platform-sync.js +7 -4
  160. package/dist/core/sync/platform-sync.js.map +1 -1
  161. package/dist/core/sync/root-files-sync.js +59 -1
  162. package/dist/core/sync/root-files-sync.js.map +1 -1
  163. package/dist/core/token-store.js +73 -0
  164. package/dist/core/token-store.js.map +1 -0
  165. package/dist/core/uninstall/uninstall-file-discovery.js +1 -2
  166. package/dist/core/uninstall/uninstall-file-discovery.js.map +1 -1
  167. package/dist/index.js +4 -0
  168. package/dist/index.js.map +1 -1
  169. package/dist/tui/app.js +95 -0
  170. package/dist/tui/app.js.map +1 -0
  171. package/dist/tui/components/package-list.js +73 -0
  172. package/dist/tui/components/package-list.js.map +1 -0
  173. package/dist/tui/controller.js +365 -0
  174. package/dist/tui/controller.js.map +1 -0
  175. package/dist/tui/index.js +12 -0
  176. package/dist/tui/index.js.map +1 -0
  177. package/dist/tui/services/file-index.js +64 -0
  178. package/dist/tui/services/file-index.js.map +1 -0
  179. package/dist/tui/services/packages.js +18 -0
  180. package/dist/tui/services/packages.js.map +1 -0
  181. package/dist/tui/services/save.js +21 -0
  182. package/dist/tui/services/save.js.map +1 -0
  183. package/dist/tui/state/app-state.js +15 -0
  184. package/dist/tui/state/app-state.js.map +1 -0
  185. package/dist/tui/state.js +17 -0
  186. package/dist/tui/state.js.map +1 -0
  187. package/dist/tui/types.js +2 -0
  188. package/dist/tui/types.js.map +1 -0
  189. package/dist/tui/views/add-file-modal.js +129 -0
  190. package/dist/tui/views/add-file-modal.js.map +1 -0
  191. package/dist/tui/views/file-preview.js +44 -0
  192. package/dist/tui/views/file-preview.js.map +1 -0
  193. package/dist/tui/views/list-packages.js +73 -0
  194. package/dist/tui/views/list-packages.js.map +1 -0
  195. package/dist/tui/views/main-menu.js +29 -0
  196. package/dist/tui/views/main-menu.js.map +1 -0
  197. package/dist/tui/views/manage-view.js +81 -0
  198. package/dist/tui/views/manage-view.js.map +1 -0
  199. package/dist/tui/views/package-hub.js +120 -0
  200. package/dist/tui/views/package-hub.js.map +1 -0
  201. package/dist/tui/views/placeholder.js +24 -0
  202. package/dist/tui/views/placeholder.js.map +1 -0
  203. package/dist/types/index.js.map +1 -1
  204. package/dist/utils/bun-bootstrap.js +72 -0
  205. package/dist/utils/bun-bootstrap.js.map +1 -0
  206. package/dist/utils/file-processing.js +5 -58
  207. package/dist/utils/file-processing.js.map +1 -1
  208. package/dist/utils/formatters.js +3 -1
  209. package/dist/utils/formatters.js.map +1 -1
  210. package/dist/utils/http-client.js +27 -5
  211. package/dist/utils/http-client.js.map +1 -1
  212. package/dist/utils/index-based-installer.js +40 -35
  213. package/dist/utils/index-based-installer.js.map +1 -1
  214. package/dist/utils/install-file-discovery.js +18 -24
  215. package/dist/utils/install-file-discovery.js.map +1 -1
  216. package/dist/utils/install-orchestrator.js +21 -21
  217. package/dist/utils/install-orchestrator.js.map +1 -1
  218. package/dist/utils/jsonc.js +44 -0
  219. package/dist/utils/jsonc.js.map +1 -0
  220. package/dist/utils/manifest-paths.js +27 -0
  221. package/dist/utils/manifest-paths.js.map +1 -0
  222. package/dist/utils/package-copy.js +199 -0
  223. package/dist/utils/package-copy.js.map +1 -0
  224. package/dist/utils/package-filters.js +125 -0
  225. package/dist/utils/package-filters.js.map +1 -0
  226. package/dist/utils/package-index-yml.js +15 -10
  227. package/dist/utils/package-index-yml.js.map +1 -1
  228. package/dist/utils/package-installation.js +4 -113
  229. package/dist/utils/package-installation.js.map +1 -1
  230. package/dist/utils/package-local-files.js +2 -35
  231. package/dist/utils/package-local-files.js.map +1 -1
  232. package/dist/utils/package-management.js +191 -75
  233. package/dist/utils/package-management.js.map +1 -1
  234. package/dist/utils/package-merge.js +48 -0
  235. package/dist/utils/package-merge.js.map +1 -0
  236. package/dist/utils/package-name.js +29 -0
  237. package/dist/utils/package-name.js.map +1 -1
  238. package/dist/utils/package-versioning.js +16 -4
  239. package/dist/utils/package-versioning.js.map +1 -1
  240. package/dist/utils/package-yml.js +41 -12
  241. package/dist/utils/package-yml.js.map +1 -1
  242. package/dist/utils/path-normalization.js +8 -53
  243. package/dist/utils/path-normalization.js.map +1 -1
  244. package/dist/utils/paths.js +17 -9
  245. package/dist/utils/paths.js.map +1 -1
  246. package/dist/utils/platform-file.js +16 -59
  247. package/dist/utils/platform-file.js.map +1 -1
  248. package/dist/utils/platform-mapper.js +29 -41
  249. package/dist/utils/platform-mapper.js.map +1 -1
  250. package/dist/utils/platform-specific-paths.js.map +1 -1
  251. package/dist/utils/platform-utils.js +28 -139
  252. package/dist/utils/platform-utils.js.map +1 -1
  253. package/dist/utils/platform-yaml-merge.js +13 -6
  254. package/dist/utils/platform-yaml-merge.js.map +1 -1
  255. package/dist/utils/prompts.js +0 -31
  256. package/dist/utils/prompts.js.map +1 -1
  257. package/dist/utils/registry-entry-filter.js +38 -24
  258. package/dist/utils/registry-entry-filter.js.map +1 -1
  259. package/dist/utils/registry-paths.js +48 -0
  260. package/dist/utils/registry-paths.js.map +1 -0
  261. package/dist/utils/root-file-installer.js +19 -0
  262. package/dist/utils/root-file-installer.js.map +1 -1
  263. package/dist/utils/root-file-registry.js.map +1 -1
  264. package/dist/utils/tarball.js +6 -2
  265. package/dist/utils/tarball.js.map +1 -1
  266. package/dist/utils/version-ranges.js +11 -8
  267. package/dist/utils/version-ranges.js.map +1 -1
  268. package/package.json +3 -2
  269. package/platforms.jsonc +178 -0
  270. package/specs/auth/auth-device-flow.md +70 -0
  271. package/specs/install/install-behavior.md +30 -0
  272. package/specs/install/package-yml-canonical.md +21 -1
  273. package/specs/install/version-resolution.md +9 -7
  274. package/specs/login/login-device-flow.md +70 -0
  275. package/specs/package/README.md +60 -0
  276. package/specs/package/nested-packages-and-parent-packages.md +79 -0
  277. package/specs/package/package-index-yml.md +171 -0
  278. package/specs/package/package-root-layout.md +78 -0
  279. package/specs/package/registry-payload-and-copy.md +77 -0
  280. package/specs/package/universal-content.md +144 -0
  281. package/specs/platforms.md +193 -0
  282. package/specs/push/push-behavior.md +38 -10
  283. package/specs/push/push-errors-and-hints.md +19 -6
  284. package/specs/push/push-remote-upload.md +3 -0
  285. package/specs/push/push-scoping.md +14 -22
  286. package/specs/push/push-version-selection.md +18 -16
  287. package/specs/save/README.md +40 -0
  288. package/specs/save/save-conflict-resolution.md +146 -0
  289. package/specs/save/save-file-discovery.md +101 -0
  290. package/specs/save/save-frontmatter-overrides.md +81 -0
  291. package/specs/save/save-modes-inputs.md +55 -0
  292. package/specs/save/save-naming-scoping.md +93 -0
  293. package/specs/save/save-package-detection.md +60 -0
  294. package/specs/save/save-registry-sync.md +126 -0
  295. package/specs/save-pack.md +1 -0
  296. package/dist/commands/release.js +0 -33
  297. package/dist/commands/release.js.map +0 -1
  298. package/dist/commands/tag.js +0 -311
  299. package/dist/commands/tag.js.map +0 -1
  300. package/dist/commands/update.js +0 -30
  301. package/dist/commands/update.js.map +0 -1
  302. package/dist/core/add/formula-index-updater.js +0 -290
  303. package/dist/core/add/formula-index-updater.js.map +0 -1
  304. package/dist/core/discovery/ai-files-discovery.js +0 -2
  305. package/dist/core/discovery/ai-files-discovery.js.map +0 -1
  306. package/dist/core/discovery/formula-files-discovery.js +0 -14
  307. package/dist/core/discovery/formula-files-discovery.js.map +0 -1
  308. package/dist/core/discovery/index-files-discovery.js +0 -91
  309. package/dist/core/discovery/index-files-discovery.js.map +0 -1
  310. package/dist/core/discovery/md-files-discovery.js +0 -82
  311. package/dist/core/discovery/md-files-discovery.js.map +0 -1
  312. package/dist/core/discovery/package-files-discovery.js +0 -14
  313. package/dist/core/discovery/package-files-discovery.js.map +0 -1
  314. package/dist/core/discovery/platform-discovery.js +0 -84
  315. package/dist/core/discovery/platform-discovery.js.map +0 -1
  316. package/dist/core/discovery/root-files-discovery.js +0 -2
  317. package/dist/core/discovery/root-files-discovery.js.map +0 -1
  318. package/dist/core/formula.js +0 -170
  319. package/dist/core/formula.js.map +0 -1
  320. package/dist/core/git-registry.js +0 -46
  321. package/dist/core/git-registry.js.map +0 -1
  322. package/dist/core/groundzero.js +0 -277
  323. package/dist/core/groundzero.js.map +0 -1
  324. package/dist/core/install/scenario.js +0 -11
  325. package/dist/core/install/scenario.js.map +0 -1
  326. package/dist/core/package-sync.js +0 -219
  327. package/dist/core/package-sync.js.map +0 -1
  328. package/dist/core/save/formula-file-generator.js +0 -167
  329. package/dist/core/save/formula-file-generator.js.map +0 -1
  330. package/dist/core/save/formula-saver.js +0 -52
  331. package/dist/core/save/formula-saver.js.map +0 -1
  332. package/dist/core/save/formula-yml-generator.js +0 -89
  333. package/dist/core/save/formula-yml-generator.js.map +0 -1
  334. package/dist/core/save/formula-yml-versioning.js +0 -108
  335. package/dist/core/save/formula-yml-versioning.js.map +0 -1
  336. package/dist/core/save/generic-file-sync.js +0 -38
  337. package/dist/core/save/generic-file-sync.js.map +0 -1
  338. package/dist/core/save/md-files-sync.js +0 -33
  339. package/dist/core/save/md-files-sync.js.map +0 -1
  340. package/dist/core/save/package-yml-versioning.js +0 -108
  341. package/dist/core/save/package-yml-versioning.js.map +0 -1
  342. package/dist/core/save/platform-sync.js +0 -95
  343. package/dist/core/save/platform-sync.js.map +0 -1
  344. package/dist/core/save/root-files-sync.js +0 -140
  345. package/dist/core/save/root-files-sync.js.map +0 -1
  346. package/dist/core/save/save-candidate-types.js +0 -2
  347. package/dist/core/save/save-candidate-types.js.map +0 -1
  348. package/dist/core/save/save-conflict-types.js +0 -2
  349. package/dist/core/save/save-conflict-types.js.map +0 -1
  350. package/dist/core/save/save-file-discovery.js +0 -5
  351. package/dist/core/save/save-file-discovery.js.map +0 -1
  352. package/dist/core/status-file-discovery.js +0 -175
  353. package/dist/core/status-file-discovery.js.map +0 -1
  354. package/dist/utils/discovery/file-processing.js +0 -156
  355. package/dist/utils/discovery/file-processing.js.map +0 -1
  356. package/dist/utils/discovery/formula-discovery.js +0 -211
  357. package/dist/utils/discovery/formula-discovery.js.map +0 -1
  358. package/dist/utils/discovery/platform-discovery.js +0 -2
  359. package/dist/utils/discovery/platform-discovery.js.map +0 -1
  360. package/dist/utils/formula-discovery.js +0 -102
  361. package/dist/utils/formula-discovery.js.map +0 -1
  362. package/dist/utils/formula-index-yml.js +0 -122
  363. package/dist/utils/formula-index-yml.js.map +0 -1
  364. package/dist/utils/formula-installation.js +0 -110
  365. package/dist/utils/formula-installation.js.map +0 -1
  366. package/dist/utils/formula-local-files.js +0 -38
  367. package/dist/utils/formula-local-files.js.map +0 -1
  368. package/dist/utils/formula-management.js +0 -191
  369. package/dist/utils/formula-management.js.map +0 -1
  370. package/dist/utils/formula-name.js +0 -97
  371. package/dist/utils/formula-name.js.map +0 -1
  372. package/dist/utils/formula-versioning.js +0 -109
  373. package/dist/utils/formula-versioning.js.map +0 -1
  374. package/dist/utils/formula-yml.js +0 -82
  375. package/dist/utils/formula-yml.js.map +0 -1
  376. package/dist/utils/git.js +0 -54
  377. package/dist/utils/git.js.map +0 -1
  378. package/dist/utils/id-based-discovery.js +0 -126
  379. package/dist/utils/id-based-discovery.js.map +0 -1
  380. package/dist/utils/id-based-installer.js +0 -249
  381. package/dist/utils/id-based-installer.js.map +0 -1
  382. package/dist/utils/index-yml-based-installer.js +0 -375
  383. package/dist/utils/index-yml-based-installer.js.map +0 -1
  384. package/dist/utils/index-yml.js +0 -124
  385. package/dist/utils/index-yml.js.map +0 -1
  386. package/dist/utils/md-frontmatter.js +0 -3
  387. package/dist/utils/md-frontmatter.js.map +0 -1
  388. package/dist/utils/package-link-yml.js +0 -92
  389. package/dist/utils/package-link-yml.js.map +0 -1
  390. package/dist/utils/platform-discovery.js +0 -2
  391. package/dist/utils/platform-discovery.js.map +0 -1
  392. package/dist/utils/platform-frontmatter-split.js +0 -15
  393. package/dist/utils/platform-frontmatter-split.js.map +0 -1
  394. package/dist/utils/timestamp-encoder.js +0 -13
  395. package/dist/utils/timestamp-encoder.js.map +0 -1
  396. package/dist/utils/wip-versioning.js +0 -24
  397. package/dist/utils/wip-versioning.js.map +0 -1
@@ -0,0 +1,171 @@
1
+ ### Package Index File (`package.index.yml`)
2
+
3
+ The `package.index.yml` file tracks the mapping between package files and their **actually installed** workspace locations.
4
+
5
+ ---
6
+
7
+ #### Location
8
+
9
+ - **Root package**: `cwd/.openpackage/package.index.yml`
10
+ - **Nested package**: `cwd/.openpackage/packages/<name>/.openpackage/package.index.yml`
11
+
12
+ > **Note**: `package.index.yml` is **never** included in the registry payload. It's workspace-local metadata.
13
+
14
+ ---
15
+
16
+ #### Excluded Content
17
+
18
+ The following files are **never** included in the index, even though they may exist in the package:
19
+
20
+ | File | Reason |
21
+ |------|--------|
22
+ | `package.yml` | Package manifest; not synced to workspace |
23
+ | `.openpackage/package.yml` | Same as above (path variant) |
24
+ | `package.index.yml` | Index file itself; workspace-local metadata |
25
+
26
+ The index only contains entries for content that is **actually synced** to workspace locations.
27
+
28
+ ---
29
+
30
+ #### Structure
31
+
32
+ ```yaml
33
+ # This file is managed by OpenPackage. Do not edit manually.
34
+
35
+ workspace:
36
+ hash: <workspace-hash>
37
+ version: <installed-version>
38
+ files:
39
+ <registry-key>:
40
+ - <installed-path>
41
+ - <installed-path>
42
+ <registry-key>:
43
+ - <installed-path>
44
+ ```
45
+
46
+ ---
47
+
48
+ #### Registry Keys
49
+
50
+ Registry keys are **relative to the package root**:
51
+
52
+ | Content Type | Key Format | Example |
53
+ |--------------|------------|---------|
54
+ | Universal content | `.openpackage/<subdir>/<file>` | `.openpackage/commands/test.md` |
55
+ | Root-level content | `<path>` | `<dir>/helper.md` |
56
+ | Root files | `<filename>` | `AGENTS.md` |
57
+
58
+ ---
59
+
60
+ #### Values (Installed Paths)
61
+
62
+ Values are **relative to the workspace root (`cwd`)** and represent **paths that actually exist**:
63
+
64
+ | Content Type | Value Format | Example |
65
+ |--------------|--------------|---------|
66
+ | Universal content | Platform-specific paths | `.cursor/commands/test.md`, `.opencode/commands/test.md` |
67
+ | Root-level content | Same as key | `ai/helper.md` |
68
+
69
+ > **Important**: The index only records paths where files **actually exist**. If a file is only installed to one platform (e.g., `.cursor/`), only that path appears in the index—not hypothetical paths for other platforms.
70
+
71
+ ---
72
+
73
+ #### Index Update Behavior
74
+
75
+ The index is updated differently depending on the operation:
76
+
77
+ | Operation | Behavior |
78
+ |-----------|----------|
79
+ | **Add** | Records only the source path that was used to add the file. If you add `.cursor/commands/test.md`, only that path is recorded. |
80
+ | **Save/Sync** | Expands the index to include all platform paths where files were actually created during sync. |
81
+ | **Install** | Populates the index with all platform paths where files were installed. |
82
+
83
+ This ensures the index reflects the **current state** of the workspace, not hypothetical future states.
84
+
85
+ ---
86
+
87
+ #### Root Package Skip Logic
88
+
89
+ For **root packages only**, when a registry key maps to the exact same value, the mapping is **skipped** because:
90
+ - The file is already at the correct location
91
+ - No installation/syncing needed
92
+ - Avoids redundant mappings
93
+
94
+ **Example**: For a root package, `<dir>/helper.md` → `<dir>/helper.md` is skipped.
95
+
96
+ ---
97
+
98
+ #### Nested Package Full Mapping
99
+
100
+ For **nested packages**, all mappings are included because:
101
+ - Files live inside the nested package directory
102
+ - Need to be mapped OUT to workspace root during install
103
+
104
+ **Example**: For nested package `foo`:
105
+ - File at `.openpackage/packages/foo/<dir>/helper.md`
106
+ - Key: `<dir>/helper.md`
107
+ - Value: `<dir>/helper.md` (installed at workspace root)
108
+
109
+ ---
110
+
111
+ #### Complete Examples
112
+
113
+ **After `opkg add .cursor/commands/test.md`** (only source path recorded):
114
+
115
+ ```yaml
116
+ workspace:
117
+ hash: abc123
118
+ version: 1.0.0-abc123.xyz
119
+ files:
120
+ .openpackage/commands/test.md:
121
+ - .cursor/commands/test.md # Only the source path that exists
122
+ ```
123
+
124
+ **After `opkg save`** (all synced paths recorded):
125
+
126
+ ```yaml
127
+ workspace:
128
+ hash: abc123
129
+ version: 1.0.0-abc123.xyz
130
+ files:
131
+ .openpackage/commands/test.md:
132
+ - .cursor/commands/test.md # Original source
133
+ - .opencode/command/test.md # Synced by save
134
+ .openpackage/rules/auth.md:
135
+ - .cursor/rules/auth.mdc
136
+ # Note: package.yml is NOT included (it's the manifest, not synced content)
137
+ # Note: <dir>/helper.md is SKIPPED for root packages (maps to itself)
138
+ ```
139
+
140
+ **Nested package** (`cwd/.openpackage/packages/foo/.openpackage/package.index.yml`):
141
+
142
+ ```yaml
143
+ workspace:
144
+ hash: abc123
145
+ version: 1.0.0
146
+ files:
147
+ .openpackage/commands/test.md:
148
+ - .cursor/commands/test.md
149
+ - .opencode/command/test.md
150
+ <dir>/helper.md:
151
+ - <dir>/helper.md
152
+ AGENTS.md:
153
+ - AGENTS.md
154
+ ```
155
+
156
+ ---
157
+
158
+ #### Add Command Examples
159
+
160
+ When adding files, the index only records the **source path that exists**:
161
+
162
+ | Command | Package | Stored At | Registry Key | Values (in index) |
163
+ |---------|---------|-----------|--------------|-------------------|
164
+ | `opkg add foo <dir>/foo.md` | Nested `foo` | `.openpackage/packages/foo/<dir>/foo.md` | `<dir>/foo.md` | `<dir>/foo.md` |
165
+ | `opkg add foo .cursor/test/foo.md` | Nested `foo` | `.openpackage/packages/foo/.openpackage/test/foo.md` | `.openpackage/test/foo.md` | `.cursor/test/foo.md` (only source) |
166
+ | `opkg add <dir>/foo.md` | Root | `.openpackage/<dir>/foo.md` | `<dir>/foo.md` | SKIPPED |
167
+ | `opkg add .cursor/test/foo.md` | Root | `.openpackage/test/foo.md` | `.openpackage/test/foo.md` | `.cursor/test/foo.md` (only source) |
168
+
169
+ > **Note**: After `opkg save`, the index will expand to include other platform paths (e.g., `.opencode/test/foo.md`) once those files are actually synced.
170
+
171
+
@@ -0,0 +1,78 @@
1
+ ### Package Root Layout
2
+
3
+ Every package root directory (workspace root, nested, or registry) uses this structure:
4
+
5
+ ```text
6
+ <package-root>/
7
+ .openpackage/ # REQUIRED – package content directory
8
+ package.yml # REQUIRED – package manifest (marks this as a package)
9
+ package.index.yml # OPTIONAL – install/index metadata (never in registry payload)
10
+ agents/ # universal content subdirs
11
+ rules/
12
+ commands/
13
+ skills/
14
+ <custom-subdirs>/ # any additional universal content
15
+ <root-dirs>/ # OPTIONAL – root-level content (outside .openpackage/)
16
+ AGENTS.md # OPTIONAL – universal root file
17
+ <other-root-files> # OPTIONAL – platform-specific root files (e.g. CLAUDE.md)
18
+ README.md # OPTIONAL – documentation
19
+ packages/ # OPTIONAL – nested packages (workspace root only)
20
+ ```
21
+
22
+ ---
23
+
24
+ #### Two Types of Package Content
25
+
26
+ 1. **Root-level content** (outside `.openpackage/`):
27
+ - Any files/directories at the package root (e.g., `<dir>/foo.md`, `AGENTS.md`, `CLAUDE.md`)
28
+ - Live directly at the package root level, outside `.openpackage/`
29
+ - Stored and mapped without transformation
30
+
31
+ 2. **Universal content** (inside `.openpackage/`):
32
+ - Platform-normalized files stored under `.openpackage/<subdir>/`
33
+ - Source files like `.cursor/commands/test.md` are normalized to `.openpackage/commands/test.md`
34
+ - Mapped to platform-specific locations during install (e.g., `.cursor/commands/`, `.opencode/commands/`)
35
+
36
+ ---
37
+
38
+ #### Key Invariants
39
+
40
+ - **`.openpackage/package.yml`** marks a directory as a package root.
41
+ - **Universal content** (rules, agents, commands, skills, custom subdirs) lives **under `.openpackage/`**.
42
+ - **Root-level content** (any directories/files outside `.openpackage/`) lives **at the package root** (sibling of `.openpackage/`).
43
+ - **Nested packages** live under `packages/` and are treated as **independent packages**.
44
+ - The **same structure** applies to workspace root packages, nested packages, and registry copies.
45
+
46
+ ---
47
+
48
+ #### Concrete Examples
49
+
50
+ **Workspace root package** (package root = `cwd/`):
51
+
52
+ ```text
53
+ cwd/
54
+ .openpackage/
55
+ package.yml
56
+ package.index.yml
57
+ commands/
58
+ test.md
59
+ rules/
60
+ auth.md
61
+ <root-dir>/ # any root-level directory
62
+ helper.md
63
+ AGENTS.md
64
+ ```
65
+
66
+ **Nested package** (package root = `cwd/.openpackage/packages/foo/`):
67
+
68
+ ```text
69
+ cwd/.openpackage/packages/foo/
70
+ .openpackage/
71
+ package.yml
72
+ package.index.yml
73
+ commands/
74
+ test.md
75
+ <root-dir>/ # any root-level directory
76
+ helper.md
77
+ ```
78
+
@@ -0,0 +1,77 @@
1
+ ### Registry Payload and 1:1 Copy
2
+
3
+ The **registry payload** for a given version is defined by two layers of rules.
4
+
5
+ ---
6
+
7
+ #### 1. Static Rules
8
+
9
+ **Always exclude:**
10
+ - `package.index.yml` (workspace-local metadata)
11
+ - Anything under `packages/` (nested packages are separate units)
12
+
13
+ **Always include (cannot be excluded):**
14
+ - `.openpackage/package.yml` (package manifest)
15
+
16
+ **Included by default (removable via manifest `exclude`):**
17
+ - Every platform root file declared in `platforms.jsonc` (e.g., `CLAUDE.md`, `WARP.md`, `AGENTS.md`) when it exists
18
+ - Any `.openpackage/<universal-subdir>/…` directory (agents, rules, commands, skills, etc.)
19
+ - Any root-level content (directories/files at package root, outside `.openpackage/`)
20
+
21
+ **Everything else starts excluded by default.**
22
+
23
+ ---
24
+
25
+ #### 2. Manifest Filters
26
+
27
+ In `package.yml`:
28
+
29
+ - **`include`** (array): Expands the payload by listing additional glob-like patterns relative to the package root
30
+ - **`exclude`** (array): Removes matches after include rules are applied (but never overrides hard includes/excludes)
31
+
32
+ > **Note**: Newly created nested packages default their `package.yml` to `include: ["**"]`, so they start including all files until the author narrows the list.
33
+
34
+ ---
35
+
36
+ #### Save and Install Operations
37
+
38
+ **When saving:**
39
+
40
+ 1. The save pipeline reads files from the package root using the rules above
41
+ 2. Files are written **unchanged** to: `~/.openpackage/registry/<name>/<version>/...`
42
+
43
+ **When installing:**
44
+
45
+ 1. The install pipeline loads `pkg.files` from the registry
46
+ 2. Files are written 1:1 to: `cwd/.openpackage/packages/<name>/...` for local cache
47
+ 3. Universal content is mapped to platform-specific locations in the workspace
48
+
49
+ ---
50
+
51
+ #### Package Structure in Registry
52
+
53
+ Registry copies maintain the same structure as workspace packages:
54
+
55
+ ```text
56
+ ~/.openpackage/registry/<name>/<version>/
57
+ .openpackage/
58
+ package.yml # package manifest
59
+ commands/ # universal content
60
+ test.md
61
+ rules/
62
+ auth.md
63
+ <root-dir>/ # root-level content (any directory)
64
+ helper.md
65
+ AGENTS.md # root files
66
+ ```
67
+
68
+ ---
69
+
70
+ #### Guarantees
71
+
72
+ This system guarantees that:
73
+
74
+ - The **workspace package**, **local cache**, and **registry version directory** all share the **same tree shape**
75
+ - Save and install operations are **pure copies** at the package boundary, without structural rewrites
76
+ - Packages can be moved between locations (workspace root ↔ nested ↔ registry) without modification
77
+
@@ -0,0 +1,144 @@
1
+ ### Universal Content
2
+
3
+ #### Universal Content vs. Root-Level Content
4
+
5
+ Packages contain two types of content:
6
+
7
+ | Type | Location | Description | Install Behavior |
8
+ |------|----------|-------------|------------------|
9
+ | **Universal content** | `<package-root>/.openpackage/<subdir>/` | Platform-normalized files | Mapped to platform-specific paths |
10
+ | **Root-level content** | `<package-root>/<path>` (outside `.openpackage/`) | Any files/dirs at package root | Copied 1:1 to same relative path |
11
+
12
+ ---
13
+
14
+ #### Universal Content Layout under `.openpackage/`
15
+
16
+ Inside `.openpackage/`, each universal subdir is canonical:
17
+
18
+ ```text
19
+ <package-root>/
20
+ .openpackage/
21
+ package.yml # package manifest
22
+ agents/
23
+ <name>.md # universal markdown
24
+ <name>.<platform>.md # platform-suffixed markdown (optional)
25
+ <name>.<platform>.yml # YAML override for frontmatter (optional)
26
+ rules/
27
+ ...
28
+ commands/
29
+ ...
30
+ skills/
31
+ ...
32
+ <custom-subdirs>/ # any additional subdirs
33
+ ...
34
+ ```
35
+
36
+ **Definitions:**
37
+
38
+ - **Universal markdown**:
39
+ - Paths like `.openpackage/agents/foo.md`
40
+ - Contains shared body and (after save) shared frontmatter
41
+
42
+ - **Platform-suffixed markdown**:
43
+ - Paths like `.openpackage/agents/foo.<platform>.md`
44
+ - Represents platform-specific variants of a universal file
45
+
46
+ - **YAML override files**:
47
+ - Paths like `.openpackage/agents/foo.<platform>.yml`
48
+ - Contains only the **per-platform difference** in frontmatter
49
+
50
+ ---
51
+
52
+ #### Root-Level Content (Outside `.openpackage/`)
53
+
54
+ Root-level content lives at the package root, **not** under `.openpackage/`:
55
+
56
+ ```text
57
+ <package-root>/
58
+ .openpackage/
59
+ ... # universal content inside
60
+ <root-dir>/ # any root-level directory
61
+ helper.md
62
+ prompts/
63
+ system.md
64
+ AGENTS.md # root files
65
+ CLAUDE.md
66
+ README.md
67
+ ```
68
+
69
+ Root-level content:
70
+ - Is stored and copied **without transformation**
71
+ - Maps to the **same relative path** in the workspace
72
+ - Includes any directories at the package root, platform root files (`AGENTS.md`, `CLAUDE.md`), etc.
73
+
74
+ ---
75
+
76
+ #### Registry Paths (Keys in `package.index.yml`)
77
+
78
+ Registry paths are **relative to the package root**:
79
+
80
+ | Content Type | Example Registry Path |
81
+ |--------------|----------------------|
82
+ | Universal content | `.openpackage/commands/test.md` |
83
+ | Root-level content | `<dir>/helper.md` |
84
+ | Root files | `AGENTS.md` |
85
+
86
+ **Rules:**
87
+
88
+ - Universal subdir content **always** has `.openpackage/` prefix
89
+ - Root-level content uses its natural path (no prefix)
90
+ - Root files use their filename directly
91
+
92
+ ---
93
+
94
+ #### Install Mapping Examples
95
+
96
+ **Universal content** (platform-specific mapping):
97
+
98
+ | Registry Path | Installed Paths |
99
+ |---------------|-----------------|
100
+ | `.openpackage/commands/test.md` | `.cursor/commands/test.md`, `.opencode/commands/test.md`, etc. |
101
+ | `.openpackage/rules/auth.md` | `.cursor/rules/auth.mdc`, etc. |
102
+
103
+ **Root-level content** (1:1 mapping):
104
+
105
+ | Registry Path | Installed Path |
106
+ |---------------|----------------|
107
+ | `<dir>/helper.md` | `<dir>/helper.md` |
108
+ | `AGENTS.md` | `AGENTS.md` |
109
+
110
+ ---
111
+
112
+ #### Consistent Layout Across Locations
113
+
114
+ These layouts apply identically whether the package lives at:
115
+
116
+ - **Workspace root**: `cwd/` (content at `cwd/.openpackage/...`)
117
+ - **Nested package**: `cwd/.openpackage/packages/<name>/` (content at `cwd/.openpackage/packages/<name>/.openpackage/...`)
118
+ - **Registry**: `~/.openpackage/registry/<name>/<version>/` (content at `.../.openpackage/...`)
119
+
120
+ ---
121
+
122
+ #### Frontmatter and Overrides
123
+
124
+ In the canonical structure:
125
+
126
+ - Each universal markdown file (`.openpackage/<subdir>/<name>.md`) is the **single source of truth** for:
127
+ - Markdown body
128
+ - Shared frontmatter keys/common metadata
129
+
130
+ - Platform overrides live alongside their universal file:
131
+
132
+ ```text
133
+ .openpackage/agents/foo.md # universal body + shared frontmatter
134
+ .openpackage/agents/foo.claude.yml # CLAUDE-specific frontmatter diff
135
+ .openpackage/agents/foo.claude.md # optional CLAUDE-specific markdown body
136
+ ```
137
+
138
+ The save pipeline:
139
+
140
+ 1. Normalizes workspace markdown and computes:
141
+ - Universal frontmatter to keep in `foo.md`
142
+ - Per-platform differences to write as `foo.<platform>.yml`
143
+ 2. Writes override files into the `.openpackage/<subdir>/` tree
144
+
@@ -0,0 +1,193 @@
1
+ ## Platforms system behavior
2
+
3
+ ### Overview
4
+
5
+ The platforms system provides a unified way to describe and work with different AI coding platforms (e.g. Cursor, Claude, Gemini) so that OpenPackage can manage platform‑specific rules, commands, agents, and skills consistently.
6
+
7
+ From a user’s perspective, the platform layer answers:
8
+ - **Which platforms are supported in this workspace?**
9
+ - **Where do their files live on disk?**
10
+ - **Which files belong to which platform (or to the generic `ai` space)?**
11
+ - **Which root files (e.g. `CLAUDE.md`) are active, and how are they used?**
12
+
13
+ All platform definitions (names, directories, root files, and subdirectories) are centralized in `platforms.jsonc`.
14
+
15
+ Each platform entry in `platforms.jsonc` has the shape:
16
+
17
+ - `name` (string): Human‑readable display name.
18
+ - `rootDir` (string): Platform root directory (e.g. `.cursor`, `.claude`).
19
+ - `rootFile?` (string): Optional root file at the project root (e.g. `CLAUDE.md`, `QWEN.md`).
20
+ - `subdirs` (object): Map from universal subdir keys (`rules`, `commands`, `agents`, `skills`) to:
21
+ - `path` (string): Directory path under `rootDir`.
22
+ - `exts?` (string[]): Allowed workspace file extensions. When omitted, all extensions are allowed; when an empty array, no extensions are allowed.
23
+ - `transformations?` (array): Optional extension conversion rules with `{ packageExt, workspaceExt }` entries that describe how files convert between registry and workspace formats.
24
+ - `aliases?` (string[]): Optional CLI aliases that resolve to this platform.
25
+ - `enabled?` (boolean): When `false`, the platform exists in config but is treated as disabled.
26
+
27
+ ---
28
+
29
+ ### Platform identities and aliases
30
+
31
+ - **Platform id**: each platform has a lowercase id (e.g. `cursor`, `claude`, `gemini`) used throughout the CLI. These ids are the top‑level keys in `platforms.jsonc`.
32
+ - **Enabled flag**:
33
+ - Platforms are considered **enabled by default**.
34
+ - A platform can be explicitly disabled in `platforms.jsonc` via `enabled: false` (e.g. for experimental or unsupported platforms).
35
+ - Functions that list or iterate platforms only include **enabled** platforms by default, with optional flags to include disabled ones when needed.
36
+ - **Aliases**:
37
+ - Each platform can declare **human‑friendly aliases** in its `aliases` array (e.g. `claudecode`, `codexcli`, `geminicli`, `kilocode`, `qwencode`).
38
+ - Aliases are resolved case‑insensitively to a canonical platform id.
39
+ - User‑facing prompts or configs can accept either the platform id or any of its aliases.
40
+
41
+ **Resolution behavior**
42
+
43
+ - Given a string input (e.g. from CLI flags, prompts, or config), the system:
44
+ - First treats it as a platform id (after lowercasing).
45
+ - If there is no direct match, it looks it up in the alias map.
46
+ - If neither match, the platform is treated as **unknown**.
47
+
48
+ ---
49
+
50
+ ### Directory layout and universal subdirs
51
+
52
+ Each platform defines:
53
+ - A **root directory** (e.g. `.cursor`, `.claude`, `.gemini`).
54
+ - Optional **root file** at the project root (e.g. `CLAUDE.md`, `GEMINI.md`, `QWEN.md`, `WARP.md`, or the shared `AGENTS.md`).
55
+ - A set of **universal subdirectories**, which describe where different kinds of content live:
56
+ - `rules` – steering/rules files for a platform.
57
+ - `commands` – command/workflow prompt files.
58
+ - `agents` – agent definitions.
59
+ - `skills` – skill or tool definitions.
60
+
61
+ For each subdirectory, the platform definition specifies:
62
+ - **Path** under the platform root (e.g. `.cursor/rules`, `.factory/droids`, `.kilo/workflows`).
63
+ - **Allowed extensions**: which workspace file extensions are considered part of that subdir (e.g. `.md`, `.mdc`, `.toml`). Omit to allow any extension or set an empty list to disallow all files.
64
+ - **Extension transformations**: optional `{ packageExt, workspaceExt }` pairs that describe how files convert between registry/universal formats and platform-specific workspace formats (e.g. Cursor rules convert `.md` registry files to `.mdc` in the workspace).
65
+
66
+ **Examples**
67
+
68
+ - Cursor:
69
+ - Root dir: `.cursor`
70
+ - Subdirs:
71
+ - `rules` → `.cursor/rules` (reads `.mdc` + `.md`, writes `.mdc`)
72
+ - `commands` → `.cursor/commands` (reads/writes `.md`)
73
+ - Claude:
74
+ - Root dir: `.claude`
75
+ - Root file: `CLAUDE.md`
76
+ - Subdirs:
77
+ - `commands` → `.claude/commands`
78
+ - `agents` → `.claude/agents`
79
+ - `skills` → `.claude/skills`
80
+
81
+ The system exposes a **platform directory map** that, given a working directory, tells callers where each platform’s `rules`, `commands`, `agents`, and `skills` live on disk.
82
+
83
+ ---
84
+
85
+ ### Platform detection
86
+
87
+ The platforms system can **detect which platforms are present** in a workspace using two signals:
88
+
89
+ 1. **Platform directories**:
90
+ - For each enabled platform, the system checks whether its root directory exists in the current working directory.
91
+ - If the root directory exists, the platform is marked as **present**.
92
+
93
+ 2. **Root files**:
94
+ - For platforms that define a root file (e.g. `CLAUDE.md`, `GEMINI.md`, `QWEN.md`, `WARP.md`), the system checks whether those files exist at the project root.
95
+ - If a root file exists, the corresponding platform is also marked as **present**, even if its standard directory structure is missing.
96
+ - The shared `AGENTS.md` file is treated as **universal** and not attributed to a single platform.
97
+
98
+ The result is:
99
+ - A list of **detection results** (for each platform: `{ name, detected }`).
100
+ - A convenience list of **detected platforms only** (used by higher‑level features like setup flows).
101
+
102
+ ---
103
+
104
+ ### Platform‑specific directories and creation
105
+
106
+ The platforms system provides helpers for:
107
+
108
+ - **Getting directory paths** for each platform:
109
+ - For each enabled platform, callers can retrieve:
110
+ - The `rules` directory path.
111
+ - Optional `commands`, `agents`, and `skills` directory paths.
112
+ - Optional `rootFile` path, if the platform defines one.
113
+ - **Creating missing platform directories**:
114
+ - Given a list of platform ids and a working directory:
115
+ - Ensures the `rules` directory exists for each platform.
116
+ - Creates directories as needed and returns a list of newly created paths.
117
+
118
+ These helpers allow commands like `opkg init` or platform setup flows to create the necessary folder structure for one or more platforms.
119
+
120
+ ---
121
+
122
+ ### Validating platform structure
123
+
124
+ For a given platform and working directory, the system can validate:
125
+ - That the `rules` directory exists.
126
+ - That the configured root file (if any) exists.
127
+
128
+ It returns:
129
+ - A simple `{ valid: boolean, issues: string[] }` result:
130
+ - `valid = true` when the platform’s required directories/files are present.
131
+ - `issues` describing any missing or inconsistent paths.
132
+
133
+ This is used by higher‑level commands to surface actionable warnings when a platform’s layout is incomplete.
134
+
135
+ ---
136
+
137
+ ### File extension behavior
138
+
139
+ For each platform’s `rules` subdir, the system exposes:
140
+ - The **set of file extensions** that are considered valid rules files for that platform.
141
+ - Example: Cursor rules accept `.mdc` and `.md`, Gemini commands accept `.toml`, etc.
142
+ - Higher‑level discovery utilities rely on this to:
143
+ - Filter files by extension when searching for platform content.
144
+ - Decide which files are safe to manage or delete during uninstall/cleanup operations.
145
+
146
+ ---
147
+
148
+ ### Universal subdirectory listing
149
+
150
+ For any detected platform, the platforms system can return a **normalized list of its subdirectories**:
151
+ - Each entry includes:
152
+ - The full directory path.
153
+ - The universal label (`rules`, `commands`, `agents`, `skills`).
154
+ - A short leaf name (last path component) for display.
155
+
156
+ This list is consumed by:
157
+ - Discovery utilities that search for platform‑specific files.
158
+ - Uninstall/cleanup flows that remove platform files for a given package.
159
+
160
+ ---
161
+
162
+ ### Platform inference from file paths
163
+
164
+ The platforms system helps determine which platform a given file belongs to by:
165
+
166
+ 1. **Using path‑to‑platform mappings**:
167
+ - A dedicated mapper converts full workspace paths into a *universal* representation that includes the platform id where possible (e.g. `.cursor/rules/foo.mdc` → platform `cursor` + `rules/foo.mdc`).
168
+
169
+ 2. **Checking for generic workspace directories**:
170
+ - Files that do not live under a known platform root (for example, a conventional `ai/` folder) are treated as workspace-level content rather than being assigned to a specific platform.
171
+
172
+ 3. **Looking at source directory names**:
173
+ - If a file lives under a known platform root directory (e.g. `.cursor`, `.claude`), the system infers that platform from the directory.
174
+
175
+ 4. **Parsing registry paths with platform suffixes**:
176
+ - As a final fallback, the system inspects registry paths for explicit platform suffixes (e.g. `rules/file.cursor.md`) and maps them back to a platform id when possible.
177
+
178
+ The result is a best‑effort platform id (or a `workspace` classification) for a given file, which other components use to route content to the right registry paths and conflict‑resolution logic.
179
+
180
+ ---
181
+
182
+ ### Root file handling
183
+
184
+ The platforms system exposes **all known platform root filenames**, derived from the `rootFile` fields in `platforms.jsonc` plus the universal `AGENTS.md`. These are used to:
185
+ - Discover root files in the workspace or in the local registry.
186
+ - Map root files back to platforms (except for universal `AGENTS.md`).
187
+ - Coordinate how content from multiple platform‑specific root files is merged or extracted into a universal view (handled by other utilities).
188
+
189
+ From a behavioral perspective:
190
+ - Platforms that define root files can participate in root‑file‑based flows (e.g. reading/writing `CLAUDE.md`).
191
+ - Platforms without root files rely exclusively on their directory layout (`.cursor/rules`, `.kilo/workflows`, etc.).
192
+
193
+