@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
@@ -0,0 +1,156 @@
1
+ import path from 'path';
2
+ import * as fs from 'fs';
3
+ import { AI_TOOLS, OPENSPEC_SKILL_NAMES } from './config.js';
4
+ import { FileSystemUtils } from '../utils/file-system.js';
5
+ const TARGET_MARKER = '.openspec-target';
6
+ /** Returns the ownership-marker path for one shared skills root. */
7
+ function markerPath(projectPath, skillsDir) {
8
+ return path.join(projectPath, skillsDir, 'skills', TARGET_MARKER);
9
+ }
10
+ /** Reads a valid-looking marker value without letting linked roots escape. */
11
+ export function readSharedSkillTarget(projectPath, skillsDir) {
12
+ try {
13
+ const target = markerPath(projectPath, skillsDir);
14
+ FileSystemUtils.assertProjectArtifactPath(projectPath, target);
15
+ return fs.readFileSync(target, 'utf-8').trim() || undefined;
16
+ }
17
+ catch {
18
+ return undefined;
19
+ }
20
+ }
21
+ /** Whether a tool still has an allowlisted managed skill under an old root. */
22
+ function hasLegacySkills(projectPath, tool) {
23
+ return (tool.legacySkillsDirs ?? []).some((root) => {
24
+ const skillsDir = path.join(projectPath, root, 'skills');
25
+ return OPENSPEC_SKILL_NAMES.some((skillName) => {
26
+ try {
27
+ const skillFile = path.join(skillsDir, skillName, 'SKILL.md');
28
+ FileSystemUtils.assertProjectArtifactPath(projectPath, skillFile);
29
+ return fs.existsSync(skillFile);
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ });
35
+ });
36
+ }
37
+ /**
38
+ * Infers pre-marker ownership from generated invocation syntax. This preserves
39
+ * both existing generic `.agents` trees and Codex trees users moved manually.
40
+ */
41
+ function inferSharedSkillTarget(projectPath, skillsDir) {
42
+ let foundGenericReference = false;
43
+ for (const skillName of OPENSPEC_SKILL_NAMES) {
44
+ const skillFile = path.join(projectPath, skillsDir, 'skills', skillName, 'SKILL.md');
45
+ try {
46
+ FileSystemUtils.assertProjectArtifactPath(projectPath, skillFile);
47
+ const content = fs.readFileSync(skillFile, 'utf-8');
48
+ if (content.includes('$openspec-'))
49
+ return 'codex';
50
+ if (content.includes('/openspec-'))
51
+ foundGenericReference = true;
52
+ }
53
+ catch {
54
+ // Missing, unreadable, or out-of-project files provide no ownership signal.
55
+ }
56
+ }
57
+ return foundGenericReference ? 'agents' : undefined;
58
+ }
59
+ /** Whether the canonical shared root already contains an OpenSpec skill. */
60
+ function hasCurrentSkills(projectPath, skillsDir) {
61
+ return OPENSPEC_SKILL_NAMES.some((skillName) => {
62
+ const skillFile = path.join(projectPath, skillsDir, 'skills', skillName, 'SKILL.md');
63
+ try {
64
+ FileSystemUtils.assertProjectArtifactPath(projectPath, skillFile);
65
+ return fs.existsSync(skillFile);
66
+ }
67
+ catch {
68
+ return false;
69
+ }
70
+ });
71
+ }
72
+ /**
73
+ * A shared skill root can only hold one rendered variant of each skill.
74
+ * Keep the writer recorded so later updates do not infer every tool that
75
+ * happens to use the same directory.
76
+ */
77
+ export function reconcileSharedSkillTargets(projectPath, tools) {
78
+ const byRoot = new Map();
79
+ for (const tool of tools) {
80
+ if (!tool.skillsDir)
81
+ continue;
82
+ const group = byRoot.get(tool.skillsDir) ?? [];
83
+ group.push(tool);
84
+ byRoot.set(tool.skillsDir, group);
85
+ }
86
+ const reconciled = [];
87
+ for (const group of byRoot.values()) {
88
+ if (group.length === 1) {
89
+ reconciled.push(group[0]);
90
+ continue;
91
+ }
92
+ const root = group[0].skillsDir;
93
+ const marked = readSharedSkillTarget(projectPath, root);
94
+ const markedTool = group.find((tool) => tool.value === marked);
95
+ if (markedTool) {
96
+ reconciled.push(markedTool);
97
+ continue;
98
+ }
99
+ const inferred = inferSharedSkillTarget(projectPath, root);
100
+ const legacyCodex = group.find((tool) => tool.value === 'codex' && hasLegacySkills(projectPath, tool));
101
+ if (inferred === 'agents' && legacyCodex) {
102
+ // Before ownership markers existed, selecting both targets produced a
103
+ // generic canonical tree plus a Codex-only legacy tree. Codex now emits
104
+ // a dual-syntax canonical tree, so it can safely consolidate that state.
105
+ reconciled.push(legacyCodex);
106
+ continue;
107
+ }
108
+ const inferredTool = group.find((tool) => tool.value === inferred);
109
+ if (inferredTool) {
110
+ reconciled.push(inferredTool);
111
+ continue;
112
+ }
113
+ // An unmarked canonical tree predates Codex's move into `.agents`; keep
114
+ // that established agents target instead of overwriting it from `.codex`.
115
+ if (hasCurrentSkills(projectPath, root)) {
116
+ reconciled.push(group.find((tool) => tool.value === 'agents') ?? group[0]);
117
+ continue;
118
+ }
119
+ const legacyTool = group.find((tool) => hasLegacySkills(projectPath, tool));
120
+ if (legacyTool) {
121
+ reconciled.push(legacyTool);
122
+ continue;
123
+ }
124
+ // `.agents` existed as the vendor-neutral target before Codex adopted it.
125
+ // Unmarked trees therefore retain that established meaning.
126
+ reconciled.push(group.find((tool) => tool.value === 'agents') ?? group[0]);
127
+ }
128
+ return reconciled;
129
+ }
130
+ /**
131
+ * Returns whether a tool is the active writer for its physical skills root.
132
+ * Non-shared roots are always active.
133
+ */
134
+ export function isSharedSkillTargetActive(projectPath, toolId) {
135
+ const tool = AI_TOOLS.find((candidate) => candidate.value === toolId);
136
+ if (!tool?.skillsDir)
137
+ return false;
138
+ const sharingRoot = AI_TOOLS.filter((candidate) => candidate.skillsDir === tool.skillsDir);
139
+ if (sharingRoot.length < 2)
140
+ return true;
141
+ return reconcileSharedSkillTargets(projectPath, sharingRoot)
142
+ .some((candidate) => candidate.value === toolId);
143
+ }
144
+ export function writeSharedSkillTarget(projectPath, toolId) {
145
+ const tool = AI_TOOLS.find((candidate) => candidate.value === toolId);
146
+ if (!tool?.skillsDir)
147
+ return;
148
+ const sharingRoot = AI_TOOLS.filter((candidate) => candidate.skillsDir === tool.skillsDir);
149
+ if (sharingRoot.length < 2)
150
+ return;
151
+ const target = markerPath(projectPath, tool.skillsDir);
152
+ FileSystemUtils.assertProjectArtifactPath(projectPath, target);
153
+ fs.mkdirSync(path.dirname(target), { recursive: true });
154
+ fs.writeFileSync(target, `${toolId}\n`, 'utf-8');
155
+ }
156
+ //# sourceMappingURL=shared-skill-target.js.map
@@ -5,28 +5,16 @@
5
5
  * Applies delta specs from a change to main specs without archiving.
6
6
  */
7
7
  export interface SpecUpdate {
8
+ /** Capability id relative to the specs root, forward-slash separated (e.g. "web" or "platform/session-layout"). */
9
+ id: string;
10
+ /** Allowed root for the delta source. */
11
+ sourceRoot: string;
8
12
  source: string;
13
+ /** Allowed root for the main-spec target. */
14
+ targetRoot: string;
9
15
  target: string;
10
16
  exists: boolean;
11
17
  }
12
- export interface ApplyResult {
13
- capability: string;
14
- added: number;
15
- modified: number;
16
- removed: number;
17
- renamed: number;
18
- }
19
- export interface SpecsApplyOutput {
20
- changeName: string;
21
- capabilities: ApplyResult[];
22
- totals: {
23
- added: number;
24
- modified: number;
25
- removed: number;
26
- renamed: number;
27
- };
28
- noChanges: boolean;
29
- }
30
18
  /**
31
19
  * Find all delta spec files that need to be applied from a change.
32
20
  */
@@ -45,7 +33,75 @@ export declare function buildUpdatedSpec(update: SpecUpdate, changeName: string,
45
33
  removed: number;
46
34
  renamed: number;
47
35
  };
36
+ warnings: string[];
37
+ /**
38
+ * Every canonical `### Requirement:` block the delta could act on is gone.
39
+ * This is only a *candidate* signal for retirement (#1302): the validator, not
40
+ * this count, decides whether `rebuilt` is actually unwritable - it recognises
41
+ * requirement shapes this parser sweeps into the preamble, so a spec can be
42
+ * blockless here and still validate. See `isRetirableSpec` in archive.ts.
43
+ */
44
+ noRequirementBlocks: boolean;
45
+ /**
46
+ * Every non-blank line of the spec this merge cannot name.
47
+ *
48
+ * Retirement deletes the whole file, so the only safe question is whether the
49
+ * merge can account for all of it. `extractRequirementsSection` splits a spec
50
+ * into five slices, and auditing a subset is how this guard kept failing: for
51
+ * seven rounds it looked for requirement-SHAPED text and was beaten by a new
52
+ * disguise each time, and when it started asking where content landed it
53
+ * still read only the preamble and the tail - so content simply moved into a
54
+ * slice nobody checked, and authored prose sitting inside a removed block's
55
+ * raw was deleted while the report said only "Purpose" was lost.
56
+ *
57
+ * So this accounts for the whole file: the title, the `## Purpose` section,
58
+ * the `## Requirements` header, and, inside each requirement block, the parts
59
+ * that make up a requirement - its header, its statement, and its scenarios'
60
+ * bullets. Every other non-blank line is reported and refuses the retirement.
61
+ *
62
+ * Fails safe in every direction: a line this cannot classify counts as
63
+ * unaccounted, which refuses rather than deletes.
64
+ */
65
+ unaccountedContent: string[];
48
66
  }>;
67
+ /**
68
+ * Retire a capability whose last requirement a delta removed: delete its main
69
+ * spec and prune any directories the deletion leaves empty. Returns false when
70
+ * there was nothing to delete.
71
+ *
72
+ * Gated by the caller on the change's `retire_capabilities` marker, so the one
73
+ * archive action that removes a file from `openspec/specs/` is always something
74
+ * the author asked for rather than something inferred from a delta's shape. The
75
+ * file is recoverable from git, which the report names; applying REMOVED already
76
+ * deletes requirement content from a main spec, so deleting the spec once
77
+ * nothing is left is the same operation carried to its end rather than a new
78
+ * kind of act.
79
+ *
80
+ * Only the generated `spec.md` is removed - a directory holding anything else (a
81
+ * nested capability, a hand-kept note) is left in place.
82
+ *
83
+ * The target must resolve inside the selected specs root. A capability-directory
84
+ * symlink must not turn a retirement marker into authorization to delete an
85
+ * unrelated external file. A symlinked `spec.md` itself is safe: unlink removes
86
+ * the link and leaves its target alone.
87
+ *
88
+ * Directory pruning IS bounded, by REAL paths rather than string prefixes:
89
+ * `path.resolve` collapses `..` but does not resolve symlinks, and `readdir` and
90
+ * `rmdir` both follow them, so a symlinked capability directory would otherwise
91
+ * let the walk delete directories outside the specs root entirely.
92
+ */
93
+ export declare function retireSpec(update: SpecUpdate, mainSpecsDir: string, options?: {
94
+ silent?: boolean;
95
+ displayPath?: string;
96
+ beforeMutate?: () => Promise<void>;
97
+ verifyDisplaced?: (displacedPath: string) => Promise<void>;
98
+ deferDelete?: boolean;
99
+ }): Promise<{
100
+ retired: boolean;
101
+ resolvedPath?: string;
102
+ displacedPath?: string;
103
+ }>;
104
+ export declare function finalizeRetiredSpec(target: string, displacedPath: string, mainSpecsDir: string): Promise<void>;
49
105
  /**
50
106
  * Write an updated spec to disk.
51
107
  */
@@ -57,22 +113,13 @@ export declare function writeUpdatedSpec(update: SpecUpdate, rebuilt: string, co
57
113
  }, options?: {
58
114
  silent?: boolean;
59
115
  displayPath?: string;
116
+ beforeMutate?: () => Promise<void>;
60
117
  }): Promise<void>;
61
118
  /**
62
- * Build a skeleton spec for new capabilities.
63
- */
64
- export declare function buildSpecSkeleton(specFolderName: string, changeName: string): string;
65
- /**
66
- * Apply all delta specs from a change to main specs.
67
- *
68
- * @param projectRoot - The project root directory
69
- * @param changeName - The name of the change to apply
70
- * @param options - Options for the operation
71
- * @returns Result of the operation with counts
119
+ * Build a skeleton spec for new capabilities. When the delta spec authored a
120
+ * `## Purpose`, carry it over instead of the TBD placeholder (#1413) - archive
121
+ * invents the Purpose for a brand-new main spec either way, and the author's
122
+ * own wording beats a placeholder they then have to hand-edit.
72
123
  */
73
- export declare function applySpecs(projectRoot: string, changeName: string, options?: {
74
- dryRun?: boolean;
75
- skipValidation?: boolean;
76
- silent?: boolean;
77
- }): Promise<SpecsApplyOutput>;
124
+ export declare function buildSpecSkeleton(specFolderName: string, changeName: string, purpose?: string): string;
78
125
  //# sourceMappingURL=specs-apply.d.ts.map