@niujiajie/freespec 0.0.0-stage → 1.15.0

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 (308) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +58 -2
  3. package/bin/freespec.js +5 -0
  4. package/dist/cli/index.d.ts +25 -0
  5. package/dist/cli/index.js +359 -0
  6. package/dist/commands/shared-output.d.ts +18 -0
  7. package/dist/commands/shared-output.js +61 -0
  8. package/dist/commands/workflow/default-schema.d.ts +2 -0
  9. package/dist/commands/workflow/default-schema.js +4 -0
  10. package/dist/commands/workflow/index.d.ts +13 -0
  11. package/dist/commands/workflow/index.js +10 -0
  12. package/dist/commands/workflow/instructions.d.ts +39 -0
  13. package/dist/commands/workflow/instructions.js +565 -0
  14. package/dist/commands/workflow/new-change.d.ts +19 -0
  15. package/dist/commands/workflow/new-change.js +135 -0
  16. package/dist/commands/workflow/shared.d.ts +94 -0
  17. package/dist/commands/workflow/shared.js +169 -0
  18. package/dist/commands/workflow/status.d.ts +18 -0
  19. package/dist/commands/workflow/status.js +201 -0
  20. package/dist/core/artifact-graph/graph.d.ts +72 -0
  21. package/dist/core/artifact-graph/graph.js +165 -0
  22. package/dist/core/artifact-graph/index.d.ts +9 -0
  23. package/dist/core/artifact-graph/index.js +14 -0
  24. package/dist/core/artifact-graph/instruction-loader.d.ts +208 -0
  25. package/dist/core/artifact-graph/instruction-loader.js +268 -0
  26. package/dist/core/artifact-graph/outputs.d.ts +19 -0
  27. package/dist/core/artifact-graph/outputs.js +351 -0
  28. package/dist/core/artifact-graph/resolver.d.ts +89 -0
  29. package/dist/core/artifact-graph/resolver.js +342 -0
  30. package/dist/core/artifact-graph/schema.d.ts +27 -0
  31. package/dist/core/artifact-graph/schema.js +160 -0
  32. package/dist/core/artifact-graph/state.d.ts +12 -0
  33. package/dist/core/artifact-graph/state.js +31 -0
  34. package/dist/core/artifact-graph/types.d.ts +40 -0
  35. package/dist/core/artifact-graph/types.js +59 -0
  36. package/dist/core/available-tools.d.ts +18 -0
  37. package/dist/core/available-tools.js +49 -0
  38. package/dist/core/change-layout.d.ts +17 -0
  39. package/dist/core/change-layout.js +30 -0
  40. package/dist/core/change-metadata/index.d.ts +2 -0
  41. package/dist/core/change-metadata/index.js +2 -0
  42. package/dist/core/change-metadata/schema.d.ts +23 -0
  43. package/dist/core/change-metadata/schema.js +46 -0
  44. package/dist/core/change-status-policy.d.ts +49 -0
  45. package/dist/core/change-status-policy.js +50 -0
  46. package/dist/core/command-generation/adapters/amazon-q.d.ts +17 -0
  47. package/dist/core/command-generation/adapters/amazon-q.js +32 -0
  48. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  49. package/dist/core/command-generation/adapters/antigravity.js +27 -0
  50. package/dist/core/command-generation/adapters/atomcode.d.ts +24 -0
  51. package/dist/core/command-generation/adapters/atomcode.js +46 -0
  52. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  53. package/dist/core/command-generation/adapters/auggie.js +28 -0
  54. package/dist/core/command-generation/adapters/bob.d.ts +18 -0
  55. package/dist/core/command-generation/adapters/bob.js +33 -0
  56. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  57. package/dist/core/command-generation/adapters/claude.js +32 -0
  58. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  59. package/dist/core/command-generation/adapters/cline.js +27 -0
  60. package/dist/core/command-generation/adapters/codeassistant.d.ts +15 -0
  61. package/dist/core/command-generation/adapters/codeassistant.js +29 -0
  62. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  63. package/dist/core/command-generation/adapters/codebuddy.js +29 -0
  64. package/dist/core/command-generation/adapters/codestudio.d.ts +13 -0
  65. package/dist/core/command-generation/adapters/codestudio.js +27 -0
  66. package/dist/core/command-generation/adapters/command-code.d.ts +19 -0
  67. package/dist/core/command-generation/adapters/command-code.js +34 -0
  68. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  69. package/dist/core/command-generation/adapters/continue.js +33 -0
  70. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  71. package/dist/core/command-generation/adapters/costrict.js +28 -0
  72. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  73. package/dist/core/command-generation/adapters/crush.js +30 -0
  74. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  75. package/dist/core/command-generation/adapters/cursor.js +31 -0
  76. package/dist/core/command-generation/adapters/devin.d.ts +19 -0
  77. package/dist/core/command-generation/adapters/devin.js +36 -0
  78. package/dist/core/command-generation/adapters/easycode.d.ts +17 -0
  79. package/dist/core/command-generation/adapters/easycode.js +28 -0
  80. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  81. package/dist/core/command-generation/adapters/factory.js +28 -0
  82. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  83. package/dist/core/command-generation/adapters/gemini.js +27 -0
  84. package/dist/core/command-generation/adapters/gigacode.d.ts +17 -0
  85. package/dist/core/command-generation/adapters/gigacode.js +31 -0
  86. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  87. package/dist/core/command-generation/adapters/github-copilot.js +27 -0
  88. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  89. package/dist/core/command-generation/adapters/iflow.js +30 -0
  90. package/dist/core/command-generation/adapters/index.d.ts +40 -0
  91. package/dist/core/command-generation/adapters/index.js +40 -0
  92. package/dist/core/command-generation/adapters/junie.d.ts +13 -0
  93. package/dist/core/command-generation/adapters/junie.js +27 -0
  94. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  95. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  96. package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
  97. package/dist/core/command-generation/adapters/kiro.js +27 -0
  98. package/dist/core/command-generation/adapters/lingma.d.ts +13 -0
  99. package/dist/core/command-generation/adapters/lingma.js +30 -0
  100. package/dist/core/command-generation/adapters/oh-my-pi.d.ts +21 -0
  101. package/dist/core/command-generation/adapters/oh-my-pi.js +42 -0
  102. package/dist/core/command-generation/adapters/opencode.d.ts +14 -0
  103. package/dist/core/command-generation/adapters/opencode.js +38 -0
  104. package/dist/core/command-generation/adapters/pi.d.ts +18 -0
  105. package/dist/core/command-generation/adapters/pi.js +39 -0
  106. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  107. package/dist/core/command-generation/adapters/qoder.js +30 -0
  108. package/dist/core/command-generation/adapters/qwen.d.ts +17 -0
  109. package/dist/core/command-generation/adapters/qwen.js +31 -0
  110. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  111. package/dist/core/command-generation/adapters/roocode.js +27 -0
  112. package/dist/core/command-generation/adapters/trae.d.ts +13 -0
  113. package/dist/core/command-generation/adapters/trae.js +28 -0
  114. package/dist/core/command-generation/adapters/zcode.d.ts +16 -0
  115. package/dist/core/command-generation/adapters/zcode.js +33 -0
  116. package/dist/core/command-generation/generator.d.ts +29 -0
  117. package/dist/core/command-generation/generator.js +43 -0
  118. package/dist/core/command-generation/index.d.ts +22 -0
  119. package/dist/core/command-generation/index.js +24 -0
  120. package/dist/core/command-generation/invocation.d.ts +73 -0
  121. package/dist/core/command-generation/invocation.js +77 -0
  122. package/dist/core/command-generation/registry.d.ts +36 -0
  123. package/dist/core/command-generation/registry.js +114 -0
  124. package/dist/core/command-generation/toml.d.ts +19 -0
  125. package/dist/core/command-generation/toml.js +39 -0
  126. package/dist/core/command-generation/types.d.ts +63 -0
  127. package/dist/core/command-generation/types.js +8 -0
  128. package/dist/core/command-generation/yaml.d.ts +36 -0
  129. package/dist/core/command-generation/yaml.js +48 -0
  130. package/dist/core/command-surface.d.ts +15 -0
  131. package/dist/core/command-surface.js +33 -0
  132. package/dist/core/config-prompts.d.ts +9 -0
  133. package/dist/core/config-prompts.js +56 -0
  134. package/dist/core/config-schema.d.ts +98 -0
  135. package/dist/core/config-schema.js +308 -0
  136. package/dist/core/config.d.ts +50 -0
  137. package/dist/core/config.js +122 -0
  138. package/dist/core/file-state.d.ts +36 -0
  139. package/dist/core/file-state.js +144 -0
  140. package/dist/core/file-view.d.ts +13 -0
  141. package/dist/core/file-view.js +14 -0
  142. package/dist/core/global-config.d.ts +101 -0
  143. package/dist/core/global-config.js +182 -0
  144. package/dist/core/id.d.ts +17 -0
  145. package/dist/core/id.js +30 -0
  146. package/dist/core/index.d.ts +6 -0
  147. package/dist/core/index.js +7 -0
  148. package/dist/core/init.d.ts +57 -0
  149. package/dist/core/init.js +836 -0
  150. package/dist/core/list.d.ts +11 -0
  151. package/dist/core/list.js +197 -0
  152. package/dist/core/migration.d.ts +121 -0
  153. package/dist/core/migration.js +540 -0
  154. package/dist/core/onboarding-commands.d.ts +30 -0
  155. package/dist/core/onboarding-commands.js +38 -0
  156. package/dist/core/openspec-root.d.ts +47 -0
  157. package/dist/core/openspec-root.js +196 -0
  158. package/dist/core/planning-home.d.ts +16 -0
  159. package/dist/core/planning-home.js +67 -0
  160. package/dist/core/profile-sync-drift.d.ts +31 -0
  161. package/dist/core/profile-sync-drift.js +201 -0
  162. package/dist/core/profiles.d.ts +19 -0
  163. package/dist/core/profiles.js +33 -0
  164. package/dist/core/project-config.d.ts +132 -0
  165. package/dist/core/project-config.js +519 -0
  166. package/dist/core/references.d.ts +10 -0
  167. package/dist/core/references.js +46 -0
  168. package/dist/core/root-selection.d.ts +59 -0
  169. package/dist/core/root-selection.js +132 -0
  170. package/dist/core/shared/allowed-tools.d.ts +12 -0
  171. package/dist/core/shared/allowed-tools.js +12 -0
  172. package/dist/core/shared/ide-restart.d.ts +26 -0
  173. package/dist/core/shared/ide-restart.js +42 -0
  174. package/dist/core/shared/index.d.ts +11 -0
  175. package/dist/core/shared/index.js +11 -0
  176. package/dist/core/shared/skill-content-equivalence.d.ts +7 -0
  177. package/dist/core/shared/skill-content-equivalence.js +45 -0
  178. package/dist/core/shared/skill-files.d.ts +7 -0
  179. package/dist/core/shared/skill-files.js +43 -0
  180. package/dist/core/shared/skill-generation.d.ts +49 -0
  181. package/dist/core/shared/skill-generation.js +125 -0
  182. package/dist/core/shared/skill-paths.d.ts +13 -0
  183. package/dist/core/shared/skill-paths.js +23 -0
  184. package/dist/core/shared/tool-detection.d.ts +99 -0
  185. package/dist/core/shared/tool-detection.js +318 -0
  186. package/dist/core/shared-skill-target.d.ts +51 -0
  187. package/dist/core/shared-skill-target.js +239 -0
  188. package/dist/core/store/errors.d.ts +20 -0
  189. package/dist/core/store/errors.js +22 -0
  190. package/dist/core/store/index.d.ts +2 -0
  191. package/dist/core/store/index.js +2 -0
  192. package/dist/core/styles/palette.d.ts +7 -0
  193. package/dist/core/styles/palette.js +8 -0
  194. package/dist/core/templates/optional-workflow.d.ts +69 -0
  195. package/dist/core/templates/optional-workflow.js +140 -0
  196. package/dist/core/templates/types.d.ts +19 -0
  197. package/dist/core/templates/types.js +5 -0
  198. package/dist/core/templates/workflows/personal.d.ts +22 -0
  199. package/dist/core/templates/workflows/personal.js +225 -0
  200. package/dist/core/update-plan.d.ts +127 -0
  201. package/dist/core/update-plan.js +390 -0
  202. package/dist/core/update.d.ts +154 -0
  203. package/dist/core/update.js +723 -0
  204. package/dist/core/version-check.d.ts +188 -0
  205. package/dist/core/version-check.js +906 -0
  206. package/dist/core/zod-issues.d.ts +4 -0
  207. package/dist/core/zod-issues.js +10 -0
  208. package/dist/index.d.ts +3 -0
  209. package/dist/index.js +3 -0
  210. package/dist/prompts/searchable-multi-select.d.ts +35 -0
  211. package/dist/prompts/searchable-multi-select.js +188 -0
  212. package/dist/telemetry/config.d.ts +37 -0
  213. package/dist/telemetry/config.js +148 -0
  214. package/dist/telemetry/index.d.ts +39 -0
  215. package/dist/telemetry/index.js +217 -0
  216. package/dist/telemetry/opt-out.d.ts +17 -0
  217. package/dist/telemetry/opt-out.js +27 -0
  218. package/dist/ui/ascii-patterns.d.ts +16 -0
  219. package/dist/ui/ascii-patterns.js +133 -0
  220. package/dist/ui/welcome-screen.d.ts +18 -0
  221. package/dist/ui/welcome-screen.js +199 -0
  222. package/dist/utils/change-metadata.d.ts +116 -0
  223. package/dist/utils/change-metadata.js +324 -0
  224. package/dist/utils/change-utils.d.ts +79 -0
  225. package/dist/utils/change-utils.js +121 -0
  226. package/dist/utils/ci.d.ts +12 -0
  227. package/dist/utils/ci.js +16 -0
  228. package/dist/utils/command-references.d.ts +104 -0
  229. package/dist/utils/command-references.js +190 -0
  230. package/dist/utils/date.d.ts +8 -0
  231. package/dist/utils/date.js +13 -0
  232. package/dist/utils/executable-path.d.ts +5 -0
  233. package/dist/utils/executable-path.js +44 -0
  234. package/dist/utils/file-system.d.ts +58 -0
  235. package/dist/utils/file-system.js +432 -0
  236. package/dist/utils/index.d.ts +6 -0
  237. package/dist/utils/index.js +9 -0
  238. package/dist/utils/interactive.d.ts +85 -0
  239. package/dist/utils/interactive.js +174 -0
  240. package/dist/utils/item-discovery.d.ts +15 -0
  241. package/dist/utils/item-discovery.js +33 -0
  242. package/dist/utils/line-endings.d.ts +34 -0
  243. package/dist/utils/line-endings.js +46 -0
  244. package/dist/utils/match.d.ts +3 -0
  245. package/dist/utils/match.js +22 -0
  246. package/dist/utils/nested-change.d.ts +35 -0
  247. package/dist/utils/nested-change.js +185 -0
  248. package/dist/utils/shell-detection.d.ts +20 -0
  249. package/dist/utils/shell-detection.js +94 -0
  250. package/dist/utils/task-progress.d.ts +67 -0
  251. package/dist/utils/task-progress.js +184 -0
  252. package/package.json +74 -4
  253. package/schemas//351/273/230/350/256/244/schema.yaml +68 -0
  254. package/schemas//351/273/230/350/256/244/templates//344/273/273/345/212/241/346/270/205/345/215/225.md +25 -0
  255. package/schemas//351/273/230/350/256/244/templates//346/265/213/350/257/225/347/224/250/344/276/213.md +34 -0
  256. package/schemas//351/273/230/350/256/244/templates//350/256/276/350/256/241/346/226/207/346/241/243.md +172 -0
  257. package/schemas//351/273/230/350/256/244/templates//351/234/200/346/261/202/346/226/207/346/241/243.md +19 -0
  258. package/skill-files//344/273/273/345/212/241/references//346/212/244/346/240/217.md +43 -0
  259. package/skill-files//344/273/273/345/212/241/references//347/262/222/345/272/246.md +23 -0
  260. package/skill-files//344/273/273/345/212/241/references//347/272/246/346/235/237.md +8 -0
  261. package/skill-files//344/273/273/345/212/241/scripts/check-tasks.mjs +83 -0
  262. package/skill-files//345/206/231Java/references/Java/350/247/204/350/214/203.md +25 -0
  263. package/skill-files//345/206/231Java/references//345/215/261/351/231/251/345/206/231/346/263/225.md +27 -0
  264. package/skill-files//345/206/231Java/references//345/256/214/346/210/220/345/257/271/347/205/247.md +15 -0
  265. package/skill-files//345/206/231Java/references//346/212/244/346/240/217.md +35 -0
  266. package/skill-files//345/206/231Java/references//347/272/246/346/235/237.md +8 -0
  267. package/skill-files//345/206/231Java/references//350/270/251/345/235/221.md +17 -0
  268. package/skill-files//345/256/241Java/references//346/212/244/346/240/217.md +19 -0
  269. package/skill-files//345/256/241Java/references//347/244/272/344/276/213.md +23 -0
  270. package/skill-files//345/256/241Java/references//347/272/246/346/235/237.md +7 -0
  271. package/skill-files//345/256/241Java/references//350/247/204/345/210/231.md +23 -0
  272. package/skill-files//345/256/241Java/references//351/242/206/345/237/237/346/243/200/351/241/271.md +58 -0
  273. package/skill-files//345/256/241/346/226/207/346/241/243/references//346/212/244/346/240/217.md +18 -0
  274. package/skill-files//345/256/241/346/226/207/346/241/243/references//347/272/246/346/235/237.md +8 -0
  275. package/skill-files//345/256/241/346/226/207/346/241/243/references//347/273/264/345/272/246.md +17 -0
  276. package/skill-files//345/256/241/346/226/207/346/241/243/references//350/270/251/345/235/221.md +11 -0
  277. package/skill-files//346/226/260/345/273/272/references//344/272/244/346/216/245.md +11 -0
  278. package/skill-files//346/226/260/345/273/272/references//346/212/244/346/240/217.md +14 -0
  279. package/skill-files//346/226/260/345/273/272/references//347/272/246/346/235/237.md +7 -0
  280. package/skill-files//346/267/261/346/200/235/config/prompts.yaml +114 -0
  281. package/skill-files//346/267/261/346/200/235/references//344/270/211/346/226/271/346/240/270/345/257/271.md +72 -0
  282. package/skill-files//346/267/261/346/200/235/references//344/276/213/345/255/220.md +39 -0
  283. package/skill-files//346/267/261/346/200/235/references//346/200/216/344/271/210/346/203/263.md +61 -0
  284. package/skill-files//346/267/261/346/200/235/references//346/212/244/346/240/217.md +26 -0
  285. package/skill-files//346/267/261/346/200/235/references//347/202/271/351/200/211/346/217/220/351/227/256.md +66 -0
  286. package/skill-files//346/267/261/346/200/235/references//347/231/273/350/256/260.md +45 -0
  287. package/skill-files//346/267/261/346/200/235/references//347/272/246/346/235/237.md +9 -0
  288. package/skill-files//347/224/250/344/276/213/references//346/200/216/344/271/210/345/206/231.md +13 -0
  289. package/skill-files//347/224/250/344/276/213/references//346/212/244/346/240/217.md +42 -0
  290. package/skill-files//347/224/250/344/276/213/references//347/272/246/346/235/237.md +5 -0
  291. package/skill-files//347/224/250/344/276/213/scripts/check-cases.mjs +70 -0
  292. package/skill-files//350/256/276/350/256/241/references//345/207/206/345/244/207.md +25 -0
  293. package/skill-files//350/256/276/350/256/241/references//346/212/244/346/240/217.md +134 -0
  294. package/skill-files//350/256/276/350/256/241/references//346/226/207/351/243/216.md +17 -0
  295. package/skill-files//350/256/276/350/256/241/references//347/225/214/351/235/242.md +18 -0
  296. package/skill-files//350/256/276/350/256/241/references//347/261/273/345/236/213.md +19 -0
  297. package/skill-files//350/256/276/350/256/241/references//347/272/246/346/235/237.md +25 -0
  298. package/skill-files//350/256/276/350/256/241/scripts/_smoke.mjs +72 -0
  299. package/skill-files//350/256/276/350/256/241/scripts/check-design.mjs +331 -0
  300. package/skill-files//351/234/200/346/261/202/references//346/212/244/346/240/217.md +26 -0
  301. package/skill-files//351/234/200/346/261/202/references//346/226/207/351/243/216.md +23 -0
  302. package/skill-files//351/234/200/346/261/202/references//346/267/261/346/200/235/346/221/204/345/205/245.md +21 -0
  303. package/skill-files//351/234/200/346/261/202/references//347/272/246/346/235/237.md +8 -0
  304. package/skill-files//351/234/200/346/261/202/references//351/234/200/346/261/202/345/276/205/345/256/232.md +13 -0
  305. package/skill-files//351/234/200/346/261/202/scripts/check-requirements.mjs +60 -0
  306. package/skill-files//351/252/214/346/224/266/references//346/212/244/346/240/217.md +27 -0
  307. package/skill-files//351/252/214/346/224/266/references//346/240/270/345/257/271.md +17 -0
  308. package/skill-files//351/252/214/346/224/266/references//347/272/246/346/235/237.md +7 -0
@@ -0,0 +1,50 @@
1
+ export declare const OPENSPEC_DIR_NAME = "freespec";
2
+ export declare const OPENSPEC_SKILL_NAMES: readonly ["freespec-新建", "freespec-深思", "freespec-需求", "freespec-设计", "freespec-任务", "freespec-审文档", "freespec-用例", "freespec-验收", "freespec-写Java", "freespec-审Java"];
3
+ export declare const OPENSPEC_MARKERS: {
4
+ start: string;
5
+ end: string;
6
+ };
7
+ export interface FreeSpecConfig {
8
+ aiTools: string[];
9
+ }
10
+ export interface AIToolOption {
11
+ name: string;
12
+ value: string;
13
+ available: boolean;
14
+ successLabel?: string;
15
+ skillsDir?: string;
16
+ legacySkillsDirs?: string[];
17
+ globalSkillsDir?: string;
18
+ detectionPaths?: string[];
19
+ searchAliases?: string[];
20
+ setupNote?: string;
21
+ requiresIdeRestart?: boolean;
22
+ }
23
+ export declare const AI_TOOLS: AIToolOption[];
24
+ /**
25
+ * The vendor-neutral target every assistant that is not listed above can use.
26
+ * Named wherever a tool lookup comes up empty, so "my tool isn't here" is never
27
+ * a dead end (#653).
28
+ */
29
+ export declare const UNIVERSAL_TOOL_ID = "agents";
30
+ /** The universal target's entry, or undefined if it was removed from AI_TOOLS. */
31
+ export declare function getUniversalTool(): AIToolOption | undefined;
32
+ /**
33
+ * One-line pointer at the universal target for non-interactive errors, the
34
+ * scripted counterpart of the picker's empty-search hint. Undefined when the
35
+ * target is not among the tools on offer, so the hint never names a choice the
36
+ * caller cannot make.
37
+ */
38
+ export declare function universalToolFallbackHint(offeredToolIds: string[]): string | undefined;
39
+ /**
40
+ * Retired tool ids that still resolve, so a rebrand does not break scripted
41
+ * `--tools` invocations. Windsurf was rebranded to Devin Desktop on
42
+ * 2026-06-02 and its config directory moved from `.windsurf/` to `.devin/`;
43
+ * `--tools windsurf` therefore configures `devin`.
44
+ */
45
+ export declare const TOOL_ID_ALIASES: Record<string, string>;
46
+ /**
47
+ * Resolves a tool id through TOOL_ID_ALIASES, leaving current ids untouched.
48
+ */
49
+ export declare function resolveToolIdAlias(toolId: string): string;
50
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1,122 @@
1
+ export const OPENSPEC_DIR_NAME = 'freespec';
2
+ export const OPENSPEC_SKILL_NAMES = [
3
+ 'freespec-新建',
4
+ 'freespec-深思',
5
+ 'freespec-需求',
6
+ 'freespec-设计',
7
+ 'freespec-任务',
8
+ 'freespec-审文档',
9
+ 'freespec-用例',
10
+ 'freespec-验收',
11
+ 'freespec-写Java',
12
+ 'freespec-审Java',
13
+ ];
14
+ export const OPENSPEC_MARKERS = {
15
+ start: '<!-- FREESPEC:START -->',
16
+ end: '<!-- FREESPEC:END -->'
17
+ };
18
+ export const AI_TOOLS = [
19
+ { name: 'Amazon Q Developer', value: 'amazon-q', available: true, successLabel: 'Amazon Q Developer', skillsDir: '.amazonq', requiresIdeRestart: true },
20
+ { name: 'Amp', value: 'amp', available: true, successLabel: 'Amp', skillsDir: '.agents', detectionPaths: ['.amp', '.agents/skills'] },
21
+ // Antigravity moved workspace skills and workflows from `.agent` to the
22
+ // shared `.agents` root in v1.20.5. Detection keys off `.agent` and
23
+ // `.agents/workflows` rather than the bare `.agents` root: that root is
24
+ // shared with Codex, Zed, and the vendor-neutral target, so its presence
25
+ // alone says nothing about Antigravity.
26
+ { name: 'Antigravity', value: 'antigravity', available: true, successLabel: 'Antigravity', skillsDir: '.agents', legacySkillsDirs: ['.agent'], detectionPaths: ['.agent', '.agents/workflows'], requiresIdeRestart: true },
27
+ { name: 'AtomCode', value: 'atomcode', available: true, successLabel: 'AtomCode', skillsDir: '.atomcode' },
28
+ { name: 'Auggie (Augment CLI)', value: 'auggie', available: true, successLabel: 'Auggie', skillsDir: '.augment' },
29
+ { name: 'IBM Bob', value: 'bob', available: true, successLabel: 'IBM Bob', skillsDir: '.bob' },
30
+ { name: 'Claude Code', value: 'claude', available: true, successLabel: 'Claude Code', skillsDir: '.claude' },
31
+ { name: 'Cline', value: 'cline', available: true, successLabel: 'Cline', skillsDir: '.cline', requiresIdeRestart: true },
32
+ { name: 'Command Code', value: 'command-code', available: true, successLabel: 'Command Code', skillsDir: '.commandcode' },
33
+ { name: 'CodeArts', value: 'codeartsagent', available: true, successLabel: 'CodeArts', skillsDir: '.codeartsdoer' },
34
+ { name: 'Codex', value: 'codex', available: true, successLabel: 'Codex', skillsDir: '.agents', legacySkillsDirs: ['.codex'], detectionPaths: ['.agents/skills', '.codex/skills'] },
35
+ { name: 'DeepSeek Harness', value: 'dsh', available: true, successLabel: 'DeepSeek Harness', skillsDir: '.dsh' },
36
+ { name: 'Devin Desktop (formerly Windsurf)', value: 'devin', available: true, successLabel: 'Devin Desktop', skillsDir: '.devin', detectionPaths: ['.devin', '.windsurf'], requiresIdeRestart: true },
37
+ { name: 'ForgeCode', value: 'forgecode', available: true, successLabel: 'ForgeCode', skillsDir: '.forge' },
38
+ { name: 'CodeBuddy Code (CLI)', value: 'codebuddy', available: true, successLabel: 'CodeBuddy Code', skillsDir: '.codebuddy' },
39
+ { name: 'Code Studio', value: 'codestudio', available: true, successLabel: 'Code Studio', skillsDir: '.codestudio', requiresIdeRestart: true },
40
+ { name: 'Continue', value: 'continue', available: true, successLabel: 'Continue (VS Code / JetBrains / Cli)', skillsDir: '.continue', requiresIdeRestart: true },
41
+ { name: 'CoStrict', value: 'costrict', available: true, successLabel: 'CoStrict', skillsDir: '.cospec', requiresIdeRestart: true },
42
+ { name: 'Crush', value: 'crush', available: true, successLabel: 'Crush', skillsDir: '.crush' },
43
+ { name: 'Cursor', value: 'cursor', available: true, successLabel: 'Cursor', skillsDir: '.cursor', requiresIdeRestart: true },
44
+ { name: 'EasyCode', value: 'easycode', available: true, successLabel: 'EasyCode', skillsDir: '.easycode' },
45
+ { name: 'Factory Droid', value: 'factory', available: true, successLabel: 'Factory Droid', skillsDir: '.factory' },
46
+ { name: 'Gemini CLI', value: 'gemini', available: true, successLabel: 'Gemini CLI', skillsDir: '.gemini' },
47
+ { name: 'GitHub Copilot', value: 'github-copilot', available: true, successLabel: 'GitHub Copilot', skillsDir: '.github', detectionPaths: ['.github/copilot-instructions.md', '.github/instructions', '.github/workflows/copilot-setup-steps.yml', '.github/prompts', '.github/agents', '.github/skills', '.github/.mcp.json'], requiresIdeRestart: true },
48
+ { name: 'GigaCode', value: 'gigacode', available: true, successLabel: 'GigaCode', skillsDir: '.gigacode' },
49
+ { name: 'Grok Build', value: 'grok', available: true, successLabel: 'Grok Build', skillsDir: '.grok' },
50
+ { name: 'GSD', value: 'gsd', available: true, successLabel: 'GSD', skillsDir: '.agents', detectionPaths: ['.gsd'] },
51
+ { name: 'Hermes Agent', value: 'hermes', available: true, successLabel: 'Hermes Agent', skillsDir: '.hermes', detectionPaths: ['.hermes', 'HERMES.md', '.hermes.md'], setupNote: "Hermes only loads skills from ~/.hermes/skills by default. Add this project's .hermes/skills directory to skills.external_dirs in ~/.hermes/config.yaml so Hermes picks up the generated FreeSpec skills." },
52
+ { name: 'iFlow', value: 'iflow', available: true, successLabel: 'iFlow', skillsDir: '.iflow' },
53
+ { name: 'Junie', value: 'junie', available: true, successLabel: 'Junie', skillsDir: '.junie', requiresIdeRestart: true },
54
+ { name: 'Kilo Code', value: 'kilocode', available: true, successLabel: 'Kilo Code', skillsDir: '.kilocode', requiresIdeRestart: true },
55
+ { name: 'Kimi Code', value: 'kimi', available: true, successLabel: 'Kimi Code', skillsDir: '.kimi-code', detectionPaths: ['.kimi-code', '.kimi'] },
56
+ { name: 'Kiro', value: 'kiro', available: true, successLabel: 'Kiro', skillsDir: '.kiro', requiresIdeRestart: true },
57
+ { name: 'Lingma', value: 'lingma', available: true, successLabel: 'Lingma', skillsDir: '.lingma', requiresIdeRestart: true },
58
+ { name: 'MiniMax Code', value: 'minimax-code', available: true, successLabel: 'MiniMax Code', globalSkillsDir: '.minimax' },
59
+ { name: 'Mistral Vibe', value: 'vibe', available: true, successLabel: 'Mistral Vibe', skillsDir: '.vibe' },
60
+ { name: 'Oh My Pi', value: 'oh-my-pi', available: true, successLabel: 'Oh My Pi', skillsDir: '.omp' },
61
+ { name: 'OpenCode', value: 'opencode', available: true, successLabel: 'OpenCode', skillsDir: '.opencode' },
62
+ { name: 'Pi', value: 'pi', available: true, successLabel: 'Pi', skillsDir: '.pi' },
63
+ { name: 'SourceCraft Code Assistant', value: 'codeassistant', available: true, successLabel: 'SourceCraft Code Assistant', skillsDir: '.codeassistant' },
64
+ { name: 'Qoder', value: 'qoder', available: true, successLabel: 'Qoder', skillsDir: '.qoder', requiresIdeRestart: true },
65
+ { name: 'Qwen Code', value: 'qwen', available: true, successLabel: 'Qwen Code', skillsDir: '.qwen' },
66
+ { name: 'Rovo Dev CLI', value: 'rovodev', available: true, successLabel: 'Rovo Dev CLI', skillsDir: '.rovodev', detectionPaths: ['.rovodev/skills', '.rovodev'] },
67
+ { name: 'Zoo Code', value: 'roocode', available: true, successLabel: 'Zoo Code', skillsDir: '.roo', requiresIdeRestart: true },
68
+ { name: 'Trae', value: 'trae', available: true, successLabel: 'Trae', skillsDir: '.trae', requiresIdeRestart: true },
69
+ { name: 'Veai', value: 'veai', available: true, successLabel: 'Veai', skillsDir: '.veai' },
70
+ { name: 'Warp', value: 'warp', available: true, successLabel: 'Warp', skillsDir: '.warp', detectionPaths: ['.warp', 'WARP.md'] },
71
+ { name: 'Zed Agent', value: 'zed', available: true, successLabel: 'Zed Agent', skillsDir: '.agents', detectionPaths: ['.zed', '.agents/skills'] },
72
+ { name: 'ZCode', value: 'zcode', available: true, successLabel: 'ZCode', skillsDir: '.zcode' },
73
+ // Vendor-neutral target for assistants that read the shared `.agents` root.
74
+ // Detection keys off `.agents/skills` rather than the bare root: frameworks use
75
+ // `.agents/` for more than skills, so the root alone says nothing about skills.
76
+ // A project that does keep skills there is a project this target fits, the same
77
+ // way `.claude/` selects Claude Code — the signal is the user's setup, not
78
+ // FreeSpec's own files.
79
+ // The picker is searchable, so this entry also answers to the words someone
80
+ // whose assistant is not on the list actually types (#653) — it is named for
81
+ // a directory, which none of them would guess. Aliases are single words: the
82
+ // space bar toggles a selection rather than typing into the search box.
83
+ { name: 'Other / Universal (shared .agents skills)', value: 'agents', available: true, successLabel: 'shared .agents skills', skillsDir: '.agents', detectionPaths: ['.agents/skills'], searchAliases: ['universal', 'other', 'generic', 'custom', 'proprietary', 'unlisted', 'unsupported', 'vendor-neutral', 'agents.md'] }
84
+ ];
85
+ /**
86
+ * The vendor-neutral target every assistant that is not listed above can use.
87
+ * Named wherever a tool lookup comes up empty, so "my tool isn't here" is never
88
+ * a dead end (#653).
89
+ */
90
+ export const UNIVERSAL_TOOL_ID = 'agents';
91
+ /** The universal target's entry, or undefined if it was removed from AI_TOOLS. */
92
+ export function getUniversalTool() {
93
+ return AI_TOOLS.find((tool) => tool.value === UNIVERSAL_TOOL_ID);
94
+ }
95
+ /**
96
+ * One-line pointer at the universal target for non-interactive errors, the
97
+ * scripted counterpart of the picker's empty-search hint. Undefined when the
98
+ * target is not among the tools on offer, so the hint never names a choice the
99
+ * caller cannot make.
100
+ */
101
+ export function universalToolFallbackHint(offeredToolIds) {
102
+ const universal = getUniversalTool();
103
+ if (!universal || !offeredToolIds.includes(universal.value))
104
+ return undefined;
105
+ return `Tool not listed? Use --tools ${universal.value}: the vendor-neutral target that writes ${universal.skillsDir}/skills/ for any assistant.`;
106
+ }
107
+ /**
108
+ * Retired tool ids that still resolve, so a rebrand does not break scripted
109
+ * `--tools` invocations. Windsurf was rebranded to Devin Desktop on
110
+ * 2026-06-02 and its config directory moved from `.windsurf/` to `.devin/`;
111
+ * `--tools windsurf` therefore configures `devin`.
112
+ */
113
+ export const TOOL_ID_ALIASES = {
114
+ windsurf: 'devin',
115
+ };
116
+ /**
117
+ * Resolves a tool id through TOOL_ID_ALIASES, leaving current ids untouched.
118
+ */
119
+ export function resolveToolIdAlias(toolId) {
120
+ return TOOL_ID_ALIASES[toolId] ?? toolId;
121
+ }
122
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,36 @@
1
+ import * as nodeFs from 'node:fs';
2
+ import { StoreError } from './store/errors.js';
3
+ /**
4
+ * Shared machine-local state-file mechanics (extracted from the store
5
+ * registry in slice 7.1, its second consumer). Callers own the
6
+ * diagnostic data (code, target, wording); the factory owns the
7
+ * shared mechanics - the fix strings describe the lock's own
8
+ * behavior (stale-steal, creation), so their templates live here.
9
+ */
10
+ export type FileLockErrorKind = 'create-failed' | 'timeout';
11
+ export interface FileLockErrorInfo {
12
+ lockPath: string;
13
+ /** The original errno error for 'create-failed'. */
14
+ cause?: unknown;
15
+ }
16
+ export interface FileLockOptions {
17
+ lockPath: string;
18
+ errorFor: (kind: FileLockErrorKind, info: FileLockErrorInfo) => Error;
19
+ }
20
+ export interface LockErrorData {
21
+ /** Noun phrase for the create-failed message, e.g. "the registry lock file". */
22
+ createSubject: string;
23
+ /** The full timeout message, e.g. "Store registry is busy." */
24
+ busyMessage: string;
25
+ code: string;
26
+ target: string;
27
+ }
28
+ /** One template for lock diagnostics; callers supply the data. */
29
+ export declare function makeLockErrorFactory(data: LockErrorData): (kind: FileLockErrorKind, info: FileLockErrorInfo) => StoreError;
30
+ export declare function isNodeErrorCode(error: unknown, code: string): boolean;
31
+ export declare function pathIsFile(filePath: string): Promise<boolean>;
32
+ export declare function pathIsDirectory(dirPath: string): Promise<boolean>;
33
+ export declare function writeFileAtomically(filePath: string, content: string): Promise<void>;
34
+ export declare function acquireFileLock(options: FileLockOptions): Promise<nodeFs.promises.FileHandle>;
35
+ export declare function releaseFileLock(lock: nodeFs.promises.FileHandle, lockPath: string): Promise<void>;
36
+ //# sourceMappingURL=file-state.d.ts.map
@@ -0,0 +1,144 @@
1
+ import * as nodeFs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { FileSystemUtils } from '../utils/file-system.js';
5
+ import { StoreError } from './store/errors.js';
6
+ const fs = nodeFs.promises;
7
+ /** One template for lock diagnostics; callers supply the data. */
8
+ export function makeLockErrorFactory(data) {
9
+ return (kind, info) => {
10
+ if (kind === 'create-failed') {
11
+ // A permission or filesystem problem, not contention - say so.
12
+ return new StoreError(`Cannot create ${data.createSubject} ${info.lockPath} (${info.cause?.code ?? info.cause}).`, data.code, {
13
+ target: data.target,
14
+ fix: `Check permissions on ${path.dirname(info.lockPath)}.`,
15
+ });
16
+ }
17
+ return new StoreError(data.busyMessage, data.code, {
18
+ target: data.target,
19
+ fix: `Retry shortly; if this persists, delete the stale lock file ${info.lockPath}.`,
20
+ });
21
+ };
22
+ }
23
+ const LOCK_DEADLINE_MS = 5000;
24
+ const LOCK_POLL_MS = 25;
25
+ const PRIVATE_FILE_MODE = 0o600;
26
+ const lockOwnership = new WeakMap();
27
+ function isUnsupportedSyncError(error) {
28
+ return (isNodeErrorCode(error, 'EINVAL') ||
29
+ isNodeErrorCode(error, 'ENOTSUP') ||
30
+ isNodeErrorCode(error, 'ENOSYS'));
31
+ }
32
+ export function isNodeErrorCode(error, code) {
33
+ return (typeof error === 'object' &&
34
+ error !== null &&
35
+ 'code' in error &&
36
+ error.code === code);
37
+ }
38
+ export async function pathIsFile(filePath) {
39
+ try {
40
+ return (await fs.stat(filePath)).isFile();
41
+ }
42
+ catch {
43
+ return false;
44
+ }
45
+ }
46
+ // Deliberately not FileSystemUtils.directoryExists: that variant
47
+ // debug-logs non-ENOENT failures, which is noise inside prompt
48
+ // validators, and pathIsFile has no FileSystemUtils equivalent - the
49
+ // silent symmetric pair lives here.
50
+ export async function pathIsDirectory(dirPath) {
51
+ try {
52
+ return (await fs.stat(dirPath)).isDirectory();
53
+ }
54
+ catch {
55
+ return false;
56
+ }
57
+ }
58
+ async function sleep(milliseconds) {
59
+ await new Promise((resolve) => setTimeout(resolve, milliseconds));
60
+ }
61
+ export async function writeFileAtomically(filePath, content) {
62
+ const dirPath = path.dirname(filePath);
63
+ await FileSystemUtils.createDirectory(dirPath);
64
+ const tempPath = path.join(dirPath, `.${path.basename(filePath)}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`);
65
+ try {
66
+ await fs.writeFile(tempPath, content, {
67
+ encoding: 'utf-8',
68
+ mode: PRIVATE_FILE_MODE,
69
+ });
70
+ await fs.rename(tempPath, filePath);
71
+ }
72
+ catch (error) {
73
+ await fs.rm(tempPath, { force: true }).catch(() => undefined);
74
+ throw error;
75
+ }
76
+ }
77
+ export async function acquireFileLock(options) {
78
+ const { lockPath, errorFor } = options;
79
+ const lockDir = path.dirname(lockPath);
80
+ await FileSystemUtils.createDirectory(lockDir);
81
+ if (!(await FileSystemUtils.canWriteFile(lockDir))) {
82
+ throw errorFor('create-failed', { lockPath, cause: 'EACCES' });
83
+ }
84
+ const deadline = Date.now() + LOCK_DEADLINE_MS;
85
+ while (true) {
86
+ try {
87
+ const lock = await fs.open(lockPath, 'wx', PRIVATE_FILE_MODE);
88
+ const ownershipToken = `${process.pid}:${randomUUID()}`;
89
+ try {
90
+ await lock.writeFile(ownershipToken, 'utf-8');
91
+ try {
92
+ await lock.sync();
93
+ }
94
+ catch (error) {
95
+ // Some FUSE and network filesystems support exclusive lock files but
96
+ // explicitly do not implement fsync. The token is still visible to
97
+ // cooperating processes, so do not make those projects unusable.
98
+ if (!isUnsupportedSyncError(error)) {
99
+ throw error;
100
+ }
101
+ }
102
+ }
103
+ catch (error) {
104
+ await lock.close().catch(() => undefined);
105
+ await fs.rm(lockPath, { force: true }).catch(() => undefined);
106
+ throw error;
107
+ }
108
+ lockOwnership.set(lock, ownershipToken);
109
+ return lock;
110
+ }
111
+ catch (error) {
112
+ if (!isNodeErrorCode(error, 'EEXIST')) {
113
+ // A permission or filesystem problem, not contention - say so.
114
+ throw errorFor('create-failed', { lockPath, cause: error });
115
+ }
116
+ // Never steal by age: unlinking a supposedly stale path can race with
117
+ // its replacement and erase a live owner's lock. The timeout diagnostic
118
+ // gives the user an explicit recovery path for genuinely orphaned locks.
119
+ if (Date.now() >= deadline) {
120
+ throw errorFor('timeout', { lockPath });
121
+ }
122
+ await sleep(LOCK_POLL_MS);
123
+ }
124
+ }
125
+ }
126
+ export async function releaseFileLock(lock, lockPath) {
127
+ const ownershipToken = lockOwnership.get(lock);
128
+ lockOwnership.delete(lock);
129
+ await lock.close().catch(() => undefined);
130
+ if (ownershipToken === undefined) {
131
+ return;
132
+ }
133
+ try {
134
+ const currentToken = await fs.readFile(lockPath, 'utf-8');
135
+ if (currentToken === ownershipToken) {
136
+ await fs.rm(lockPath, { force: true });
137
+ }
138
+ }
139
+ catch {
140
+ // The lock was already removed or replaced with an unreadable path.
141
+ // In either case, this owner must not remove anything else.
142
+ }
143
+ }
144
+ //# sourceMappingURL=file-state.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * How a check reads the files it inspects. Normally the disk. `update
3
+ * --dry-run` passes the tree as it has planned it, so a step that reads what
4
+ * an earlier step wrote sees the same thing it would in a real update.
5
+ */
6
+ export interface FileView {
7
+ exists(filePath: string): boolean;
8
+ /** Throws, like `fs.readFileSync`, when the file is absent. */
9
+ read(filePath: string): string;
10
+ isDirectory(filePath: string): boolean;
11
+ }
12
+ export declare const DISK_VIEW: FileView;
13
+ //# sourceMappingURL=file-view.d.ts.map
@@ -0,0 +1,14 @@
1
+ import * as fs from 'fs';
2
+ export const DISK_VIEW = {
3
+ exists: (filePath) => fs.existsSync(filePath),
4
+ read: (filePath) => fs.readFileSync(filePath, 'utf-8'),
5
+ isDirectory: (filePath) => {
6
+ try {
7
+ return fs.statSync(filePath).isDirectory();
8
+ }
9
+ catch {
10
+ return false;
11
+ }
12
+ },
13
+ };
14
+ //# sourceMappingURL=file-view.js.map
@@ -0,0 +1,101 @@
1
+ export declare const GLOBAL_CONFIG_DIR_NAME = "freespec";
2
+ export declare const GLOBAL_CONFIG_FILE_NAME = "config.json";
3
+ export declare const GLOBAL_DATA_DIR_NAME = "freespec";
4
+ export type Profile = 'core' | 'custom';
5
+ export type Delivery = 'both' | 'skills' | 'commands';
6
+ /** Telemetry section of global config (identity + opt-out). */
7
+ export interface TelemetryConfig {
8
+ /** When false, telemetry is disabled. Unset means enabled (opt-out model). */
9
+ enabled?: boolean;
10
+ /** Anonymous random UUID; no relation to the user. */
11
+ anonymousId?: string;
12
+ /** Whether the first-run telemetry notice has been shown. */
13
+ noticeSeen?: boolean;
14
+ }
15
+ export interface GlobalConfig {
16
+ featureFlags?: Record<string, boolean>;
17
+ profile?: Profile;
18
+ delivery?: Delivery;
19
+ workflows?: string[];
20
+ /**
21
+ * Machine-level fallback store id, consulted during root resolution only
22
+ * when no --store flag, local root, or project-level store: pointer resolves.
23
+ */
24
+ defaultStore?: string;
25
+ /** Workset opener rows (slice 7.1); hand-edited, validated on use. */
26
+ openers?: unknown;
27
+ /** Anonymous usage analytics settings and identity. */
28
+ telemetry?: TelemetryConfig;
29
+ /** Whether the first-run shell-completions tip has been shown. */
30
+ completionTipSeen?: boolean;
31
+ /** Whether the one-time note about the standalone install has been shown. */
32
+ standaloneTipSeen?: boolean;
33
+ }
34
+ /**
35
+ * Gets the global configuration directory path following XDG Base Directory Specification.
36
+ *
37
+ * - All platforms: $XDG_CONFIG_HOME/freespec/ if XDG_CONFIG_HOME is set
38
+ * - Unix/macOS fallback: ~/.config/freespec/
39
+ * - Windows fallback: %APPDATA%/freespec/
40
+ */
41
+ export declare function getGlobalConfigDir(): string;
42
+ /**
43
+ * Gets the global data directory path following XDG Base Directory Specification.
44
+ * Used for user data like schema overrides.
45
+ *
46
+ * - All platforms: $XDG_DATA_HOME/freespec/ if XDG_DATA_HOME is set
47
+ * - Unix/macOS fallback: ~/.local/share/freespec/
48
+ * - Windows fallback: %LOCALAPPDATA%/freespec/
49
+ */
50
+ export interface GlobalDataDirOptions {
51
+ env?: NodeJS.ProcessEnv;
52
+ platform?: NodeJS.Platform;
53
+ homedir?: string;
54
+ }
55
+ export declare function getGlobalDataDir(options?: GlobalDataDirOptions): string;
56
+ /**
57
+ * Gets the path to the global config file.
58
+ */
59
+ export declare function getGlobalConfigPath(): string;
60
+ /**
61
+ * Loads the global configuration from disk.
62
+ * Returns default configuration if file doesn't exist or is invalid.
63
+ * Merges loaded config with defaults to ensure new fields are available.
64
+ */
65
+ export declare function getGlobalConfig(): GlobalConfig;
66
+ /**
67
+ * Whether a parsed JSON root can serve as a global config object.
68
+ *
69
+ * Valid JSON that is not a plain object (`null`, an array, a string, a number,
70
+ * a boolean) still reads as defaults, so it is just as unsafe to save over as
71
+ * a file that did not parse at all. Every reader and writer of the global
72
+ * config shares this one predicate so they cannot drift apart.
73
+ */
74
+ export declare function isConfigRootObject(parsed: unknown): boolean;
75
+ /**
76
+ * The one-line, actionable refusal every global-config writer reports when it
77
+ * declines to overwrite a file it could not read.
78
+ */
79
+ export declare function unreadableGlobalConfigMessage(configPath: string): string;
80
+ /**
81
+ * Whether the global config file exists but cannot be read or parsed.
82
+ *
83
+ * getGlobalConfig() answers with defaults for such a file so that reads keep
84
+ * working, but those defaults are not the user's settings: saving them back
85
+ * would erase everything the file holds, and the file may contain an opt-out
86
+ * such as `telemetry.enabled: false` that the defaults do not.
87
+ */
88
+ export declare function isGlobalConfigUnreadable(): boolean;
89
+ export interface SaveGlobalConfigOptions {
90
+ /** Overwrite a config file that cannot be parsed. Only a reset should. */
91
+ replaceUnreadable?: boolean;
92
+ }
93
+ /**
94
+ * Saves the global configuration to disk.
95
+ * Creates the config directory if it doesn't exist. Refuses to overwrite an
96
+ * existing file it cannot parse unless `replaceUnreadable` is set.
97
+ */
98
+ export declare function saveGlobalConfig(config: GlobalConfig, options?: SaveGlobalConfigOptions): void;
99
+ /** The bytes `saveGlobalConfig` writes, for a caller that only plans the write. */
100
+ export declare function serializeGlobalConfig(config: GlobalConfig): string;
101
+ //# sourceMappingURL=global-config.d.ts.map