synarcx 0.1.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 (288) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +90 -0
  3. package/bin/synarcx.js +3 -0
  4. package/dist/cli/index.d.ts +2 -0
  5. package/dist/cli/index.js +474 -0
  6. package/dist/commands/change.d.ts +35 -0
  7. package/dist/commands/change.js +278 -0
  8. package/dist/commands/completion.d.ts +72 -0
  9. package/dist/commands/completion.js +264 -0
  10. package/dist/commands/config.d.ts +36 -0
  11. package/dist/commands/config.js +552 -0
  12. package/dist/commands/feedback.d.ts +9 -0
  13. package/dist/commands/feedback.js +170 -0
  14. package/dist/commands/schema.d.ts +6 -0
  15. package/dist/commands/schema.js +870 -0
  16. package/dist/commands/show.d.ts +14 -0
  17. package/dist/commands/show.js +132 -0
  18. package/dist/commands/spec.d.ts +15 -0
  19. package/dist/commands/spec.js +226 -0
  20. package/dist/commands/validate.d.ts +24 -0
  21. package/dist/commands/validate.js +295 -0
  22. package/dist/commands/workflow/index.d.ts +17 -0
  23. package/dist/commands/workflow/index.js +12 -0
  24. package/dist/commands/workflow/instructions.d.ts +29 -0
  25. package/dist/commands/workflow/instructions.js +327 -0
  26. package/dist/commands/workflow/new-change.d.ts +11 -0
  27. package/dist/commands/workflow/new-change.js +45 -0
  28. package/dist/commands/workflow/schemas.d.ts +10 -0
  29. package/dist/commands/workflow/schemas.js +34 -0
  30. package/dist/commands/workflow/shared.d.ts +57 -0
  31. package/dist/commands/workflow/shared.js +117 -0
  32. package/dist/commands/workflow/status.d.ts +14 -0
  33. package/dist/commands/workflow/status.js +75 -0
  34. package/dist/commands/workflow/templates.d.ts +16 -0
  35. package/dist/commands/workflow/templates.js +69 -0
  36. package/dist/commands/workspace/open.d.ts +29 -0
  37. package/dist/commands/workspace/open.js +84 -0
  38. package/dist/commands/workspace/operations.d.ts +18 -0
  39. package/dist/commands/workspace/operations.js +461 -0
  40. package/dist/commands/workspace/selection.d.ts +5 -0
  41. package/dist/commands/workspace/selection.js +90 -0
  42. package/dist/commands/workspace/types.d.ts +83 -0
  43. package/dist/commands/workspace/types.js +36 -0
  44. package/dist/commands/workspace.d.ts +3 -0
  45. package/dist/commands/workspace.js +635 -0
  46. package/dist/core/archive.d.ts +11 -0
  47. package/dist/core/archive.js +319 -0
  48. package/dist/core/artifact-graph/graph.d.ts +56 -0
  49. package/dist/core/artifact-graph/graph.js +141 -0
  50. package/dist/core/artifact-graph/index.d.ts +8 -0
  51. package/dist/core/artifact-graph/index.js +14 -0
  52. package/dist/core/artifact-graph/instruction-loader.d.ts +143 -0
  53. package/dist/core/artifact-graph/instruction-loader.js +217 -0
  54. package/dist/core/artifact-graph/outputs.d.ts +14 -0
  55. package/dist/core/artifact-graph/outputs.js +39 -0
  56. package/dist/core/artifact-graph/resolver.d.ts +81 -0
  57. package/dist/core/artifact-graph/resolver.js +258 -0
  58. package/dist/core/artifact-graph/schema.d.ts +13 -0
  59. package/dist/core/artifact-graph/schema.js +108 -0
  60. package/dist/core/artifact-graph/state.d.ts +12 -0
  61. package/dist/core/artifact-graph/state.js +31 -0
  62. package/dist/core/artifact-graph/types.d.ts +45 -0
  63. package/dist/core/artifact-graph/types.js +43 -0
  64. package/dist/core/available-tools.d.ts +17 -0
  65. package/dist/core/available-tools.js +43 -0
  66. package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
  67. package/dist/core/command-generation/adapters/amazon-q.js +26 -0
  68. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  69. package/dist/core/command-generation/adapters/antigravity.js +26 -0
  70. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  71. package/dist/core/command-generation/adapters/auggie.js +27 -0
  72. package/dist/core/command-generation/adapters/bob.d.ts +14 -0
  73. package/dist/core/command-generation/adapters/bob.js +45 -0
  74. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  75. package/dist/core/command-generation/adapters/claude.js +50 -0
  76. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  77. package/dist/core/command-generation/adapters/cline.js +27 -0
  78. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  79. package/dist/core/command-generation/adapters/codebuddy.js +28 -0
  80. package/dist/core/command-generation/adapters/codex.d.ts +16 -0
  81. package/dist/core/command-generation/adapters/codex.js +39 -0
  82. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  83. package/dist/core/command-generation/adapters/continue.js +28 -0
  84. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  85. package/dist/core/command-generation/adapters/costrict.js +27 -0
  86. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  87. package/dist/core/command-generation/adapters/crush.js +30 -0
  88. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  89. package/dist/core/command-generation/adapters/cursor.js +44 -0
  90. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  91. package/dist/core/command-generation/adapters/factory.js +27 -0
  92. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  93. package/dist/core/command-generation/adapters/gemini.js +26 -0
  94. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  95. package/dist/core/command-generation/adapters/github-copilot.js +26 -0
  96. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  97. package/dist/core/command-generation/adapters/iflow.js +29 -0
  98. package/dist/core/command-generation/adapters/index.d.ts +32 -0
  99. package/dist/core/command-generation/adapters/index.js +32 -0
  100. package/dist/core/command-generation/adapters/junie.d.ts +13 -0
  101. package/dist/core/command-generation/adapters/junie.js +26 -0
  102. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  103. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  104. package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
  105. package/dist/core/command-generation/adapters/kiro.js +26 -0
  106. package/dist/core/command-generation/adapters/lingma.d.ts +13 -0
  107. package/dist/core/command-generation/adapters/lingma.js +30 -0
  108. package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
  109. package/dist/core/command-generation/adapters/opencode.js +27 -0
  110. package/dist/core/command-generation/adapters/pi.d.ts +18 -0
  111. package/dist/core/command-generation/adapters/pi.js +55 -0
  112. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  113. package/dist/core/command-generation/adapters/qoder.js +30 -0
  114. package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
  115. package/dist/core/command-generation/adapters/qwen.js +26 -0
  116. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  117. package/dist/core/command-generation/adapters/roocode.js +27 -0
  118. package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
  119. package/dist/core/command-generation/adapters/windsurf.js +51 -0
  120. package/dist/core/command-generation/generator.d.ts +21 -0
  121. package/dist/core/command-generation/generator.js +27 -0
  122. package/dist/core/command-generation/index.d.ts +22 -0
  123. package/dist/core/command-generation/index.js +24 -0
  124. package/dist/core/command-generation/registry.d.ts +36 -0
  125. package/dist/core/command-generation/registry.js +98 -0
  126. package/dist/core/command-generation/types.d.ts +56 -0
  127. package/dist/core/command-generation/types.js +8 -0
  128. package/dist/core/completions/command-registry.d.ts +7 -0
  129. package/dist/core/completions/command-registry.js +596 -0
  130. package/dist/core/completions/completion-provider.d.ts +71 -0
  131. package/dist/core/completions/completion-provider.js +129 -0
  132. package/dist/core/completions/factory.d.ts +64 -0
  133. package/dist/core/completions/factory.js +75 -0
  134. package/dist/core/completions/generators/bash-generator.d.ts +35 -0
  135. package/dist/core/completions/generators/bash-generator.js +230 -0
  136. package/dist/core/completions/generators/fish-generator.d.ts +32 -0
  137. package/dist/core/completions/generators/fish-generator.js +160 -0
  138. package/dist/core/completions/generators/powershell-generator.d.ts +36 -0
  139. package/dist/core/completions/generators/powershell-generator.js +266 -0
  140. package/dist/core/completions/generators/zsh-generator.d.ts +47 -0
  141. package/dist/core/completions/generators/zsh-generator.js +274 -0
  142. package/dist/core/completions/installers/bash-installer.d.ts +87 -0
  143. package/dist/core/completions/installers/bash-installer.js +318 -0
  144. package/dist/core/completions/installers/fish-installer.d.ts +43 -0
  145. package/dist/core/completions/installers/fish-installer.js +143 -0
  146. package/dist/core/completions/installers/powershell-installer.d.ts +102 -0
  147. package/dist/core/completions/installers/powershell-installer.js +387 -0
  148. package/dist/core/completions/installers/zsh-installer.d.ts +117 -0
  149. package/dist/core/completions/installers/zsh-installer.js +421 -0
  150. package/dist/core/completions/templates/bash-templates.d.ts +6 -0
  151. package/dist/core/completions/templates/bash-templates.js +30 -0
  152. package/dist/core/completions/templates/fish-templates.d.ts +7 -0
  153. package/dist/core/completions/templates/fish-templates.js +45 -0
  154. package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
  155. package/dist/core/completions/templates/powershell-templates.js +34 -0
  156. package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
  157. package/dist/core/completions/templates/zsh-templates.js +45 -0
  158. package/dist/core/completions/types.d.ts +101 -0
  159. package/dist/core/completions/types.js +2 -0
  160. package/dist/core/config-prompts.d.ts +9 -0
  161. package/dist/core/config-prompts.js +34 -0
  162. package/dist/core/config-schema.d.ts +86 -0
  163. package/dist/core/config-schema.js +213 -0
  164. package/dist/core/config.d.ts +19 -0
  165. package/dist/core/config.js +38 -0
  166. package/dist/core/converters/json-converter.d.ts +6 -0
  167. package/dist/core/converters/json-converter.js +51 -0
  168. package/dist/core/global-config.d.ts +49 -0
  169. package/dist/core/global-config.js +124 -0
  170. package/dist/core/index.d.ts +3 -0
  171. package/dist/core/index.js +4 -0
  172. package/dist/core/init.d.ts +37 -0
  173. package/dist/core/init.js +585 -0
  174. package/dist/core/legacy-cleanup.d.ts +169 -0
  175. package/dist/core/legacy-cleanup.js +578 -0
  176. package/dist/core/list.d.ts +9 -0
  177. package/dist/core/list.js +172 -0
  178. package/dist/core/migration.d.ts +23 -0
  179. package/dist/core/migration.js +108 -0
  180. package/dist/core/parsers/change-parser.d.ts +13 -0
  181. package/dist/core/parsers/change-parser.js +197 -0
  182. package/dist/core/parsers/markdown-parser.d.ts +26 -0
  183. package/dist/core/parsers/markdown-parser.js +227 -0
  184. package/dist/core/parsers/requirement-blocks.d.ts +37 -0
  185. package/dist/core/parsers/requirement-blocks.js +201 -0
  186. package/dist/core/parsers/spec-structure.d.ts +9 -0
  187. package/dist/core/parsers/spec-structure.js +88 -0
  188. package/dist/core/profile-sync-drift.d.ts +38 -0
  189. package/dist/core/profile-sync-drift.js +197 -0
  190. package/dist/core/profiles.d.ts +26 -0
  191. package/dist/core/profiles.js +37 -0
  192. package/dist/core/project-config.d.ts +64 -0
  193. package/dist/core/project-config.js +224 -0
  194. package/dist/core/schemas/base.schema.d.ts +13 -0
  195. package/dist/core/schemas/base.schema.js +13 -0
  196. package/dist/core/schemas/change.schema.d.ts +73 -0
  197. package/dist/core/schemas/change.schema.js +31 -0
  198. package/dist/core/schemas/index.d.ts +4 -0
  199. package/dist/core/schemas/index.js +4 -0
  200. package/dist/core/schemas/spec.schema.d.ts +18 -0
  201. package/dist/core/schemas/spec.schema.js +15 -0
  202. package/dist/core/shared/index.d.ts +8 -0
  203. package/dist/core/shared/index.js +8 -0
  204. package/dist/core/shared/skill-generation.d.ts +49 -0
  205. package/dist/core/shared/skill-generation.js +90 -0
  206. package/dist/core/shared/tool-detection.d.ts +71 -0
  207. package/dist/core/shared/tool-detection.js +152 -0
  208. package/dist/core/specs-apply.d.ts +73 -0
  209. package/dist/core/specs-apply.js +393 -0
  210. package/dist/core/styles/palette.d.ts +7 -0
  211. package/dist/core/styles/palette.js +8 -0
  212. package/dist/core/templates/index.d.ts +8 -0
  213. package/dist/core/templates/index.js +9 -0
  214. package/dist/core/templates/skill-templates.d.ts +15 -0
  215. package/dist/core/templates/skill-templates.js +14 -0
  216. package/dist/core/templates/types.d.ts +19 -0
  217. package/dist/core/templates/types.js +5 -0
  218. package/dist/core/templates/workflows/analyze.d.ts +4 -0
  219. package/dist/core/templates/workflows/analyze.js +101 -0
  220. package/dist/core/templates/workflows/apply-change.d.ts +10 -0
  221. package/dist/core/templates/workflows/apply-change.js +308 -0
  222. package/dist/core/templates/workflows/archive-change.d.ts +10 -0
  223. package/dist/core/templates/workflows/archive-change.js +271 -0
  224. package/dist/core/templates/workflows/clarify.d.ts +4 -0
  225. package/dist/core/templates/workflows/clarify.js +108 -0
  226. package/dist/core/templates/workflows/debug.d.ts +4 -0
  227. package/dist/core/templates/workflows/debug.js +117 -0
  228. package/dist/core/templates/workflows/explore.d.ts +10 -0
  229. package/dist/core/templates/workflows/explore.js +479 -0
  230. package/dist/core/templates/workflows/propose.d.ts +10 -0
  231. package/dist/core/templates/workflows/propose.js +216 -0
  232. package/dist/core/templates/workflows/sync.d.ts +4 -0
  233. package/dist/core/templates/workflows/sync.js +108 -0
  234. package/dist/core/update.d.ts +82 -0
  235. package/dist/core/update.js +555 -0
  236. package/dist/core/validation/constants.d.ts +34 -0
  237. package/dist/core/validation/constants.js +40 -0
  238. package/dist/core/validation/types.d.ts +18 -0
  239. package/dist/core/validation/types.js +2 -0
  240. package/dist/core/validation/validator.d.ts +33 -0
  241. package/dist/core/validation/validator.js +418 -0
  242. package/dist/core/view.d.ts +8 -0
  243. package/dist/core/view.js +169 -0
  244. package/dist/core/workspace/foundation.d.ts +79 -0
  245. package/dist/core/workspace/foundation.js +367 -0
  246. package/dist/core/workspace/index.d.ts +5 -0
  247. package/dist/core/workspace/index.js +5 -0
  248. package/dist/core/workspace/link-input.d.ts +9 -0
  249. package/dist/core/workspace/link-input.js +32 -0
  250. package/dist/core/workspace/open-surface.d.ts +24 -0
  251. package/dist/core/workspace/open-surface.js +137 -0
  252. package/dist/core/workspace/openers.d.ts +21 -0
  253. package/dist/core/workspace/openers.js +119 -0
  254. package/dist/index.d.ts +3 -0
  255. package/dist/index.js +3 -0
  256. package/dist/prompts/searchable-multi-select.d.ts +28 -0
  257. package/dist/prompts/searchable-multi-select.js +159 -0
  258. package/dist/ui/ascii-patterns.d.ts +25 -0
  259. package/dist/ui/ascii-patterns.js +140 -0
  260. package/dist/ui/welcome-screen.d.ts +10 -0
  261. package/dist/ui/welcome-screen.js +144 -0
  262. package/dist/utils/change-metadata.d.ts +51 -0
  263. package/dist/utils/change-metadata.js +147 -0
  264. package/dist/utils/change-utils.d.ts +62 -0
  265. package/dist/utils/change-utils.js +122 -0
  266. package/dist/utils/command-references.d.ts +18 -0
  267. package/dist/utils/command-references.js +20 -0
  268. package/dist/utils/file-system.d.ts +41 -0
  269. package/dist/utils/file-system.js +301 -0
  270. package/dist/utils/index.d.ts +6 -0
  271. package/dist/utils/index.js +9 -0
  272. package/dist/utils/interactive.d.ts +18 -0
  273. package/dist/utils/interactive.js +21 -0
  274. package/dist/utils/item-discovery.d.ts +4 -0
  275. package/dist/utils/item-discovery.js +73 -0
  276. package/dist/utils/match.d.ts +3 -0
  277. package/dist/utils/match.js +22 -0
  278. package/dist/utils/shell-detection.d.ts +20 -0
  279. package/dist/utils/shell-detection.js +41 -0
  280. package/dist/utils/task-progress.d.ts +8 -0
  281. package/dist/utils/task-progress.js +36 -0
  282. package/package.json +76 -0
  283. package/schemas/synarcx/schema.yaml +153 -0
  284. package/schemas/synarcx/templates/design.md +19 -0
  285. package/schemas/synarcx/templates/proposal.md +23 -0
  286. package/schemas/synarcx/templates/spec.md +8 -0
  287. package/schemas/synarcx/templates/tasks.md +9 -0
  288. package/scripts/postinstall.js +83 -0
@@ -0,0 +1,51 @@
1
+ import { type ChangeMetadata } from '../core/artifact-graph/types.js';
2
+ /**
3
+ * Error thrown when change metadata validation fails.
4
+ */
5
+ export declare class ChangeMetadataError extends Error {
6
+ readonly metadataPath: string;
7
+ readonly cause?: Error | undefined;
8
+ constructor(message: string, metadataPath: string, cause?: Error | undefined);
9
+ }
10
+ /**
11
+ * Validates that a schema name is valid (exists in available schemas).
12
+ *
13
+ * @param schemaName - The schema name to validate
14
+ * @param projectRoot - Optional project root for project-local schema resolution
15
+ * @returns The validated schema name
16
+ * @throws Error if schema is not found
17
+ */
18
+ export declare function validateSchemaName(schemaName: string, projectRoot?: string): string;
19
+ /**
20
+ * Writes change metadata to .synspec.yaml in the change directory.
21
+ *
22
+ * @param changeDir - The path to the change directory
23
+ * @param metadata - The metadata to write
24
+ * @param projectRoot - Optional project root for project-local schema resolution
25
+ * @throws ChangeMetadataError if validation fails or write fails
26
+ */
27
+ export declare function writeChangeMetadata(changeDir: string, metadata: ChangeMetadata, projectRoot?: string): void;
28
+ /**
29
+ * Reads change metadata from .synspec.yaml in the change directory.
30
+ *
31
+ * @param changeDir - The path to the change directory
32
+ * @param projectRoot - Optional project root for project-local schema resolution
33
+ * @returns The validated metadata, or null if no metadata file exists
34
+ * @throws ChangeMetadataError if the file exists but is invalid
35
+ */
36
+ export declare function readChangeMetadata(changeDir: string, projectRoot?: string): ChangeMetadata | null;
37
+ /**
38
+ * Resolves the schema for a change, with explicit override taking precedence.
39
+ *
40
+ * Resolution order:
41
+ * 1. Explicit schema (if provided)
42
+ * 2. Schema from .synspec.yaml metadata (if exists)
43
+ * 3. Schema from synspec/config.yaml (if exists)
44
+ * 4. Default 'synarcx'
45
+ *
46
+ * @param changeDir - The path to the change directory
47
+ * @param explicitSchema - Optional explicit schema override
48
+ * @returns The resolved schema name
49
+ */
50
+ export declare function resolveSchemaForChange(changeDir: string, explicitSchema?: string): string;
51
+ //# sourceMappingURL=change-metadata.d.ts.map
@@ -0,0 +1,147 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as yaml from 'yaml';
4
+ import { ChangeMetadataSchema } from '../core/artifact-graph/types.js';
5
+ import { listSchemas } from '../core/artifact-graph/resolver.js';
6
+ import { readProjectConfig } from '../core/project-config.js';
7
+ const METADATA_FILENAME = '.synspec.yaml';
8
+ /**
9
+ * Error thrown when change metadata validation fails.
10
+ */
11
+ export class ChangeMetadataError extends Error {
12
+ metadataPath;
13
+ cause;
14
+ constructor(message, metadataPath, cause) {
15
+ super(message);
16
+ this.metadataPath = metadataPath;
17
+ this.cause = cause;
18
+ this.name = 'ChangeMetadataError';
19
+ }
20
+ }
21
+ /**
22
+ * Validates that a schema name is valid (exists in available schemas).
23
+ *
24
+ * @param schemaName - The schema name to validate
25
+ * @param projectRoot - Optional project root for project-local schema resolution
26
+ * @returns The validated schema name
27
+ * @throws Error if schema is not found
28
+ */
29
+ export function validateSchemaName(schemaName, projectRoot) {
30
+ const availableSchemas = listSchemas(projectRoot);
31
+ if (!availableSchemas.includes(schemaName)) {
32
+ throw new Error(`Unknown schema '${schemaName}'. Available: ${availableSchemas.join(', ')}`);
33
+ }
34
+ return schemaName;
35
+ }
36
+ /**
37
+ * Writes change metadata to .synspec.yaml in the change directory.
38
+ *
39
+ * @param changeDir - The path to the change directory
40
+ * @param metadata - The metadata to write
41
+ * @param projectRoot - Optional project root for project-local schema resolution
42
+ * @throws ChangeMetadataError if validation fails or write fails
43
+ */
44
+ export function writeChangeMetadata(changeDir, metadata, projectRoot) {
45
+ const metaPath = path.join(changeDir, METADATA_FILENAME);
46
+ // Validate schema exists
47
+ validateSchemaName(metadata.schema, projectRoot);
48
+ // Validate with Zod
49
+ const parseResult = ChangeMetadataSchema.safeParse(metadata);
50
+ if (!parseResult.success) {
51
+ throw new ChangeMetadataError(`Invalid metadata: ${parseResult.error.message}`, metaPath);
52
+ }
53
+ // Write YAML file
54
+ const content = yaml.stringify(parseResult.data);
55
+ try {
56
+ fs.writeFileSync(metaPath, content, 'utf-8');
57
+ }
58
+ catch (err) {
59
+ const ioError = err instanceof Error ? err : new Error(String(err));
60
+ throw new ChangeMetadataError(`Failed to write metadata: ${ioError.message}`, metaPath, ioError);
61
+ }
62
+ }
63
+ /**
64
+ * Reads change metadata from .synspec.yaml in the change directory.
65
+ *
66
+ * @param changeDir - The path to the change directory
67
+ * @param projectRoot - Optional project root for project-local schema resolution
68
+ * @returns The validated metadata, or null if no metadata file exists
69
+ * @throws ChangeMetadataError if the file exists but is invalid
70
+ */
71
+ export function readChangeMetadata(changeDir, projectRoot) {
72
+ const metaPath = path.join(changeDir, METADATA_FILENAME);
73
+ if (!fs.existsSync(metaPath)) {
74
+ return null;
75
+ }
76
+ let content;
77
+ try {
78
+ content = fs.readFileSync(metaPath, 'utf-8');
79
+ }
80
+ catch (err) {
81
+ const ioError = err instanceof Error ? err : new Error(String(err));
82
+ throw new ChangeMetadataError(`Failed to read metadata: ${ioError.message}`, metaPath, ioError);
83
+ }
84
+ let parsed;
85
+ try {
86
+ parsed = yaml.parse(content);
87
+ }
88
+ catch (err) {
89
+ const parseError = err instanceof Error ? err : new Error(String(err));
90
+ throw new ChangeMetadataError(`Invalid YAML in metadata file: ${parseError.message}`, metaPath, parseError);
91
+ }
92
+ // Validate with Zod
93
+ const parseResult = ChangeMetadataSchema.safeParse(parsed);
94
+ if (!parseResult.success) {
95
+ throw new ChangeMetadataError(`Invalid metadata: ${parseResult.error.message}`, metaPath);
96
+ }
97
+ // Validate that the schema exists
98
+ const availableSchemas = listSchemas(projectRoot);
99
+ if (!availableSchemas.includes(parseResult.data.schema)) {
100
+ throw new ChangeMetadataError(`Unknown schema '${parseResult.data.schema}'. Available: ${availableSchemas.join(', ')}`, metaPath);
101
+ }
102
+ return parseResult.data;
103
+ }
104
+ /**
105
+ * Resolves the schema for a change, with explicit override taking precedence.
106
+ *
107
+ * Resolution order:
108
+ * 1. Explicit schema (if provided)
109
+ * 2. Schema from .synspec.yaml metadata (if exists)
110
+ * 3. Schema from synspec/config.yaml (if exists)
111
+ * 4. Default 'synarcx'
112
+ *
113
+ * @param changeDir - The path to the change directory
114
+ * @param explicitSchema - Optional explicit schema override
115
+ * @returns The resolved schema name
116
+ */
117
+ export function resolveSchemaForChange(changeDir, explicitSchema) {
118
+ // Derive project root from changeDir (changeDir is typically projectRoot/synspec/changes/change-name)
119
+ const projectRoot = path.resolve(changeDir, '../../..');
120
+ // 1. Explicit override wins
121
+ if (explicitSchema) {
122
+ return explicitSchema;
123
+ }
124
+ // 2. Try reading from metadata
125
+ try {
126
+ const metadata = readChangeMetadata(changeDir, projectRoot);
127
+ if (metadata?.schema) {
128
+ return metadata.schema;
129
+ }
130
+ }
131
+ catch {
132
+ // If metadata read fails, continue to next option
133
+ }
134
+ // 3. Try reading from project config
135
+ try {
136
+ const config = readProjectConfig(projectRoot);
137
+ if (config?.schema) {
138
+ return config.schema;
139
+ }
140
+ }
141
+ catch {
142
+ // If config read fails, fall back to default
143
+ }
144
+ // 4. Default
145
+ return 'synarcx';
146
+ }
147
+ //# sourceMappingURL=change-metadata.js.map
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Options for creating a change.
3
+ */
4
+ export interface CreateChangeOptions {
5
+ /** The workflow schema to use (default: 'synarcx') */
6
+ schema?: string;
7
+ }
8
+ /**
9
+ * Result of creating a change.
10
+ */
11
+ export interface CreateChangeResult {
12
+ /** The schema that was actually used (resolved from options, config, or default) */
13
+ schema: string;
14
+ }
15
+ /**
16
+ * Result of validating a change name.
17
+ */
18
+ export interface ValidationResult {
19
+ valid: boolean;
20
+ error?: string;
21
+ }
22
+ /**
23
+ * Validates that a change name follows kebab-case conventions.
24
+ *
25
+ * Valid names:
26
+ * - Start with a lowercase letter
27
+ * - Contain only lowercase letters, numbers, and hyphens
28
+ * - Do not start or end with a hyphen
29
+ * - Do not contain consecutive hyphens
30
+ *
31
+ * @param name - The change name to validate
32
+ * @returns Validation result with `valid: true` or `valid: false` with an error message
33
+ *
34
+ * @example
35
+ * validateChangeName('add-auth') // { valid: true }
36
+ * validateChangeName('Add-Auth') // { valid: false, error: '...' }
37
+ */
38
+ export declare function validateChangeName(name: string): ValidationResult;
39
+ /**
40
+ * Creates a new change directory with metadata file.
41
+ *
42
+ * @param projectRoot - The root directory of the project (where `synspec/` lives)
43
+ * @param name - The change name (must be valid kebab-case)
44
+ * @param options - Optional settings for the change
45
+ * @throws Error if the change name is invalid
46
+ * @throws Error if the schema name is invalid
47
+ * @throws Error if the change directory already exists
48
+ *
49
+ * @returns Result containing the resolved schema name
50
+ *
51
+ * @example
52
+ * // Creates synspec/changes/add-auth/ with default schema
53
+ * const result = await createChange('/path/to/project', 'add-auth')
54
+ * console.log(result.schema) // 'synarcx' or value from config
55
+ *
56
+ * @example
57
+ * // Creates synspec/changes/add-auth/ with custom schema
58
+ * const result = await createChange('/path/to/project', 'add-auth', { schema: 'my-workflow' })
59
+ * console.log(result.schema) // 'my-workflow'
60
+ */
61
+ export declare function createChange(projectRoot: string, name: string, options?: CreateChangeOptions): Promise<CreateChangeResult>;
62
+ //# sourceMappingURL=change-utils.d.ts.map
@@ -0,0 +1,122 @@
1
+ import path from 'path';
2
+ import { FileSystemUtils } from './file-system.js';
3
+ import { writeChangeMetadata, validateSchemaName } from './change-metadata.js';
4
+ import { readProjectConfig } from '../core/project-config.js';
5
+ import { SYNSPEC_DIR_NAME } from '../core/config.js';
6
+ const DEFAULT_SCHEMA = 'synarcx';
7
+ /**
8
+ * Validates that a change name follows kebab-case conventions.
9
+ *
10
+ * Valid names:
11
+ * - Start with a lowercase letter
12
+ * - Contain only lowercase letters, numbers, and hyphens
13
+ * - Do not start or end with a hyphen
14
+ * - Do not contain consecutive hyphens
15
+ *
16
+ * @param name - The change name to validate
17
+ * @returns Validation result with `valid: true` or `valid: false` with an error message
18
+ *
19
+ * @example
20
+ * validateChangeName('add-auth') // { valid: true }
21
+ * validateChangeName('Add-Auth') // { valid: false, error: '...' }
22
+ */
23
+ export function validateChangeName(name) {
24
+ // Pattern: starts with lowercase letter, followed by lowercase letters/numbers,
25
+ // optionally followed by hyphen + lowercase letters/numbers (repeatable)
26
+ const kebabCasePattern = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/;
27
+ if (!name) {
28
+ return { valid: false, error: 'Change name cannot be empty' };
29
+ }
30
+ if (!kebabCasePattern.test(name)) {
31
+ // Provide specific error messages for common mistakes
32
+ if (/[A-Z]/.test(name)) {
33
+ return { valid: false, error: 'Change name must be lowercase (use kebab-case)' };
34
+ }
35
+ if (/\s/.test(name)) {
36
+ return { valid: false, error: 'Change name cannot contain spaces (use hyphens instead)' };
37
+ }
38
+ if (/_/.test(name)) {
39
+ return { valid: false, error: 'Change name cannot contain underscores (use hyphens instead)' };
40
+ }
41
+ if (name.startsWith('-')) {
42
+ return { valid: false, error: 'Change name cannot start with a hyphen' };
43
+ }
44
+ if (name.endsWith('-')) {
45
+ return { valid: false, error: 'Change name cannot end with a hyphen' };
46
+ }
47
+ if (/--/.test(name)) {
48
+ return { valid: false, error: 'Change name cannot contain consecutive hyphens' };
49
+ }
50
+ if (/[^a-z0-9-]/.test(name)) {
51
+ return { valid: false, error: 'Change name can only contain lowercase letters, numbers, and hyphens' };
52
+ }
53
+ if (/^[0-9]/.test(name)) {
54
+ return { valid: false, error: 'Change name must start with a letter' };
55
+ }
56
+ return { valid: false, error: 'Change name must follow kebab-case convention (e.g., add-auth, refactor-db)' };
57
+ }
58
+ return { valid: true };
59
+ }
60
+ /**
61
+ * Creates a new change directory with metadata file.
62
+ *
63
+ * @param projectRoot - The root directory of the project (where `synspec/` lives)
64
+ * @param name - The change name (must be valid kebab-case)
65
+ * @param options - Optional settings for the change
66
+ * @throws Error if the change name is invalid
67
+ * @throws Error if the schema name is invalid
68
+ * @throws Error if the change directory already exists
69
+ *
70
+ * @returns Result containing the resolved schema name
71
+ *
72
+ * @example
73
+ * // Creates synspec/changes/add-auth/ with default schema
74
+ * const result = await createChange('/path/to/project', 'add-auth')
75
+ * console.log(result.schema) // 'synarcx' or value from config
76
+ *
77
+ * @example
78
+ * // Creates synspec/changes/add-auth/ with custom schema
79
+ * const result = await createChange('/path/to/project', 'add-auth', { schema: 'my-workflow' })
80
+ * console.log(result.schema) // 'my-workflow'
81
+ */
82
+ export async function createChange(projectRoot, name, options = {}) {
83
+ // Validate the name first
84
+ const validation = validateChangeName(name);
85
+ if (!validation.valid) {
86
+ throw new Error(validation.error);
87
+ }
88
+ // Determine schema: explicit option → project config → hardcoded default
89
+ let schemaName;
90
+ if (options.schema) {
91
+ schemaName = options.schema;
92
+ }
93
+ else {
94
+ // Try to read from project config
95
+ try {
96
+ const config = readProjectConfig(projectRoot);
97
+ schemaName = config?.schema ?? DEFAULT_SCHEMA;
98
+ }
99
+ catch {
100
+ // If config read fails, use default
101
+ schemaName = DEFAULT_SCHEMA;
102
+ }
103
+ }
104
+ // Validate the resolved schema
105
+ validateSchemaName(schemaName, projectRoot);
106
+ // Build the change directory path
107
+ const changeDir = path.join(projectRoot, SYNSPEC_DIR_NAME, 'changes', name);
108
+ // Check if change already exists
109
+ if (await FileSystemUtils.directoryExists(changeDir)) {
110
+ throw new Error(`Change '${name}' already exists at ${changeDir}`);
111
+ }
112
+ // Create the directory (including parent directories if needed)
113
+ await FileSystemUtils.createDirectory(changeDir);
114
+ // Write metadata file with schema and creation date
115
+ const today = new Date().toISOString().split('T')[0];
116
+ writeChangeMetadata(changeDir, {
117
+ schema: schemaName,
118
+ created: today,
119
+ }, projectRoot);
120
+ return { schema: schemaName };
121
+ }
122
+ //# sourceMappingURL=change-utils.js.map
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Command Reference Utilities
3
+ *
4
+ * Utilities for transforming command references to tool-specific formats.
5
+ */
6
+ /**
7
+ * Transforms colon-based command references to hyphen-based format.
8
+ * Converts `/syn:` patterns to `/syn-` for tools that use hyphen syntax.
9
+ *
10
+ * @param text - The text containing command references
11
+ * @returns Text with command references transformed to hyphen format
12
+ *
13
+ * @example
14
+ * transformToHyphenCommands('/syn:sync') // returns '/syn-sync'
15
+ * transformToHyphenCommands('Use /syn:apply to implement') // returns 'Use /syn-apply to implement'
16
+ */
17
+ export declare function transformToHyphenCommands(text: string): string;
18
+ //# sourceMappingURL=command-references.d.ts.map
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Command Reference Utilities
3
+ *
4
+ * Utilities for transforming command references to tool-specific formats.
5
+ */
6
+ /**
7
+ * Transforms colon-based command references to hyphen-based format.
8
+ * Converts `/syn:` patterns to `/syn-` for tools that use hyphen syntax.
9
+ *
10
+ * @param text - The text containing command references
11
+ * @returns Text with command references transformed to hyphen format
12
+ *
13
+ * @example
14
+ * transformToHyphenCommands('/syn:sync') // returns '/syn-sync'
15
+ * transformToHyphenCommands('Use /syn:apply to implement') // returns 'Use /syn-apply to implement'
16
+ */
17
+ export function transformToHyphenCommands(text) {
18
+ return text.replace(/\/syn:/g, '/syn-');
19
+ }
20
+ //# sourceMappingURL=command-references.js.map
@@ -0,0 +1,41 @@
1
+ export declare class FileSystemUtils {
2
+ /**
3
+ * Converts a path to use forward slashes (POSIX style).
4
+ * Essential for cross-platform compatibility with glob libraries like fast-glob.
5
+ */
6
+ static toPosixPath(p: string): string;
7
+ /**
8
+ * Returns a canonical absolute path when the target exists.
9
+ * Falls back to path.resolve() so callers can still produce a stable absolute path.
10
+ */
11
+ static canonicalizeExistingPath(targetPath: string): string;
12
+ private static isWindowsBasePath;
13
+ private static normalizeSegments;
14
+ static joinPath(basePath: string, ...segments: string[]): string;
15
+ static createDirectory(dirPath: string): Promise<void>;
16
+ static fileExists(filePath: string): Promise<boolean>;
17
+ /**
18
+ * Finds the first existing parent directory by walking up the directory tree.
19
+ * @param dirPath Starting directory path
20
+ * @returns The first existing directory path, or null if root is reached without finding one
21
+ */
22
+ private static findFirstExistingDirectory;
23
+ static canWriteFile(filePath: string): Promise<boolean>;
24
+ static directoryExists(dirPath: string): Promise<boolean>;
25
+ static writeFile(filePath: string, content: string): Promise<void>;
26
+ static readFile(filePath: string): Promise<string>;
27
+ static updateFileWithMarkers(filePath: string, content: string, startMarker: string, endMarker: string): Promise<void>;
28
+ static ensureWritePermissions(dirPath: string): Promise<boolean>;
29
+ }
30
+ /**
31
+ * Removes a marker block from file content.
32
+ * Only removes markers that are on their own lines (ignores inline mentions).
33
+ * Cleans up double blank lines that may result from removal.
34
+ *
35
+ * @param content - File content with markers
36
+ * @param startMarker - The start marker string
37
+ * @param endMarker - The end marker string
38
+ * @returns Content with marker block removed, or original content if markers not found/invalid
39
+ */
40
+ export declare function removeMarkerBlock(content: string, startMarker: string, endMarker: string): string;
41
+ //# sourceMappingURL=file-system.d.ts.map