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,79 @@
1
+ export declare const WORKSPACE_METADATA_DIR_NAME = ".synarcx-workspace";
2
+ export declare const WORKSPACE_SHARED_STATE_FILE_NAME = "workspace.yaml";
3
+ export declare const WORKSPACE_LOCAL_STATE_FILE_NAME = "local.yaml";
4
+ export declare const WORKSPACE_CHANGES_DIR_NAME = "changes";
5
+ export declare const MANAGED_WORKSPACES_DIR_NAME = "workspaces";
6
+ export declare const WORKSPACE_REGISTRY_FILE_NAME = "registry.yaml";
7
+ export declare const WORKSPACE_LOCAL_STATE_IGNORE_PATTERN = ".synarcx-workspace/local.yaml";
8
+ export declare const WORKSPACE_CODE_WORKSPACE_EXTENSION = ".code-workspace";
9
+ export declare const WORKSPACE_SUPPORTED_OPENER_VALUES: readonly ["codex", "claude", "github-copilot", "editor"];
10
+ export declare const WORKSPACE_AGENT_OPENER_IDS: readonly ["codex", "claude", "github-copilot"];
11
+ export declare const WORKSPACE_EDITOR_OPENER_IDS: readonly ["vscode"];
12
+ export type WorkspaceSupportedOpenerValue = typeof WORKSPACE_SUPPORTED_OPENER_VALUES[number];
13
+ export type WorkspaceAgentOpenerId = typeof WORKSPACE_AGENT_OPENER_IDS[number];
14
+ export type WorkspaceEditorOpenerId = typeof WORKSPACE_EDITOR_OPENER_IDS[number];
15
+ export type WorkspacePreferredOpener = {
16
+ kind: 'agent';
17
+ id: WorkspaceAgentOpenerId;
18
+ } | {
19
+ kind: 'editor';
20
+ id: WorkspaceEditorOpenerId;
21
+ };
22
+ export interface WorkspaceSharedState {
23
+ version: 1;
24
+ name: string;
25
+ links: Record<string, WorkspaceLinkState>;
26
+ }
27
+ export type WorkspaceLinkState = Record<string, unknown>;
28
+ export interface WorkspaceLocalState {
29
+ version: 1;
30
+ paths: Record<string, string>;
31
+ preferred_opener?: WorkspacePreferredOpener;
32
+ }
33
+ export interface WorkspaceRegistryState {
34
+ version: 1;
35
+ workspaces: Record<string, string>;
36
+ }
37
+ export interface WorkspaceRegistryEntry {
38
+ name: string;
39
+ workspaceRoot: string;
40
+ }
41
+ export interface WorkspacePathOptions {
42
+ globalDataDir?: string;
43
+ }
44
+ export declare function getWorkspaceMetadataDir(workspaceRoot: string): string;
45
+ export declare function getWorkspaceSharedStatePath(workspaceRoot: string): string;
46
+ export declare function getWorkspaceLocalStatePath(workspaceRoot: string): string;
47
+ export declare function getWorkspaceChangesDir(workspaceRoot: string): string;
48
+ export declare function getManagedWorkspacesDir(options?: WorkspacePathOptions): string;
49
+ export declare function getManagedWorkspaceRoot(workspaceName: string, options?: WorkspacePathOptions): string;
50
+ export declare function getWorkspaceRegistryPath(options?: WorkspacePathOptions): string;
51
+ export declare function getWorkspaceCodeWorkspaceFileName(workspaceName: string): string;
52
+ export declare function getWorkspaceCodeWorkspacePath(workspaceRoot: string, workspaceName: string): string;
53
+ export declare function getWorkspacePortableIgnorePatterns(workspaceName?: string): string[];
54
+ export declare function validateWorkspaceName(name: string): string;
55
+ export declare function validateWorkspaceLinkName(name: string): string;
56
+ export declare function isValidWorkspaceName(name: string): boolean;
57
+ export declare function isValidWorkspaceLinkName(name: string): boolean;
58
+ export declare function isWorkspaceRoot(candidateRoot: string): Promise<boolean>;
59
+ export declare function findWorkspaceRoot(startPath?: string): Promise<string | null>;
60
+ export declare function isWorkspaceAgentOpenerId(value: string): value is WorkspaceAgentOpenerId;
61
+ export declare function isWorkspaceSupportedOpenerValue(value: string): value is WorkspaceSupportedOpenerValue;
62
+ export declare function parseWorkspacePreferredOpenerValue(value: string): WorkspacePreferredOpener;
63
+ export declare function validateWorkspacePreferredOpener(opener: WorkspacePreferredOpener): WorkspacePreferredOpener;
64
+ export declare function parseWorkspaceSharedState(content: string): WorkspaceSharedState;
65
+ export declare function parseWorkspaceLocalState(content: string): WorkspaceLocalState;
66
+ export declare function parseWorkspaceRegistryState(content: string): WorkspaceRegistryState;
67
+ export declare function serializeWorkspaceSharedState(state: WorkspaceSharedState): string;
68
+ export declare function serializeWorkspaceLocalState(state: WorkspaceLocalState): string;
69
+ export declare function serializeWorkspaceRegistryState(state: WorkspaceRegistryState): string;
70
+ export declare function listWorkspaceRegistryEntries(registry: WorkspaceRegistryState): WorkspaceRegistryEntry[];
71
+ export declare function readWorkspaceSharedState(workspaceRoot: string): Promise<WorkspaceSharedState>;
72
+ export declare function readWorkspaceLocalState(workspaceRoot: string): Promise<WorkspaceLocalState>;
73
+ export declare function readOptionalWorkspaceLocalState(workspaceRoot: string): Promise<WorkspaceLocalState | null>;
74
+ export declare function writeWorkspaceSharedState(workspaceRoot: string, state: WorkspaceSharedState): Promise<void>;
75
+ export declare function writeWorkspaceLocalState(workspaceRoot: string, state: WorkspaceLocalState): Promise<void>;
76
+ export declare function readWorkspaceRegistryState(options?: WorkspacePathOptions): Promise<WorkspaceRegistryState | null>;
77
+ export declare function writeWorkspaceRegistryState(state: WorkspaceRegistryState, options?: WorkspacePathOptions): Promise<void>;
78
+ export declare function workspaceChangesDirExists(workspaceRoot: string): Promise<boolean>;
79
+ //# sourceMappingURL=foundation.d.ts.map
@@ -0,0 +1,367 @@
1
+ import * as nodeFs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
4
+ import { z } from 'zod';
5
+ import { getGlobalDataDir } from '../global-config.js';
6
+ import { FileSystemUtils } from '../../utils/file-system.js';
7
+ const fs = nodeFs.promises;
8
+ export const WORKSPACE_METADATA_DIR_NAME = '.synarcx-workspace';
9
+ export const WORKSPACE_SHARED_STATE_FILE_NAME = 'workspace.yaml';
10
+ export const WORKSPACE_LOCAL_STATE_FILE_NAME = 'local.yaml';
11
+ export const WORKSPACE_CHANGES_DIR_NAME = 'changes';
12
+ export const MANAGED_WORKSPACES_DIR_NAME = 'workspaces';
13
+ export const WORKSPACE_REGISTRY_FILE_NAME = 'registry.yaml';
14
+ export const WORKSPACE_LOCAL_STATE_IGNORE_PATTERN = `${WORKSPACE_METADATA_DIR_NAME}/${WORKSPACE_LOCAL_STATE_FILE_NAME}`;
15
+ export const WORKSPACE_CODE_WORKSPACE_EXTENSION = '.code-workspace';
16
+ export const WORKSPACE_SUPPORTED_OPENER_VALUES = [
17
+ 'codex',
18
+ 'claude',
19
+ 'github-copilot',
20
+ 'editor',
21
+ ];
22
+ export const WORKSPACE_AGENT_OPENER_IDS = [
23
+ 'codex',
24
+ 'claude',
25
+ 'github-copilot',
26
+ ];
27
+ export const WORKSPACE_EDITOR_OPENER_IDS = ['vscode'];
28
+ function joinWorkspacePath(basePath, ...segments) {
29
+ return FileSystemUtils.joinPath(basePath, ...segments);
30
+ }
31
+ export function getWorkspaceMetadataDir(workspaceRoot) {
32
+ return joinWorkspacePath(workspaceRoot, WORKSPACE_METADATA_DIR_NAME);
33
+ }
34
+ export function getWorkspaceSharedStatePath(workspaceRoot) {
35
+ return joinWorkspacePath(getWorkspaceMetadataDir(workspaceRoot), WORKSPACE_SHARED_STATE_FILE_NAME);
36
+ }
37
+ export function getWorkspaceLocalStatePath(workspaceRoot) {
38
+ return joinWorkspacePath(getWorkspaceMetadataDir(workspaceRoot), WORKSPACE_LOCAL_STATE_FILE_NAME);
39
+ }
40
+ export function getWorkspaceChangesDir(workspaceRoot) {
41
+ return joinWorkspacePath(workspaceRoot, WORKSPACE_CHANGES_DIR_NAME);
42
+ }
43
+ export function getManagedWorkspacesDir(options = {}) {
44
+ return joinWorkspacePath(options.globalDataDir ?? getGlobalDataDir(), MANAGED_WORKSPACES_DIR_NAME);
45
+ }
46
+ export function getManagedWorkspaceRoot(workspaceName, options = {}) {
47
+ validateWorkspaceName(workspaceName);
48
+ return joinWorkspacePath(getManagedWorkspacesDir(options), workspaceName);
49
+ }
50
+ export function getWorkspaceRegistryPath(options = {}) {
51
+ return joinWorkspacePath(getManagedWorkspacesDir(options), WORKSPACE_REGISTRY_FILE_NAME);
52
+ }
53
+ export function getWorkspaceCodeWorkspaceFileName(workspaceName) {
54
+ validateWorkspaceName(workspaceName);
55
+ return `${workspaceName}${WORKSPACE_CODE_WORKSPACE_EXTENSION}`;
56
+ }
57
+ export function getWorkspaceCodeWorkspacePath(workspaceRoot, workspaceName) {
58
+ return joinWorkspacePath(workspaceRoot, getWorkspaceCodeWorkspaceFileName(workspaceName));
59
+ }
60
+ export function getWorkspacePortableIgnorePatterns(workspaceName) {
61
+ return workspaceName
62
+ ? [WORKSPACE_LOCAL_STATE_IGNORE_PATTERN, getWorkspaceCodeWorkspaceFileName(workspaceName)]
63
+ : [WORKSPACE_LOCAL_STATE_IGNORE_PATTERN];
64
+ }
65
+ function validateFolderStyleName(name, label) {
66
+ if (name.length === 0) {
67
+ throw new Error(`${label} must not be empty`);
68
+ }
69
+ if (name === '.' || name === '..') {
70
+ throw new Error(`${label} must not be '${name}'`);
71
+ }
72
+ if (/[\\/]/u.test(name)) {
73
+ throw new Error(`${label} must not contain path separators`);
74
+ }
75
+ return name;
76
+ }
77
+ export function validateWorkspaceName(name) {
78
+ validateFolderStyleName(name, 'Workspace name');
79
+ if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(name)) {
80
+ throw new Error('Workspace name must be kebab-case with lowercase letters, numbers, and single hyphen separators');
81
+ }
82
+ return name;
83
+ }
84
+ export function validateWorkspaceLinkName(name) {
85
+ return validateFolderStyleName(name, 'Workspace link name');
86
+ }
87
+ export function isValidWorkspaceName(name) {
88
+ try {
89
+ validateWorkspaceName(name);
90
+ return true;
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ }
96
+ export function isValidWorkspaceLinkName(name) {
97
+ try {
98
+ validateWorkspaceLinkName(name);
99
+ return true;
100
+ }
101
+ catch {
102
+ return false;
103
+ }
104
+ }
105
+ async function pathIsFile(filePath) {
106
+ try {
107
+ return (await fs.stat(filePath)).isFile();
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ async function pathIsDirectory(dirPath) {
114
+ try {
115
+ return (await fs.stat(dirPath)).isDirectory();
116
+ }
117
+ catch {
118
+ return false;
119
+ }
120
+ }
121
+ export async function isWorkspaceRoot(candidateRoot) {
122
+ return pathIsFile(getWorkspaceSharedStatePath(candidateRoot));
123
+ }
124
+ async function getSearchStartDirectory(startPath) {
125
+ const resolvedStart = path.resolve(startPath);
126
+ try {
127
+ const stats = await fs.stat(resolvedStart);
128
+ return stats.isDirectory() ? resolvedStart : path.dirname(resolvedStart);
129
+ }
130
+ catch {
131
+ return resolvedStart;
132
+ }
133
+ }
134
+ export async function findWorkspaceRoot(startPath = process.cwd()) {
135
+ let currentDir = await getSearchStartDirectory(startPath);
136
+ while (true) {
137
+ if (await isWorkspaceRoot(currentDir)) {
138
+ return process.platform === 'win32'
139
+ ? FileSystemUtils.canonicalizeExistingPath(currentDir)
140
+ : currentDir;
141
+ }
142
+ const parentDir = path.dirname(currentDir);
143
+ if (parentDir === currentDir) {
144
+ return null;
145
+ }
146
+ currentDir = parentDir;
147
+ }
148
+ }
149
+ function isPlainObject(value) {
150
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
151
+ }
152
+ const PlainObjectSchema = z.custom(isPlainObject, {
153
+ message: 'must be an object',
154
+ });
155
+ const SharedStateSchema = z.object({
156
+ version: z.literal(1),
157
+ name: z.string(),
158
+ links: z.record(z.string(), PlainObjectSchema),
159
+ }).strict();
160
+ const LocalStateSchema = z.object({
161
+ version: z.literal(1),
162
+ paths: z.record(z.string(), z.string()),
163
+ preferred_opener: z
164
+ .object({
165
+ kind: z.enum(['agent', 'editor']),
166
+ id: z.string(),
167
+ })
168
+ .strict()
169
+ .optional(),
170
+ }).strict();
171
+ const RegistryStateSchema = z.object({
172
+ version: z.literal(1),
173
+ workspaces: z.record(z.string(), z.string()),
174
+ }).strict();
175
+ function formatZodIssues(error) {
176
+ return error.issues
177
+ .map((issue) => {
178
+ const location = issue.path.length > 0 ? issue.path.join('.') : 'root';
179
+ return `${location}: ${issue.message}`;
180
+ })
181
+ .join('; ');
182
+ }
183
+ function parseYamlObject(content, label) {
184
+ try {
185
+ return parseYaml(content);
186
+ }
187
+ catch (error) {
188
+ const message = error instanceof Error ? error.message : String(error);
189
+ throw new Error(`Invalid ${label}: ${message}`);
190
+ }
191
+ }
192
+ function assertValidMapKeys(keys, validator, label) {
193
+ for (const key of keys) {
194
+ try {
195
+ validator(key);
196
+ }
197
+ catch (error) {
198
+ const message = error instanceof Error ? error.message : String(error);
199
+ throw new Error(`Invalid ${label} '${key}': ${message}`);
200
+ }
201
+ }
202
+ }
203
+ function formatSupportedOpenerValues() {
204
+ return WORKSPACE_SUPPORTED_OPENER_VALUES.join(', ');
205
+ }
206
+ export function isWorkspaceAgentOpenerId(value) {
207
+ return WORKSPACE_AGENT_OPENER_IDS.includes(value);
208
+ }
209
+ export function isWorkspaceSupportedOpenerValue(value) {
210
+ return WORKSPACE_SUPPORTED_OPENER_VALUES.includes(value);
211
+ }
212
+ export function parseWorkspacePreferredOpenerValue(value) {
213
+ if (value === 'editor') {
214
+ return {
215
+ kind: 'editor',
216
+ id: 'vscode',
217
+ };
218
+ }
219
+ if (isWorkspaceAgentOpenerId(value)) {
220
+ return {
221
+ kind: 'agent',
222
+ id: value,
223
+ };
224
+ }
225
+ throw new Error(`Unsupported workspace opener '${value}'. Supported values: ${formatSupportedOpenerValues()}`);
226
+ }
227
+ export function validateWorkspacePreferredOpener(opener) {
228
+ if (opener.kind === 'editor' && opener.id === 'vscode') {
229
+ return opener;
230
+ }
231
+ if (opener.kind === 'agent' && isWorkspaceAgentOpenerId(opener.id)) {
232
+ return opener;
233
+ }
234
+ throw new Error(`Unsupported workspace opener '${opener.kind}:${opener.id}'. Supported values: ${formatSupportedOpenerValues()}`);
235
+ }
236
+ export function parseWorkspaceSharedState(content) {
237
+ const raw = parseYamlObject(content, 'workspace shared state');
238
+ const result = SharedStateSchema.safeParse(raw);
239
+ if (!result.success) {
240
+ throw new Error(`Invalid workspace shared state: ${formatZodIssues(result.error)}`);
241
+ }
242
+ validateWorkspaceName(result.data.name);
243
+ assertValidMapKeys(Object.keys(result.data.links), validateWorkspaceLinkName, 'workspace link name');
244
+ return {
245
+ version: 1,
246
+ name: result.data.name,
247
+ links: result.data.links,
248
+ };
249
+ }
250
+ export function parseWorkspaceLocalState(content) {
251
+ const raw = parseYamlObject(content, 'workspace local state');
252
+ const result = LocalStateSchema.safeParse(raw);
253
+ if (!result.success) {
254
+ throw new Error(`Invalid workspace local state: ${formatZodIssues(result.error)}`);
255
+ }
256
+ assertValidMapKeys(Object.keys(result.data.paths), validateWorkspaceLinkName, 'workspace local path name');
257
+ const preferredOpener = result.data.preferred_opener
258
+ ? validateWorkspacePreferredOpener(result.data.preferred_opener)
259
+ : undefined;
260
+ return {
261
+ version: 1,
262
+ paths: result.data.paths,
263
+ ...(preferredOpener ? { preferred_opener: preferredOpener } : {}),
264
+ };
265
+ }
266
+ export function parseWorkspaceRegistryState(content) {
267
+ const raw = parseYamlObject(content, 'workspace registry state');
268
+ const result = RegistryStateSchema.safeParse(raw);
269
+ if (!result.success) {
270
+ throw new Error(`Invalid workspace registry state: ${formatZodIssues(result.error)}`);
271
+ }
272
+ assertValidMapKeys(Object.keys(result.data.workspaces), validateWorkspaceName, 'workspace registry name');
273
+ return {
274
+ version: 1,
275
+ workspaces: result.data.workspaces,
276
+ };
277
+ }
278
+ export function serializeWorkspaceSharedState(state) {
279
+ validateWorkspaceName(state.name);
280
+ assertValidMapKeys(Object.keys(state.links), validateWorkspaceLinkName, 'workspace link name');
281
+ for (const [linkName, linkState] of Object.entries(state.links)) {
282
+ if (!isPlainObject(linkState)) {
283
+ throw new Error(`Invalid workspace link '${linkName}': link state must be an object`);
284
+ }
285
+ }
286
+ return stringifyYaml({
287
+ version: 1,
288
+ name: state.name,
289
+ links: state.links,
290
+ });
291
+ }
292
+ export function serializeWorkspaceLocalState(state) {
293
+ assertValidMapKeys(Object.keys(state.paths), validateWorkspaceLinkName, 'workspace local path name');
294
+ for (const [linkName, localPath] of Object.entries(state.paths)) {
295
+ if (typeof localPath !== 'string') {
296
+ throw new Error(`Invalid workspace local path '${linkName}': path must be a string`);
297
+ }
298
+ }
299
+ const preferredOpener = state.preferred_opener
300
+ ? validateWorkspacePreferredOpener(state.preferred_opener)
301
+ : undefined;
302
+ return stringifyYaml({
303
+ version: 1,
304
+ paths: state.paths,
305
+ ...(preferredOpener ? { preferred_opener: preferredOpener } : {}),
306
+ });
307
+ }
308
+ export function serializeWorkspaceRegistryState(state) {
309
+ assertValidMapKeys(Object.keys(state.workspaces), validateWorkspaceName, 'workspace registry name');
310
+ for (const [workspaceName, workspaceRoot] of Object.entries(state.workspaces)) {
311
+ if (typeof workspaceRoot !== 'string') {
312
+ throw new Error(`Invalid workspace registry entry '${workspaceName}': path must be a string`);
313
+ }
314
+ }
315
+ return stringifyYaml({
316
+ version: 1,
317
+ workspaces: state.workspaces,
318
+ });
319
+ }
320
+ export function listWorkspaceRegistryEntries(registry) {
321
+ return Object.entries(registry.workspaces)
322
+ .map(([name, workspaceRoot]) => ({ name, workspaceRoot }))
323
+ .sort((a, b) => a.name.localeCompare(b.name));
324
+ }
325
+ export async function readWorkspaceSharedState(workspaceRoot) {
326
+ return parseWorkspaceSharedState(await fs.readFile(getWorkspaceSharedStatePath(workspaceRoot), 'utf-8'));
327
+ }
328
+ export async function readWorkspaceLocalState(workspaceRoot) {
329
+ return parseWorkspaceLocalState(await fs.readFile(getWorkspaceLocalStatePath(workspaceRoot), 'utf-8'));
330
+ }
331
+ function isFileNotFoundError(error) {
332
+ return (typeof error === 'object' &&
333
+ error !== null &&
334
+ 'code' in error &&
335
+ error.code === 'ENOENT');
336
+ }
337
+ export async function readOptionalWorkspaceLocalState(workspaceRoot) {
338
+ try {
339
+ return await readWorkspaceLocalState(workspaceRoot);
340
+ }
341
+ catch (error) {
342
+ if (isFileNotFoundError(error)) {
343
+ return null;
344
+ }
345
+ throw error;
346
+ }
347
+ }
348
+ export async function writeWorkspaceSharedState(workspaceRoot, state) {
349
+ await FileSystemUtils.writeFile(getWorkspaceSharedStatePath(workspaceRoot), serializeWorkspaceSharedState(state));
350
+ }
351
+ export async function writeWorkspaceLocalState(workspaceRoot, state) {
352
+ await FileSystemUtils.writeFile(getWorkspaceLocalStatePath(workspaceRoot), serializeWorkspaceLocalState(state));
353
+ }
354
+ export async function readWorkspaceRegistryState(options = {}) {
355
+ const registryPath = getWorkspaceRegistryPath(options);
356
+ if (!(await pathIsFile(registryPath))) {
357
+ return null;
358
+ }
359
+ return parseWorkspaceRegistryState(await fs.readFile(registryPath, 'utf-8'));
360
+ }
361
+ export async function writeWorkspaceRegistryState(state, options = {}) {
362
+ await FileSystemUtils.writeFile(getWorkspaceRegistryPath(options), serializeWorkspaceRegistryState(state));
363
+ }
364
+ export async function workspaceChangesDirExists(workspaceRoot) {
365
+ return pathIsDirectory(getWorkspaceChangesDir(workspaceRoot));
366
+ }
367
+ //# sourceMappingURL=foundation.js.map
@@ -0,0 +1,5 @@
1
+ export * from './foundation.js';
2
+ export * from './link-input.js';
3
+ export * from './openers.js';
4
+ export * from './open-surface.js';
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,5 @@
1
+ export * from './foundation.js';
2
+ export * from './link-input.js';
3
+ export * from './openers.js';
4
+ export * from './open-surface.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,9 @@
1
+ export interface WorkspaceParsedLinkInput {
2
+ name?: string;
3
+ pathInput: string;
4
+ }
5
+ export interface WorkspaceLinkInputParseOptions {
6
+ cwd?: string;
7
+ }
8
+ export declare function parseWorkspaceSetupLinkInput(value: string, options?: WorkspaceLinkInputParseOptions): Promise<WorkspaceParsedLinkInput>;
9
+ //# sourceMappingURL=link-input.d.ts.map
@@ -0,0 +1,32 @@
1
+ import * as nodeFs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ const fs = nodeFs.promises;
4
+ async function directoryExists(inputPath, cwd) {
5
+ if (inputPath.length === 0) {
6
+ return false;
7
+ }
8
+ const resolvedPath = path.isAbsolute(inputPath)
9
+ ? path.resolve(inputPath)
10
+ : path.resolve(cwd, inputPath);
11
+ try {
12
+ return (await fs.stat(resolvedPath)).isDirectory();
13
+ }
14
+ catch {
15
+ return false;
16
+ }
17
+ }
18
+ export async function parseWorkspaceSetupLinkInput(value, options = {}) {
19
+ const cwd = options.cwd ?? process.cwd();
20
+ if (await directoryExists(value, cwd)) {
21
+ return { pathInput: value };
22
+ }
23
+ const separatorIndex = value.indexOf('=');
24
+ if (separatorIndex === -1) {
25
+ return { pathInput: value };
26
+ }
27
+ return {
28
+ name: value.slice(0, separatorIndex),
29
+ pathInput: value.slice(separatorIndex + 1),
30
+ };
31
+ }
32
+ //# sourceMappingURL=link-input.js.map
@@ -0,0 +1,24 @@
1
+ import { WorkspaceLocalState, WorkspaceSharedState } from './foundation.js';
2
+ export declare const WORKSPACE_GUIDANCE_START_MARKER = "<!-- OPENSPEC:WORKSPACE-GUIDANCE:START -->";
3
+ export declare const WORKSPACE_GUIDANCE_END_MARKER = "<!-- OPENSPEC:WORKSPACE-GUIDANCE:END -->";
4
+ export declare const WORKSPACE_GUIDANCE_BODY = "# synarcx Workspace Guidance\n\nThis directory is a synarcx workspace for planning across linked repos or folders.\n\n- Use `changes/` for workspace-level planning.\n- Linked repos and folders are available for exploration and planning.\n- Repo or folder visibility supports exploration and planning.\n- Make implementation edits after the user explicitly asks for implementation work.\n- Treat linked repos and folders as the implementation homes for their owned code.\n- Use synarcx workspace commands instead of hand-editing `.synarcx-workspace/*.yaml`.";
5
+ export interface WorkspaceOpenLink {
6
+ name: string;
7
+ path: string;
8
+ }
9
+ export interface WorkspaceSkippedOpenLink {
10
+ name: string;
11
+ path: string | null;
12
+ reason: 'missing-local-path' | 'path-missing';
13
+ }
14
+ export interface WorkspaceOpenSurfaceLinks {
15
+ links: WorkspaceOpenLink[];
16
+ skipped: WorkspaceSkippedOpenLink[];
17
+ }
18
+ export declare function buildWorkspaceGuidanceBlock(): string;
19
+ export declare function applyWorkspaceGuidanceBlock(existingContent: string): string;
20
+ export declare function buildWorkspaceCodeWorkspaceContent(links: WorkspaceOpenLink[]): string;
21
+ export declare function writeWorkspaceCodeWorkspaceFile(codeWorkspacePath: string, links: WorkspaceOpenLink[]): Promise<void>;
22
+ export declare function resolveWorkspaceOpenLinks(sharedState: WorkspaceSharedState, localState: WorkspaceLocalState): Promise<WorkspaceOpenSurfaceLinks>;
23
+ export declare function syncWorkspaceOpenSurface(workspaceRoot: string, sharedState: WorkspaceSharedState, localState: WorkspaceLocalState): Promise<WorkspaceOpenSurfaceLinks>;
24
+ //# sourceMappingURL=open-surface.d.ts.map
@@ -0,0 +1,137 @@
1
+ import * as nodeFs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { FileSystemUtils } from '../../utils/file-system.js';
4
+ import { getWorkspaceCodeWorkspacePath, getWorkspacePortableIgnorePatterns, } from './foundation.js';
5
+ const fs = nodeFs.promises;
6
+ export const WORKSPACE_GUIDANCE_START_MARKER = '<!-- OPENSPEC:WORKSPACE-GUIDANCE:START -->';
7
+ export const WORKSPACE_GUIDANCE_END_MARKER = '<!-- OPENSPEC:WORKSPACE-GUIDANCE:END -->';
8
+ export const WORKSPACE_GUIDANCE_BODY = `# synarcx Workspace Guidance
9
+
10
+ This directory is a synarcx workspace for planning across linked repos or folders.
11
+
12
+ - Use \`changes/\` for workspace-level planning.
13
+ - Linked repos and folders are available for exploration and planning.
14
+ - Repo or folder visibility supports exploration and planning.
15
+ - Make implementation edits after the user explicitly asks for implementation work.
16
+ - Treat linked repos and folders as the implementation homes for their owned code.
17
+ - Use synarcx workspace commands instead of hand-editing \`.synarcx-workspace/*.yaml\`.`;
18
+ async function fileExists(filePath) {
19
+ try {
20
+ return (await fs.stat(filePath)).isFile();
21
+ }
22
+ catch {
23
+ return false;
24
+ }
25
+ }
26
+ async function directoryExists(dirPath) {
27
+ try {
28
+ return (await fs.stat(dirPath)).isDirectory();
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ export function buildWorkspaceGuidanceBlock() {
35
+ return `${WORKSPACE_GUIDANCE_START_MARKER}
36
+ ${WORKSPACE_GUIDANCE_BODY}
37
+ ${WORKSPACE_GUIDANCE_END_MARKER}`;
38
+ }
39
+ export function applyWorkspaceGuidanceBlock(existingContent) {
40
+ const block = buildWorkspaceGuidanceBlock();
41
+ const startIndex = existingContent.indexOf(WORKSPACE_GUIDANCE_START_MARKER);
42
+ const endIndex = existingContent.indexOf(WORKSPACE_GUIDANCE_END_MARKER);
43
+ if (startIndex !== -1 || endIndex !== -1) {
44
+ if (startIndex === -1 || endIndex === -1 || endIndex < startIndex) {
45
+ throw new Error('Invalid synarcx workspace guidance marker state in AGENTS.md.');
46
+ }
47
+ const before = existingContent.slice(0, startIndex).trimEnd();
48
+ const after = existingContent
49
+ .slice(endIndex + WORKSPACE_GUIDANCE_END_MARKER.length)
50
+ .trimStart();
51
+ const prefix = before.length > 0 ? `${before}\n\n` : '';
52
+ const suffix = after.length > 0 ? `\n\n${after.trimEnd()}\n` : '\n';
53
+ return `${prefix}${block}${suffix}`;
54
+ }
55
+ if (existingContent.trim().length === 0) {
56
+ return `${block}\n`;
57
+ }
58
+ return `${existingContent.trimEnd()}\n\n${block}\n`;
59
+ }
60
+ export function buildWorkspaceCodeWorkspaceContent(links) {
61
+ const folders = [
62
+ {
63
+ path: '.',
64
+ },
65
+ ...links.map((link) => ({
66
+ name: link.name,
67
+ path: link.path,
68
+ })),
69
+ ];
70
+ return `${JSON.stringify({ folders }, null, 2)}\n`;
71
+ }
72
+ export async function writeWorkspaceCodeWorkspaceFile(codeWorkspacePath, links) {
73
+ await FileSystemUtils.writeFile(codeWorkspacePath, buildWorkspaceCodeWorkspaceContent(links));
74
+ }
75
+ export async function resolveWorkspaceOpenLinks(sharedState, localState) {
76
+ const links = [];
77
+ const skipped = [];
78
+ for (const linkName of Object.keys(sharedState.links).sort((a, b) => a.localeCompare(b))) {
79
+ const localPath = localState.paths[linkName] ?? null;
80
+ if (!localPath) {
81
+ skipped.push({
82
+ name: linkName,
83
+ path: null,
84
+ reason: 'missing-local-path',
85
+ });
86
+ continue;
87
+ }
88
+ if (!(await directoryExists(localPath))) {
89
+ skipped.push({
90
+ name: linkName,
91
+ path: localPath,
92
+ reason: 'path-missing',
93
+ });
94
+ continue;
95
+ }
96
+ links.push({
97
+ name: linkName,
98
+ path: localPath,
99
+ });
100
+ }
101
+ return { links, skipped };
102
+ }
103
+ async function syncWorkspaceGuidance(workspaceRoot) {
104
+ const agentsPath = path.join(workspaceRoot, 'AGENTS.md');
105
+ const existingContent = (await fileExists(agentsPath))
106
+ ? await fs.readFile(agentsPath, 'utf-8')
107
+ : '';
108
+ await FileSystemUtils.writeFile(agentsPath, applyWorkspaceGuidanceBlock(existingContent));
109
+ }
110
+ async function syncWorkspaceCodeWorkspace(workspaceRoot, sharedState, links) {
111
+ await writeWorkspaceCodeWorkspaceFile(getWorkspaceCodeWorkspacePath(workspaceRoot, sharedState.name), links);
112
+ }
113
+ async function syncWorkspaceIgnoreRules(workspaceRoot, workspaceName) {
114
+ const gitignorePath = path.join(workspaceRoot, '.gitignore');
115
+ const patterns = getWorkspacePortableIgnorePatterns(workspaceName);
116
+ const existingContent = (await fileExists(gitignorePath))
117
+ ? await fs.readFile(gitignorePath, 'utf-8')
118
+ : '';
119
+ const existingLines = new Set(existingContent
120
+ .split(/\r?\n/u)
121
+ .map((line) => line.trim())
122
+ .filter((line) => line.length > 0));
123
+ const missingPatterns = patterns.filter((pattern) => !existingLines.has(pattern));
124
+ if (missingPatterns.length === 0) {
125
+ return;
126
+ }
127
+ const prefix = existingContent.length > 0 && !existingContent.endsWith('\n') ? '\n' : '';
128
+ await FileSystemUtils.writeFile(gitignorePath, `${existingContent}${prefix}${missingPatterns.join('\n')}\n`);
129
+ }
130
+ export async function syncWorkspaceOpenSurface(workspaceRoot, sharedState, localState) {
131
+ const openLinks = await resolveWorkspaceOpenLinks(sharedState, localState);
132
+ await syncWorkspaceGuidance(workspaceRoot);
133
+ await syncWorkspaceCodeWorkspace(workspaceRoot, sharedState, openLinks.links);
134
+ await syncWorkspaceIgnoreRules(workspaceRoot, sharedState.name);
135
+ return openLinks;
136
+ }
137
+ //# sourceMappingURL=open-surface.js.map