@codewalla_india/openspec 1.3.1 → 1.3.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 (333) hide show
  1. package/LICENSE +22 -22
  2. package/README.md +272 -191
  3. package/bin/openspec.js +5 -5
  4. package/dist/cli/index.js +99 -62
  5. package/dist/commands/change.d.ts +0 -2
  6. package/dist/commands/change.js +107 -86
  7. package/dist/commands/config.js +14 -16
  8. package/dist/commands/doctor.js +9 -4
  9. package/dist/commands/feedback.js +79 -30
  10. package/dist/commands/modify.d.ts +26 -0
  11. package/dist/commands/modify.js +147 -0
  12. package/dist/commands/schema.js +170 -91
  13. package/dist/commands/show.js +5 -2
  14. package/dist/commands/spec.js +49 -29
  15. package/dist/commands/store.js +15 -21
  16. package/dist/commands/validate.d.ts +8 -0
  17. package/dist/commands/validate.js +43 -20
  18. package/dist/commands/workflow/index.d.ts +2 -2
  19. package/dist/commands/workflow/index.js +1 -1
  20. package/dist/commands/workflow/instructions.d.ts +6 -26
  21. package/dist/commands/workflow/instructions.js +183 -376
  22. package/dist/commands/workflow/new-change.d.ts +0 -4
  23. package/dist/commands/workflow/new-change.js +10 -28
  24. package/dist/commands/workflow/shared.d.ts +34 -19
  25. package/dist/commands/workflow/shared.js +34 -4
  26. package/dist/commands/workflow/status.js +10 -32
  27. package/dist/commands/workflow/templates.js +15 -5
  28. package/dist/commands/workset.d.ts +2 -2
  29. package/dist/commands/workset.js +19 -22
  30. package/dist/comprehension-quiz/fingerprint.d.ts +39 -0
  31. package/dist/comprehension-quiz/fingerprint.js +84 -0
  32. package/dist/comprehension-quiz/index.d.ts +42 -0
  33. package/dist/comprehension-quiz/index.js +47 -0
  34. package/dist/comprehension-quiz/pass-record.d.ts +44 -0
  35. package/dist/comprehension-quiz/pass-record.js +98 -0
  36. package/dist/comprehension-quiz/providers/anthropic.d.ts +34 -0
  37. package/dist/comprehension-quiz/providers/anthropic.js +53 -0
  38. package/dist/comprehension-quiz/providers/factory.d.ts +44 -0
  39. package/dist/comprehension-quiz/providers/factory.js +174 -0
  40. package/dist/comprehension-quiz/providers/interface.d.ts +59 -0
  41. package/dist/comprehension-quiz/providers/interface.js +63 -0
  42. package/dist/comprehension-quiz/providers/local.d.ts +34 -0
  43. package/dist/comprehension-quiz/providers/local.js +53 -0
  44. package/dist/comprehension-quiz/providers/ollama.d.ts +34 -0
  45. package/dist/comprehension-quiz/providers/ollama.js +53 -0
  46. package/dist/comprehension-quiz/providers/openai.d.ts +34 -0
  47. package/dist/comprehension-quiz/providers/openai.js +53 -0
  48. package/dist/comprehension-quiz/question-generator.d.ts +69 -0
  49. package/dist/comprehension-quiz/question-generator.js +141 -0
  50. package/dist/comprehension-quiz/quiz-executor.d.ts +70 -0
  51. package/dist/comprehension-quiz/quiz-executor.js +165 -0
  52. package/dist/comprehension-quiz/types.d.ts +115 -0
  53. package/dist/comprehension-quiz/types.js +11 -0
  54. package/dist/core/archive.d.ts +14 -1
  55. package/dist/core/archive.js +1350 -190
  56. package/dist/core/artifact-graph/graph.d.ts +28 -9
  57. package/dist/core/artifact-graph/graph.js +94 -43
  58. package/dist/core/artifact-graph/index.d.ts +1 -1
  59. package/dist/core/artifact-graph/index.js +1 -1
  60. package/dist/core/artifact-graph/instruction-loader.d.ts +30 -3
  61. package/dist/core/artifact-graph/instruction-loader.js +70 -12
  62. package/dist/core/artifact-graph/outputs.d.ts +1 -0
  63. package/dist/core/artifact-graph/outputs.js +67 -5
  64. package/dist/core/artifact-graph/resolver.d.ts +14 -0
  65. package/dist/core/artifact-graph/resolver.js +69 -15
  66. package/dist/core/artifact-graph/types.js +21 -3
  67. package/dist/core/available-tools.d.ts +2 -2
  68. package/dist/core/available-tools.js +14 -3
  69. package/dist/core/change-metadata/schema.d.ts +2 -0
  70. package/dist/core/change-metadata/schema.js +13 -0
  71. package/dist/core/change-status-policy.d.ts +10 -1
  72. package/dist/core/change-status-policy.js +30 -2
  73. package/dist/core/command-generation/adapters/amazon-q.d.ts +4 -0
  74. package/dist/core/command-generation/adapters/amazon-q.js +11 -5
  75. package/dist/core/command-generation/adapters/antigravity.js +6 -5
  76. package/dist/core/command-generation/adapters/auggie.js +7 -6
  77. package/dist/core/command-generation/adapters/bob.d.ts +5 -1
  78. package/dist/core/command-generation/adapters/bob.js +11 -10
  79. package/dist/core/command-generation/adapters/claude.d.ts +1 -1
  80. package/dist/core/command-generation/adapters/claude.js +12 -17
  81. package/dist/core/command-generation/adapters/cline.js +5 -5
  82. package/dist/core/command-generation/adapters/codebuddy.js +8 -7
  83. package/dist/core/command-generation/adapters/continue.js +8 -7
  84. package/dist/core/command-generation/adapters/costrict.js +7 -6
  85. package/dist/core/command-generation/adapters/crush.js +9 -9
  86. package/dist/core/command-generation/adapters/cursor.js +8 -8
  87. package/dist/core/command-generation/adapters/devin.d.ts +19 -0
  88. package/dist/core/command-generation/adapters/devin.js +36 -0
  89. package/dist/core/command-generation/adapters/factory.js +7 -6
  90. package/dist/core/command-generation/adapters/gemini.js +40 -5
  91. package/dist/core/command-generation/adapters/github-copilot.js +6 -5
  92. package/dist/core/command-generation/adapters/iflow.js +9 -8
  93. package/dist/core/command-generation/adapters/index.d.ts +4 -2
  94. package/dist/core/command-generation/adapters/index.js +4 -2
  95. package/dist/core/command-generation/adapters/junie.js +6 -5
  96. package/dist/core/command-generation/adapters/kilocode.js +1 -1
  97. package/dist/core/command-generation/adapters/kiro.js +6 -5
  98. package/dist/core/command-generation/adapters/lingma.js +9 -9
  99. package/dist/core/command-generation/adapters/oh-my-pi.d.ts +21 -0
  100. package/dist/core/command-generation/adapters/oh-my-pi.js +42 -0
  101. package/dist/core/command-generation/adapters/opencode.js +6 -8
  102. package/dist/core/command-generation/adapters/pi.d.ts +2 -2
  103. package/dist/core/command-generation/adapters/pi.js +7 -10
  104. package/dist/core/command-generation/adapters/qoder.js +9 -9
  105. package/dist/core/command-generation/adapters/qwen.d.ts +7 -3
  106. package/dist/core/command-generation/adapters/qwen.js +14 -9
  107. package/dist/core/command-generation/adapters/roocode.d.ts +4 -4
  108. package/dist/core/command-generation/adapters/roocode.js +9 -9
  109. package/dist/core/command-generation/adapters/trae.d.ts +13 -0
  110. package/dist/core/command-generation/adapters/trae.js +28 -0
  111. package/dist/core/command-generation/adapters/zcode.d.ts +16 -0
  112. package/dist/core/command-generation/adapters/zcode.js +33 -0
  113. package/dist/core/command-generation/generator.d.ts +8 -0
  114. package/dist/core/command-generation/generator.js +15 -1
  115. package/dist/core/command-generation/index.d.ts +1 -1
  116. package/dist/core/command-generation/index.js +1 -1
  117. package/dist/core/command-generation/invocation.d.ts +73 -0
  118. package/dist/core/command-generation/invocation.js +77 -0
  119. package/dist/core/command-generation/registry.js +8 -4
  120. package/dist/core/command-generation/types.d.ts +9 -2
  121. package/dist/core/command-generation/yaml.d.ts +20 -6
  122. package/dist/core/command-generation/yaml.js +31 -21
  123. package/dist/core/command-surface.d.ts +15 -0
  124. package/dist/core/command-surface.js +33 -0
  125. package/dist/core/completions/command-registry.js +16 -61
  126. package/dist/core/completions/generators/bash-generator.js +41 -41
  127. package/dist/core/completions/generators/fish-generator.js +7 -7
  128. package/dist/core/completions/generators/powershell-generator.js +44 -37
  129. package/dist/core/completions/generators/zsh-generator.js +33 -33
  130. package/dist/core/completions/installers/zsh-installer.d.ts +9 -0
  131. package/dist/core/completions/installers/zsh-installer.js +20 -4
  132. package/dist/core/completions/templates/bash-templates.js +24 -24
  133. package/dist/core/completions/templates/fish-templates.js +38 -38
  134. package/dist/core/completions/templates/powershell-templates.js +28 -28
  135. package/dist/core/completions/templates/zsh-templates.js +39 -39
  136. package/dist/core/config-prompts.d.ts +1 -1
  137. package/dist/core/config-prompts.js +14 -1
  138. package/dist/core/config-schema.d.ts +10 -1
  139. package/dist/core/config-schema.js +67 -1
  140. package/dist/core/config.d.ts +15 -0
  141. package/dist/core/config.js +46 -5
  142. package/dist/core/file-state.js +56 -24
  143. package/dist/core/github-copilot/cloud-agent.d.ts +95 -0
  144. package/dist/core/github-copilot/cloud-agent.js +497 -0
  145. package/dist/core/global-config.d.ts +16 -0
  146. package/dist/core/init.d.ts +58 -0
  147. package/dist/core/init.js +474 -73
  148. package/dist/core/legacy-cleanup.d.ts +59 -0
  149. package/dist/core/legacy-cleanup.js +253 -24
  150. package/dist/core/list.js +23 -16
  151. package/dist/core/migration.d.ts +73 -1
  152. package/dist/core/migration.js +360 -11
  153. package/dist/core/modify/conflict-detector.d.ts +26 -0
  154. package/dist/core/modify/conflict-detector.js +62 -0
  155. package/dist/core/modify/dependency-propagator.d.ts +38 -0
  156. package/dist/core/modify/dependency-propagator.js +103 -0
  157. package/dist/core/modify/history-tracker.d.ts +34 -0
  158. package/dist/core/modify/history-tracker.js +114 -0
  159. package/dist/core/modify/index.d.ts +7 -0
  160. package/dist/core/modify/index.js +7 -0
  161. package/dist/core/onboarding-commands.d.ts +30 -0
  162. package/dist/core/onboarding-commands.js +38 -0
  163. package/dist/core/openspec-root.js +18 -15
  164. package/dist/core/parsers/change-parser.d.ts +17 -2
  165. package/dist/core/parsers/change-parser.js +35 -21
  166. package/dist/core/parsers/code-fence.d.ts +15 -0
  167. package/dist/core/parsers/code-fence.js +49 -0
  168. package/dist/core/parsers/markdown-parser.d.ts +0 -3
  169. package/dist/core/parsers/markdown-parser.js +7 -60
  170. package/dist/core/parsers/requirement-blocks.d.ts +29 -0
  171. package/dist/core/parsers/requirement-blocks.js +150 -31
  172. package/dist/core/parsers/requirement-text.d.ts +48 -0
  173. package/dist/core/parsers/requirement-text.js +98 -0
  174. package/dist/core/parsers/spec-structure.d.ts +1 -1
  175. package/dist/core/parsers/spec-structure.js +20 -30
  176. package/dist/core/profile-sync-drift.d.ts +0 -8
  177. package/dist/core/profile-sync-drift.js +49 -50
  178. package/dist/core/profiles.d.ts +2 -2
  179. package/dist/core/profiles.js +2 -2
  180. package/dist/core/project-config.d.ts +27 -18
  181. package/dist/core/project-config.js +101 -34
  182. package/dist/core/references.js +42 -4
  183. package/dist/core/relationship-health.d.ts +8 -0
  184. package/dist/core/relationship-health.js +13 -0
  185. package/dist/core/root-selection.d.ts +9 -6
  186. package/dist/core/root-selection.js +42 -5
  187. package/dist/core/schemas/base.schema.js +7 -2
  188. package/dist/core/shared/allowed-tools.d.ts +12 -0
  189. package/dist/core/shared/allowed-tools.js +12 -0
  190. package/dist/core/shared/index.d.ts +1 -0
  191. package/dist/core/shared/index.js +1 -0
  192. package/dist/core/shared/skill-content-equivalence.d.ts +7 -0
  193. package/dist/core/shared/skill-content-equivalence.js +41 -0
  194. package/dist/core/shared/skill-generation.js +17 -13
  195. package/dist/core/shared/skill-paths.d.ts +13 -0
  196. package/dist/core/shared/skill-paths.js +23 -0
  197. package/dist/core/shared/tool-detection.d.ts +27 -7
  198. package/dist/core/shared/tool-detection.js +167 -37
  199. package/dist/core/shared-skill-target.d.ts +16 -0
  200. package/dist/core/shared-skill-target.js +156 -0
  201. package/dist/core/specs-apply.d.ts +80 -33
  202. package/dist/core/specs-apply.js +667 -145
  203. package/dist/core/store/git.d.ts +13 -0
  204. package/dist/core/store/git.js +24 -0
  205. package/dist/core/store/operations.js +20 -0
  206. package/dist/core/templates/skill-templates.d.ts +3 -2
  207. package/dist/core/templates/skill-templates.js +3 -2
  208. package/dist/core/templates/workflows/apply-change.d.ts +10 -0
  209. package/dist/core/templates/workflows/apply-change.js +186 -224
  210. package/dist/core/templates/workflows/archive-change.js +387 -260
  211. package/dist/core/templates/workflows/bulk-archive-change.js +655 -475
  212. package/dist/core/templates/workflows/continue-change.js +210 -219
  213. package/dist/core/templates/workflows/explore.js +479 -443
  214. package/dist/core/templates/workflows/feedback.js +97 -97
  215. package/dist/core/templates/workflows/ff-change.js +200 -191
  216. package/dist/core/templates/workflows/modify-change.d.ts +4 -1
  217. package/dist/core/templates/workflows/modify-change.js +237 -115
  218. package/dist/core/templates/workflows/new-change.js +127 -134
  219. package/dist/core/templates/workflows/onboard.js +548 -542
  220. package/dist/core/templates/workflows/propose.js +273 -217
  221. package/dist/core/templates/workflows/store-selection.d.ts +1 -1
  222. package/dist/core/templates/workflows/store-selection.js +1 -1
  223. package/dist/core/templates/workflows/sync-specs.js +500 -273
  224. package/dist/core/templates/workflows/update-change.d.ts +10 -0
  225. package/dist/core/templates/workflows/update-change.js +177 -0
  226. package/dist/core/templates/workflows/verify-change.js +324 -326
  227. package/dist/core/update.d.ts +40 -5
  228. package/dist/core/update.js +411 -96
  229. package/dist/core/validation/constants.d.ts +4 -1
  230. package/dist/core/validation/constants.js +4 -1
  231. package/dist/core/validation/plan-validator.d.ts +8 -0
  232. package/dist/core/validation/plan-validator.js +45 -0
  233. package/dist/core/validation/task-numbering.d.ts +16 -0
  234. package/dist/core/validation/task-numbering.js +57 -0
  235. package/dist/core/validation/validator.d.ts +27 -3
  236. package/dist/core/validation/validator.js +337 -48
  237. package/dist/core/version-check.d.ts +152 -0
  238. package/dist/core/version-check.js +731 -0
  239. package/dist/core/view.js +13 -18
  240. package/dist/prompts/searchable-multi-select.js +1 -1
  241. package/dist/telemetry/caller-detection.d.ts +27 -0
  242. package/dist/telemetry/caller-detection.js +85 -0
  243. package/dist/telemetry/caller-detection.test.d.ts +5 -0
  244. package/dist/telemetry/config.d.ts +48 -2
  245. package/dist/telemetry/config.js +113 -11
  246. package/dist/telemetry/config.test.d.ts +5 -0
  247. package/dist/telemetry/deduplication.d.ts +35 -0
  248. package/dist/telemetry/deduplication.js +82 -0
  249. package/dist/telemetry/deduplication.test.d.ts +5 -0
  250. package/dist/telemetry/identity.d.ts +62 -22
  251. package/dist/telemetry/identity.js +147 -102
  252. package/dist/telemetry/index.d.ts +126 -15
  253. package/dist/telemetry/index.js +569 -37
  254. package/dist/telemetry/sanitization.d.ts +40 -0
  255. package/dist/telemetry/sanitization.js +114 -0
  256. package/dist/telemetry/sanitization.test.d.ts +5 -0
  257. package/dist/telemetry/throttling.d.ts +20 -0
  258. package/dist/telemetry/throttling.js +70 -0
  259. package/dist/ui/welcome-screen.d.ts +9 -1
  260. package/dist/ui/welcome-screen.js +91 -38
  261. package/dist/utils/change-metadata.d.ts +43 -0
  262. package/dist/utils/change-metadata.js +123 -7
  263. package/dist/utils/change-utils.d.ts +10 -4
  264. package/dist/utils/change-utils.js +20 -13
  265. package/dist/utils/ci.d.ts +12 -0
  266. package/dist/utils/ci.js +16 -0
  267. package/dist/utils/command-references.d.ts +92 -6
  268. package/dist/utils/command-references.js +180 -7
  269. package/dist/utils/date.d.ts +8 -0
  270. package/dist/utils/date.js +13 -0
  271. package/dist/utils/file-system.d.ts +10 -0
  272. package/dist/utils/file-system.js +70 -0
  273. package/dist/utils/index.d.ts +1 -1
  274. package/dist/utils/index.js +1 -1
  275. package/dist/utils/interactive.d.ts +23 -0
  276. package/dist/utils/interactive.js +32 -0
  277. package/dist/utils/item-discovery.d.ts +19 -0
  278. package/dist/utils/item-discovery.js +30 -48
  279. package/dist/utils/shell-detection.d.ts +1 -1
  280. package/dist/utils/shell-detection.js +64 -11
  281. package/dist/utils/spec-discovery.d.ts +40 -0
  282. package/dist/utils/spec-discovery.js +115 -0
  283. package/dist/utils/task-progress.d.ts +29 -1
  284. package/dist/utils/task-progress.js +109 -15
  285. package/package.json +96 -84
  286. package/schemas/spec-driven/schema.yaml +252 -184
  287. package/schemas/spec-driven/templates/design.md +19 -19
  288. package/schemas/spec-driven/templates/plan-template.md +91 -0
  289. package/schemas/spec-driven/templates/proposal.md +29 -24
  290. package/schemas/spec-driven/templates/spec.md +11 -8
  291. package/schemas/spec-driven/templates/tasks.md +9 -9
  292. package/scripts/postinstall.js +83 -83
  293. package/dist/core/command-generation/adapters/codex.d.ts +0 -16
  294. package/dist/core/command-generation/adapters/codex.js +0 -39
  295. package/dist/core/command-generation/adapters/windsurf.d.ts +0 -14
  296. package/dist/core/command-generation/adapters/windsurf.js +0 -38
  297. package/dist/core/comprehension/config.d.ts +0 -20
  298. package/dist/core/comprehension/config.js +0 -23
  299. package/dist/core/comprehension/fingerprint.d.ts +0 -14
  300. package/dist/core/comprehension/fingerprint.js +0 -33
  301. package/dist/core/comprehension/index.d.ts +0 -57
  302. package/dist/core/comprehension/index.js +0 -87
  303. package/dist/core/comprehension/pass-record.d.ts +0 -29
  304. package/dist/core/comprehension/pass-record.js +0 -64
  305. package/dist/core/comprehension/stats.d.ts +0 -35
  306. package/dist/core/comprehension/stats.js +0 -133
  307. package/dist/core/templates/workflows/comprehension-guidance.d.ts +0 -9
  308. package/dist/core/templates/workflows/comprehension-guidance.js +0 -73
  309. package/dist/core/templates/workflows/mcp-guidance.d.ts +0 -13
  310. package/dist/core/templates/workflows/mcp-guidance.js +0 -131
  311. package/dist/core/templates/workflows/user-prompt-guidance.d.ts +0 -16
  312. package/dist/core/templates/workflows/user-prompt-guidance.js +0 -48
  313. package/dist/telemetry/caller.d.ts +0 -5
  314. package/dist/telemetry/caller.js +0 -29
  315. package/dist/telemetry/client.d.ts +0 -27
  316. package/dist/telemetry/client.js +0 -127
  317. package/dist/telemetry/command-context.d.ts +0 -13
  318. package/dist/telemetry/command-context.js +0 -59
  319. package/dist/telemetry/comprehension.d.ts +0 -44
  320. package/dist/telemetry/comprehension.js +0 -105
  321. package/dist/telemetry/content.d.ts +0 -10
  322. package/dist/telemetry/content.js +0 -56
  323. package/dist/telemetry/git-stats.d.ts +0 -12
  324. package/dist/telemetry/git-stats.js +0 -69
  325. package/dist/telemetry/identify-cache.d.ts +0 -7
  326. package/dist/telemetry/identify-cache.js +0 -47
  327. package/dist/telemetry/input.d.ts +0 -17
  328. package/dist/telemetry/input.js +0 -68
  329. package/dist/telemetry/marker.d.ts +0 -37
  330. package/dist/telemetry/marker.js +0 -67
  331. package/dist/telemetry/workflow.d.ts +0 -85
  332. package/dist/telemetry/workflow.js +0 -318
  333. package/schemas/spec-driven/templates/plan.md +0 -19
@@ -6,7 +6,7 @@
6
6
  import { Option } from 'commander';
7
7
  import { resolveRootForCommand, } from '../core/root-selection.js';
8
8
  import { readOptionalStoreMetadataState } from '../core/store/foundation.js';
9
- import { gitOriginUrl, isGitRepositoryAtRoot } from '../core/store/git.js';
9
+ import { gitOriginUrl, gitTrackingDrift, isGitRepositoryAtRoot } from '../core/store/git.js';
10
10
  import { classifyOpenSpecDir, readProjectConfig, resolveConfigFilePath, } from '../core/project-config.js';
11
11
  import { findRepoPlanningRootSync } from '../core/planning-home.js';
12
12
  import { gatherRelationshipData } from './shared-gather.js';
@@ -27,7 +27,8 @@ async function gatherHealth(root) {
27
27
  referenceEntries,
28
28
  registryUnreadable,
29
29
  };
30
- // Store facts for store-backed roots (explicit --store or declared).
30
+ // Store facts for store-backed roots (explicit --store, a declared
31
+ // pointer, or the global default).
31
32
  // Missing/invalid metadata never reaches here: store resolution
32
33
  // verifies identity first and fails with the existing taxonomy
33
34
  // (recorded amendment - corrupt store.yaml is an exit-1 resolution
@@ -35,14 +36,18 @@ async function gatherHealth(root) {
35
36
  if (root.storeId) {
36
37
  const metadata = await readOptionalStoreMetadataState(root.path).catch(() => null);
37
38
  // 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;
39
+ // another repo would record the ENCLOSING repo's origin (and drift).
40
+ const isRepo = await isGitRepositoryAtRoot(root.path);
41
+ const [originUrl, drift] = isRepo
42
+ ? await Promise.all([gitOriginUrl(root.path), gitTrackingDrift(root.path)])
43
+ : [null, null];
40
44
  input.storeFacts = {
41
45
  id: root.storeId,
42
46
  metadataPresent: metadata !== null,
43
47
  metadataValid: metadata !== null,
44
48
  ...(metadata?.remote ? { canonicalRemote: metadata.remote } : {}),
45
49
  ...(originUrl ? { originUrl } : {}),
50
+ ...(drift ? { drift } : {}),
46
51
  };
47
52
  }
48
53
  // The 3.2 both-shapes wrong turn, structured — including a malformed
@@ -1,7 +1,6 @@
1
1
  import { execSync, execFileSync } from 'child_process';
2
2
  import { createRequire } from 'module';
3
3
  import os from 'os';
4
- import { trackEvent } from '../telemetry/index.js';
5
4
  const require = createRequire(import.meta.url);
6
5
  /**
7
6
  * Check if gh CLI is installed and available in PATH
@@ -60,10 +59,10 @@ function generateMetadata() {
60
59
  const version = getVersion();
61
60
  const platform = getPlatform();
62
61
  const timestamp = getTimestamp();
63
- return `---
64
- Submitted via OpenSpec CLI
65
- - Version: ${version}
66
- - Platform: ${platform}
62
+ return `---
63
+ Submitted via OpenSpec CLI
64
+ - Version: ${version}
65
+ - Platform: ${platform}
67
66
  - Timestamp: ${timestamp}`;
68
67
  }
69
68
  /**
@@ -88,7 +87,7 @@ function formatBody(bodyText) {
88
87
  * Generate a pre-filled GitHub issue URL for manual submission
89
88
  */
90
89
  function generateManualSubmissionUrl(title, body) {
91
- const repo = 'codewalla-engineering/OpenSpec';
90
+ const repo = 'codewalla-engineering/openspec-upstream-sync';
92
91
  const encodedTitle = encodeURIComponent(title);
93
92
  const encodedBody = encodeURIComponent(body);
94
93
  const encodedLabels = encodeURIComponent('feedback');
@@ -106,38 +105,88 @@ function displayFormattedFeedback(title, body) {
106
105
  console.log('--- END FEEDBACK ---\n');
107
106
  }
108
107
  /**
109
- * Submit feedback via gh CLI
108
+ * Check whether gh refused the issue because the repository does not define
109
+ * the label. gh resolves label names before creating the issue, so this
110
+ * failure means no issue was created.
111
+ *
112
+ * Only gh's stderr is inspected. The error message also embeds the command
113
+ * line, which carries the user's own feedback text.
114
+ */
115
+ function isMissingLabelError(error) {
116
+ return /could not add label/i.test(error?.stderr?.toString() ?? '');
117
+ }
118
+ /**
119
+ * Report a gh CLI failure and exit, preserving gh's exit code.
120
+ *
121
+ * gh failed after the user already typed their feedback (issues disabled,
122
+ * network, rate limit, ...), so show the same manual-submission path the
123
+ * missing-gh and unauthenticated flows get instead of discarding the text.
124
+ */
125
+ function reportGhFailure(error, title, body) {
126
+ // Display the error output from gh CLI
127
+ if (error.stderr) {
128
+ console.error(error.stderr.toString());
129
+ }
130
+ else if (error.message) {
131
+ console.error(error.message);
132
+ }
133
+ displayFormattedFeedback(title, body);
134
+ const manualUrl = generateManualSubmissionUrl(title, body);
135
+ console.log('Please submit your feedback manually:');
136
+ console.log(manualUrl);
137
+ // Exit with the same code as gh CLI
138
+ process.exit(error.status ?? 1);
139
+ }
140
+ /**
141
+ * Create the feedback issue via gh CLI
110
142
  * Uses execFileSync to prevent shell injection vulnerabilities
111
143
  */
144
+ function createIssue(title, body, labels) {
145
+ const args = [
146
+ 'issue',
147
+ 'create',
148
+ '--repo',
149
+ 'codewalla-engineering/openspec-upstream-sync',
150
+ '--title',
151
+ title,
152
+ '--body',
153
+ body,
154
+ ];
155
+ for (const label of labels) {
156
+ args.push('--label', label);
157
+ }
158
+ const result = execFileSync('gh', args, { encoding: 'utf-8', stdio: 'pipe' });
159
+ return result.trim();
160
+ }
161
+ /**
162
+ * Submit feedback via gh CLI
163
+ */
112
164
  function submitViaGhCli(title, body) {
165
+ let issueUrl;
166
+ let labelApplied = true;
113
167
  try {
114
- const result = execFileSync('gh', [
115
- 'issue',
116
- 'create',
117
- '--repo',
118
- 'codewalla-engineering/OpenSpec',
119
- '--title',
120
- title,
121
- '--body',
122
- body,
123
- '--label',
124
- 'feedback',
125
- ], { encoding: 'utf-8', stdio: 'pipe' });
126
- const issueUrl = result.trim();
127
- trackEvent('feedback_submitted', { has_body: Boolean(body) });
128
- console.log(`\n✓ Feedback submitted successfully!`);
129
- console.log(`Issue URL: ${issueUrl}\n`);
168
+ issueUrl = createIssue(title, body, ['feedback']);
130
169
  }
131
170
  catch (error) {
132
- // Display the error output from gh CLI
133
- if (error.stderr) {
134
- console.error(error.stderr.toString());
171
+ if (!isMissingLabelError(error)) {
172
+ reportGhFailure(error, title, body);
173
+ return;
135
174
  }
136
- else if (error.message) {
137
- console.error(error.message);
175
+ // The repository does not define the 'feedback' label. Nothing was
176
+ // created, so retry unlabeled rather than dropping the feedback.
177
+ try {
178
+ issueUrl = createIssue(title, body, []);
179
+ labelApplied = false;
138
180
  }
139
- // Exit with the same code as gh CLI
140
- process.exit(error.status ?? 1);
181
+ catch (retryError) {
182
+ reportGhFailure(retryError, title, body);
183
+ return;
184
+ }
185
+ }
186
+ console.log(`\n✓ Feedback submitted successfully!`);
187
+ console.log(`Issue URL: ${issueUrl}\n`);
188
+ if (!labelApplied) {
189
+ console.log("Note: created without the 'feedback' label because the repository does not define it.\n");
141
190
  }
142
191
  }
143
192
  /**
@@ -0,0 +1,26 @@
1
+ import { Command } from 'commander';
2
+ export interface ModifyCommandOptions {
3
+ artifact: string;
4
+ workflowInput?: string;
5
+ editor?: boolean;
6
+ change: string;
7
+ json?: boolean;
8
+ }
9
+ export interface ModifyCommandOutput {
10
+ success: boolean;
11
+ artifactsToUpdate: Array<{
12
+ artifactId: string;
13
+ filePath: string;
14
+ modificationScope: 'direct' | 'propagated';
15
+ }>;
16
+ conflicts?: Array<{
17
+ artifactId: string;
18
+ affectedSections: string[];
19
+ }>;
20
+ reason?: string;
21
+ }
22
+ /**
23
+ * Creates the modify command.
24
+ */
25
+ export declare function createModifyCommand(): Command;
26
+ //# sourceMappingURL=modify.d.ts.map
@@ -0,0 +1,147 @@
1
+ import { Command } from 'commander';
2
+ import { join } from 'node:path';
3
+ import { ArtifactGraph } from '../core/artifact-graph/graph.js';
4
+ import { canModify } from '../core/change-status-policy.js';
5
+ import { DependencyPropagator } from '../core/modify/dependency-propagator.js';
6
+ import { ConflictDetector } from '../core/modify/conflict-detector.js';
7
+ import { HistoryTracker } from '../core/modify/history-tracker.js';
8
+ import { resolveCurrentPlanningHomeSync } from '../core/planning-home.js';
9
+ import { resolveArtifactOutputPath } from '../core/artifact-graph/outputs.js';
10
+ import { trackArtifactModifyRequested, trackArtifactRevisionRequested, trackChangeProposalReady } from '../telemetry/index.js';
11
+ /**
12
+ * Creates the modify command.
13
+ */
14
+ export function createModifyCommand() {
15
+ const command = new Command('modify')
16
+ .description('Modify planning artifacts before implementation starts')
17
+ .option('--artifact <id>', 'Artifact ID to modify')
18
+ .option('--workflow-input <path>', 'Workflow input file')
19
+ .option('--editor', 'Open in editor after modification')
20
+ .option('--json', 'Output JSON')
21
+ .argument('[change]', 'Change name')
22
+ .action(async (changeName, options) => {
23
+ const modifyOptions = {
24
+ artifact: options.artifact,
25
+ workflowInput: options.workflowInput,
26
+ editor: options.editor,
27
+ change: changeName,
28
+ json: options.json,
29
+ };
30
+ try {
31
+ const result = await executeModify(modifyOptions);
32
+ if (options.json) {
33
+ console.log(JSON.stringify(result, null, 2));
34
+ }
35
+ else {
36
+ console.log(formatOutput(result));
37
+ }
38
+ }
39
+ catch (error) {
40
+ const errorOutput = {
41
+ success: false,
42
+ artifactsToUpdate: [],
43
+ reason: error instanceof Error ? error.message : String(error),
44
+ };
45
+ if (options.json) {
46
+ console.log(JSON.stringify(errorOutput, null, 2));
47
+ }
48
+ else {
49
+ console.error(`Error: ${errorOutput.reason}`);
50
+ }
51
+ process.exit(1);
52
+ }
53
+ });
54
+ return command;
55
+ }
56
+ /**
57
+ * Executes the modify command logic.
58
+ */
59
+ async function executeModify(options) {
60
+ const planningHome = resolveCurrentPlanningHomeSync();
61
+ const changesDir = planningHome.changesDir;
62
+ const changeRoot = planningHome.root;
63
+ // Pre-apply validation: check if implementation has started
64
+ const canModifyResult = await canModify(options.change, changesDir);
65
+ if (!canModifyResult.canModify) {
66
+ return {
67
+ success: false,
68
+ artifactsToUpdate: [],
69
+ reason: canModifyResult.reason,
70
+ };
71
+ }
72
+ // Load artifact graph
73
+ const schemaPath = planningHome.defaultSchema;
74
+ const graph = ArtifactGraph.fromYaml(schemaPath);
75
+ // Get artifact to modify
76
+ const artifactId = options.artifact;
77
+ if (!artifactId) {
78
+ throw new Error('--artifact flag is required');
79
+ }
80
+ const artifact = graph.getArtifact(artifactId);
81
+ if (!artifact) {
82
+ throw new Error(`Artifact not found: ${artifactId}`);
83
+ }
84
+ // Calculate update scope
85
+ const propagator = new DependencyPropagator(graph, changeRoot);
86
+ const updateScope = propagator.calculateUpdateScope([artifactId]);
87
+ // Build artifact paths map
88
+ const artifactPaths = new Map();
89
+ for (const id of updateScope) {
90
+ const art = graph.getArtifact(id);
91
+ if (art) {
92
+ const changeDir = join(changesDir, options.change);
93
+ const path = resolveArtifactOutputPath(changeDir, art.generates);
94
+ artifactPaths.set(id, path);
95
+ }
96
+ }
97
+ // Check for conflicts
98
+ const conflictDetector = new ConflictDetector(changeRoot);
99
+ const conflicts = await conflictDetector.detectAllConflicts(artifactPaths, new Map());
100
+ if (conflicts.length > 0) {
101
+ return {
102
+ success: false,
103
+ artifactsToUpdate: [],
104
+ conflicts,
105
+ reason: 'Conflicts detected with manual edits. Resolve conflicts before modifying.',
106
+ };
107
+ }
108
+ // Record modification history
109
+ const historyTracker = new HistoryTracker(changeRoot);
110
+ await historyTracker.recordModification(options.change, [artifactId], options.workflowInput || 'Manual modification');
111
+ // Emit telemetry events
112
+ await trackArtifactModifyRequested(options.change, artifactId);
113
+ // Track proposal ready if proposal artifact is being modified
114
+ if (artifactId === 'proposal') {
115
+ await trackChangeProposalReady(options.change);
116
+ }
117
+ for (const id of updateScope) {
118
+ if (id !== artifactId) {
119
+ await trackArtifactRevisionRequested(options.change, id);
120
+ }
121
+ }
122
+ // Build result
123
+ const artifactsToUpdate = updateScope.map((id) => ({
124
+ artifactId: id,
125
+ filePath: artifactPaths.get(id) || '',
126
+ modificationScope: id === artifactId ? 'direct' : 'propagated',
127
+ }));
128
+ return {
129
+ success: true,
130
+ artifactsToUpdate,
131
+ };
132
+ }
133
+ /**
134
+ * Formats the command output for human-readable display.
135
+ */
136
+ function formatOutput(result) {
137
+ if (!result.success) {
138
+ return `Modification failed: ${result.reason}`;
139
+ }
140
+ let output = `Modification successful. ${result.artifactsToUpdate.length} artifacts to update:\n\n`;
141
+ for (const artifact of result.artifactsToUpdate) {
142
+ const scope = artifact.modificationScope === 'direct' ? 'direct' : 'propagated';
143
+ output += ` - ${artifact.artifactId} (${scope}): ${artifact.filePath}\n`;
144
+ }
145
+ return output;
146
+ }
147
+ //# sourceMappingURL=modify.js.map