@codewalla_india/openspec 1.0.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 (356) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +225 -0
  3. package/bin/openspec.js +5 -0
  4. package/dist/cli/index.d.ts +10 -0
  5. package/dist/cli/index.js +548 -0
  6. package/dist/commands/change.d.ts +39 -0
  7. package/dist/commands/change.js +279 -0
  8. package/dist/commands/completion.d.ts +72 -0
  9. package/dist/commands/completion.js +264 -0
  10. package/dist/commands/config.d.ts +36 -0
  11. package/dist/commands/config.js +552 -0
  12. package/dist/commands/context.d.ts +3 -0
  13. package/dist/commands/context.js +155 -0
  14. package/dist/commands/doctor.d.ts +8 -0
  15. package/dist/commands/doctor.js +163 -0
  16. package/dist/commands/feedback.d.ts +9 -0
  17. package/dist/commands/feedback.js +183 -0
  18. package/dist/commands/schema.d.ts +6 -0
  19. package/dist/commands/schema.js +869 -0
  20. package/dist/commands/shared-gather.d.ts +14 -0
  21. package/dist/commands/shared-gather.js +31 -0
  22. package/dist/commands/shared-output.d.ts +18 -0
  23. package/dist/commands/shared-output.js +61 -0
  24. package/dist/commands/show.d.ts +19 -0
  25. package/dist/commands/show.js +177 -0
  26. package/dist/commands/spec.d.ts +19 -0
  27. package/dist/commands/spec.js +236 -0
  28. package/dist/commands/store.d.ts +3 -0
  29. package/dist/commands/store.js +547 -0
  30. package/dist/commands/validate.d.ts +26 -0
  31. package/dist/commands/validate.js +330 -0
  32. package/dist/commands/workflow/index.d.ts +17 -0
  33. package/dist/commands/workflow/index.js +12 -0
  34. package/dist/commands/workflow/instructions.d.ts +45 -0
  35. package/dist/commands/workflow/instructions.js +500 -0
  36. package/dist/commands/workflow/new-change.d.ts +20 -0
  37. package/dist/commands/workflow/new-change.js +106 -0
  38. package/dist/commands/workflow/schemas.d.ts +10 -0
  39. package/dist/commands/workflow/schemas.js +34 -0
  40. package/dist/commands/workflow/shared.d.ts +84 -0
  41. package/dist/commands/workflow/shared.js +133 -0
  42. package/dist/commands/workflow/status.d.ts +16 -0
  43. package/dist/commands/workflow/status.js +92 -0
  44. package/dist/commands/workflow/templates.d.ts +16 -0
  45. package/dist/commands/workflow/templates.js +69 -0
  46. package/dist/commands/workset-input.d.ts +19 -0
  47. package/dist/commands/workset-input.js +112 -0
  48. package/dist/commands/workset-prompts.d.ts +12 -0
  49. package/dist/commands/workset-prompts.js +143 -0
  50. package/dist/commands/workset.d.ts +25 -0
  51. package/dist/commands/workset.js +446 -0
  52. package/dist/core/archive.d.ts +22 -0
  53. package/dist/core/archive.js +471 -0
  54. package/dist/core/artifact-graph/graph.d.ts +56 -0
  55. package/dist/core/artifact-graph/graph.js +141 -0
  56. package/dist/core/artifact-graph/index.d.ts +9 -0
  57. package/dist/core/artifact-graph/index.js +14 -0
  58. package/dist/core/artifact-graph/instruction-loader.d.ts +188 -0
  59. package/dist/core/artifact-graph/instruction-loader.js +233 -0
  60. package/dist/core/artifact-graph/outputs.d.ts +14 -0
  61. package/dist/core/artifact-graph/outputs.js +39 -0
  62. package/dist/core/artifact-graph/resolver.d.ts +81 -0
  63. package/dist/core/artifact-graph/resolver.js +257 -0
  64. package/dist/core/artifact-graph/schema.d.ts +13 -0
  65. package/dist/core/artifact-graph/schema.js +108 -0
  66. package/dist/core/artifact-graph/state.d.ts +12 -0
  67. package/dist/core/artifact-graph/state.js +31 -0
  68. package/dist/core/artifact-graph/types.d.ts +40 -0
  69. package/dist/core/artifact-graph/types.js +29 -0
  70. package/dist/core/available-tools.d.ts +17 -0
  71. package/dist/core/available-tools.js +43 -0
  72. package/dist/core/change-metadata/index.d.ts +2 -0
  73. package/dist/core/change-metadata/index.js +2 -0
  74. package/dist/core/change-metadata/schema.d.ts +19 -0
  75. package/dist/core/change-metadata/schema.js +30 -0
  76. package/dist/core/change-status-policy.d.ts +37 -0
  77. package/dist/core/change-status-policy.js +35 -0
  78. package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
  79. package/dist/core/command-generation/adapters/amazon-q.js +26 -0
  80. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  81. package/dist/core/command-generation/adapters/antigravity.js +26 -0
  82. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  83. package/dist/core/command-generation/adapters/auggie.js +27 -0
  84. package/dist/core/command-generation/adapters/bob.d.ts +14 -0
  85. package/dist/core/command-generation/adapters/bob.js +32 -0
  86. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  87. package/dist/core/command-generation/adapters/claude.js +37 -0
  88. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  89. package/dist/core/command-generation/adapters/cline.js +27 -0
  90. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  91. package/dist/core/command-generation/adapters/codebuddy.js +28 -0
  92. package/dist/core/command-generation/adapters/codex.d.ts +16 -0
  93. package/dist/core/command-generation/adapters/codex.js +39 -0
  94. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  95. package/dist/core/command-generation/adapters/continue.js +28 -0
  96. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  97. package/dist/core/command-generation/adapters/costrict.js +27 -0
  98. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  99. package/dist/core/command-generation/adapters/crush.js +30 -0
  100. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  101. package/dist/core/command-generation/adapters/cursor.js +31 -0
  102. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  103. package/dist/core/command-generation/adapters/factory.js +27 -0
  104. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  105. package/dist/core/command-generation/adapters/gemini.js +26 -0
  106. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  107. package/dist/core/command-generation/adapters/github-copilot.js +26 -0
  108. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  109. package/dist/core/command-generation/adapters/iflow.js +29 -0
  110. package/dist/core/command-generation/adapters/index.d.ts +32 -0
  111. package/dist/core/command-generation/adapters/index.js +32 -0
  112. package/dist/core/command-generation/adapters/junie.d.ts +13 -0
  113. package/dist/core/command-generation/adapters/junie.js +26 -0
  114. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  115. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  116. package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
  117. package/dist/core/command-generation/adapters/kiro.js +26 -0
  118. package/dist/core/command-generation/adapters/lingma.d.ts +13 -0
  119. package/dist/core/command-generation/adapters/lingma.js +30 -0
  120. package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
  121. package/dist/core/command-generation/adapters/opencode.js +29 -0
  122. package/dist/core/command-generation/adapters/pi.d.ts +18 -0
  123. package/dist/core/command-generation/adapters/pi.js +42 -0
  124. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  125. package/dist/core/command-generation/adapters/qoder.js +30 -0
  126. package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
  127. package/dist/core/command-generation/adapters/qwen.js +26 -0
  128. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  129. package/dist/core/command-generation/adapters/roocode.js +27 -0
  130. package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
  131. package/dist/core/command-generation/adapters/windsurf.js +38 -0
  132. package/dist/core/command-generation/generator.d.ts +21 -0
  133. package/dist/core/command-generation/generator.js +27 -0
  134. package/dist/core/command-generation/index.d.ts +22 -0
  135. package/dist/core/command-generation/index.js +24 -0
  136. package/dist/core/command-generation/registry.d.ts +36 -0
  137. package/dist/core/command-generation/registry.js +98 -0
  138. package/dist/core/command-generation/types.d.ts +56 -0
  139. package/dist/core/command-generation/types.js +8 -0
  140. package/dist/core/command-generation/yaml.d.ts +22 -0
  141. package/dist/core/command-generation/yaml.js +38 -0
  142. package/dist/core/completions/command-registry.d.ts +3 -0
  143. package/dist/core/completions/command-registry.js +778 -0
  144. package/dist/core/completions/completion-provider.d.ts +71 -0
  145. package/dist/core/completions/completion-provider.js +129 -0
  146. package/dist/core/completions/factory.d.ts +64 -0
  147. package/dist/core/completions/factory.js +75 -0
  148. package/dist/core/completions/generators/bash-generator.d.ts +35 -0
  149. package/dist/core/completions/generators/bash-generator.js +230 -0
  150. package/dist/core/completions/generators/fish-generator.d.ts +32 -0
  151. package/dist/core/completions/generators/fish-generator.js +160 -0
  152. package/dist/core/completions/generators/powershell-generator.d.ts +36 -0
  153. package/dist/core/completions/generators/powershell-generator.js +266 -0
  154. package/dist/core/completions/generators/zsh-generator.d.ts +47 -0
  155. package/dist/core/completions/generators/zsh-generator.js +276 -0
  156. package/dist/core/completions/installers/bash-installer.d.ts +87 -0
  157. package/dist/core/completions/installers/bash-installer.js +321 -0
  158. package/dist/core/completions/installers/fish-installer.d.ts +43 -0
  159. package/dist/core/completions/installers/fish-installer.js +151 -0
  160. package/dist/core/completions/installers/powershell-installer.d.ts +102 -0
  161. package/dist/core/completions/installers/powershell-installer.js +415 -0
  162. package/dist/core/completions/installers/zsh-installer.d.ts +117 -0
  163. package/dist/core/completions/installers/zsh-installer.js +424 -0
  164. package/dist/core/completions/shared-flags.d.ts +13 -0
  165. package/dist/core/completions/shared-flags.js +33 -0
  166. package/dist/core/completions/templates/bash-templates.d.ts +6 -0
  167. package/dist/core/completions/templates/bash-templates.js +30 -0
  168. package/dist/core/completions/templates/fish-templates.d.ts +7 -0
  169. package/dist/core/completions/templates/fish-templates.js +45 -0
  170. package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
  171. package/dist/core/completions/templates/powershell-templates.js +34 -0
  172. package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
  173. package/dist/core/completions/templates/zsh-templates.js +45 -0
  174. package/dist/core/completions/types.d.ts +101 -0
  175. package/dist/core/completions/types.js +2 -0
  176. package/dist/core/comprehension/config.d.ts +20 -0
  177. package/dist/core/comprehension/config.js +23 -0
  178. package/dist/core/comprehension/fingerprint.d.ts +5 -0
  179. package/dist/core/comprehension/fingerprint.js +25 -0
  180. package/dist/core/comprehension/index.d.ts +49 -0
  181. package/dist/core/comprehension/index.js +78 -0
  182. package/dist/core/comprehension/pass-record.d.ts +29 -0
  183. package/dist/core/comprehension/pass-record.js +64 -0
  184. package/dist/core/comprehension/stats.d.ts +18 -0
  185. package/dist/core/comprehension/stats.js +41 -0
  186. package/dist/core/config-prompts.d.ts +9 -0
  187. package/dist/core/config-prompts.js +34 -0
  188. package/dist/core/config-schema.d.ts +87 -0
  189. package/dist/core/config-schema.js +239 -0
  190. package/dist/core/config.d.ts +18 -0
  191. package/dist/core/config.js +39 -0
  192. package/dist/core/converters/json-converter.d.ts +6 -0
  193. package/dist/core/converters/json-converter.js +51 -0
  194. package/dist/core/file-state.d.ts +36 -0
  195. package/dist/core/file-state.js +112 -0
  196. package/dist/core/global-config.d.ts +51 -0
  197. package/dist/core/global-config.js +124 -0
  198. package/dist/core/id.d.ts +17 -0
  199. package/dist/core/id.js +30 -0
  200. package/dist/core/index.d.ts +6 -0
  201. package/dist/core/index.js +7 -0
  202. package/dist/core/init.d.ts +37 -0
  203. package/dist/core/init.js +613 -0
  204. package/dist/core/legacy-cleanup.d.ts +162 -0
  205. package/dist/core/legacy-cleanup.js +514 -0
  206. package/dist/core/list.d.ts +11 -0
  207. package/dist/core/list.js +185 -0
  208. package/dist/core/migration.d.ts +23 -0
  209. package/dist/core/migration.js +108 -0
  210. package/dist/core/openers.d.ts +77 -0
  211. package/dist/core/openers.js +251 -0
  212. package/dist/core/openspec-root.d.ts +45 -0
  213. package/dist/core/openspec-root.js +192 -0
  214. package/dist/core/parsers/change-parser.d.ts +13 -0
  215. package/dist/core/parsers/change-parser.js +197 -0
  216. package/dist/core/parsers/markdown-parser.d.ts +26 -0
  217. package/dist/core/parsers/markdown-parser.js +227 -0
  218. package/dist/core/parsers/requirement-blocks.d.ts +37 -0
  219. package/dist/core/parsers/requirement-blocks.js +201 -0
  220. package/dist/core/parsers/spec-structure.d.ts +9 -0
  221. package/dist/core/parsers/spec-structure.js +88 -0
  222. package/dist/core/planning-home.d.ts +16 -0
  223. package/dist/core/planning-home.js +67 -0
  224. package/dist/core/profile-sync-drift.d.ts +38 -0
  225. package/dist/core/profile-sync-drift.js +200 -0
  226. package/dist/core/profiles.d.ts +26 -0
  227. package/dist/core/profiles.js +40 -0
  228. package/dist/core/project-config.d.ts +120 -0
  229. package/dist/core/project-config.js +406 -0
  230. package/dist/core/references.d.ts +63 -0
  231. package/dist/core/references.js +310 -0
  232. package/dist/core/relationship-health.d.ts +65 -0
  233. package/dist/core/relationship-health.js +64 -0
  234. package/dist/core/root-selection.d.ts +122 -0
  235. package/dist/core/root-selection.js +337 -0
  236. package/dist/core/schemas/base.schema.d.ts +13 -0
  237. package/dist/core/schemas/base.schema.js +13 -0
  238. package/dist/core/schemas/change.schema.d.ts +73 -0
  239. package/dist/core/schemas/change.schema.js +31 -0
  240. package/dist/core/schemas/index.d.ts +4 -0
  241. package/dist/core/schemas/index.js +4 -0
  242. package/dist/core/schemas/spec.schema.d.ts +18 -0
  243. package/dist/core/schemas/spec.schema.js +15 -0
  244. package/dist/core/shared/index.d.ts +8 -0
  245. package/dist/core/shared/index.js +8 -0
  246. package/dist/core/shared/skill-generation.d.ts +49 -0
  247. package/dist/core/shared/skill-generation.js +96 -0
  248. package/dist/core/shared/tool-detection.d.ts +71 -0
  249. package/dist/core/shared/tool-detection.js +158 -0
  250. package/dist/core/specs-apply.d.ts +78 -0
  251. package/dist/core/specs-apply.js +394 -0
  252. package/dist/core/store/errors.d.ts +20 -0
  253. package/dist/core/store/errors.js +22 -0
  254. package/dist/core/store/foundation.d.ts +56 -0
  255. package/dist/core/store/foundation.js +251 -0
  256. package/dist/core/store/git.d.ts +23 -0
  257. package/dist/core/store/git.js +137 -0
  258. package/dist/core/store/index.d.ts +5 -0
  259. package/dist/core/store/index.js +5 -0
  260. package/dist/core/store/operations.d.ts +114 -0
  261. package/dist/core/store/operations.js +783 -0
  262. package/dist/core/store/registry.d.ts +58 -0
  263. package/dist/core/store/registry.js +275 -0
  264. package/dist/core/styles/palette.d.ts +7 -0
  265. package/dist/core/styles/palette.js +8 -0
  266. package/dist/core/templates/index.d.ts +8 -0
  267. package/dist/core/templates/index.js +9 -0
  268. package/dist/core/templates/skill-templates.d.ts +19 -0
  269. package/dist/core/templates/skill-templates.js +18 -0
  270. package/dist/core/templates/types.d.ts +19 -0
  271. package/dist/core/templates/types.js +5 -0
  272. package/dist/core/templates/workflows/apply-change.d.ts +10 -0
  273. package/dist/core/templates/workflows/apply-change.js +337 -0
  274. package/dist/core/templates/workflows/archive-change.d.ts +10 -0
  275. package/dist/core/templates/workflows/archive-change.js +278 -0
  276. package/dist/core/templates/workflows/bulk-archive-change.d.ts +10 -0
  277. package/dist/core/templates/workflows/bulk-archive-change.js +493 -0
  278. package/dist/core/templates/workflows/comprehension-guidance.d.ts +9 -0
  279. package/dist/core/templates/workflows/comprehension-guidance.js +58 -0
  280. package/dist/core/templates/workflows/continue-change.d.ts +10 -0
  281. package/dist/core/templates/workflows/continue-change.js +239 -0
  282. package/dist/core/templates/workflows/explore.d.ts +10 -0
  283. package/dist/core/templates/workflows/explore.js +464 -0
  284. package/dist/core/templates/workflows/feedback.d.ts +9 -0
  285. package/dist/core/templates/workflows/feedback.js +108 -0
  286. package/dist/core/templates/workflows/ff-change.d.ts +10 -0
  287. package/dist/core/templates/workflows/ff-change.js +205 -0
  288. package/dist/core/templates/workflows/mcp-guidance.d.ts +13 -0
  289. package/dist/core/templates/workflows/mcp-guidance.js +116 -0
  290. package/dist/core/templates/workflows/new-change.d.ts +10 -0
  291. package/dist/core/templates/workflows/new-change.js +148 -0
  292. package/dist/core/templates/workflows/onboard.d.ts +10 -0
  293. package/dist/core/templates/workflows/onboard.js +566 -0
  294. package/dist/core/templates/workflows/propose.d.ts +10 -0
  295. package/dist/core/templates/workflows/propose.js +228 -0
  296. package/dist/core/templates/workflows/store-selection.d.ts +8 -0
  297. package/dist/core/templates/workflows/store-selection.js +8 -0
  298. package/dist/core/templates/workflows/sync-specs.d.ts +10 -0
  299. package/dist/core/templates/workflows/sync-specs.js +291 -0
  300. package/dist/core/templates/workflows/verify-change.d.ts +10 -0
  301. package/dist/core/templates/workflows/verify-change.js +346 -0
  302. package/dist/core/update.d.ts +82 -0
  303. package/dist/core/update.js +557 -0
  304. package/dist/core/validation/constants.d.ts +34 -0
  305. package/dist/core/validation/constants.js +40 -0
  306. package/dist/core/validation/types.d.ts +18 -0
  307. package/dist/core/validation/types.js +2 -0
  308. package/dist/core/validation/validator.d.ts +44 -0
  309. package/dist/core/validation/validator.js +435 -0
  310. package/dist/core/view.d.ts +8 -0
  311. package/dist/core/view.js +168 -0
  312. package/dist/core/working-set.d.ts +47 -0
  313. package/dist/core/working-set.js +43 -0
  314. package/dist/core/worksets.d.ts +75 -0
  315. package/dist/core/worksets.js +245 -0
  316. package/dist/core/zod-issues.d.ts +4 -0
  317. package/dist/core/zod-issues.js +10 -0
  318. package/dist/index.d.ts +3 -0
  319. package/dist/index.js +3 -0
  320. package/dist/prompts/searchable-multi-select.d.ts +28 -0
  321. package/dist/prompts/searchable-multi-select.js +159 -0
  322. package/dist/telemetry/config.d.ts +38 -0
  323. package/dist/telemetry/config.js +136 -0
  324. package/dist/telemetry/index.d.ts +31 -0
  325. package/dist/telemetry/index.js +164 -0
  326. package/dist/ui/ascii-patterns.d.ts +16 -0
  327. package/dist/ui/ascii-patterns.js +133 -0
  328. package/dist/ui/welcome-screen.d.ts +10 -0
  329. package/dist/ui/welcome-screen.js +146 -0
  330. package/dist/utils/change-metadata.d.ts +55 -0
  331. package/dist/utils/change-metadata.js +141 -0
  332. package/dist/utils/change-utils.d.ts +71 -0
  333. package/dist/utils/change-utils.js +138 -0
  334. package/dist/utils/command-references.d.ts +18 -0
  335. package/dist/utils/command-references.js +20 -0
  336. package/dist/utils/file-system.d.ts +41 -0
  337. package/dist/utils/file-system.js +320 -0
  338. package/dist/utils/index.d.ts +6 -0
  339. package/dist/utils/index.js +9 -0
  340. package/dist/utils/interactive.d.ts +18 -0
  341. package/dist/utils/interactive.js +21 -0
  342. package/dist/utils/item-discovery.d.ts +4 -0
  343. package/dist/utils/item-discovery.js +72 -0
  344. package/dist/utils/match.d.ts +3 -0
  345. package/dist/utils/match.js +22 -0
  346. package/dist/utils/shell-detection.d.ts +20 -0
  347. package/dist/utils/shell-detection.js +41 -0
  348. package/dist/utils/task-progress.d.ts +8 -0
  349. package/dist/utils/task-progress.js +36 -0
  350. package/package.json +84 -0
  351. package/schemas/spec-driven/schema.yaml +153 -0
  352. package/schemas/spec-driven/templates/design.md +19 -0
  353. package/schemas/spec-driven/templates/proposal.md +23 -0
  354. package/schemas/spec-driven/templates/spec.md +8 -0
  355. package/schemas/spec-driven/templates/tasks.md +9 -0
  356. package/scripts/postinstall.js +83 -0
@@ -0,0 +1,155 @@
1
+ /**
2
+ * `openspec context` (slice 4.1): the working set a root's declarations
3
+ * describe, as an agent brief (JSON), a human listing, or an editor
4
+ * view (`--code-workspace`). Assembly is presentation over the Phase 3
5
+ * relationship data; doctor is the health surface. The only write this
6
+ * command can perform is the explicitly requested workspace file.
7
+ */
8
+ import * as fs from 'node:fs';
9
+ import * as path from 'node:path';
10
+ import { Option } from 'commander';
11
+ import { resolveRootForCommand, } from '../core/root-selection.js';
12
+ import { inspectRelationships } from '../core/relationship-health.js';
13
+ import { assembleWorkingSet, buildCodeWorkspaceJson, isAvailableMember, } from '../core/working-set.js';
14
+ import { StoreError } from '../core/store/errors.js';
15
+ import { COMMAND_REGISTRY } from '../core/completions/command-registry.js';
16
+ import { COMMON_FLAGS } from '../core/completions/shared-flags.js';
17
+ import { emitFailure, printJson } from './shared-output.js';
18
+ import { gatherRelationshipData } from './shared-gather.js';
19
+ const FAILURE_PAYLOAD = { root: null, members: [] };
20
+ async function gatherWorkingSet(root) {
21
+ const data = await gatherRelationshipData(root);
22
+ // Reuse the 3.6 composition for member classification; the
23
+ // doctor-only wrong-turn detections and store facts are deliberately
24
+ // absent — doctor is the health surface.
25
+ const health = inspectRelationships({
26
+ root,
27
+ rootHealthy: data.rootInspection.healthy,
28
+ rootStatus: data.rootInspection.diagnostics,
29
+ referenceEntries: data.referenceEntries,
30
+ registryUnreadable: data.registrySnapshot.unreadable,
31
+ });
32
+ return {
33
+ workingSet: assembleWorkingSet({
34
+ root,
35
+ referenceEntries: data.referenceEntries,
36
+ topLevelStatus: health.status,
37
+ }),
38
+ declaredReferenceCount: data.projectConfig?.references?.length ?? 0,
39
+ };
40
+ }
41
+ function memberLine(member) {
42
+ return ` ${member.id} ${member.path}`;
43
+ }
44
+ function printHumanWorkingSet(workingSet, declaredReferenceCount) {
45
+ const rootLabel = workingSet.root.store_id ?? path.basename(workingSet.root.path);
46
+ console.log(`Working context for ${rootLabel} (${workingSet.root.path})`);
47
+ console.log('');
48
+ console.log('OpenSpec root');
49
+ console.log(` ${rootLabel} ${workingSet.root.path}`);
50
+ const availableStores = workingSet.members.filter((member) => member.role === 'referenced_store' && isAvailableMember(member));
51
+ const unavailable = workingSet.members.filter((member) => !isAvailableMember(member));
52
+ if (availableStores.length > 0) {
53
+ console.log('');
54
+ console.log('Referenced stores');
55
+ for (const member of availableStores) {
56
+ console.log(memberLine(member));
57
+ if (member.fetch) {
58
+ console.log(` Fetch: ${member.fetch}`);
59
+ }
60
+ }
61
+ }
62
+ if (workingSet.members.length === 0) {
63
+ console.log('');
64
+ // Self-references are silently omitted from the index; an
65
+ // emptied-by-omission set must not claim nothing was declared.
66
+ console.log(declaredReferenceCount > 0
67
+ ? 'Declared references all resolve to this root; the working set is this root alone.'
68
+ : 'No references declared; the working set is this root alone.');
69
+ }
70
+ if (unavailable.length > 0 || workingSet.status.length > 0) {
71
+ console.log('');
72
+ console.log('Not available on this machine');
73
+ for (const member of unavailable) {
74
+ if (member.status.length === 0) {
75
+ console.log(` - ${member.id}`);
76
+ continue;
77
+ }
78
+ for (const diagnostic of member.status) {
79
+ console.log(` - ${member.id}: ${diagnostic.message}`);
80
+ if (diagnostic.fix) {
81
+ console.log(` Fix: ${diagnostic.fix}`);
82
+ }
83
+ }
84
+ }
85
+ for (const diagnostic of workingSet.status) {
86
+ console.log(` Note: ${diagnostic.message}`);
87
+ if (diagnostic.fix) {
88
+ console.log(` Fix: ${diagnostic.fix}`);
89
+ }
90
+ }
91
+ }
92
+ }
93
+ function writeCodeWorkspace(workingSet, outputPath, force) {
94
+ const resolved = path.resolve(outputPath);
95
+ if (fs.existsSync(resolved) && !force) {
96
+ throw new StoreError(`Refusing to overwrite ${resolved}.`, 'context_file_exists', {
97
+ target: 'context.output',
98
+ fix: `Pass --force to overwrite, or choose a different path.`,
99
+ });
100
+ }
101
+ const parent = path.dirname(resolved);
102
+ if (!fs.existsSync(parent)) {
103
+ throw new StoreError(`Output directory does not exist: ${parent}.`, 'context_output_dir_missing', { target: 'context.output', fix: 'Create the directory first, or choose another path.' });
104
+ }
105
+ const rootName = workingSet.root.store_id ?? path.basename(workingSet.root.path);
106
+ fs.writeFileSync(resolved, buildCodeWorkspaceJson(workingSet, rootName));
107
+ const available = workingSet.members.filter(isAvailableMember).length;
108
+ const skipped = workingSet.members
109
+ .filter((member) => !isAvailableMember(member))
110
+ .map((member) => member.id);
111
+ const summary = skipped.length > 0
112
+ ? `Wrote ${resolved} (${available + 1} folders; not available: ${skipped.join(', ')})`
113
+ : `Wrote ${resolved} (${available + 1} folders)`;
114
+ // stderr keeps JSON stdout pure; for humans it reads inline.
115
+ console.error(summary);
116
+ }
117
+ export function registerContextCommand(program) {
118
+ const description = COMMAND_REGISTRY.find((entry) => entry.name === 'context')?.description ??
119
+ 'Print the working context for the resolved OpenSpec root';
120
+ program
121
+ .command('context')
122
+ .description(description)
123
+ .option('--store <id>', COMMON_FLAGS.store.description)
124
+ .addOption(new Option('--store-path <path>', 'Removed; register the store and use --store').hideHelp())
125
+ .option('--json', 'Output the agent brief as JSON')
126
+ .option('--code-workspace <path>', 'Also write a VS Code workspace file for the set')
127
+ .option('--force', 'Overwrite an existing --code-workspace file')
128
+ .action(async (options) => {
129
+ try {
130
+ const root = await resolveRootForCommand({ store: options.store, storePath: options.storePath }, { json: options.json, failurePayload: FAILURE_PAYLOAD, allowImplicitRoot: false });
131
+ if (!root) {
132
+ return;
133
+ }
134
+ const { workingSet, declaredReferenceCount } = await gatherWorkingSet(root);
135
+ if (options.json) {
136
+ // The write runs FIRST: a write failure must leave stdout
137
+ // holding exactly one JSON document (the failure payload).
138
+ if (options.codeWorkspace) {
139
+ writeCodeWorkspace(workingSet, options.codeWorkspace, options.force === true);
140
+ }
141
+ printJson(workingSet);
142
+ }
143
+ else {
144
+ printHumanWorkingSet(workingSet, declaredReferenceCount);
145
+ if (options.codeWorkspace) {
146
+ writeCodeWorkspace(workingSet, options.codeWorkspace, options.force === true);
147
+ }
148
+ }
149
+ }
150
+ catch (error) {
151
+ emitFailure(options.json, FAILURE_PAYLOAD, error, 'context_failed');
152
+ }
153
+ });
154
+ }
155
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1,8 @@
1
+ /**
2
+ * `openspec doctor` (slice 3.6): the root-scoped relationship-health
3
+ * report. Read-only — it answers "are the roots this work relates to
4
+ * available on this machine?" and never clones, syncs, or repairs.
5
+ */
6
+ import { Command } from 'commander';
7
+ export declare function registerDoctorCommand(program: Command): void;
8
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1,163 @@
1
+ /**
2
+ * `openspec doctor` (slice 3.6): the root-scoped relationship-health
3
+ * report. Read-only — it answers "are the roots this work relates to
4
+ * available on this machine?" and never clones, syncs, or repairs.
5
+ */
6
+ import { Option } from 'commander';
7
+ import { resolveRootForCommand, } from '../core/root-selection.js';
8
+ import { readOptionalStoreMetadataState } from '../core/store/foundation.js';
9
+ import { gitOriginUrl, isGitRepositoryAtRoot } from '../core/store/git.js';
10
+ import { classifyOpenSpecDir, readProjectConfig, resolveConfigFilePath, } from '../core/project-config.js';
11
+ import { findRepoPlanningRootSync } from '../core/planning-home.js';
12
+ import { gatherRelationshipData } from './shared-gather.js';
13
+ import { inspectRelationships, } from '../core/relationship-health.js';
14
+ import { COMMAND_REGISTRY } from '../core/completions/command-registry.js';
15
+ import { COMMON_FLAGS } from '../core/completions/shared-flags.js';
16
+ import { emitFailure, printJson } from './shared-output.js';
17
+ import * as path from 'node:path';
18
+ const FAILURE_PAYLOAD = { root: null, store: null, references: [] };
19
+ async function gatherHealth(root) {
20
+ const data = await gatherRelationshipData(root);
21
+ const { registrySnapshot, projectConfig, referenceEntries, rootInspection, } = data;
22
+ const registryUnreadable = registrySnapshot.unreadable;
23
+ const input = {
24
+ root,
25
+ rootHealthy: rootInspection.healthy,
26
+ rootStatus: rootInspection.diagnostics,
27
+ referenceEntries,
28
+ registryUnreadable,
29
+ };
30
+ // Store facts for store-backed roots (explicit --store or declared).
31
+ // Missing/invalid metadata never reaches here: store resolution
32
+ // verifies identity first and fails with the existing taxonomy
33
+ // (recorded amendment - corrupt store.yaml is an exit-1 resolution
34
+ // failure, not a health finding).
35
+ if (root.storeId) {
36
+ const metadata = await readOptionalStoreMetadataState(root.path).catch(() => null);
37
+ // git -C walks UP the tree: probing a non-repo store nested inside
38
+ // another repo would record the ENCLOSING repo's origin.
39
+ const originUrl = (await isGitRepositoryAtRoot(root.path)) ? await gitOriginUrl(root.path) : null;
40
+ input.storeFacts = {
41
+ id: root.storeId,
42
+ metadataPresent: metadata !== null,
43
+ metadataValid: metadata !== null,
44
+ ...(metadata?.remote ? { canonicalRemote: metadata.remote } : {}),
45
+ ...(originUrl ? { originUrl } : {}),
46
+ };
47
+ }
48
+ // The 3.2 both-shapes wrong turn, structured — including a malformed
49
+ // pointer value, which the resolver is silent about on planning-shaped
50
+ // roots.
51
+ if (root.source === 'nearest') {
52
+ const { hasPlanningShape, pointer } = classifyOpenSpecDir(root.path);
53
+ if (hasPlanningShape && pointer.filePath) {
54
+ if (pointer.value !== undefined) {
55
+ input.bothShapesPointer = { value: pointer.value, filePath: pointer.filePath };
56
+ }
57
+ else if (pointer.malformed) {
58
+ input.malformedPointer = { filePath: pointer.filePath, reason: pointer.malformed };
59
+ }
60
+ }
61
+ }
62
+ // The 3.4-recorded inert-pointer wrong turn: the resolved root is the
63
+ // STORE; re-walk to the pointer directory and read ITS config.
64
+ if (root.source === 'declared') {
65
+ const pointerRoot = findRepoPlanningRootSync(process.cwd());
66
+ if (pointerRoot) {
67
+ const pointerConfig = readProjectConfig(pointerRoot);
68
+ const fields = [];
69
+ if (pointerConfig?.references?.length)
70
+ fields.push('references');
71
+ if (fields.length > 0) {
72
+ const filePath = resolveConfigFilePath(pointerRoot) ??
73
+ path.join(pointerRoot, 'openspec', 'config.yaml');
74
+ input.inertPointerDeclarations = { filePath, fields };
75
+ }
76
+ }
77
+ }
78
+ return {
79
+ health: inspectRelationships(input),
80
+ declaredReferenceCount: projectConfig?.references?.length ?? 0,
81
+ };
82
+ }
83
+ function printDiagnosticLines(prefix, status) {
84
+ for (const entry of status) {
85
+ console.log(`${prefix}- ${entry.message}`);
86
+ if (entry.fix) {
87
+ console.log(`${prefix} Fix: ${entry.fix}`);
88
+ }
89
+ }
90
+ }
91
+ function printEntrySection(title, entries, emptyLine, okLine, idOf) {
92
+ console.log('');
93
+ console.log(title);
94
+ if (entries.length === 0) {
95
+ console.log(` ${emptyLine}`);
96
+ return;
97
+ }
98
+ for (const entry of entries) {
99
+ if (entry.status.length === 0) {
100
+ console.log(` - ${okLine(entry)}`);
101
+ continue;
102
+ }
103
+ for (const diagnostic of entry.status) {
104
+ console.log(` - ${idOf(entry)}: ${diagnostic.message}`);
105
+ if (diagnostic.fix) {
106
+ console.log(` Fix: ${diagnostic.fix}`);
107
+ }
108
+ }
109
+ }
110
+ }
111
+ function printHumanHealth(health, declaredReferenceCount) {
112
+ console.log('Doctor');
113
+ console.log('');
114
+ console.log('Root');
115
+ console.log(` Location: ${health.root.path}`);
116
+ console.log(` OpenSpec root: ${health.root.healthy ? 'ok' : 'unhealthy'}`);
117
+ if (health.store) {
118
+ const metadataNote = health.store.metadata.valid ? 'metadata ok' : 'metadata invalid';
119
+ console.log(` Store: ${health.store.id} (${metadataNote})`);
120
+ }
121
+ printDiagnosticLines(' ', [...health.root.status, ...(health.store?.status ?? [])]);
122
+ // "(none declared)" must never lie: self-references are omitted from
123
+ // the index, so an emptied-by-omission list gets its own line.
124
+ const referencesEmptyLine = health.references.length === 0 && declaredReferenceCount > 0
125
+ ? '(declared references all resolve to this root)'
126
+ : '(none declared)';
127
+ printEntrySection('References', health.references, referencesEmptyLine, (entry) => `${entry.store_id}: ok${entry.root ? ` (${entry.root})` : ''}`, (entry) => entry.store_id);
128
+ for (const entry of health.status) {
129
+ console.log('');
130
+ console.log(`Note: ${entry.message}`);
131
+ if (entry.fix) {
132
+ console.log(`Fix: ${entry.fix}`);
133
+ }
134
+ }
135
+ }
136
+ export function registerDoctorCommand(program) {
137
+ const description = COMMAND_REGISTRY.find((entry) => entry.name === 'doctor')?.description ??
138
+ 'Report relationship health for the resolved OpenSpec root';
139
+ program
140
+ .command('doctor')
141
+ .description(description)
142
+ .option('--store <id>', COMMON_FLAGS.store.description)
143
+ .addOption(new Option('--store-path <path>', 'Removed; register the store and use --store').hideHelp())
144
+ .option('--json', 'Output as JSON')
145
+ .action(async (options) => {
146
+ try {
147
+ const root = await resolveRootForCommand({ store: options.store, storePath: options.storePath }, { json: options.json, failurePayload: FAILURE_PAYLOAD, allowImplicitRoot: false });
148
+ if (!root) {
149
+ return;
150
+ }
151
+ const { health, declaredReferenceCount } = await gatherHealth(root);
152
+ if (options.json) {
153
+ printJson(health);
154
+ return;
155
+ }
156
+ printHumanHealth(health, declaredReferenceCount);
157
+ }
158
+ catch (error) {
159
+ emitFailure(options.json, FAILURE_PAYLOAD, error, 'doctor_failed');
160
+ }
161
+ });
162
+ }
163
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Feedback command implementation
3
+ */
4
+ export declare class FeedbackCommand {
5
+ execute(message: string, options?: {
6
+ body?: string;
7
+ }): Promise<void>;
8
+ }
9
+ //# sourceMappingURL=feedback.d.ts.map
@@ -0,0 +1,183 @@
1
+ import { execSync, execFileSync } from 'child_process';
2
+ import { createRequire } from 'module';
3
+ import os from 'os';
4
+ const require = createRequire(import.meta.url);
5
+ /**
6
+ * Check if gh CLI is installed and available in PATH
7
+ * Uses platform-appropriate command: 'where' on Windows, 'which' on Unix/macOS
8
+ */
9
+ function isGhInstalled() {
10
+ try {
11
+ const command = process.platform === 'win32' ? 'where gh' : 'which gh';
12
+ execSync(command, { stdio: 'pipe' });
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ /**
20
+ * Check if gh CLI is authenticated
21
+ */
22
+ function isGhAuthenticated() {
23
+ try {
24
+ execSync('gh auth status', { stdio: 'pipe' });
25
+ return true;
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ /**
32
+ * Get OpenSpec version from package.json
33
+ */
34
+ function getVersion() {
35
+ try {
36
+ const { version } = require('../../package.json');
37
+ return version;
38
+ }
39
+ catch {
40
+ return 'unknown';
41
+ }
42
+ }
43
+ /**
44
+ * Get platform name
45
+ */
46
+ function getPlatform() {
47
+ return os.platform();
48
+ }
49
+ /**
50
+ * Get current timestamp in ISO format
51
+ */
52
+ function getTimestamp() {
53
+ return new Date().toISOString();
54
+ }
55
+ /**
56
+ * Generate metadata footer for feedback
57
+ */
58
+ function generateMetadata() {
59
+ const version = getVersion();
60
+ const platform = getPlatform();
61
+ const timestamp = getTimestamp();
62
+ return `---
63
+ Submitted via OpenSpec CLI
64
+ - Version: ${version}
65
+ - Platform: ${platform}
66
+ - Timestamp: ${timestamp}`;
67
+ }
68
+ /**
69
+ * Format the feedback title
70
+ */
71
+ function formatTitle(message) {
72
+ return `Feedback: ${message}`;
73
+ }
74
+ /**
75
+ * Format the full feedback body
76
+ */
77
+ function formatBody(bodyText) {
78
+ const parts = [];
79
+ if (bodyText) {
80
+ parts.push(bodyText);
81
+ parts.push(''); // Empty line before metadata
82
+ }
83
+ parts.push(generateMetadata());
84
+ return parts.join('\n');
85
+ }
86
+ /**
87
+ * Generate a pre-filled GitHub issue URL for manual submission
88
+ */
89
+ function generateManualSubmissionUrl(title, body) {
90
+ const repo = 'Fission-AI/OpenSpec';
91
+ const encodedTitle = encodeURIComponent(title);
92
+ const encodedBody = encodeURIComponent(body);
93
+ const encodedLabels = encodeURIComponent('feedback');
94
+ return `https://github.com/${repo}/issues/new?title=${encodedTitle}&body=${encodedBody}&labels=${encodedLabels}`;
95
+ }
96
+ /**
97
+ * Display formatted feedback content for manual submission
98
+ */
99
+ function displayFormattedFeedback(title, body) {
100
+ console.log('\n--- FORMATTED FEEDBACK ---');
101
+ console.log(`Title: ${title}`);
102
+ console.log(`Labels: feedback`);
103
+ console.log('\nBody:');
104
+ console.log(body);
105
+ console.log('--- END FEEDBACK ---\n');
106
+ }
107
+ /**
108
+ * Submit feedback via gh CLI
109
+ * Uses execFileSync to prevent shell injection vulnerabilities
110
+ */
111
+ function submitViaGhCli(title, body) {
112
+ try {
113
+ const result = execFileSync('gh', [
114
+ 'issue',
115
+ 'create',
116
+ '--repo',
117
+ 'Fission-AI/OpenSpec',
118
+ '--title',
119
+ title,
120
+ '--body',
121
+ body,
122
+ '--label',
123
+ 'feedback',
124
+ ], { encoding: 'utf-8', stdio: 'pipe' });
125
+ const issueUrl = result.trim();
126
+ console.log(`\n✓ Feedback submitted successfully!`);
127
+ console.log(`Issue URL: ${issueUrl}\n`);
128
+ }
129
+ catch (error) {
130
+ // Display the error output from gh CLI
131
+ if (error.stderr) {
132
+ console.error(error.stderr.toString());
133
+ }
134
+ else if (error.message) {
135
+ console.error(error.message);
136
+ }
137
+ // Exit with the same code as gh CLI
138
+ process.exit(error.status ?? 1);
139
+ }
140
+ }
141
+ /**
142
+ * Handle fallback when gh CLI is not available or not authenticated
143
+ */
144
+ function handleFallback(title, body, reason) {
145
+ if (reason === 'missing') {
146
+ console.log('⚠️ GitHub CLI not found. Manual submission required.');
147
+ }
148
+ else {
149
+ console.log('⚠️ GitHub authentication required. Manual submission required.');
150
+ }
151
+ displayFormattedFeedback(title, body);
152
+ const manualUrl = generateManualSubmissionUrl(title, body);
153
+ console.log('Please submit your feedback manually:');
154
+ console.log(manualUrl);
155
+ if (reason === 'unauthenticated') {
156
+ console.log('\nTo auto-submit in the future: gh auth login');
157
+ }
158
+ // Exit with success code (fallback is successful)
159
+ process.exit(0);
160
+ }
161
+ /**
162
+ * Feedback command implementation
163
+ */
164
+ export class FeedbackCommand {
165
+ async execute(message, options) {
166
+ // Format title and body once for all code paths
167
+ const title = formatTitle(message);
168
+ const body = formatBody(options?.body);
169
+ // Check if gh CLI is installed
170
+ if (!isGhInstalled()) {
171
+ handleFallback(title, body, 'missing');
172
+ return;
173
+ }
174
+ // Check if gh CLI is authenticated
175
+ if (!isGhAuthenticated()) {
176
+ handleFallback(title, body, 'unauthenticated');
177
+ return;
178
+ }
179
+ // Submit via gh CLI
180
+ submitViaGhCli(title, body);
181
+ }
182
+ }
183
+ //# sourceMappingURL=feedback.js.map
@@ -0,0 +1,6 @@
1
+ import { Command } from 'commander';
2
+ /**
3
+ * Register the schema command and all its subcommands.
4
+ */
5
+ export declare function registerSchemaCommand(program: Command): void;
6
+ //# sourceMappingURL=schema.d.ts.map