@shrkcrft/cli 0.1.0-alpha.2

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 (450) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/dist/asset-preview/apply-action-hint-stub.d.ts +28 -0
  4. package/dist/asset-preview/apply-action-hint-stub.d.ts.map +1 -0
  5. package/dist/asset-preview/apply-action-hint-stub.js +170 -0
  6. package/dist/asset-preview/apply-asset-preview.d.ts +31 -0
  7. package/dist/asset-preview/apply-asset-preview.d.ts.map +1 -0
  8. package/dist/asset-preview/apply-asset-preview.js +210 -0
  9. package/dist/asset-preview/apply-knowledge-stale-fix.d.ts +37 -0
  10. package/dist/asset-preview/apply-knowledge-stale-fix.d.ts.map +1 -0
  11. package/dist/asset-preview/apply-knowledge-stale-fix.js +344 -0
  12. package/dist/asset-preview/apply-missing-barrel.d.ts +15 -0
  13. package/dist/asset-preview/apply-missing-barrel.d.ts.map +1 -0
  14. package/dist/asset-preview/apply-missing-barrel.js +65 -0
  15. package/dist/asset-preview/apply-template-drift-fix.d.ts +21 -0
  16. package/dist/asset-preview/apply-template-drift-fix.d.ts.map +1 -0
  17. package/dist/asset-preview/apply-template-drift-fix.js +125 -0
  18. package/dist/asset-preview/apply-template-update.d.ts +43 -0
  19. package/dist/asset-preview/apply-template-update.d.ts.map +1 -0
  20. package/dist/asset-preview/apply-template-update.js +257 -0
  21. package/dist/asset-preview/entry-mutator.d.ts +106 -0
  22. package/dist/asset-preview/entry-mutator.d.ts.map +1 -0
  23. package/dist/asset-preview/entry-mutator.js +428 -0
  24. package/dist/authoring/authoring-kit.d.ts +36 -0
  25. package/dist/authoring/authoring-kit.d.ts.map +1 -0
  26. package/dist/authoring/authoring-kit.js +106 -0
  27. package/dist/command-registry.d.ts +158 -0
  28. package/dist/command-registry.d.ts.map +1 -0
  29. package/dist/command-registry.js +348 -0
  30. package/dist/commands/apply.command.d.ts +3 -0
  31. package/dist/commands/apply.command.d.ts.map +1 -0
  32. package/dist/commands/apply.command.js +879 -0
  33. package/dist/commands/architecture.command.d.ts +5 -0
  34. package/dist/commands/architecture.command.d.ts.map +1 -0
  35. package/dist/commands/architecture.command.js +141 -0
  36. package/dist/commands/ask.command.d.ts +3 -0
  37. package/dist/commands/ask.command.d.ts.map +1 -0
  38. package/dist/commands/ask.command.js +58 -0
  39. package/dist/commands/audit.command.d.ts +3 -0
  40. package/dist/commands/audit.command.d.ts.map +1 -0
  41. package/dist/commands/audit.command.js +141 -0
  42. package/dist/commands/biome.command.d.ts +7 -0
  43. package/dist/commands/biome.command.d.ts.map +1 -0
  44. package/dist/commands/biome.command.js +350 -0
  45. package/dist/commands/boundaries.command.d.ts +9 -0
  46. package/dist/commands/boundaries.command.d.ts.map +1 -0
  47. package/dist/commands/boundaries.command.js +314 -0
  48. package/dist/commands/brief.command.d.ts +3 -0
  49. package/dist/commands/brief.command.d.ts.map +1 -0
  50. package/dist/commands/brief.command.js +206 -0
  51. package/dist/commands/bundle.command.d.ts +3 -0
  52. package/dist/commands/bundle.command.d.ts.map +1 -0
  53. package/dist/commands/bundle.command.js +1183 -0
  54. package/dist/commands/changes.command.d.ts +3 -0
  55. package/dist/commands/changes.command.d.ts.map +1 -0
  56. package/dist/commands/changes.command.js +155 -0
  57. package/dist/commands/check.command.d.ts +3 -0
  58. package/dist/commands/check.command.d.ts.map +1 -0
  59. package/dist/commands/check.command.js +553 -0
  60. package/dist/commands/checks.command.d.ts +29 -0
  61. package/dist/commands/checks.command.d.ts.map +1 -0
  62. package/dist/commands/checks.command.js +521 -0
  63. package/dist/commands/ci.command.d.ts +3 -0
  64. package/dist/commands/ci.command.d.ts.map +1 -0
  65. package/dist/commands/ci.command.js +680 -0
  66. package/dist/commands/codemod.command.d.ts +3 -0
  67. package/dist/commands/codemod.command.d.ts.map +1 -0
  68. package/dist/commands/codemod.command.js +130 -0
  69. package/dist/commands/command-catalog.d.ts +265 -0
  70. package/dist/commands/command-catalog.d.ts.map +1 -0
  71. package/dist/commands/command-catalog.js +3242 -0
  72. package/dist/commands/commands.command.d.ts +92 -0
  73. package/dist/commands/commands.command.d.ts.map +1 -0
  74. package/dist/commands/commands.command.js +1208 -0
  75. package/dist/commands/constructs.command.d.ts +15 -0
  76. package/dist/commands/constructs.command.d.ts.map +1 -0
  77. package/dist/commands/constructs.command.js +669 -0
  78. package/dist/commands/context.command.d.ts +3 -0
  79. package/dist/commands/context.command.d.ts.map +1 -0
  80. package/dist/commands/context.command.js +120 -0
  81. package/dist/commands/contract-gate.command.d.ts +5 -0
  82. package/dist/commands/contract-gate.command.d.ts.map +1 -0
  83. package/dist/commands/contract-gate.command.js +208 -0
  84. package/dist/commands/contract-templates.command.d.ts +8 -0
  85. package/dist/commands/contract-templates.command.d.ts.map +1 -0
  86. package/dist/commands/contract-templates.command.js +151 -0
  87. package/dist/commands/contract.command.d.ts +3 -0
  88. package/dist/commands/contract.command.d.ts.map +1 -0
  89. package/dist/commands/contract.command.js +105 -0
  90. package/dist/commands/conventions.command.d.ts +8 -0
  91. package/dist/commands/conventions.command.d.ts.map +1 -0
  92. package/dist/commands/conventions.command.js +169 -0
  93. package/dist/commands/coverage.command.d.ts +3 -0
  94. package/dist/commands/coverage.command.d.ts.map +1 -0
  95. package/dist/commands/coverage.command.js +56 -0
  96. package/dist/commands/daily.commands.d.ts +5 -0
  97. package/dist/commands/daily.commands.d.ts.map +1 -0
  98. package/dist/commands/daily.commands.js +224 -0
  99. package/dist/commands/dashboard-export.command.d.ts +4 -0
  100. package/dist/commands/dashboard-export.command.d.ts.map +1 -0
  101. package/dist/commands/dashboard-export.command.js +86 -0
  102. package/dist/commands/dashboard.command.d.ts +3 -0
  103. package/dist/commands/dashboard.command.d.ts.map +1 -0
  104. package/dist/commands/dashboard.command.js +106 -0
  105. package/dist/commands/dev.command.d.ts +3 -0
  106. package/dist/commands/dev.command.d.ts.map +1 -0
  107. package/dist/commands/dev.command.js +1392 -0
  108. package/dist/commands/diagnostics.command.d.ts +5 -0
  109. package/dist/commands/diagnostics.command.d.ts.map +1 -0
  110. package/dist/commands/diagnostics.command.js +97 -0
  111. package/dist/commands/docs.command.d.ts +4 -0
  112. package/dist/commands/docs.command.d.ts.map +1 -0
  113. package/dist/commands/docs.command.js +34 -0
  114. package/dist/commands/doctor.command.d.ts +7 -0
  115. package/dist/commands/doctor.command.d.ts.map +1 -0
  116. package/dist/commands/doctor.command.js +681 -0
  117. package/dist/commands/drift.command.d.ts +3 -0
  118. package/dist/commands/drift.command.d.ts.map +1 -0
  119. package/dist/commands/drift.command.js +124 -0
  120. package/dist/commands/eslint.command.d.ts +7 -0
  121. package/dist/commands/eslint.command.d.ts.map +1 -0
  122. package/dist/commands/eslint.command.js +423 -0
  123. package/dist/commands/explore.command.d.ts +3 -0
  124. package/dist/commands/explore.command.d.ts.map +1 -0
  125. package/dist/commands/explore.command.js +65 -0
  126. package/dist/commands/export-bundle.command.d.ts +6 -0
  127. package/dist/commands/export-bundle.command.d.ts.map +1 -0
  128. package/dist/commands/export-bundle.command.js +96 -0
  129. package/dist/commands/export.command.d.ts +3 -0
  130. package/dist/commands/export.command.d.ts.map +1 -0
  131. package/dist/commands/export.command.js +83 -0
  132. package/dist/commands/feedback-dispatch.command.d.ts +12 -0
  133. package/dist/commands/feedback-dispatch.command.d.ts.map +1 -0
  134. package/dist/commands/feedback-dispatch.command.js +63 -0
  135. package/dist/commands/feedback.command.d.ts +11 -0
  136. package/dist/commands/feedback.command.d.ts.map +1 -0
  137. package/dist/commands/feedback.command.js +336 -0
  138. package/dist/commands/fix.command.d.ts +3 -0
  139. package/dist/commands/fix.command.d.ts.map +1 -0
  140. package/dist/commands/fix.command.js +776 -0
  141. package/dist/commands/gen.command.d.ts +3 -0
  142. package/dist/commands/gen.command.d.ts.map +1 -0
  143. package/dist/commands/gen.command.js +136 -0
  144. package/dist/commands/git.command.d.ts +6 -0
  145. package/dist/commands/git.command.d.ts.map +1 -0
  146. package/dist/commands/git.command.js +81 -0
  147. package/dist/commands/graph.command.d.ts +3 -0
  148. package/dist/commands/graph.command.d.ts.map +1 -0
  149. package/dist/commands/graph.command.js +287 -0
  150. package/dist/commands/grounding.command.d.ts +7 -0
  151. package/dist/commands/grounding.command.d.ts.map +1 -0
  152. package/dist/commands/grounding.command.js +54 -0
  153. package/dist/commands/help.command.d.ts +20 -0
  154. package/dist/commands/help.command.d.ts.map +1 -0
  155. package/dist/commands/help.command.js +127 -0
  156. package/dist/commands/helper.command.d.ts +6 -0
  157. package/dist/commands/helper.command.d.ts.map +1 -0
  158. package/dist/commands/helper.command.js +170 -0
  159. package/dist/commands/ide.command.d.ts +6 -0
  160. package/dist/commands/ide.command.d.ts.map +1 -0
  161. package/dist/commands/ide.command.js +340 -0
  162. package/dist/commands/impact.command.d.ts +3 -0
  163. package/dist/commands/impact.command.d.ts.map +1 -0
  164. package/dist/commands/impact.command.js +819 -0
  165. package/dist/commands/import.command.d.ts +3 -0
  166. package/dist/commands/import.command.d.ts.map +1 -0
  167. package/dist/commands/import.command.js +115 -0
  168. package/dist/commands/infer.command.d.ts +3 -0
  169. package/dist/commands/infer.command.d.ts.map +1 -0
  170. package/dist/commands/infer.command.js +227 -0
  171. package/dist/commands/ingest.command.d.ts +6 -0
  172. package/dist/commands/ingest.command.d.ts.map +1 -0
  173. package/dist/commands/ingest.command.js +532 -0
  174. package/dist/commands/init.command.d.ts +3 -0
  175. package/dist/commands/init.command.d.ts.map +1 -0
  176. package/dist/commands/init.command.js +301 -0
  177. package/dist/commands/inspect.command.d.ts +3 -0
  178. package/dist/commands/inspect.command.d.ts.map +1 -0
  179. package/dist/commands/inspect.command.js +122 -0
  180. package/dist/commands/knowledge-author.command.d.ts +22 -0
  181. package/dist/commands/knowledge-author.command.d.ts.map +1 -0
  182. package/dist/commands/knowledge-author.command.js +366 -0
  183. package/dist/commands/knowledge-propose.command.d.ts +3 -0
  184. package/dist/commands/knowledge-propose.command.d.ts.map +1 -0
  185. package/dist/commands/knowledge-propose.command.js +125 -0
  186. package/dist/commands/knowledge.command.d.ts +18 -0
  187. package/dist/commands/knowledge.command.d.ts.map +1 -0
  188. package/dist/commands/knowledge.command.js +538 -0
  189. package/dist/commands/languages.command.d.ts +3 -0
  190. package/dist/commands/languages.command.d.ts.map +1 -0
  191. package/dist/commands/languages.command.js +300 -0
  192. package/dist/commands/lint.command.d.ts +15 -0
  193. package/dist/commands/lint.command.d.ts.map +1 -0
  194. package/dist/commands/lint.command.js +194 -0
  195. package/dist/commands/mcp.command.d.ts +3 -0
  196. package/dist/commands/mcp.command.d.ts.map +1 -0
  197. package/dist/commands/mcp.command.js +74 -0
  198. package/dist/commands/memory.command.d.ts +11 -0
  199. package/dist/commands/memory.command.d.ts.map +1 -0
  200. package/dist/commands/memory.command.js +264 -0
  201. package/dist/commands/onboard.command.d.ts +3 -0
  202. package/dist/commands/onboard.command.d.ts.map +1 -0
  203. package/dist/commands/onboard.command.js +650 -0
  204. package/dist/commands/orchestrate.command.d.ts +3 -0
  205. package/dist/commands/orchestrate.command.d.ts.map +1 -0
  206. package/dist/commands/orchestrate.command.js +49 -0
  207. package/dist/commands/owners.command.d.ts +5 -0
  208. package/dist/commands/owners.command.d.ts.map +1 -0
  209. package/dist/commands/owners.command.js +113 -0
  210. package/dist/commands/ownership.command.d.ts +5 -0
  211. package/dist/commands/ownership.command.d.ts.map +1 -0
  212. package/dist/commands/ownership.command.js +117 -0
  213. package/dist/commands/pack-author.command.d.ts +30 -0
  214. package/dist/commands/pack-author.command.d.ts.map +1 -0
  215. package/dist/commands/pack-author.command.js +242 -0
  216. package/dist/commands/packs-new.d.ts +27 -0
  217. package/dist/commands/packs-new.d.ts.map +1 -0
  218. package/dist/commands/packs-new.js +805 -0
  219. package/dist/commands/packs.command.d.ts +15 -0
  220. package/dist/commands/packs.command.d.ts.map +1 -0
  221. package/dist/commands/packs.command.js +958 -0
  222. package/dist/commands/paths.command.d.ts +6 -0
  223. package/dist/commands/paths.command.d.ts.map +1 -0
  224. package/dist/commands/paths.command.js +97 -0
  225. package/dist/commands/pipelines.command.d.ts +9 -0
  226. package/dist/commands/pipelines.command.d.ts.map +1 -0
  227. package/dist/commands/pipelines.command.js +308 -0
  228. package/dist/commands/plan-check.command.d.ts +27 -0
  229. package/dist/commands/plan-check.command.d.ts.map +1 -0
  230. package/dist/commands/plan-check.command.js +150 -0
  231. package/dist/commands/plan-simulate.command.d.ts +3 -0
  232. package/dist/commands/plan-simulate.command.d.ts.map +1 -0
  233. package/dist/commands/plan-simulate.command.js +60 -0
  234. package/dist/commands/plan.command.d.ts +8 -0
  235. package/dist/commands/plan.command.d.ts.map +1 -0
  236. package/dist/commands/plan.command.js +139 -0
  237. package/dist/commands/playbooks.command.d.ts +10 -0
  238. package/dist/commands/playbooks.command.d.ts.map +1 -0
  239. package/dist/commands/playbooks.command.js +296 -0
  240. package/dist/commands/plugin.command.d.ts +11 -0
  241. package/dist/commands/plugin.command.d.ts.map +1 -0
  242. package/dist/commands/plugin.command.js +394 -0
  243. package/dist/commands/policy.command.d.ts +8 -0
  244. package/dist/commands/policy.command.d.ts.map +1 -0
  245. package/dist/commands/policy.command.js +451 -0
  246. package/dist/commands/pr.command.d.ts +3 -0
  247. package/dist/commands/pr.command.d.ts.map +1 -0
  248. package/dist/commands/pr.command.js +132 -0
  249. package/dist/commands/preflight.command.d.ts +3 -0
  250. package/dist/commands/preflight.command.d.ts.map +1 -0
  251. package/dist/commands/preflight.command.js +102 -0
  252. package/dist/commands/presets.command.d.ts +17 -0
  253. package/dist/commands/presets.command.d.ts.map +1 -0
  254. package/dist/commands/presets.command.js +647 -0
  255. package/dist/commands/profiles.command.d.ts +7 -0
  256. package/dist/commands/profiles.command.d.ts.map +1 -0
  257. package/dist/commands/profiles.command.js +151 -0
  258. package/dist/commands/provenance.command.d.ts +26 -0
  259. package/dist/commands/provenance.command.d.ts.map +1 -0
  260. package/dist/commands/provenance.command.js +237 -0
  261. package/dist/commands/quality.command.d.ts +5 -0
  262. package/dist/commands/quality.command.d.ts.map +1 -0
  263. package/dist/commands/quality.command.js +69 -0
  264. package/dist/commands/recommend.command.d.ts +4 -0
  265. package/dist/commands/recommend.command.d.ts.map +1 -0
  266. package/dist/commands/recommend.command.js +270 -0
  267. package/dist/commands/registrations.command.d.ts +3 -0
  268. package/dist/commands/registrations.command.d.ts.map +1 -0
  269. package/dist/commands/registrations.command.js +300 -0
  270. package/dist/commands/registry.command.d.ts +4 -0
  271. package/dist/commands/registry.command.d.ts.map +1 -0
  272. package/dist/commands/registry.command.js +37 -0
  273. package/dist/commands/release.command.d.ts +4 -0
  274. package/dist/commands/release.command.d.ts.map +1 -0
  275. package/dist/commands/release.command.js +639 -0
  276. package/dist/commands/repo.command.d.ts +3 -0
  277. package/dist/commands/repo.command.d.ts.map +1 -0
  278. package/dist/commands/repo.command.js +24 -0
  279. package/dist/commands/report.command.d.ts +3 -0
  280. package/dist/commands/report.command.d.ts.map +1 -0
  281. package/dist/commands/report.command.js +511 -0
  282. package/dist/commands/reposet.command.d.ts +6 -0
  283. package/dist/commands/reposet.command.d.ts.map +1 -0
  284. package/dist/commands/reposet.command.js +120 -0
  285. package/dist/commands/review.command.d.ts +3 -0
  286. package/dist/commands/review.command.d.ts.map +1 -0
  287. package/dist/commands/review.command.js +354 -0
  288. package/dist/commands/risk.command.d.ts +3 -0
  289. package/dist/commands/risk.command.d.ts.map +1 -0
  290. package/dist/commands/risk.command.js +56 -0
  291. package/dist/commands/rounds.command.d.ts +8 -0
  292. package/dist/commands/rounds.command.d.ts.map +1 -0
  293. package/dist/commands/rounds.command.js +180 -0
  294. package/dist/commands/rules.command.d.ts +49 -0
  295. package/dist/commands/rules.command.d.ts.map +1 -0
  296. package/dist/commands/rules.command.js +435 -0
  297. package/dist/commands/runtime.command.d.ts +3 -0
  298. package/dist/commands/runtime.command.d.ts.map +1 -0
  299. package/dist/commands/runtime.command.js +56 -0
  300. package/dist/commands/safety.command.d.ts +3 -0
  301. package/dist/commands/safety.command.d.ts.map +1 -0
  302. package/dist/commands/safety.command.js +117 -0
  303. package/dist/commands/scaffolds.command.d.ts +5 -0
  304. package/dist/commands/scaffolds.command.d.ts.map +1 -0
  305. package/dist/commands/scaffolds.command.js +122 -0
  306. package/dist/commands/schemas.command.d.ts +21 -0
  307. package/dist/commands/schemas.command.d.ts.map +1 -0
  308. package/dist/commands/schemas.command.js +296 -0
  309. package/dist/commands/search.command.d.ts +12 -0
  310. package/dist/commands/search.command.d.ts.map +1 -0
  311. package/dist/commands/search.command.js +275 -0
  312. package/dist/commands/self-config.command.d.ts +7 -0
  313. package/dist/commands/self-config.command.d.ts.map +1 -0
  314. package/dist/commands/self-config.command.js +156 -0
  315. package/dist/commands/self.command.d.ts +3 -0
  316. package/dist/commands/self.command.d.ts.map +1 -0
  317. package/dist/commands/self.command.js +117 -0
  318. package/dist/commands/simulate.command.d.ts +3 -0
  319. package/dist/commands/simulate.command.d.ts.map +1 -0
  320. package/dist/commands/simulate.command.js +54 -0
  321. package/dist/commands/spec.command.d.ts +29 -0
  322. package/dist/commands/spec.command.d.ts.map +1 -0
  323. package/dist/commands/spec.command.js +985 -0
  324. package/dist/commands/start-here.command.d.ts +3 -0
  325. package/dist/commands/start-here.command.d.ts.map +1 -0
  326. package/dist/commands/start-here.command.js +35 -0
  327. package/dist/commands/stats.command.d.ts +3 -0
  328. package/dist/commands/stats.command.d.ts.map +1 -0
  329. package/dist/commands/stats.command.js +88 -0
  330. package/dist/commands/surface.command.d.ts +15 -0
  331. package/dist/commands/surface.command.d.ts.map +1 -0
  332. package/dist/commands/surface.command.js +328 -0
  333. package/dist/commands/task-context.command.d.ts +7 -0
  334. package/dist/commands/task-context.command.d.ts.map +1 -0
  335. package/dist/commands/task-context.command.js +646 -0
  336. package/dist/commands/task.command.d.ts +3 -0
  337. package/dist/commands/task.command.d.ts.map +1 -0
  338. package/dist/commands/task.command.js +301 -0
  339. package/dist/commands/template-quality.command.d.ts +5 -0
  340. package/dist/commands/template-quality.command.d.ts.map +1 -0
  341. package/dist/commands/template-quality.command.js +128 -0
  342. package/dist/commands/templates.command.d.ts +26 -0
  343. package/dist/commands/templates.command.d.ts.map +1 -0
  344. package/dist/commands/templates.command.js +964 -0
  345. package/dist/commands/test.command.d.ts +3 -0
  346. package/dist/commands/test.command.d.ts.map +1 -0
  347. package/dist/commands/test.command.js +262 -0
  348. package/dist/commands/tests.command.d.ts +5 -0
  349. package/dist/commands/tests.command.d.ts.map +1 -0
  350. package/dist/commands/tests.command.js +97 -0
  351. package/dist/commands/trace.command.d.ts +3 -0
  352. package/dist/commands/trace.command.d.ts.map +1 -0
  353. package/dist/commands/trace.command.js +121 -0
  354. package/dist/commands/upgrade.command.d.ts +4 -0
  355. package/dist/commands/upgrade.command.d.ts.map +1 -0
  356. package/dist/commands/upgrade.command.js +43 -0
  357. package/dist/commands/version.command.d.ts +3 -0
  358. package/dist/commands/version.command.d.ts.map +1 -0
  359. package/dist/commands/version.command.js +10 -0
  360. package/dist/commands/why.command.d.ts +24 -0
  361. package/dist/commands/why.command.d.ts.map +1 -0
  362. package/dist/commands/why.command.js +119 -0
  363. package/dist/dashboard/dashboard-api-server.d.ts +21 -0
  364. package/dist/dashboard/dashboard-api-server.d.ts.map +1 -0
  365. package/dist/dashboard/dashboard-api-server.js +410 -0
  366. package/dist/dashboard/live-session-server.d.ts +18 -0
  367. package/dist/dashboard/live-session-server.d.ts.map +1 -0
  368. package/dist/dashboard/live-session-server.js +133 -0
  369. package/dist/diff/collect-changed-paths.d.ts +27 -0
  370. package/dist/diff/collect-changed-paths.d.ts.map +1 -0
  371. package/dist/diff/collect-changed-paths.js +68 -0
  372. package/dist/doctor/doctor-tags.d.ts +63 -0
  373. package/dist/doctor/doctor-tags.d.ts.map +1 -0
  374. package/dist/doctor/doctor-tags.js +146 -0
  375. package/dist/export/export-formats.d.ts +22 -0
  376. package/dist/export/export-formats.d.ts.map +1 -0
  377. package/dist/export/export-formats.js +135 -0
  378. package/dist/index.d.ts +22 -0
  379. package/dist/index.d.ts.map +1 -0
  380. package/dist/index.js +21 -0
  381. package/dist/init/detected-block.d.ts +57 -0
  382. package/dist/init/detected-block.d.ts.map +1 -0
  383. package/dist/init/detected-block.js +197 -0
  384. package/dist/init/gitignore.d.ts +30 -0
  385. package/dist/init/gitignore.d.ts.map +1 -0
  386. package/dist/init/gitignore.js +110 -0
  387. package/dist/init/init-templates.d.ts +6 -0
  388. package/dist/init/init-templates.d.ts.map +1 -0
  389. package/dist/init/init-templates.js +413 -0
  390. package/dist/main.d.ts +18 -0
  391. package/dist/main.d.ts.map +1 -0
  392. package/dist/main.js +699 -0
  393. package/dist/output/failure-hints.d.ts +55 -0
  394. package/dist/output/failure-hints.d.ts.map +1 -0
  395. package/dist/output/failure-hints.js +159 -0
  396. package/dist/output/format-output.d.ts +9 -0
  397. package/dist/output/format-output.d.ts.map +1 -0
  398. package/dist/output/format-output.js +26 -0
  399. package/dist/output/print-error.d.ts +3 -0
  400. package/dist/output/print-error.d.ts.map +1 -0
  401. package/dist/output/print-error.js +14 -0
  402. package/dist/output/watch-loop.d.ts +37 -0
  403. package/dist/output/watch-loop.d.ts.map +1 -0
  404. package/dist/output/watch-loop.js +115 -0
  405. package/dist/schemas/json-schemas.d.ts +1630 -0
  406. package/dist/schemas/json-schemas.d.ts.map +1 -0
  407. package/dist/schemas/json-schemas.js +811 -0
  408. package/dist/surface/about.d.ts +10 -0
  409. package/dist/surface/about.d.ts.map +1 -0
  410. package/dist/surface/about.js +53 -0
  411. package/dist/surface/load-surface-context.d.ts +34 -0
  412. package/dist/surface/load-surface-context.d.ts.map +1 -0
  413. package/dist/surface/load-surface-context.js +100 -0
  414. package/dist/surface/no-args-landing.d.ts +7 -0
  415. package/dist/surface/no-args-landing.d.ts.map +1 -0
  416. package/dist/surface/no-args-landing.js +36 -0
  417. package/dist/surface/not-enabled-error.d.ts +24 -0
  418. package/dist/surface/not-enabled-error.d.ts.map +1 -0
  419. package/dist/surface/not-enabled-error.js +36 -0
  420. package/dist/surface/profiles.d.ts +37 -0
  421. package/dist/surface/profiles.d.ts.map +1 -0
  422. package/dist/surface/profiles.js +151 -0
  423. package/dist/surface/shape-defaults.d.ts +21 -0
  424. package/dist/surface/shape-defaults.d.ts.map +1 -0
  425. package/dist/surface/shape-defaults.js +50 -0
  426. package/dist/surface/spine-extractor.d.ts +38 -0
  427. package/dist/surface/spine-extractor.d.ts.map +1 -0
  428. package/dist/surface/spine-extractor.js +100 -0
  429. package/dist/surface/surface-config-writer.d.ts +59 -0
  430. package/dist/surface/surface-config-writer.d.ts.map +1 -0
  431. package/dist/surface/surface-config-writer.js +135 -0
  432. package/dist/surface/surface-summary.d.ts +66 -0
  433. package/dist/surface/surface-summary.d.ts.map +1 -0
  434. package/dist/surface/surface-summary.js +162 -0
  435. package/dist/surface/tier.d.ts +100 -0
  436. package/dist/surface/tier.d.ts.map +1 -0
  437. package/dist/surface/tier.js +172 -0
  438. package/dist/task-next/apply-batch-runner.d.ts +42 -0
  439. package/dist/task-next/apply-batch-runner.d.ts.map +1 -0
  440. package/dist/task-next/apply-batch-runner.js +192 -0
  441. package/dist/task-next/task-next-ranker.d.ts +75 -0
  442. package/dist/task-next/task-next-ranker.d.ts.map +1 -0
  443. package/dist/task-next/task-next-ranker.js +179 -0
  444. package/dist/usage/usage-log.d.ts +54 -0
  445. package/dist/usage/usage-log.d.ts.map +1 -0
  446. package/dist/usage/usage-log.js +105 -0
  447. package/dist/validation/run-validation-loop.d.ts +38 -0
  448. package/dist/validation/run-validation-loop.d.ts.map +1 -0
  449. package/dist/validation/run-validation-loop.js +100 -0
  450. package/package.json +73 -0
@@ -0,0 +1,958 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
10
+ import * as nodePath from 'node:path';
11
+ import { pathToFileURL } from 'node:url';
12
+ import { buildPackDoctorReport, buildPackSignatureStatusReport, checkPackSymbolCompat, explainPackSignatureStatus, inspectSharkcraft, mergePackReleaseChecks, runPackReleaseCheck, runPackReleaseChecksForReport, } from '@shrkcrft/inspector';
13
+ import { PACK_SECRET_ENV, signPackManifest, validatePackManifest, verifyPackManifest, } from '@shrkcrft/plugin-api';
14
+ import { flagBool, flagString, resolveCwd, } from "../command-registry.js";
15
+ import { asJson, header, kv } from "../output/format-output.js";
16
+ function statusLabel(valid) {
17
+ return valid ? 'OK ' : 'INVALID';
18
+ }
19
+ export const packsContributionsCommand = {
20
+ name: 'contributions',
21
+ description: 'List all pack/local contributions across every supported kind. Read-only inventory.',
22
+ usage: 'shrk packs contributions [--pack <name>] [--kind <kind>] [--format text|markdown|json] [--output <file>]',
23
+ async run(args) {
24
+ const { buildPackContributionsInventoryAsync, renderInventoryMarkdown, renderInventoryText, inspectSharkcraft, } = await import('@shrkcrft/inspector');
25
+ const cwd = resolveCwd(args);
26
+ const inspection = await inspectSharkcraft({ cwd });
27
+ // Use the async/structural-first variant so nested step.id and
28
+ // sub-object ids don't show up as separate contribution ids.
29
+ const inv = await buildPackContributionsInventoryAsync(inspection);
30
+ const filterPack = flagString(args, 'pack');
31
+ const filterKind = flagString(args, 'kind');
32
+ let entries = inv.entries;
33
+ if (filterPack)
34
+ entries = entries.filter((e) => e.packageName === filterPack);
35
+ if (filterKind)
36
+ entries = entries.filter((e) => e.kind === filterKind);
37
+ const filtered = { ...inv, entries };
38
+ const format = flagString(args, 'format') ?? 'text';
39
+ if (flagBool(args, 'json') || format === 'json') {
40
+ process.stdout.write(asJson(filtered) + '\n');
41
+ return 0;
42
+ }
43
+ if (format === 'markdown') {
44
+ process.stdout.write(renderInventoryMarkdown(filtered));
45
+ return 0;
46
+ }
47
+ process.stdout.write(renderInventoryText(filtered));
48
+ return 0;
49
+ },
50
+ };
51
+ export const packsSignatureStatusCommand = {
52
+ name: 'signature-status',
53
+ description: 'Report pack signature freshness (present/stale/missing). Never fake-signs; never requires the secret. `--release-readiness` annotates each pack with whether it would block release:preflight (dev signature + no SHARKCRAFT_PACK_SECRET = blocking).',
54
+ usage: 'shrk packs signature-status [<pack>] [--release-readiness] [--format text|markdown|json]',
55
+ async run(args) {
56
+ const { buildPackSignatureStatusReport, inspectSharkcraft } = await import('@shrkcrft/inspector');
57
+ const cwd = resolveCwd(args);
58
+ const inspection = await inspectSharkcraft({ cwd });
59
+ const report = buildPackSignatureStatusReport(inspection);
60
+ const filter = args.positional[0];
61
+ const packs = filter
62
+ ? report.packs.filter((p) => p.packageName === filter || p.packageRoot.endsWith(filter) || p.packageRoot.includes(filter))
63
+ : report.packs;
64
+ // Derive release-blocking assessment per pack.
65
+ const releaseReadiness = flagBool(args, 'release-readiness');
66
+ const secretAvailable = report.secretAvailable;
67
+ const annotated = packs.map((p) => {
68
+ const isDev = p.dev === true;
69
+ const releaseBlocking = isDev && !secretAvailable;
70
+ const releaseBlockingReason = releaseBlocking
71
+ ? 'dev signature + SHARKCRAFT_PACK_SECRET not set — release would publish a dev signature'
72
+ : isDev && secretAvailable
73
+ ? 'dev signature — re-sign before tagging (secret is available)'
74
+ : undefined;
75
+ return {
76
+ ...p,
77
+ dev: isDev,
78
+ releaseBlocking,
79
+ ...(releaseBlockingReason ? { releaseBlockingReason } : {}),
80
+ };
81
+ });
82
+ const blockingCount = annotated.filter((p) => p.releaseBlocking).length;
83
+ const devCount = annotated.filter((p) => p.dev).length;
84
+ const filtered = {
85
+ ...report,
86
+ packs: annotated,
87
+ releaseReadiness: releaseReadiness
88
+ ? {
89
+ enabled: true,
90
+ secretAvailable,
91
+ devSigned: devCount,
92
+ releaseBlocking: blockingCount,
93
+ wouldBlockReleasePreflight: blockingCount > 0,
94
+ }
95
+ : { enabled: false },
96
+ };
97
+ const format = flagString(args, 'format') ?? 'text';
98
+ const exitCode = filtered.summary.stale > 0 || (releaseReadiness && blockingCount > 0) ? 1 : 0;
99
+ if (flagBool(args, 'json') || format === 'json') {
100
+ process.stdout.write(asJson(filtered) + '\n');
101
+ return exitCode;
102
+ }
103
+ if (format === 'markdown') {
104
+ const lines = ['# Pack signature status', ''];
105
+ lines.push(`- generatedAt: ${filtered.generatedAt}`);
106
+ lines.push(`- secret available: ${filtered.secretAvailable}`);
107
+ lines.push(`- total: ${filtered.summary.total} (present ${filtered.summary.present} / stale ${filtered.summary.stale} / missing ${filtered.summary.missing})`);
108
+ if (releaseReadiness) {
109
+ lines.push(`- dev-signed: ${devCount}`);
110
+ lines.push(`- release-blocking: ${blockingCount}`);
111
+ }
112
+ lines.push('');
113
+ lines.push('| Pack | Status | Dev | Release-blocking | Signed at | Reason | Next |');
114
+ lines.push('| --- | --- | --- | --- | --- | --- | --- |');
115
+ for (const p of annotated) {
116
+ lines.push(`| \`${p.packageName}\` | ${p.status} | ${p.dev ? 'yes' : 'no'} | ${p.releaseBlocking ? 'YES' : 'no'} | ${p.signatureSignedAt ?? ''} | ${p.reason ?? p.releaseBlockingReason ?? ''} | ${p.nextCommand ?? ''} |`);
117
+ }
118
+ process.stdout.write(lines.join('\n') + '\n');
119
+ return exitCode;
120
+ }
121
+ process.stdout.write(`=== Pack signature status ===\n`);
122
+ process.stdout.write(` total ${filtered.summary.total}\n`);
123
+ process.stdout.write(` present ${filtered.summary.present}\n`);
124
+ process.stdout.write(` stale ${filtered.summary.stale}\n`);
125
+ process.stdout.write(` missing ${filtered.summary.missing}\n`);
126
+ process.stdout.write(` secret env ${filtered.secretAvailable ? 'set' : 'NOT set (no fake-signing — re-sign manually)'}\n`);
127
+ if (releaseReadiness) {
128
+ process.stdout.write(` dev signed ${devCount}\n`);
129
+ process.stdout.write(` release-blocking ${blockingCount}\n`);
130
+ }
131
+ process.stdout.write('\n');
132
+ for (const p of annotated) {
133
+ const devTag = p.dev ? ' [dev]' : '';
134
+ const blockTag = p.releaseBlocking ? ' [release-blocking]' : '';
135
+ process.stdout.write(` ${p.status.padEnd(8)} ${p.packageName}@${p.packageVersion}${devTag}${blockTag}\n`);
136
+ if (p.reason)
137
+ process.stdout.write(` ${p.reason}\n`);
138
+ if (p.releaseBlockingReason)
139
+ process.stdout.write(` ${p.releaseBlockingReason}\n`);
140
+ if (p.nextCommand)
141
+ process.stdout.write(` next: ${p.nextCommand}\n`);
142
+ }
143
+ if (releaseReadiness && blockingCount > 0) {
144
+ process.stdout.write(`\nRelease would FAIL CLOSED — set SHARKCRAFT_PACK_SECRET and run \`shrk packs sign <pack>\` for each dev-signed pack.\n`);
145
+ }
146
+ return exitCode;
147
+ },
148
+ };
149
+ export const packsConflictsCommand = {
150
+ name: 'conflicts',
151
+ description: 'Surface duplicate-id / shadowed / stale-signature conflicts across pack contributions. Read-only.',
152
+ usage: 'shrk packs conflicts [--severity error|warning|info] [--format text|markdown|json]',
153
+ async run(args) {
154
+ const { buildPackContributionsInventoryAsync, inspectSharkcraft, selectConflicts } = await import('@shrkcrft/inspector');
155
+ const cwd = resolveCwd(args);
156
+ const inspection = await inspectSharkcraft({ cwd });
157
+ // Async/structural-first inventory eliminates nested-id duplicate noise.
158
+ const inv = await buildPackContributionsInventoryAsync(inspection);
159
+ let conflicts = selectConflicts(inv);
160
+ const sev = flagString(args, 'severity');
161
+ if (sev)
162
+ conflicts = conflicts.filter((c) => c.severity === sev);
163
+ if (flagBool(args, 'json') || flagString(args, 'format') === 'json') {
164
+ process.stdout.write(asJson({ conflicts, totals: inv.totals }) + '\n');
165
+ return conflicts.some((c) => c.severity === 'error') ? 1 : 0;
166
+ }
167
+ if (flagString(args, 'format') === 'markdown') {
168
+ const lines = ['# Pack contributions conflicts', ''];
169
+ if (conflicts.length === 0) {
170
+ lines.push('None.');
171
+ }
172
+ else {
173
+ lines.push('| Severity | Kind | Contribution | Id | Message |');
174
+ lines.push('| --- | --- | --- | --- | --- |');
175
+ for (const c of conflicts) {
176
+ lines.push(`| ${c.severity} | \`${c.kind}\` | \`${c.contributionKind}\` | \`${c.id}\` | ${c.message} |`);
177
+ }
178
+ }
179
+ process.stdout.write(lines.join('\n') + '\n');
180
+ return conflicts.some((c) => c.severity === 'error') ? 1 : 0;
181
+ }
182
+ process.stdout.write(`=== Pack contributions conflicts (${conflicts.length}) ===\n`);
183
+ if (conflicts.length === 0) {
184
+ process.stdout.write('No conflicts.\n');
185
+ return 0;
186
+ }
187
+ for (const c of conflicts) {
188
+ process.stdout.write(` ${c.severity.padEnd(7)} [${c.kind}] ${c.contributionKind} "${c.id}" — ${c.message}\n`);
189
+ if (c.nextCommand)
190
+ process.stdout.write(` next: ${c.nextCommand}\n`);
191
+ }
192
+ return conflicts.some((c) => c.severity === 'error') ? 1 : 0;
193
+ },
194
+ };
195
+ export const packsListCommand = {
196
+ name: 'list',
197
+ description: 'List discovered packs (valid + invalid).',
198
+ usage: 'shrk [--cwd <dir>] packs list [--json]',
199
+ async run(args) {
200
+ const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
201
+ const packs = inspection.packs.discoveredPacks;
202
+ if (flagBool(args, 'json')) {
203
+ process.stdout.write(asJson(packs.map((p) => ({
204
+ packageName: p.packageName,
205
+ packageVersion: p.packageVersion,
206
+ valid: p.valid,
207
+ manifestPath: p.manifestPath,
208
+ contributionCounts: p.contributionCounts,
209
+ resolvedCounts: p.resolvedCounts,
210
+ signatureStatus: p.signatureStatus,
211
+ signatureMessage: p.signatureMessage,
212
+ loadError: p.loadError,
213
+ validationIssues: p.validationIssues,
214
+ }))) + '\n');
215
+ return 0;
216
+ }
217
+ process.stdout.write(header(`Packs (${packs.length})`));
218
+ if (packs.length === 0) {
219
+ process.stdout.write(' (no packs discovered in node_modules)\n');
220
+ return 0;
221
+ }
222
+ for (const p of packs) {
223
+ const c = p.contributionCounts;
224
+ const r = p.resolvedCounts;
225
+ process.stdout.write(` ${statusLabel(p.valid)} ${p.packageName}@${p.packageVersion}\n`);
226
+ process.stdout.write(` files: k=${c.knowledgeFiles} r=${c.ruleFiles} p=${c.pathFiles} t=${c.templateFiles} pl=${c.pipelineFiles} d=${c.docsFiles}\n`);
227
+ if (r) {
228
+ const totalEntries = r.knowledgeEntries + r.rules + r.pathConventions;
229
+ process.stdout.write(` resolved: entries=${totalEntries} templates=${r.templates} pipelines=${r.pipelines} docs=${r.docs}\n`);
230
+ }
231
+ if (!p.valid) {
232
+ if (p.loadError)
233
+ process.stdout.write(` error: ${p.loadError}\n`);
234
+ for (const i of p.validationIssues) {
235
+ process.stdout.write(` issue: ${i.field}: ${i.message}\n`);
236
+ }
237
+ }
238
+ }
239
+ return 0;
240
+ },
241
+ };
242
+ export const packsGetCommand = {
243
+ name: 'get',
244
+ description: 'Show full info for one pack (by package name).',
245
+ usage: 'shrk [--cwd <dir>] packs get <packageName> [--json]',
246
+ async run(args) {
247
+ const id = args.positional[0];
248
+ if (!id) {
249
+ process.stderr.write('Usage: shrk packs get <packageName>\n');
250
+ return 2;
251
+ }
252
+ const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
253
+ const pack = inspection.packs.discoveredPacks.find((p) => p.packageName === id);
254
+ if (!pack) {
255
+ process.stderr.write(`No pack with name "${id}" was discovered.\n`);
256
+ return 1;
257
+ }
258
+ if (flagBool(args, 'json')) {
259
+ process.stdout.write(asJson(pack) + '\n');
260
+ return 0;
261
+ }
262
+ process.stdout.write(header(`Pack: ${pack.packageName}`));
263
+ process.stdout.write(kv('version', pack.packageVersion) + '\n');
264
+ process.stdout.write(kv('status', pack.valid ? 'valid' : 'invalid') + '\n');
265
+ process.stdout.write(kv('manifest', pack.manifestPath) + '\n');
266
+ process.stdout.write(kv('package root', pack.packageRoot) + '\n');
267
+ if (pack.manifest?.info.description) {
268
+ process.stdout.write(kv('description', pack.manifest.info.description) + '\n');
269
+ }
270
+ const c = pack.contributionCounts;
271
+ process.stdout.write('\nContribution files:\n');
272
+ process.stdout.write(` knowledge files: ${c.knowledgeFiles}\n`);
273
+ process.stdout.write(` rule files: ${c.ruleFiles}\n`);
274
+ process.stdout.write(` path files: ${c.pathFiles}\n`);
275
+ process.stdout.write(` template files: ${c.templateFiles}\n`);
276
+ process.stdout.write(` pipeline files: ${c.pipelineFiles}\n`);
277
+ process.stdout.write(` docs files: ${c.docsFiles}\n`);
278
+ process.stdout.write(` scaffold pattern files: ${c.scaffoldPatternFiles}\n`);
279
+ if (pack.resolvedCounts) {
280
+ const r = pack.resolvedCounts;
281
+ process.stdout.write('\nResolved (after dedup against local):\n');
282
+ process.stdout.write(` knowledge entries: ${r.knowledgeEntries}\n`);
283
+ process.stdout.write(` rules: ${r.rules}\n`);
284
+ process.stdout.write(` path conventions: ${r.pathConventions}\n`);
285
+ process.stdout.write(` templates: ${r.templates}\n`);
286
+ process.stdout.write(` pipelines: ${r.pipelines}\n`);
287
+ process.stdout.write(` docs: ${r.docs}\n`);
288
+ process.stdout.write(` scaffold patterns: ${r.scaffoldPatterns ?? 0}\n`);
289
+ }
290
+ if (pack.signatureStatus) {
291
+ process.stdout.write('\nSignature:\n');
292
+ process.stdout.write(` status: ${pack.signatureStatus}\n`);
293
+ if (pack.signatureMessage) {
294
+ process.stdout.write(` message: ${pack.signatureMessage}\n`);
295
+ }
296
+ }
297
+ if (pack.loadError)
298
+ process.stdout.write(`\nLoad error: ${pack.loadError}\n`);
299
+ if (pack.validationIssues.length) {
300
+ process.stdout.write('\nValidation issues:\n');
301
+ for (const i of pack.validationIssues) {
302
+ process.stdout.write(` ${i.field}: ${i.message}\n`);
303
+ }
304
+ }
305
+ if (pack.manifest?.postInstallNotes?.length) {
306
+ process.stdout.write('\nPost-install notes:\n');
307
+ for (const n of pack.manifest.postInstallNotes) {
308
+ process.stdout.write(` • ${n}\n`);
309
+ }
310
+ }
311
+ return 0;
312
+ },
313
+ };
314
+ export const packsInspectCommand = {
315
+ name: 'inspect',
316
+ description: 'Inspect pack discovery: scanned packages, valid/invalid counts, warnings.',
317
+ usage: 'shrk [--cwd <dir>] packs inspect [--json]',
318
+ async run(args) {
319
+ const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
320
+ const { packs } = inspection;
321
+ if (flagBool(args, 'json')) {
322
+ process.stdout.write(asJson({
323
+ projectRoot: packs.projectRoot,
324
+ nodeModulesPath: packs.nodeModulesPath,
325
+ nodeModulesExists: packs.nodeModulesExists,
326
+ scannedPackageCount: packs.scannedPackageCount,
327
+ discoveredPackCount: packs.discoveredPacks.length,
328
+ validPackCount: packs.validPacks.length,
329
+ invalidPackCount: packs.invalidPacks.length,
330
+ warnings: packs.warnings,
331
+ }) + '\n');
332
+ return 0;
333
+ }
334
+ // Aggregate resolved counts across valid packs.
335
+ const totals = { entries: 0, templates: 0, pipelines: 0, docs: 0, scaffoldPatterns: 0 };
336
+ for (const p of packs.validPacks) {
337
+ const r = p.resolvedCounts;
338
+ if (!r)
339
+ continue;
340
+ totals.entries += r.knowledgeEntries + r.rules + r.pathConventions;
341
+ totals.templates += r.templates;
342
+ totals.pipelines += r.pipelines;
343
+ totals.docs += r.docs;
344
+ totals.scaffoldPatterns += r.scaffoldPatterns ?? 0;
345
+ }
346
+ process.stdout.write(header('Pack discovery'));
347
+ process.stdout.write(kv('project root', packs.projectRoot) + '\n');
348
+ process.stdout.write(kv('node_modules', packs.nodeModulesPath) + '\n');
349
+ process.stdout.write(kv('exists', packs.nodeModulesExists ? 'yes' : 'no') + '\n');
350
+ process.stdout.write(kv('scanned packages', packs.scannedPackageCount) + '\n');
351
+ process.stdout.write(kv('total resolved', `entries=${totals.entries} templates=${totals.templates} pipelines=${totals.pipelines} docs=${totals.docs} scaffoldPatterns=${totals.scaffoldPatterns}`) + '\n');
352
+ process.stdout.write(kv('discovered packs', packs.discoveredPacks.length) + '\n');
353
+ process.stdout.write(kv('valid', packs.validPacks.length) + '\n');
354
+ process.stdout.write(kv('invalid', packs.invalidPacks.length) + '\n');
355
+ if (packs.warnings.length) {
356
+ process.stdout.write('\nWarnings:\n');
357
+ for (const w of packs.warnings)
358
+ process.stdout.write(` • ${w}\n`);
359
+ }
360
+ return 0;
361
+ },
362
+ };
363
+ export const packsDoctorCommand = {
364
+ name: 'doctor',
365
+ description: 'Validate pack discovery: invalid manifests, missing files, empty contributions, duplicates, template/pipeline quality, action-hint coverage, signatures. `--release` folds pack-release-check findings into the report. `--signature-explain` adds per-pack signature explanation.',
366
+ usage: 'shrk [--cwd <dir>] packs doctor [--verify-signatures] [--require-signatures] [--release] [--strict] [--secret <secret>] [--signature-explain] [--json]',
367
+ async run(args) {
368
+ const verify = flagBool(args, 'verify-signatures') || flagBool(args, 'require-signatures');
369
+ const required = flagBool(args, 'require-signatures');
370
+ const release = flagBool(args, 'release');
371
+ const strict = flagBool(args, 'strict');
372
+ const secret = flagString(args, 'secret');
373
+ const signatureExplain = flagBool(args, 'signature-explain');
374
+ const inspection = await inspectSharkcraft({
375
+ cwd: resolveCwd(args),
376
+ ...(verify ? { verifyPackSignatures: true } : {}),
377
+ ...(secret !== undefined ? { packSecret: secret } : {}),
378
+ });
379
+ const report = buildPackDoctorReport(inspection, { requireSignatures: required });
380
+ if (release) {
381
+ const releaseChecks = await runPackReleaseChecksForReport(inspection);
382
+ mergePackReleaseChecks(inspection, report, releaseChecks, { strict });
383
+ }
384
+ let signatureExplanation;
385
+ if (signatureExplain) {
386
+ signatureExplanation = explainPackSignatureStatus(inspection, { requireSignatures: required });
387
+ }
388
+ if (flagBool(args, 'json')) {
389
+ process.stdout.write(asJson({
390
+ passed: report.passed,
391
+ packsChecked: report.packsChecked,
392
+ summary: report.summary,
393
+ discoveredPackCount: inspection.packs.discoveredPacks.length,
394
+ validPackCount: inspection.packs.validPacks.length,
395
+ invalidPackCount: inspection.packs.invalidPacks.length,
396
+ issues: report.issues,
397
+ ...(report.releaseChecks ? { releaseChecks: report.releaseChecks } : {}),
398
+ ...(signatureExplanation ? { signatureExplanation } : {}),
399
+ }) + '\n');
400
+ return report.passed ? 0 : 1;
401
+ }
402
+ process.stdout.write(header('Pack doctor'));
403
+ process.stdout.write(kv('discovered', String(inspection.packs.discoveredPacks.length)) + '\n');
404
+ process.stdout.write(kv('valid', String(inspection.packs.validPacks.length)) + '\n');
405
+ process.stdout.write(kv('invalid', String(inspection.packs.invalidPacks.length)) + '\n');
406
+ const modeParts = [];
407
+ if (required)
408
+ modeParts.push('require signatures');
409
+ else if (verify)
410
+ modeParts.push('verify signatures');
411
+ else
412
+ modeParts.push('structure only');
413
+ if (release)
414
+ modeParts.push('release-check');
415
+ if (strict)
416
+ modeParts.push('strict');
417
+ process.stdout.write(kv('mode', modeParts.join(' + ')) + '\n\n');
418
+ if (report.issues.length === 0) {
419
+ process.stdout.write('No pack issues.\n');
420
+ }
421
+ else {
422
+ for (const i of report.issues) {
423
+ process.stdout.write(`${i.severity.toUpperCase().padEnd(8)} ${i.packageName.padEnd(40)} ${i.code.padEnd(28)} ${i.message}\n`);
424
+ if (i.suggestion) {
425
+ process.stdout.write(` ↳ ${i.suggestion}\n`);
426
+ }
427
+ if (i.suggestedCommand) {
428
+ process.stdout.write(` $ ${i.suggestedCommand}\n`);
429
+ }
430
+ }
431
+ }
432
+ process.stdout.write(`\nSummary: ${report.summary.errors} errors, ${report.summary.warnings} warnings, ${report.summary.info} info\n`);
433
+ process.stdout.write(`\nVerdict: ${report.passed ? 'OK ✓' : 'pack issues need attention'}\n`);
434
+ if (signatureExplanation) {
435
+ process.stdout.write('\n--- Signature explanation ---\n');
436
+ process.stdout.write(`secret env: ${signatureExplanation.secretAvailable ? 'set' : 'NOT set'}\n`);
437
+ process.stdout.write(`mode: ${signatureExplanation.mode}\n\n`);
438
+ for (const p of signatureExplanation.packs) {
439
+ process.stdout.write(` ${p.state.padEnd(14)} ${p.packageName}@${p.packageVersion}\n`);
440
+ process.stdout.write(` ${p.explanation}\n`);
441
+ if (p.nextCommand)
442
+ process.stdout.write(` next: ${p.nextCommand}\n`);
443
+ }
444
+ }
445
+ return report.passed ? 0 : 1;
446
+ },
447
+ };
448
+ export const packsVerifyCommand = {
449
+ name: 'verify',
450
+ description: 'Verify HMAC signatures on every discovered pack. Unsigned packs are reported but do not fail.',
451
+ usage: 'shrk [--cwd <dir>] packs verify [--secret <secret>] [--required] [--json]',
452
+ async run(args) {
453
+ const secret = flagString(args, 'secret');
454
+ const inspection = await inspectSharkcraft({
455
+ cwd: resolveCwd(args),
456
+ verifyPackSignatures: true,
457
+ ...(secret !== undefined ? { packSecret: secret } : {}),
458
+ });
459
+ const required = flagBool(args, 'required');
460
+ const rows = inspection.packs.discoveredPacks.map((p) => ({
461
+ packageName: p.packageName,
462
+ packageVersion: p.packageVersion,
463
+ valid: p.valid,
464
+ signatureStatus: p.signatureStatus ?? 'not-checked',
465
+ signatureMessage: p.signatureMessage,
466
+ }));
467
+ const tampered = rows.some((r) => r.signatureStatus === 'invalid-signature');
468
+ const unsigned = rows.some((r) => r.signatureStatus === 'missing-signature');
469
+ const passed = !tampered && (!required || !unsigned);
470
+ if (flagBool(args, 'json')) {
471
+ process.stdout.write(asJson({
472
+ passed,
473
+ required,
474
+ tampered,
475
+ unsignedPresent: unsigned,
476
+ packs: rows,
477
+ }) + '\n');
478
+ return passed ? 0 : 1;
479
+ }
480
+ process.stdout.write(header(`Pack signatures (${rows.length})`));
481
+ if (rows.length === 0) {
482
+ process.stdout.write('No packs discovered.\n');
483
+ return 0;
484
+ }
485
+ for (const r of rows) {
486
+ const tag = r.signatureStatus === 'verified'
487
+ ? 'VERIFIED'
488
+ : r.signatureStatus === 'invalid-signature'
489
+ ? 'TAMPERED'
490
+ : r.signatureStatus === 'missing-signature'
491
+ ? 'UNSIGNED'
492
+ : r.signatureStatus === 'missing-secret'
493
+ ? 'NO SECRET'
494
+ : 'NOT CHECKED';
495
+ process.stdout.write(` ${tag.padEnd(12)} ${r.packageName.padEnd(40)} ${r.signatureMessage ?? ''}\n`);
496
+ }
497
+ process.stdout.write(`\nVerdict: ${passed ? 'all signatures OK ✓' : tampered ? 'TAMPERED pack detected — abort!' : 'unsigned pack present (use --required to fail)'}\n`);
498
+ if (!secret && !process.env[PACK_SECRET_ENV]) {
499
+ process.stdout.write(`(Tip: set ${PACK_SECRET_ENV} or pass --secret to verify signed packs.)\n`);
500
+ }
501
+ return passed ? 0 : 1;
502
+ },
503
+ };
504
+ /**
505
+ * Resolve the manifest source path given either a direct manifest file or a
506
+ * package directory. If a directory is passed, read its package.json's
507
+ * `sharkcraft.manifest` (or `sharkcraft` if it's a string) and resolve that.
508
+ */
509
+ function resolveManifestInput(input) {
510
+ const absolute = nodePath.resolve(input);
511
+ if (!existsSync(absolute)) {
512
+ return { error: `Input does not exist: ${absolute}` };
513
+ }
514
+ const stat = statSync(absolute);
515
+ if (stat.isFile()) {
516
+ return { manifestPath: absolute };
517
+ }
518
+ if (!stat.isDirectory()) {
519
+ return { error: `Input is neither a file nor a directory: ${absolute}` };
520
+ }
521
+ const pkgJsonPath = nodePath.join(absolute, 'package.json');
522
+ if (!existsSync(pkgJsonPath)) {
523
+ return { error: `Directory has no package.json: ${absolute}` };
524
+ }
525
+ let pkg;
526
+ try {
527
+ pkg = JSON.parse(readFileSync(pkgJsonPath, 'utf8'));
528
+ }
529
+ catch (e) {
530
+ return { error: `Failed to parse package.json: ${e.message}` };
531
+ }
532
+ const sc = pkg.sharkcraft;
533
+ let manifestRel;
534
+ if (typeof sc === 'string')
535
+ manifestRel = sc;
536
+ else if (sc && typeof sc === 'object') {
537
+ const m = sc.manifest;
538
+ if (typeof m === 'string')
539
+ manifestRel = m;
540
+ }
541
+ if (!manifestRel) {
542
+ return {
543
+ error: `package.json does not declare sharkcraft.manifest at ${pkgJsonPath}`,
544
+ };
545
+ }
546
+ const manifestPath = nodePath.resolve(absolute, manifestRel);
547
+ if (!existsSync(manifestPath)) {
548
+ return { error: `sharkcraft.manifest points at a non-existent file: ${manifestPath}` };
549
+ }
550
+ return { manifestPath };
551
+ }
552
+ async function loadManifestFromPath(manifestPath) {
553
+ if (manifestPath.endsWith('.json')) {
554
+ return JSON.parse(readFileSync(manifestPath, 'utf8'));
555
+ }
556
+ const mod = (await import(__rewriteRelativeImportExtension(pathToFileURL(manifestPath).href)));
557
+ return (mod.default ?? mod);
558
+ }
559
+ export const packsSignCommand = {
560
+ name: 'sign',
561
+ description: 'Sign a pack manifest with HMAC-SHA256 and write a .signed.json next to the source. Accepts either the manifest file directly or a package directory (uses package.json sharkcraft.manifest). --if-needed signs only when stale; --check-only never signs; --print-command prints the exact signing command. --dev signs with the well-known dev secret and marks the signature `dev: true` (NOT release-trusted).',
562
+ usage: 'shrk packs sign <path-to-manifest.ts | package-dir> [--output <out.json>] [--secret <secret>] [--key-id <id>] [--dev] [--verify-after-sign] [--if-needed] [--check-only] [--print-command] [--write-todo] [--json]',
563
+ async run(args) {
564
+ const input = args.positional[0];
565
+ if (!input) {
566
+ process.stderr.write('Usage: shrk packs sign <path-to-manifest.ts | package-dir> [--output <out.json>]\n');
567
+ return 2;
568
+ }
569
+ // `--print-command` is a fallback for agents without the
570
+ // pack secret. Resolve cheaply (no manifest load required).
571
+ const ifNeeded = flagBool(args, 'if-needed');
572
+ const checkOnly = flagBool(args, 'check-only');
573
+ const printCommand = flagBool(args, 'print-command');
574
+ const writeTodo = flagBool(args, 'write-todo');
575
+ const secretFromEnv = Boolean(process.env[PACK_SECRET_ENV]);
576
+ const secretFromFlag = Boolean(flagString(args, 'secret'));
577
+ const haveSecret = secretFromEnv || secretFromFlag;
578
+ if (printCommand) {
579
+ const printed = haveSecret
580
+ ? `shrk packs sign ${input}`
581
+ : `${PACK_SECRET_ENV}=<secret> shrk packs sign ${input}`;
582
+ if (flagBool(args, 'json')) {
583
+ process.stdout.write(asJson({ printCommand: printed, secretAvailable: haveSecret }) + '\n');
584
+ }
585
+ else {
586
+ process.stdout.write(`${printed}\n`);
587
+ }
588
+ return 0;
589
+ }
590
+ const resolved = resolveManifestInput(input);
591
+ if ('error' in resolved) {
592
+ process.stderr.write(resolved.error + '\n');
593
+ return 1;
594
+ }
595
+ const manifestPath = resolved.manifestPath;
596
+ if (ifNeeded || checkOnly) {
597
+ // Inspect the workspace and decide if this pack is stale.
598
+ const inspection = await inspectSharkcraft({ cwd: resolveCwd(args) });
599
+ const sigReport = buildPackSignatureStatusReport(inspection);
600
+ const matching = sigReport.packs.find((p) => p.packageRoot === nodePath.dirname(manifestPath) ||
601
+ p.packageRoot.endsWith(nodePath.dirname(input)) ||
602
+ manifestPath.startsWith(p.packageRoot));
603
+ const status = matching?.status ?? 'unknown';
604
+ if (checkOnly) {
605
+ if (flagBool(args, 'json')) {
606
+ process.stdout.write(asJson({ checkOnly: true, status, secretAvailable: haveSecret, pack: matching ?? null }) + '\n');
607
+ }
608
+ else {
609
+ process.stdout.write(`pack status: ${status}\n`);
610
+ if (matching?.reason)
611
+ process.stdout.write(`reason: ${matching.reason}\n`);
612
+ process.stdout.write(`secret env: ${haveSecret ? 'set' : 'NOT set'}\n`);
613
+ }
614
+ // Exit 0 only if the pack is "present"; otherwise non-zero.
615
+ return status === 'present' ? 0 : 1;
616
+ }
617
+ if (ifNeeded && status === 'present') {
618
+ if (flagBool(args, 'json')) {
619
+ process.stdout.write(asJson({ skipped: true, reason: 'signature is current', status }) + '\n');
620
+ }
621
+ else {
622
+ process.stdout.write(`Skipping sign: signature is current (status=${status}).\n`);
623
+ }
624
+ return 0;
625
+ }
626
+ if (ifNeeded && !haveSecret) {
627
+ // Honest fallback: report and offer the TODO write.
628
+ const todo = `Pack signature for ${input} is ${status}. Re-sign with:\n ${PACK_SECRET_ENV}=<secret> shrk packs sign ${input}\n`;
629
+ if (writeTodo) {
630
+ const cwd = resolveCwd(args);
631
+ const dir = nodePath.join(cwd, '.sharkcraft', 'reports');
632
+ if (!existsSync(dir))
633
+ mkdirSync(dir, { recursive: true });
634
+ const out = nodePath.join(dir, `pack-sign-todo-${nodePath.basename(input)}.md`);
635
+ writeFileSync(out, `# Pack signing TODO\n\n${todo}\n`, 'utf8');
636
+ process.stdout.write(`Wrote signing TODO: ${out}\n`);
637
+ }
638
+ if (flagBool(args, 'json')) {
639
+ process.stdout.write(asJson({ skipped: true, reason: 'secret not available', status, todo }) + '\n');
640
+ }
641
+ else {
642
+ process.stdout.write(`Cannot sign — ${PACK_SECRET_ENV} not set. Status: ${status}.\n`);
643
+ process.stdout.write(todo);
644
+ }
645
+ return 1;
646
+ }
647
+ // Otherwise fall through to the actual sign path.
648
+ }
649
+ let manifest;
650
+ try {
651
+ manifest = await loadManifestFromPath(manifestPath);
652
+ }
653
+ catch (e) {
654
+ process.stderr.write(`Failed to load manifest: ${e.message}\n`);
655
+ return 1;
656
+ }
657
+ const valid = validatePackManifest(manifest);
658
+ if (!valid.valid) {
659
+ process.stderr.write(`Refusing to sign: manifest is structurally invalid (${valid.issues
660
+ .map((i) => i.field)
661
+ .join(', ')})\n`);
662
+ return 1;
663
+ }
664
+ const secret = flagString(args, 'secret');
665
+ const keyId = flagString(args, 'key-id');
666
+ const dev = flagBool(args, 'dev');
667
+ const result = signPackManifest(manifest, {
668
+ ...(secret !== undefined ? { secret } : {}),
669
+ ...(keyId !== undefined ? { keyId } : {}),
670
+ ...(dev ? { dev: true } : {}),
671
+ });
672
+ if (!result.ok) {
673
+ process.stderr.write(result.message + '\n');
674
+ return 1;
675
+ }
676
+ const outArg = flagString(args, 'output') ?? flagString(args, 'out');
677
+ const outPath = outArg
678
+ ? nodePath.resolve(outArg)
679
+ : nodePath
680
+ .join(nodePath.dirname(manifestPath), nodePath.basename(manifestPath).replace(/\.(ts|js|json)$/i, ''))
681
+ .concat('.signed.json');
682
+ writeFileSync(outPath, JSON.stringify(result.manifest, null, 2) + '\n', 'utf8');
683
+ // Optional post-sign verification.
684
+ let verifyOutcome = 'skipped';
685
+ let verifyMessage = '';
686
+ if (flagBool(args, 'verify-after-sign')) {
687
+ const v = verifyPackManifest(result.manifest, {
688
+ ...(secret !== undefined ? { secret } : {}),
689
+ });
690
+ verifyOutcome = v.ok ? 'verified' : 'failed';
691
+ verifyMessage = v.ok ? 'Signature verified.' : v.message;
692
+ }
693
+ if (flagBool(args, 'json')) {
694
+ process.stdout.write(asJson({
695
+ source: manifestPath,
696
+ outPath,
697
+ signature: result.signature,
698
+ verifyOutcome,
699
+ verifyMessage,
700
+ }) + '\n');
701
+ return verifyOutcome === 'failed' ? 1 : 0;
702
+ }
703
+ process.stdout.write(header('Pack manifest signed'));
704
+ process.stdout.write(kv('source', manifestPath) + '\n');
705
+ process.stdout.write(kv('output', outPath) + '\n');
706
+ process.stdout.write(kv('algo', result.signature.algo) + '\n');
707
+ process.stdout.write(kv('signed at', result.signature.signedAt) + '\n');
708
+ if (result.signature.keyId)
709
+ process.stdout.write(kv('key id', result.signature.keyId) + '\n');
710
+ if (verifyOutcome !== 'skipped') {
711
+ process.stdout.write(kv('verify-after-sign', `${verifyOutcome}${verifyMessage ? ` (${verifyMessage})` : ''}`) +
712
+ '\n');
713
+ }
714
+ process.stdout.write(`\n${result.signature.hmac}\n`);
715
+ process.stdout.write(`\nHow to consume:\n 1. Ship ${nodePath.basename(outPath)} alongside the pack (or replace package.json sharkcraft.manifest with the .signed.json path).\n 2. Set SHARKCRAFT_PACK_SECRET on the consumer machine and run \`shrk packs verify\`.\n`);
716
+ return verifyOutcome === 'failed' ? 1 : 0;
717
+ },
718
+ };
719
+ export const packsReleaseCheckCommand = {
720
+ name: 'release-check',
721
+ description: 'Run a deterministic release-readiness check on a pack: manifest validation, contribution loading, signature, files whitelist.',
722
+ usage: 'shrk packs release-check <path-to-pack> [--json]',
723
+ async run(args) {
724
+ const target = args.positional[0];
725
+ if (!target) {
726
+ process.stderr.write('Usage: shrk packs release-check <path-to-pack>\n');
727
+ return 2;
728
+ }
729
+ const cwd = resolveCwd(args);
730
+ const abs = nodePath.isAbsolute(target) ? target : nodePath.resolve(cwd, target);
731
+ const result = await runPackReleaseCheck(abs);
732
+ if (flagBool(args, 'json')) {
733
+ process.stdout.write(asJson(result) + '\n');
734
+ return result.passed ? 0 : 1;
735
+ }
736
+ process.stdout.write(header(`Pack release check`));
737
+ process.stdout.write(kv('pack', result.packPath) + '\n');
738
+ process.stdout.write(kv('manifest', result.manifestFile ?? '(none)') + '\n');
739
+ process.stdout.write(kv('contributions', String(result.contributionsFound)) + '\n');
740
+ process.stdout.write(kv('passed', String(result.passed)) + '\n\n');
741
+ if (result.findings.length === 0) {
742
+ process.stdout.write('No issues.\n');
743
+ return result.passed ? 0 : 1;
744
+ }
745
+ for (const f of result.findings) {
746
+ process.stdout.write(` ${f.severity.toUpperCase().padEnd(8)} ${f.code.padEnd(28)} ${f.message}\n`);
747
+ if (f.file)
748
+ process.stdout.write(` file: ${f.file}\n`);
749
+ if (f.suggestedFix)
750
+ process.stdout.write(` fix: ${f.suggestedFix}\n`);
751
+ if (f.suggestedCommand)
752
+ process.stdout.write(` $ ${f.suggestedCommand}\n`);
753
+ }
754
+ return result.passed ? 0 : 1;
755
+ },
756
+ };
757
+ export const packsCompatCommand = {
758
+ name: 'compat',
759
+ description: 'Inspect a pack\'s plugin-api symbol compatibility. Resolves the consumer\'s installed @shrkcrft/plugin-api and diffs against the pack\'s imports. Surfaces both helper-missing import errors (from release-check) and symbol-level diffs.',
760
+ usage: 'shrk packs compat <path-to-pack> [--consumer-root <path>] [--dist-aware] [--json]',
761
+ async run(args) {
762
+ const target = args.positional[0];
763
+ if (!target) {
764
+ process.stderr.write('Usage: shrk packs compat <path-to-pack> [--consumer-root <path>] [--dist-aware]\n');
765
+ return 2;
766
+ }
767
+ const cwd = resolveCwd(args);
768
+ const abs = nodePath.isAbsolute(target) ? target : nodePath.resolve(cwd, target);
769
+ const consumerRootRaw = flagString(args, 'consumer-root');
770
+ const consumerRoot = consumerRootRaw
771
+ ? nodePath.isAbsolute(consumerRootRaw)
772
+ ? consumerRootRaw
773
+ : nodePath.resolve(cwd, consumerRootRaw)
774
+ : null;
775
+ const distAware = flagBool(args, 'dist-aware');
776
+ // Run a release-check first; surfaces helper-missing diagnostics.
777
+ const release = await runPackReleaseCheck(abs);
778
+ const helperMissing = release.findings.filter((f) => f.code === 'contribution-helper-missing');
779
+ // Symbol-level diff against the consumer's installed plugin-api.
780
+ const symbol = checkPackSymbolCompat({ packPath: abs, consumerRoot, distAware });
781
+ const passed = helperMissing.length === 0 && symbol.compatible;
782
+ if (flagBool(args, 'json')) {
783
+ process.stdout.write(asJson({
784
+ schema: 'sharkcraft.pack-compat-check/v1',
785
+ pack: release.packPath,
786
+ manifest: release.manifestFile,
787
+ consumerRoot,
788
+ helperMissing: helperMissing.map((f) => ({
789
+ file: f.file,
790
+ message: f.message,
791
+ suggestedFix: f.suggestedFix,
792
+ suggestedCommand: f.suggestedCommand,
793
+ })),
794
+ symbolCompat: symbol,
795
+ passed,
796
+ }) + '\n');
797
+ return passed ? 0 : 1;
798
+ }
799
+ process.stdout.write(header('Pack compatibility'));
800
+ process.stdout.write(kv('pack', release.packPath) + '\n');
801
+ process.stdout.write(kv('consumer root', consumerRoot ?? '(not specified)') + '\n');
802
+ process.stdout.write(kv('plugin-api source', symbol.pluginApiSource ?? '(not found)') + '\n');
803
+ process.stdout.write(kv('plugin-api resolution', symbol.pluginApiResolution) + '\n');
804
+ process.stdout.write(kv('available symbols', String(symbol.availableSymbols.length)) + '\n');
805
+ process.stdout.write(kv('source mode', symbol.sourceMode) + '\n');
806
+ process.stdout.write(kv('confidence', symbol.confidence) + '\n');
807
+ process.stdout.write(kv('files inspected', String(symbol.filesInspected.length)) + '\n');
808
+ process.stdout.write(kv('helper-missing findings', String(helperMissing.length)) + '\n');
809
+ process.stdout.write(kv('missing symbols', String(symbol.missingSymbols.length)) + '\n\n');
810
+ if (helperMissing.length === 0 && symbol.missingSymbols.length === 0) {
811
+ process.stdout.write('No backwards-compatibility issues detected.\n');
812
+ if (symbol.suggestions.length > 0) {
813
+ for (const s of symbol.suggestions)
814
+ process.stdout.write(` note: ${s}\n`);
815
+ }
816
+ return 0;
817
+ }
818
+ if (helperMissing.length > 0) {
819
+ process.stdout.write('Helper-missing import errors:\n');
820
+ for (const f of helperMissing) {
821
+ process.stdout.write(` ${f.message}\n`);
822
+ if (f.suggestedFix)
823
+ process.stdout.write(` fix: ${f.suggestedFix}\n`);
824
+ if (f.suggestedCommand)
825
+ process.stdout.write(` $ ${f.suggestedCommand}\n`);
826
+ }
827
+ }
828
+ if (symbol.missingSymbols.length > 0) {
829
+ process.stdout.write('\nMissing plugin-api symbols:\n');
830
+ for (const f of symbol.findings.filter((x) => x.status === 'missing')) {
831
+ process.stdout.write(` - ${f.symbol}\n`);
832
+ for (const file of f.files.slice(0, 5))
833
+ process.stdout.write(` used in ${file}\n`);
834
+ }
835
+ process.stdout.write('\nSuggested fixes:\n');
836
+ for (const s of symbol.suggestions)
837
+ process.stdout.write(` ${s}\n`);
838
+ }
839
+ return 1;
840
+ },
841
+ };
842
+ // ──────────────────────────────────────────────────────────────────────────
843
+ // Pack-author developer UX
844
+ // ──────────────────────────────────────────────────────────────────────────
845
+ export const packsDevStatusCommand = {
846
+ name: 'dev-status',
847
+ description: 'Inspect a pack under development: how the consumer sees it, signed-manifest staleness, contribution counts. Read-only.',
848
+ usage: 'shrk packs dev-status <packPath> [--consumer <repo>] [--json]',
849
+ async run(args) {
850
+ const { buildPackDevStatus, renderPackDevStatusText } = await import('@shrkcrft/inspector');
851
+ const packPath = args.positional[0];
852
+ if (!packPath) {
853
+ process.stderr.write('Usage: shrk packs dev-status <packPath>\n');
854
+ return 2;
855
+ }
856
+ const consumer = flagString(args, 'consumer');
857
+ const abs = nodePath.isAbsolute(packPath) ? packPath : nodePath.resolve(resolveCwd(args), packPath);
858
+ const consumerAbs = consumer
859
+ ? (nodePath.isAbsolute(consumer) ? consumer : nodePath.resolve(resolveCwd(args), consumer))
860
+ : undefined;
861
+ const status = buildPackDevStatus({
862
+ packPath: abs,
863
+ ...(consumerAbs ? { consumerPath: consumerAbs } : {}),
864
+ });
865
+ if (flagBool(args, 'json')) {
866
+ process.stdout.write(asJson(status) + '\n');
867
+ return 0;
868
+ }
869
+ process.stdout.write(renderPackDevStatusText(status));
870
+ return 0;
871
+ },
872
+ };
873
+ export const packsWatchCommand = {
874
+ name: 'watch',
875
+ description: 'Watch pack assets and re-run pack doctor on change. Never auto-signs; signing remains explicit.',
876
+ usage: 'shrk packs watch <packPath> [--cwd <consumer>] [--command <cmd>] [--debounce <ms>] [--dry-run]',
877
+ async run(args) {
878
+ const { planPackWatchCommand } = await import('@shrkcrft/inspector');
879
+ const packPath = args.positional[0];
880
+ if (!packPath) {
881
+ process.stderr.write('Usage: shrk packs watch <packPath>\n');
882
+ return 2;
883
+ }
884
+ const abs = nodePath.isAbsolute(packPath) ? packPath : nodePath.resolve(resolveCwd(args), packPath);
885
+ const command = flagString(args, 'command');
886
+ const debounceStr = flagString(args, 'debounce');
887
+ const debounceMs = debounceStr ? Number(debounceStr) : undefined;
888
+ const consumer = flagString(args, 'consumer');
889
+ const plan = planPackWatchCommand({
890
+ packPath: abs,
891
+ ...(consumer ? { consumerPath: consumer } : {}),
892
+ ...(command ? { command } : {}),
893
+ ...(debounceMs ? { debounceMs } : {}),
894
+ });
895
+ if (flagBool(args, 'dry-run')) {
896
+ if (flagBool(args, 'json')) {
897
+ process.stdout.write(asJson(plan) + '\n');
898
+ return 0;
899
+ }
900
+ process.stdout.write('=== Pack watch plan ===\n');
901
+ process.stdout.write(kv('pack', plan.packPath) + '\n');
902
+ if (plan.consumerPath)
903
+ process.stdout.write(kv('consumer', plan.consumerPath) + '\n');
904
+ process.stdout.write(kv('command', plan.command) + '\n');
905
+ process.stdout.write(kv('debounceMs', String(plan.debounceMs)) + '\n');
906
+ process.stdout.write('Globs:\n');
907
+ for (const g of plan.globs)
908
+ process.stdout.write(` • ${g}\n`);
909
+ process.stdout.write('\nDry-run: no watcher started, no commands executed.\n');
910
+ return 0;
911
+ }
912
+ // Live watcher mode — uses fs.watch with debouncing.
913
+ const fs = await import('node:fs');
914
+ const child = await import('node:child_process');
915
+ let timer = null;
916
+ let running = false;
917
+ const trigger = () => {
918
+ if (running)
919
+ return;
920
+ if (timer)
921
+ clearTimeout(timer);
922
+ timer = setTimeout(() => {
923
+ running = true;
924
+ process.stdout.write(`[watch] running: ${plan.command}\n`);
925
+ const r = child.spawnSync('bash', ['-lc', plan.command], {
926
+ cwd: abs,
927
+ stdio: 'inherit',
928
+ });
929
+ running = false;
930
+ process.stdout.write(`[watch] exit ${r.status ?? 0}; waiting for next change.\n`);
931
+ }, plan.debounceMs);
932
+ };
933
+ const watchRoots = [
934
+ nodePath.join(abs, 'src', 'assets'),
935
+ nodePath.join(abs, 'package.json'),
936
+ nodePath.join(abs, 'manifest.json'),
937
+ nodePath.join(abs, 'README.md'),
938
+ ];
939
+ for (const root of watchRoots) {
940
+ if (!fs.existsSync(root))
941
+ continue;
942
+ try {
943
+ fs.watch(root, { recursive: true }, trigger);
944
+ }
945
+ catch {
946
+ try {
947
+ fs.watch(root, trigger);
948
+ }
949
+ catch {
950
+ /* ignore */
951
+ }
952
+ }
953
+ }
954
+ process.stdout.write(`[watch] running. ctrl+c to stop.\n`);
955
+ trigger();
956
+ return await new Promise(() => undefined);
957
+ },
958
+ };